summaryrefslogtreecommitdiff
path: root/chromium/net
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2021-10-26 13:57:00 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2021-11-02 11:31:01 +0000
commit1943b3c2a1dcee36c233724fc4ee7613d71b9cf6 (patch)
tree8c1b5f12357025c197da5427ae02cfdc2f3570d6 /chromium/net
parent21ba0c5d4bf8fba15dddd97cd693bad2358b77fd (diff)
downloadqtwebengine-chromium-1943b3c2a1dcee36c233724fc4ee7613d71b9cf6.tar.gz
BASELINE: Update Chromium to 94.0.4606.111
Change-Id: I924781584def20fc800bedf6ff41fdb96c438193 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/net')
-rw-r--r--chromium/net/BUILD.gn63
-rw-r--r--chromium/net/android/dummy_spnego_authenticator.cc2
-rw-r--r--chromium/net/android/network_activation_request.h1
-rw-r--r--chromium/net/android/network_change_notifier_android.cc1
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.cc5
-rw-r--r--chromium/net/android/network_change_notifier_delegate_android.h4
-rw-r--r--chromium/net/android/unittest_support/AndroidManifest.xml7
-rw-r--r--chromium/net/base/address_list_unittest.cc2
-rw-r--r--chromium/net/base/address_tracker_linux.cc10
-rw-r--r--chromium/net/base/address_tracker_linux.h10
-rw-r--r--chromium/net/base/address_tracker_linux_unittest.cc174
-rw-r--r--chromium/net/base/backoff_entry_serializer_unittest.cc4
-rw-r--r--chromium/net/base/cache_type.h7
-rw-r--r--chromium/net/base/chunked_upload_data_stream_unittest.cc2
-rw-r--r--chromium/net/base/data_url.cc2
-rw-r--r--chromium/net/base/elements_upload_data_stream_unittest.cc2
-rw-r--r--chromium/net/base/escape.cc5
-rw-r--r--chromium/net/base/features.cc50
-rw-r--r--chromium/net/base/features.h105
-rw-r--r--chromium/net/base/file_stream_unittest.cc5
-rw-r--r--chromium/net/base/hash_value.cc2
-rw-r--r--chromium/net/base/host_mapping_rules.cc34
-rw-r--r--chromium/net/base/host_mapping_rules.h22
-rw-r--r--chromium/net/base/host_mapping_rules_unittest.cc108
-rw-r--r--chromium/net/base/host_port_pair.cc21
-rw-r--r--chromium/net/base/host_port_pair.h10
-rw-r--r--chromium/net/base/host_port_pair_unittest.cc32
-rw-r--r--chromium/net/base/interval.h1
-rw-r--r--chromium/net/base/ip_address.cc2
-rw-r--r--chromium/net/base/ip_address_unittest.cc2
-rw-r--r--chromium/net/base/ip_endpoint.cc152
-rw-r--r--chromium/net/base/ip_endpoint.h39
-rw-r--r--chromium/net/base/ip_endpoint_unittest.cc175
-rw-r--r--chromium/net/base/isolation_info.cc56
-rw-r--r--chromium/net/base/isolation_info.h17
-rw-r--r--chromium/net/base/isolation_info_unittest.cc109
-rw-r--r--chromium/net/base/mime_sniffer.cc1
-rw-r--r--chromium/net/base/mime_util.cc1
-rw-r--r--chromium/net/base/net_error_list.h5
-rw-r--r--chromium/net/base/net_errors.cc4
-rw-r--r--chromium/net/base/net_errors.h1
-rw-r--r--chromium/net/base/net_string_util_icu_alternatives_android.cc3
-rw-r--r--chromium/net/base/network_change_notifier.cc2
-rw-r--r--chromium/net/base/network_change_notifier_fuchsia_unittest.cc47
-rw-r--r--chromium/net/base/network_config_watcher_mac.cc1
-rw-r--r--chromium/net/base/network_delegate.cc57
-rw-r--r--chromium/net/base/network_delegate.h73
-rw-r--r--chromium/net/base/network_delegate_impl.cc18
-rw-r--r--chromium/net/base/network_delegate_impl.h23
-rw-r--r--chromium/net/base/network_delegate_unittest.cc129
-rw-r--r--chromium/net/base/network_interfaces_fuchsia.h1
-rw-r--r--chromium/net/base/network_interfaces_linux_unittest.cc2
-rw-r--r--chromium/net/base/network_interfaces_unittest.cc2
-rw-r--r--chromium/net/base/network_interfaces_win.cc1
-rw-r--r--chromium/net/base/network_isolation_key.cc39
-rw-r--r--chromium/net/base/network_isolation_key.h50
-rw-r--r--chromium/net/base/network_isolation_key_unittest.cc36
-rw-r--r--chromium/net/base/port_util.cc70
-rw-r--r--chromium/net/base/port_util_unittest.cc2
-rw-r--r--chromium/net/base/priority_queue_unittest.cc1
-rw-r--r--chromium/net/base/proxy_server_unittest.cc2
-rw-r--r--chromium/net/base/schemeful_site.cc5
-rw-r--r--chromium/net/base/schemeful_site.h6
-rw-r--r--chromium/net/base/schemeful_site_unittest.cc33
-rw-r--r--chromium/net/base/sys_addrinfo.h5
-rw-r--r--chromium/net/base/test_data_stream.h5
-rw-r--r--chromium/net/base/url_util.cc11
-rw-r--r--chromium/net/base/winsock_util.cc2
-rw-r--r--chromium/net/cert/asn1_util.cc17
-rw-r--r--chromium/net/cert/asn1_util.h7
-rw-r--r--chromium/net/cert/cert_and_ct_verifier.h2
-rw-r--r--chromium/net/cert/cert_database.cc8
-rw-r--r--chromium/net/cert/cert_verify_proc.cc31
-rw-r--r--chromium/net/cert/cert_verify_proc_android_unittest.cc3
-rw-r--r--chromium/net/cert/cert_verify_proc_blocklist.inc24
-rw-r--r--chromium/net/cert/cert_verify_proc_builtin.cc3
-rw-r--r--chromium/net/cert/cert_verify_proc_builtin.h1
-rw-r--r--chromium/net/cert/cert_verify_proc_unittest.cc117
-rw-r--r--chromium/net/cert/cert_verify_proc_win.cc47
-rw-r--r--chromium/net/cert/crl_set.cc2
-rw-r--r--chromium/net/cert/ct_log_verifier.cc7
-rw-r--r--chromium/net/cert/ct_log_verifier_unittest.cc2
-rw-r--r--chromium/net/cert/ct_objects_extractor_unittest.cc22
-rw-r--r--chromium/net/cert/internal/parsed_certificate.h1
-rw-r--r--chromium/net/cert/internal/path_builder.h2
-rw-r--r--chromium/net/cert/internal/revocation_checker.h1
-rw-r--r--chromium/net/cert/internal/revocation_util.h1
-rw-r--r--chromium/net/cert/internal/system_trust_store.cc65
-rw-r--r--chromium/net/cert/internal/system_trust_store.h27
-rw-r--r--chromium/net/cert/internal/trust_store_chrome.cc70
-rw-r--r--chromium/net/cert/internal/trust_store_chrome.h50
-rw-r--r--chromium/net/cert/internal/trust_store_chrome_unittest.cc99
-rw-r--r--chromium/net/cert/internal/trust_store_nss.cc26
-rw-r--r--chromium/net/cert/internal/trust_store_nss.h21
-rw-r--r--chromium/net/cert/internal/trust_store_nss_unittest.cc30
-rw-r--r--chromium/net/cert/merkle_tree_leaf_unittest.cc4
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.cc30
-rw-r--r--chromium/net/cert/multi_log_ct_verifier.h29
-rw-r--r--chromium/net/cert/multi_log_ct_verifier_unittest.cc37
-rw-r--r--chromium/net/cert/nss_cert_database_chromeos.cc2
-rw-r--r--chromium/net/cert/symantec_certs.cc2
-rw-r--r--chromium/net/cert/test_root_certs.cc2
-rw-r--r--chromium/net/cert/test_root_certs.h6
-rw-r--r--chromium/net/cert/test_root_certs_win.cc15
-rw-r--r--chromium/net/cert/trial_comparison_cert_verifier_unittest.cc3
-rw-r--r--chromium/net/cert/x509_certificate.cc64
-rw-r--r--chromium/net/cert/x509_certificate.h22
-rw-r--r--chromium/net/cert/x509_certificate_unittest.cc67
-rw-r--r--chromium/net/cert/x509_util_ios.cc10
-rw-r--r--chromium/net/cert/x509_util_mac.cc4
-rw-r--r--chromium/net/cert/x509_util_nss.cc12
-rw-r--r--chromium/net/cert/x509_util_nss_unittest.cc8
-rw-r--r--chromium/net/cert/x509_util_unittest.cc31
-rw-r--r--chromium/net/cert/x509_util_win.cc27
-rw-r--r--chromium/net/cert/x509_util_win.h17
-rw-r--r--chromium/net/cert_net/cert_net_fetcher_url_request_unittest.cc4
-rw-r--r--chromium/net/cookies/OWNERS4
-rw-r--r--chromium/net/cookies/canonical_cookie.cc447
-rw-r--r--chromium/net/cookies/canonical_cookie.h126
-rw-r--r--chromium/net/cookies/canonical_cookie_fuzzer.cc6
-rw-r--r--chromium/net/cookies/canonical_cookie_test_helpers.h129
-rw-r--r--chromium/net/cookies/canonical_cookie_unittest.cc2136
-rw-r--r--chromium/net/cookies/cookie_access_delegate.h12
-rw-r--r--chromium/net/cookies/cookie_constants.cc2
-rw-r--r--chromium/net/cookies/cookie_constants.h31
-rw-r--r--chromium/net/cookies/cookie_deletion_info_unittest.cc72
-rw-r--r--chromium/net/cookies/cookie_inclusion_status.cc154
-rw-r--r--chromium/net/cookies/cookie_inclusion_status.h52
-rw-r--r--chromium/net/cookies/cookie_monster.cc34
-rw-r--r--chromium/net/cookies/cookie_monster.h5
-rw-r--r--chromium/net/cookies/cookie_monster_perftest.cc5
-rw-r--r--chromium/net/cookies/cookie_monster_store_test.h3
-rw-r--r--chromium/net/cookies/cookie_monster_unittest.cc426
-rw-r--r--chromium/net/cookies/cookie_options.cc63
-rw-r--r--chromium/net/cookies/cookie_options.h170
-rw-r--r--chromium/net/cookies/cookie_options_unittest.cc58
-rw-r--r--chromium/net/cookies/cookie_partition_key.cc87
-rw-r--r--chromium/net/cookies/cookie_partition_key.h89
-rw-r--r--chromium/net/cookies/cookie_partition_key_fuzzer.cc42
-rw-r--r--chromium/net/cookies/cookie_partition_key_unittest.cc115
-rw-r--r--chromium/net/cookies/cookie_store.h1
-rw-r--r--chromium/net/cookies/cookie_store_test_callbacks.h1
-rw-r--r--chromium/net/cookies/cookie_store_test_helpers.h1
-rw-r--r--chromium/net/cookies/cookie_store_unittest.h29
-rw-r--r--chromium/net/cookies/cookie_util.cc216
-rw-r--r--chromium/net/cookies/cookie_util.h32
-rw-r--r--chromium/net/cookies/cookie_util_unittest.cc308
-rw-r--r--chromium/net/cookies/parse_cookie_line_fuzzer.cc5
-rw-r--r--chromium/net/cookies/parsed_cookie.cc105
-rw-r--r--chromium/net/cookies/parsed_cookie.h18
-rw-r--r--chromium/net/cookies/parsed_cookie_unittest.cc115
-rw-r--r--chromium/net/cookies/same_party_context.cc33
-rw-r--r--chromium/net/cookies/same_party_context.h63
-rw-r--r--chromium/net/cookies/test_cookie_access_delegate.cc7
-rw-r--r--chromium/net/cookies/test_cookie_access_delegate.h5
-rw-r--r--chromium/net/data/ssl/blocklist/06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem128
-rw-r--r--chromium/net/data/ssl/blocklist/0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem128
-rw-r--r--chromium/net/data/ssl/blocklist/README.md3
-rw-r--r--chromium/net/data/ssl/blocklist/c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem128
-rw-r--r--chromium/net/data/ssl/chrome_root_store/BUILD.gn161
-rw-r--r--chromium/net/data/ssl/chrome_root_store/README.md14
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem56
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem76
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem128
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem126
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem76
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem87
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem78
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem83
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem51
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem85
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem54
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem52
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem46
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem136
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem56
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem124
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem123
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem124
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem53
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem56
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem55
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem86
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem82
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem88
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem82
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem81
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem54
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem82
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem89
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem54
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem120
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem55
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem123
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem80
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem116
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem125
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem85
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem78
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem128
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem81
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem80
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem81
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem118
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem51
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem90
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem83
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem75
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem53
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem55
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem124
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem125
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem53
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem49
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem87
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem118
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem151
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem78
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem104
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem126
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem92
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem52
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem50
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem127
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem52
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem47
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem77
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem83
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem123
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem87
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem78
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem91
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem85
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem139
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem89
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem124
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem118
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem119
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem51
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem86
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem76
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem122
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem76
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem124
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem78
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem118
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem89
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem88
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem83
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem74
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/certs/fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem79
-rw-r--r--chromium/net/data/ssl/chrome_root_store/store/root_store.textproto620
-rw-r--r--chromium/net/der/input.cc4
-rw-r--r--chromium/net/der/input.h6
-rw-r--r--chromium/net/der/input_unittest.cc2
-rw-r--r--chromium/net/der/parse_values_unittest.cc2
-rw-r--r--chromium/net/der/parser.h5
-rw-r--r--chromium/net/disk_cache/backend_unittest.cc4
-rw-r--r--chromium/net/disk_cache/blockfile/backend_impl.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/block_files.cc4
-rw-r--r--chromium/net/disk_cache/blockfile/entry_impl.cc20
-rw-r--r--chromium/net/disk_cache/blockfile/entry_impl.h9
-rw-r--r--chromium/net/disk_cache/blockfile/histogram_macros.h1
-rw-r--r--chromium/net/disk_cache/blockfile/in_flight_backend_io.cc40
-rw-r--r--chromium/net/disk_cache/blockfile/in_flight_backend_io.h22
-rw-r--r--chromium/net/disk_cache/blockfile/mapped_file_unittest.cc2
-rw-r--r--chromium/net/disk_cache/blockfile/sparse_control.cc23
-rw-r--r--chromium/net/disk_cache/blockfile/sparse_control.h4
-rw-r--r--chromium/net/disk_cache/blockfile/stats.cc2
-rw-r--r--chromium/net/disk_cache/cache_util.cc28
-rw-r--r--chromium/net/disk_cache/cache_util_unittest.cc18
-rw-r--r--chromium/net/disk_cache/disk_cache.h62
-rw-r--r--chromium/net/disk_cache/disk_cache_fuzzer.cc47
-rw-r--r--chromium/net/disk_cache/disk_cache_test_base.cc12
-rw-r--r--chromium/net/disk_cache/disk_cache_test_base.h1
-rw-r--r--chromium/net/disk_cache/disk_cache_test_util.cc16
-rw-r--r--chromium/net/disk_cache/disk_cache_test_util.h23
-rw-r--r--chromium/net/disk_cache/entry_unittest.cc425
-rw-r--r--chromium/net/disk_cache/memory/mem_entry_impl.cc29
-rw-r--r--chromium/net/disk_cache/memory/mem_entry_impl.h9
-rw-r--r--chromium/net/disk_cache/net_log_parameters.cc12
-rw-r--r--chromium/net/disk_cache/net_log_parameters.h5
-rw-r--r--chromium/net/disk_cache/simple/simple_backend_impl.cc14
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.cc88
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_impl.h32
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_operation.cc42
-rw-r--r--chromium/net/disk_cache/simple/simple_entry_operation.h10
-rw-r--r--chromium/net/disk_cache/simple/simple_histogram_macros.h54
-rw-r--r--chromium/net/disk_cache/simple/simple_index.cc27
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.cc19
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file.h2
-rw-r--r--chromium/net/disk_cache/simple/simple_index_file_unittest.cc2
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.cc50
-rw-r--r--chromium/net/disk_cache/simple/simple_synchronous_entry.h11
-rw-r--r--chromium/net/dns/BUILD.gn12
-rw-r--r--chromium/net/dns/address_info_test_util.h8
-rw-r--r--chromium/net/dns/address_sorter_posix.cc2
-rw-r--r--chromium/net/dns/context_host_resolver.cc32
-rw-r--r--chromium/net/dns/context_host_resolver.h9
-rw-r--r--chromium/net/dns/context_host_resolver_unittest.cc59
-rw-r--r--chromium/net/dns/dns_config_service_linux_unittest.cc2
-rw-r--r--chromium/net/dns/dns_config_service_posix_unittest.cc2
-rw-r--r--chromium/net/dns/dns_hosts_unittest.cc2
-rw-r--r--chromium/net/dns/dns_query_unittest.cc2
-rw-r--r--chromium/net/dns/dns_response.cc11
-rw-r--r--chromium/net/dns/dns_response.h5
-rw-r--r--chromium/net/dns/dns_response_result_extractor.cc79
-rw-r--r--chromium/net/dns/dns_response_result_extractor.h6
-rw-r--r--chromium/net/dns/dns_response_result_extractor_unittest.cc358
-rw-r--r--chromium/net/dns/dns_response_unittest.cc63
-rw-r--r--chromium/net/dns/dns_session.cc1
-rw-r--r--chromium/net/dns/dns_test_util.cc72
-rw-r--r--chromium/net/dns/dns_test_util.h14
-rw-r--r--chromium/net/dns/dns_transaction.cc11
-rw-r--r--chromium/net/dns/dns_transaction.h3
-rw-r--r--chromium/net/dns/dns_transaction_unittest.cc5
-rw-r--r--chromium/net/dns/dns_util.cc1
-rw-r--r--chromium/net/dns/dns_util_unittest.cc2
-rw-r--r--chromium/net/dns/host_cache.cc161
-rw-r--r--chromium/net/dns/host_cache.h47
-rw-r--r--chromium/net/dns/host_cache_unittest.cc350
-rw-r--r--chromium/net/dns/host_resolver.cc8
-rw-r--r--chromium/net/dns/host_resolver.h27
-rw-r--r--chromium/net/dns/host_resolver_manager.cc704
-rw-r--r--chromium/net/dns/host_resolver_manager.h64
-rw-r--r--chromium/net/dns/host_resolver_manager_fuzzer.cc2
-rw-r--r--chromium/net/dns/host_resolver_manager_unittest.cc1689
-rw-r--r--chromium/net/dns/host_resolver_mdns_listener_impl.cc11
-rw-r--r--chromium/net/dns/host_resolver_mdns_task.cc5
-rw-r--r--chromium/net/dns/host_resolver_mdns_task.h2
-rw-r--r--chromium/net/dns/mapped_host_resolver.cc35
-rw-r--r--chromium/net/dns/mapped_host_resolver.h9
-rw-r--r--chromium/net/dns/mapped_host_resolver_unittest.cc161
-rw-r--r--chromium/net/dns/mdns_client_unittest.cc36
-rw-r--r--chromium/net/dns/mock_host_resolver.cc45
-rw-r--r--chromium/net/dns/mock_host_resolver.h24
-rw-r--r--chromium/net/dns/mock_mdns_socket_factory.cc33
-rw-r--r--chromium/net/dns/mock_mdns_socket_factory.h21
-rw-r--r--chromium/net/dns/public/BUILD.gn2
-rw-r--r--chromium/net/dns/public/dns_query_type.h18
-rw-r--r--chromium/net/dns/public/doh_provider_entry.cc31
-rw-r--r--chromium/net/dns/public/host_resolver_source.h (renamed from chromium/net/dns/host_resolver_source.h)8
-rw-r--r--chromium/net/dns/public/mdns_listener_update_type.h19
-rw-r--r--chromium/net/dns/resolve_context.h1
-rw-r--r--chromium/net/dns/resolve_context_unittest.cc2
-rw-r--r--chromium/net/docs/adding_doh_providers.md2
-rw-r--r--chromium/net/docs/life-of-a-feature.md2
-rw-r--r--chromium/net/extras/preload_data/decoder.cc2
-rw-r--r--chromium/net/extras/sqlite/DIR_METADATA3
-rw-r--r--chromium/net/extras/sqlite/OWNERS2
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc173
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc151
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc3
-rw-r--r--chromium/net/extras/sqlite/sqlite_persistent_store_backend_base.cc14
-rw-r--r--chromium/net/features.gni9
-rw-r--r--chromium/net/filter/brotli_source_stream_unittest.cc1
-rw-r--r--chromium/net/filter/gzip_source_stream_unittest.cc1
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser.cc2
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc2
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_vms.cc2
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc2
-rw-r--r--chromium/net/ftp/ftp_directory_listing_parser_windows_unittest.cc2
-rw-r--r--chromium/net/ftp/ftp_network_transaction.cc3
-rw-r--r--chromium/net/ftp/ftp_network_transaction_unittest.cc1
-rw-r--r--chromium/net/ftp/ftp_util_unittest.cc2
-rw-r--r--chromium/net/http/bidirectional_stream_unittest.cc4
-rw-r--r--chromium/net/http/http_auth.cc2
-rw-r--r--chromium/net/http/http_auth_cache.cc6
-rw-r--r--chromium/net/http/http_auth_controller.cc2
-rw-r--r--chromium/net/http/http_auth_filter_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_gssapi_posix.cc2
-rw-r--r--chromium/net/http/http_auth_gssapi_posix_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_handler_basic_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_handler_digest_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_handler_factory.cc19
-rw-r--r--chromium/net/http/http_auth_handler_negotiate_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_handler_ntlm.h1
-rw-r--r--chromium/net/http/http_auth_handler_ntlm_portable_unittest.cc2
-rw-r--r--chromium/net/http/http_auth_preferences.cc1
-rw-r--r--chromium/net/http/http_auth_unittest.cc2
-rw-r--r--chromium/net/http/http_basic_state.cc2
-rw-r--r--chromium/net/http/http_basic_state.h1
-rw-r--r--chromium/net/http/http_basic_stream.h1
-rw-r--r--chromium/net/http/http_byte_range_unittest.cc2
-rw-r--r--chromium/net/http/http_cache.cc1
-rw-r--r--chromium/net/http/http_cache.h10
-rw-r--r--chromium/net/http/http_cache_lookup_manager.cc1
-rw-r--r--chromium/net/http/http_cache_lookup_manager.h2
-rw-r--r--chromium/net/http/http_cache_transaction.cc2
-rw-r--r--chromium/net/http/http_cache_unittest.cc2
-rw-r--r--chromium/net/http/http_cache_writers.h2
-rw-r--r--chromium/net/http/http_chunked_decoder_unittest.cc2
-rw-r--r--chromium/net/http/http_content_disposition_unittest.cc2
-rw-r--r--chromium/net/http/http_network_layer.h1
-rw-r--r--chromium/net/http/http_network_layer_unittest.cc4
-rw-r--r--chromium/net/http/http_network_session.cc18
-rw-r--r--chromium/net/http/http_network_session.h203
-rw-r--r--chromium/net/http/http_network_session_peer.cc3
-rw-r--r--chromium/net/http/http_network_session_peer.h5
-rw-r--r--chromium/net/http/http_network_transaction.cc30
-rw-r--r--chromium/net/http/http_network_transaction_unittest.cc142
-rw-r--r--chromium/net/http/http_proxy_connect_job.cc62
-rw-r--r--chromium/net/http/http_proxy_connect_job.h16
-rw-r--r--chromium/net/http/http_proxy_connect_job_unittest.cc2
-rw-r--r--chromium/net/http/http_response_body_drainer.h7
-rw-r--r--chromium/net/http/http_response_body_drainer_unittest.cc4
-rw-r--r--chromium/net/http/http_response_headers.cc56
-rw-r--r--chromium/net/http/http_response_headers.h4
-rw-r--r--chromium/net/http/http_response_headers_unittest.cc84
-rw-r--r--chromium/net/http/http_server_properties_manager.cc1
-rw-r--r--chromium/net/http/http_server_properties_manager_unittest.cc7
-rw-r--r--chromium/net/http/http_stream_factory.cc1
-rw-r--r--chromium/net/http/http_stream_factory_job.cc97
-rw-r--r--chromium/net/http/http_stream_factory_job.h14
-rw-r--r--chromium/net/http/http_stream_factory_job_controller.cc143
-rw-r--r--chromium/net/http/http_stream_factory_job_controller.h2
-rw-r--r--chromium/net/http/http_stream_factory_job_controller_unittest.cc33
-rw-r--r--chromium/net/http/http_stream_factory_test_util.cc18
-rw-r--r--chromium/net/http/http_stream_factory_test_util.h7
-rw-r--r--chromium/net/http/http_stream_factory_unittest.cc32
-rw-r--r--chromium/net/http/http_stream_parser_unittest.cc6
-rw-r--r--chromium/net/http/http_stream_request.cc1
-rw-r--r--chromium/net/http/http_transaction_test_util.cc2
-rw-r--r--chromium/net/http/http_util.cc6
-rw-r--r--chromium/net/http/http_util.h4
-rw-r--r--chromium/net/http/http_util_unittest.cc2
-rw-r--r--chromium/net/http/http_vary_data_unittest.cc2
-rw-r--r--chromium/net/http/mock_http_cache.cc69
-rw-r--r--chromium/net/http/mock_http_cache.h13
-rw-r--r--chromium/net/http/partial_data.cc37
-rw-r--r--chromium/net/http/partial_data.h11
-rw-r--r--chromium/net/http/transport_security_persister.cc11
-rw-r--r--chromium/net/http/transport_security_persister.h7
-rw-r--r--chromium/net/http/transport_security_persister_unittest.cc34
-rw-r--r--chromium/net/http/transport_security_state.cc31
-rw-r--r--chromium/net/http/transport_security_state.h19
-rw-r--r--chromium/net/http/transport_security_state_static.json.gzbin1181819 -> 1244554 bytes
-rw-r--r--chromium/net/http/transport_security_state_static.template2
-rw-r--r--chromium/net/http/transport_security_state_static_unittest.template2
-rw-r--r--chromium/net/http/transport_security_state_test_util.cc1
-rw-r--r--chromium/net/http/transport_security_state_unittest.cc112
-rw-r--r--chromium/net/http/url_security_manager_unittest.cc2
-rw-r--r--chromium/net/http2/platform/impl/http2_string_utils_impl.h26
-rw-r--r--chromium/net/log/net_log_event_type_list.h7
-rw-r--r--chromium/net/log/net_log_source_type_list.h1
-rw-r--r--chromium/net/log/net_log_unittest.cc2
-rw-r--r--chromium/net/log/test_net_log.h1
-rw-r--r--chromium/net/log/trace_net_log_observer_unittest.cc2
-rw-r--r--chromium/net/network_error_logging/OWNERS2
-rw-r--r--chromium/net/network_error_logging/mock_persistent_nel_store.h1
-rw-r--r--chromium/net/network_error_logging/network_error_logging_service.cc2
-rw-r--r--chromium/net/nqe/network_qualities_prefs_manager.cc4
-rw-r--r--chromium/net/nqe/network_quality_estimator.cc259
-rw-r--r--chromium/net/nqe/network_quality_estimator.h26
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.cc21
-rw-r--r--chromium/net/nqe/network_quality_estimator_params.h29
-rw-r--r--chromium/net/nqe/network_quality_estimator_test_util.cc13
-rw-r--r--chromium/net/nqe/network_quality_estimator_test_util.h8
-rw-r--r--chromium/net/nqe/network_quality_estimator_unittest.cc222
-rw-r--r--chromium/net/nqe/network_quality_estimator_util.cc20
-rw-r--r--chromium/net/nqe/network_quality_estimator_util.h4
-rw-r--r--chromium/net/nqe/observation_buffer.cc6
-rw-r--r--chromium/net/nqe/throughput_analyzer.cc2
-rw-r--r--chromium/net/nqe/throughput_analyzer.h1
-rw-r--r--chromium/net/ntlm/ntlm_buffer_reader.h1
-rw-r--r--chromium/net/ntlm/ntlm_buffer_reader_unittest.cc2
-rw-r--r--chromium/net/ntlm/ntlm_buffer_writer_unittest.cc2
-rw-r--r--chromium/net/ntlm/ntlm_client_unittest.cc6
-rw-r--r--chromium/net/ntlm/ntlm_constants.h2
-rw-r--r--chromium/net/ntlm/ntlm_test_data.h2
-rw-r--r--chromium/net/ntlm/ntlm_unittest.cc22
-rw-r--r--chromium/net/proxy_resolution/multi_threaded_proxy_resolver.cc1
-rw-r--r--chromium/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc1
-rw-r--r--chromium/net/proxy_resolution/network_delegate_error_observer_unittest.cc35
-rw-r--r--chromium/net/proxy_resolution/pac_file_decider.cc10
-rw-r--r--chromium/net/proxy_resolution/pac_file_decider_unittest.cc25
-rw-r--r--chromium/net/proxy_resolution/pac_file_fetcher.cc12
-rw-r--r--chromium/net/proxy_resolution/pac_file_fetcher.h16
-rw-r--r--chromium/net/proxy_resolution/pac_file_fetcher_impl.cc5
-rw-r--r--chromium/net/proxy_resolution/pac_file_fetcher_impl.h6
-rw-r--r--chromium/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc48
-rw-r--r--chromium/net/proxy_resolution/proxy_bypass_rules_unittest.cc2
-rw-r--r--chromium/net/proxy_resolution/proxy_config_service_linux.cc1
-rw-r--r--chromium/net/proxy_resolution/proxy_config_service_linux_unittest.cc40
-rw-r--r--chromium/net/proxy_resolution/proxy_config_unittest.cc2
-rw-r--r--chromium/net/proxy_resolution/proxy_list_unittest.cc2
-rw-r--r--chromium/net/proxy_resolution/proxy_resolver.h2
-rw-r--r--chromium/net/proxy_resolution/proxy_resolver_mac.cc15
-rw-r--r--chromium/net/proxy_resolution/win/proxy_config_service_win.h1
-rw-r--r--chromium/net/proxy_resolution/win/proxy_config_service_win_unittest.cc2
-rw-r--r--chromium/net/proxy_resolution/win/windows_system_proxy_resolver_unittest.cc210
-rw-r--r--chromium/net/quic/address_utils.h6
-rw-r--r--chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc15
-rw-r--r--chromium/net/quic/crypto/proof_source_chromium.cc9
-rw-r--r--chromium/net/quic/crypto/proof_source_chromium.h3
-rw-r--r--chromium/net/quic/crypto/proof_verifier_chromium_test.cc22
-rw-r--r--chromium/net/quic/crypto_test_utils_chromium.cc1
-rw-r--r--chromium/net/quic/dedicated_web_transport_http3_client.cc8
-rw-r--r--chromium/net/quic/mock_crypto_client_stream.cc12
-rw-r--r--chromium/net/quic/mock_crypto_client_stream.h2
-rw-r--r--chromium/net/quic/mock_crypto_client_stream_factory.h1
-rw-r--r--chromium/net/quic/platform/impl/DEPS6
-rw-r--r--chromium/net/quic/platform/impl/quic_chromium_clock.cc15
-rw-r--r--chromium/net/quic/platform/impl/quic_chromium_clock.h5
-rw-r--r--chromium/net/quic/platform/impl/quic_containers_impl.h15
-rw-r--r--chromium/net/quic/platform/impl/quic_flags_impl.cc15
-rw-r--r--chromium/net/quic/platform/impl/quic_flags_impl.h13
-rw-r--r--chromium/net/quic/platform/impl/quic_flags_test.cc2
-rw-r--r--chromium/net/quic/platform/impl/quic_hostname_utils_impl.cc4
-rw-r--r--chromium/net/quic/platform/impl/quic_map_util_impl.h24
-rw-r--r--chromium/net/quic/platform/impl/quic_test_flags_utils.cc64
-rw-r--r--chromium/net/quic/platform/impl/quic_test_flags_utils.h30
-rw-r--r--chromium/net/quic/platform/impl/quic_test_impl.cc12
-rw-r--r--chromium/net/quic/platform/impl/quic_test_impl.h27
-rw-r--r--chromium/net/quic/platform/impl/quic_test_loopback_impl.cc2
-rw-r--r--chromium/net/quic/quic_chromium_alarm_factory.cc77
-rw-r--r--chromium/net/quic/quic_chromium_alarm_factory.h10
-rw-r--r--chromium/net/quic/quic_chromium_alarm_factory_test.cc192
-rw-r--r--chromium/net/quic/quic_chromium_client_session.cc67
-rw-r--r--chromium/net/quic/quic_chromium_client_session.h10
-rw-r--r--chromium/net/quic/quic_chromium_client_session_test.cc219
-rw-r--r--chromium/net/quic/quic_chromium_client_stream_test.cc38
-rw-r--r--chromium/net/quic/quic_client_session_cache.h1
-rw-r--r--chromium/net/quic/quic_connection_logger.h1
-rw-r--r--chromium/net/quic/quic_connectivity_monitor.h1
-rw-r--r--chromium/net/quic/quic_connectivity_probing_manager_test.cc92
-rw-r--r--chromium/net/quic/quic_context.h11
-rw-r--r--chromium/net/quic/quic_crypto_client_stream_factory.h1
-rw-r--r--chromium/net/quic/quic_end_to_end_unittest.cc11
-rw-r--r--chromium/net/quic/quic_event_logger.cc60
-rw-r--r--chromium/net/quic/quic_http3_logger.cc66
-rw-r--r--chromium/net/quic/quic_http3_logger.h12
-rw-r--r--chromium/net/quic/quic_http_stream.cc17
-rw-r--r--chromium/net/quic/quic_http_stream_test.cc29
-rw-r--r--chromium/net/quic/quic_network_transaction_unittest.cc115
-rw-r--r--chromium/net/quic/quic_proxy_client_socket_unittest.cc52
-rw-r--r--chromium/net/quic/quic_stream_factory.cc46
-rw-r--r--chromium/net/quic/quic_stream_factory.h15
-rw-r--r--chromium/net/quic/quic_stream_factory_fuzzer.cc14
-rw-r--r--chromium/net/quic/quic_stream_factory_peer.cc12
-rw-r--r--chromium/net/quic/quic_stream_factory_peer.h5
-rw-r--r--chromium/net/quic/quic_stream_factory_test.cc3274
-rw-r--r--chromium/net/quic/quic_test_packet_maker.cc121
-rw-r--r--chromium/net/quic/quic_test_packet_maker.h55
-rw-r--r--chromium/net/quic/quic_transport_client.cc5
-rw-r--r--chromium/net/quiche/common/platform/impl/DEPS8
-rw-r--r--chromium/net/quiche/common/platform/impl/quiche_test_impl.cc21
-rw-r--r--chromium/net/quiche/common/platform/impl/quiche_test_impl.h4
-rw-r--r--chromium/net/reporting/DIR_METADATA3
-rw-r--r--chromium/net/reporting/OWNERS4
-rw-r--r--chromium/net/reporting/mock_persistent_reporting_store.h1
-rw-r--r--chromium/net/reporting/reporting_browsing_data_remover.cc7
-rw-r--r--chromium/net/reporting/reporting_cache.h7
-rw-r--r--chromium/net/reporting/reporting_cache_impl.cc22
-rw-r--r--chromium/net/reporting/reporting_cache_impl.h6
-rw-r--r--chromium/net/reporting/reporting_cache_unittest.cc14
-rw-r--r--chromium/net/reporting/reporting_delivery_agent.cc2
-rw-r--r--chromium/net/reporting/reporting_delivery_agent_unittest.cc4
-rw-r--r--chromium/net/reporting/reporting_endpoint.cc46
-rw-r--r--chromium/net/reporting/reporting_endpoint.h17
-rw-r--r--chromium/net/reporting/reporting_endpoint_manager.cc1
-rw-r--r--chromium/net/reporting/reporting_endpoint_manager.h1
-rw-r--r--chromium/net/reporting/reporting_endpoint_manager_unittest.cc8
-rw-r--r--chromium/net/reporting/reporting_garbage_collector.cc6
-rw-r--r--chromium/net/reporting/reporting_header_parser.cc61
-rw-r--r--chromium/net/reporting/reporting_header_parser.h13
-rw-r--r--chromium/net/reporting/reporting_header_parser_unittest.cc15
-rw-r--r--chromium/net/reporting/reporting_network_change_observer.cc3
-rw-r--r--chromium/net/reporting/reporting_report.cc35
-rw-r--r--chromium/net/reporting/reporting_report.h53
-rw-r--r--chromium/net/reporting/reporting_service.cc42
-rw-r--r--chromium/net/reporting/reporting_service.h11
-rw-r--r--chromium/net/reporting/reporting_service_unittest.cc11
-rw-r--r--chromium/net/reporting/reporting_test_util.cc7
-rw-r--r--chromium/net/reporting/reporting_test_util.h10
-rw-r--r--chromium/net/reporting/reporting_uploader_unittest.cc5
-rw-r--r--chromium/net/server/OWNERS1
-rw-r--r--chromium/net/server/http_server_unittest.cc3
-rw-r--r--chromium/net/socket/client_socket_handle.cc6
-rw-r--r--chromium/net/socket/client_socket_handle.h1
-rw-r--r--chromium/net/socket/client_socket_pool.cc76
-rw-r--r--chromium/net/socket/client_socket_pool.h54
-rw-r--r--chromium/net/socket/client_socket_pool_base_unittest.cc170
-rw-r--r--chromium/net/socket/client_socket_pool_manager.cc122
-rw-r--r--chromium/net/socket/client_socket_pool_manager.h43
-rw-r--r--chromium/net/socket/client_socket_pool_unittest.cc114
-rw-r--r--chromium/net/socket/connect_job.cc92
-rw-r--r--chromium/net/socket/connect_job.h26
-rw-r--r--chromium/net/socket/connect_job_factory.cc247
-rw-r--r--chromium/net/socket/connect_job_factory.h137
-rw-r--r--chromium/net/socket/connect_job_factory_unittest.cc614
-rw-r--r--chromium/net/socket/fuzzed_server_socket.h1
-rw-r--r--chromium/net/socket/sequenced_socket_data_unittest.cc2
-rw-r--r--chromium/net/socket/socket_descriptor.h6
-rw-r--r--chromium/net/socket/socket_net_log_params.h1
-rw-r--r--chromium/net/socket/socket_test_util.cc17
-rw-r--r--chromium/net/socket/socket_test_util.h1
-rw-r--r--chromium/net/socket/socks5_client_socket.cc3
-rw-r--r--chromium/net/socket/socks5_client_socket_unittest.cc2
-rw-r--r--chromium/net/socket/socks_client_socket.cc2
-rw-r--r--chromium/net/socket/socks_client_socket_unittest.cc2
-rw-r--r--chromium/net/socket/socks_connect_job.cc12
-rw-r--r--chromium/net/socket/socks_connect_job.h15
-rw-r--r--chromium/net/socket/ssl_client_socket_impl.cc12
-rw-r--r--chromium/net/socket/ssl_client_socket_unittest.cc8
-rw-r--r--chromium/net/socket/ssl_connect_job.cc13
-rw-r--r--chromium/net/socket/ssl_connect_job.h14
-rw-r--r--chromium/net/socket/ssl_connect_job_unittest.cc39
-rw-r--r--chromium/net/socket/ssl_server_socket_unittest.cc2
-rw-r--r--chromium/net/socket/transport_client_socket_pool.cc105
-rw-r--r--chromium/net/socket/transport_client_socket_pool.h26
-rw-r--r--chromium/net/socket/transport_client_socket_pool_unittest.cc393
-rw-r--r--chromium/net/socket/transport_connect_job.cc49
-rw-r--r--chromium/net/socket/transport_connect_job.h36
-rw-r--r--chromium/net/socket/transport_connect_job_unittest.cc42
-rw-r--r--chromium/net/socket/udp_socket_posix.cc2
-rw-r--r--chromium/net/socket/udp_socket_posix_unittest.cc5
-rw-r--r--chromium/net/socket/udp_socket_unittest.cc7
-rw-r--r--chromium/net/socket/udp_socket_win.h2
-rw-r--r--chromium/net/socket/unix_domain_server_socket_posix_unittest.cc1
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool.cc10
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool.h1
-rw-r--r--chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc19
-rw-r--r--chromium/net/socket/websocket_transport_connect_job.cc42
-rw-r--r--chromium/net/socket/websocket_transport_connect_job.h15
-rw-r--r--chromium/net/spdy/OWNERS2
-rw-r--r--chromium/net/spdy/bidirectional_stream_spdy_impl_unittest.cc2
-rw-r--r--chromium/net/spdy/platform/impl/DEPS7
-rw-r--r--chromium/net/spdy/platform/impl/spdy_containers_impl.h25
-rw-r--r--chromium/net/spdy/platform/impl/spdy_string_utils_impl.cc20
-rw-r--r--chromium/net/spdy/platform/impl/spdy_string_utils_impl.h32
-rw-r--r--chromium/net/spdy/spdy_buffer_unittest.cc2
-rw-r--r--chromium/net/spdy/spdy_http_stream.cc67
-rw-r--r--chromium/net/spdy/spdy_http_stream.h11
-rw-r--r--chromium/net/spdy/spdy_http_stream_unittest.cc4
-rw-r--r--chromium/net/spdy/spdy_network_transaction_unittest.cc40
-rw-r--r--chromium/net/spdy/spdy_proxy_client_socket_unittest.cc14
-rw-r--r--chromium/net/spdy/spdy_read_queue_unittest.cc2
-rw-r--r--chromium/net/spdy/spdy_session.cc23
-rw-r--r--chromium/net/spdy/spdy_session.h12
-rw-r--r--chromium/net/spdy/spdy_session_fuzzer.cc7
-rw-r--r--chromium/net/spdy/spdy_session_pool.cc24
-rw-r--r--chromium/net/spdy/spdy_session_pool_unittest.cc211
-rw-r--r--chromium/net/spdy/spdy_session_unittest.cc51
-rw-r--r--chromium/net/spdy/spdy_stream_test_util.cc1
-rw-r--r--chromium/net/spdy/spdy_stream_unittest.cc2
-rw-r--r--chromium/net/spdy/spdy_test_util_common.cc65
-rw-r--r--chromium/net/spdy/spdy_test_util_common.h40
-rw-r--r--chromium/net/spdy/spdy_write_queue_unittest.cc2
-rw-r--r--chromium/net/ssl/OWNERS1
-rw-r--r--chromium/net/ssl/client_cert_identity_unittest.cc12
-rw-r--r--chromium/net/ssl/client_cert_store_mac.cc2
-rw-r--r--chromium/net/ssl/client_cert_store_nss.cc5
-rw-r--r--chromium/net/ssl/client_cert_store_win.cc47
-rw-r--r--chromium/net/ssl/client_cert_store_win.h11
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names.cc2
-rw-r--r--chromium/net/ssl/ssl_cipher_suite_names_unittest.cc2
-rw-r--r--chromium/net/ssl/ssl_client_auth_cache.h1
-rw-r--r--chromium/net/ssl/ssl_config.h1
-rw-r--r--chromium/net/ssl/ssl_config_service.h3
-rw-r--r--chromium/net/ssl/ssl_platform_key_win.cc86
-rw-r--r--chromium/net/ssl/ssl_platform_key_win.h5
-rw-r--r--chromium/net/ssl/ssl_platform_key_win_unittest.cc12
-rw-r--r--chromium/net/test/android/javatests/src/org/chromium/net/test/OWNERS2
-rw-r--r--chromium/net/test/cert_test_util.cc19
-rw-r--r--chromium/net/test/cert_test_util.h24
-rw-r--r--chromium/net/test/cert_test_util_nss.cc14
-rw-r--r--chromium/net/test/embedded_test_server/controllable_http_response.h2
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.cc9
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server.h8
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server_connection_listener.h5
-rw-r--r--chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc20
-rw-r--r--chromium/net/test/gtest_util.h7
-rw-r--r--chromium/net/test/net_test_suite.cc26
-rw-r--r--chromium/net/test/quic_simple_test_server.cc34
-rw-r--r--chromium/net/test/quic_simple_test_server.h33
-rw-r--r--chromium/net/test/spawned_test_server/base_test_server.cc2
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server.cc2
-rw-r--r--chromium/net/test/spawned_test_server/local_test_server.h1
-rw-r--r--chromium/net/test/spawned_test_server/remote_test_server.cc2
-rw-r--r--chromium/net/test/test_data_directory.cc15
-rw-r--r--chromium/net/test/test_data_directory.h4
-rw-r--r--chromium/net/test/url_request/url_request_failed_job.cc2
-rw-r--r--chromium/net/third_party/nss/README.chromium12
-rw-r--r--chromium/net/third_party/quiche/BUILD.gn39
-rw-r--r--chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_bug_tracker_impl.h (renamed from chromium/net/quiche/common/platform/impl/quiche_bug_tracker_impl.h)6
-rw-r--r--chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h2
-rw-r--r--chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_thread_local_impl.h27
-rw-r--r--chromium/net/third_party/quiche/src/CONTRIBUTING.md13
-rw-r--r--chromium/net/third_party/quiche/src/README.md30
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h2
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.cc51
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.h40
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils_test.cc86
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h12
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/api/quiche_thread_local.h27
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_bug_tracker_impl.h15
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_containers_impl.h21
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_estimate_memory_usage_impl.h20
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc182
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h26
-rw-r--r--chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_thread_local_impl.h24
-rw-r--r--chromium/net/third_party/quiche/src/common/print_elements.h35
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc330
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h47
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc89
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source.cc23
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source.h53
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc40
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h106
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc4
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h46
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_session.h5
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_util.h7
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h63
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h46
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc9
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h6
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc174
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h81
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc1438
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc169
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h47
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.cc63
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.h37
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider_test.cc117
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc24
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h11
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc67
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test.cc205
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.cc454
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.h99
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc158
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h15
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util_test.cc109
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc77
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h31
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc841
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc722
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h193
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc842
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h4
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc58
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h20
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc76
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h20
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc526
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/test_utils.h115
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager.h4
-rw-r--r--chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h7
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h4
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc5
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h3
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc13
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h3
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc11
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_constants.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_structures.cc1
-rw-r--r--chromium/net/third_party/quiche/src/http2/http2_structures_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_containers.h17
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_estimate_memory_usage.h21
-rw-r--r--chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h23
-rw-r--r--chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc2
-rw-r--r--chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_test.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc93
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc28
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/quic_random.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc49
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc298
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc641
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc25
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames.h43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/http_frames_test.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc39
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc38
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc55
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc155
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc249
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc433
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h116
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc329
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc88
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_alarm.cc60
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_alarm.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_alarm_test.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h53
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.cc896
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection.h145
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_context.cc36
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_context.h118
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_context_test.cc173
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc565
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_constants.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_handshaker.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc194
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h42
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc70
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h82
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer.h9
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc32
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc57
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_path_validator.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc122
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_server_id.h6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_server_id_test.cc21
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.cc155
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session.h71
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc83
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator_test.cc38
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.cc84
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream.h46
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc18
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc29
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_types.h23
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc11
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils.h12
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h4
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc35
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc13
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc224
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h61
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc124
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h35
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc71
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h19
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc170
-rw-r--r--chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h55
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h20
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_containers_test.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_estimate_memory_usage.h21
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc23
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h26
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_map_util.h24
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h17
-rw-r--r--chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.cc22
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.h16
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller_test.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc16
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc8
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc6
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc33
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h13
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc9
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc26
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc15
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc12
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h10
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h85
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc43
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc2
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.cc3
-rw-r--r--chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc17
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc63
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc34
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h1
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc5
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc144
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc4
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc14
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.cc7
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h3
-rw-r--r--chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter_test.cc10
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h8
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc6
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc30
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h3
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc25
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h14
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/http2_header_block_hpack_listener.h47
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/metadata_extension.cc195
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/metadata_extension.h116
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/metadata_extension_test.cc226
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc15
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h5
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc98
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h14
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_block_test.cc2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.h2
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_intrusive_list.h7
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc1
-rw-r--r--chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h21
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h18
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h21
-rw-r--r--chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h21
-rw-r--r--chromium/net/tools/cachetool/cachetool.cc3
-rw-r--r--chromium/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc6
-rw-r--r--chromium/net/tools/cert_verify_tool/verify_using_path_builder.h1
-rw-r--r--chromium/net/tools/content_decoder_tool/content_decoder_tool_unittest.cc1
-rw-r--r--chromium/net/tools/crash_cache/crash_cache.cc2
-rw-r--r--chromium/net/tools/dafsa/PRESUBMIT.py4
-rw-r--r--chromium/net/tools/huffman_trie/trie/trie_writer.h1
-rw-r--r--chromium/net/tools/quic/quic_client_message_loop_network_helper.h1
-rw-r--r--chromium/net/tools/quic/quic_simple_client.h1
-rw-r--r--chromium/net/tools/quic/quic_simple_server.cc5
-rw-r--r--chromium/net/tools/quic/quic_simple_server_test.cc2
-rw-r--r--chromium/net/tools/quic/quic_transport_simple_server.cc2
-rw-r--r--chromium/net/tools/quic/quic_transport_simple_server.h4
-rw-r--r--chromium/net/tools/quic/quic_transport_simple_server_bin.cc2
-rw-r--r--chromium/net/tools/root_store_tool/BUILD.gn26
-rw-r--r--chromium/net/tools/root_store_tool/README.md8
-rw-r--r--chromium/net/tools/root_store_tool/root_store.proto27
-rw-r--r--chromium/net/tools/root_store_tool/root_store_tool.cc216
-rw-r--r--chromium/net/tools/tld_cleanup/tld_cleanup_util.cc2
-rw-r--r--chromium/net/tools/transport_security_state_generator/input_file_parsers.cc2
-rw-r--r--chromium/net/traffic_annotation/network_traffic_annotation.h5
-rw-r--r--chromium/net/url_request/http_with_dns_over_https_unittest.cc8
-rw-r--r--chromium/net/url_request/redirect_info.h1
-rw-r--r--chromium/net/url_request/report_sender.h1
-rw-r--r--chromium/net/url_request/url_fetcher.h3
-rw-r--r--chromium/net/url_request/url_request.cc23
-rw-r--r--chromium/net/url_request/url_request.h16
-rw-r--r--chromium/net/url_request/url_request_context.cc7
-rw-r--r--chromium/net/url_request/url_request_context.h9
-rw-r--r--chromium/net/url_request/url_request_context_builder.cc68
-rw-r--r--chromium/net/url_request/url_request_context_builder.h19
-rw-r--r--chromium/net/url_request/url_request_context_storage.cc2
-rw-r--r--chromium/net/url_request/url_request_filter.cc1
-rw-r--r--chromium/net/url_request/url_request_http_job.cc187
-rw-r--r--chromium/net/url_request/url_request_http_job.h4
-rw-r--r--chromium/net/url_request/url_request_http_job_unittest.cc216
-rw-r--r--chromium/net/url_request/url_request_job.cc7
-rw-r--r--chromium/net/url_request/url_request_job.h4
-rw-r--r--chromium/net/url_request/url_request_quic_perftest.cc6
-rw-r--r--chromium/net/url_request/url_request_quic_unittest.cc18
-rw-r--r--chromium/net/url_request/url_request_test_job.cc3
-rw-r--r--chromium/net/url_request/url_request_test_job.h3
-rw-r--r--chromium/net/url_request/url_request_test_util.cc103
-rw-r--r--chromium/net/url_request/url_request_test_util.h124
-rw-r--r--chromium/net/url_request/url_request_throttler_simulation_unittest.cc2
-rw-r--r--chromium/net/url_request/url_request_throttler_unittest.cc2
-rw-r--r--chromium/net/url_request/url_request_unittest.cc286
-rw-r--r--chromium/net/websockets/websocket_basic_handshake_stream.cc1
-rw-r--r--chromium/net/websockets/websocket_basic_stream_adapters_test.cc8
-rw-r--r--chromium/net/websockets/websocket_basic_stream_test.cc6
-rw-r--r--chromium/net/websockets/websocket_channel.cc57
-rw-r--r--chromium/net/websockets/websocket_channel_test.cc193
-rw-r--r--chromium/net/websockets/websocket_deflate_parameters_test.cc2
-rw-r--r--chromium/net/websockets/websocket_extension_parser_test.cc2
-rw-r--r--chromium/net/websockets/websocket_frame_parser_test.cc2
-rw-r--r--chromium/net/websockets/websocket_frame_perftest.cc2
-rw-r--r--chromium/net/websockets/websocket_frame_test.cc2
-rw-r--r--chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc4
-rw-r--r--chromium/net/websockets/websocket_http2_handshake_stream.cc34
-rw-r--r--chromium/net/websockets/websocket_http2_handshake_stream.h7
-rw-r--r--chromium/net/websockets/websocket_stream_cookie_test.cc3
-rw-r--r--chromium/net/websockets/websocket_stream_create_test_base.h1
-rw-r--r--chromium/net/websockets/websocket_stream_test.cc2
-rw-r--r--chromium/net/websockets/websocket_test_util.cc2
1135 files changed, 43397 insertions, 15028 deletions
diff --git a/chromium/net/BUILD.gn b/chromium/net/BUILD.gn
index 0dbd3da90b2..d5d72fbbea5 100644
--- a/chromium/net/BUILD.gn
+++ b/chromium/net/BUILD.gn
@@ -82,6 +82,7 @@ buildflag_header("buildflags") {
"USE_EXTERNAL_GSSAPI=$use_external_gssapi",
"TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED=$trial_comparison_cert_verifier_supported",
"BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED=$builtin_cert_verifier_feature_supported",
+ "CHROME_ROOT_STORE_SUPPORTED=$chrome_root_store_supported",
]
}
@@ -231,8 +232,6 @@ component("net") {
"base/sockaddr_storage.cc",
"base/sockaddr_storage.h",
"base/sys_addrinfo.h",
- "base/test_data_stream.cc",
- "base/test_data_stream.h",
"base/transport_info.cc",
"base/transport_info.h",
"base/upload_bytes_element_reader.cc",
@@ -411,12 +410,16 @@ component("net") {
"cookies/cookie_monster_netlog_params.h",
"cookies/cookie_options.cc",
"cookies/cookie_options.h",
+ "cookies/cookie_partition_key.cc",
+ "cookies/cookie_partition_key.h",
"cookies/cookie_store.cc",
"cookies/cookie_store.h",
"cookies/cookie_util.cc",
"cookies/cookie_util.h",
"cookies/parsed_cookie.cc",
"cookies/parsed_cookie.h",
+ "cookies/same_party_context.cc",
+ "cookies/same_party_context.h",
"cookies/site_for_cookies.cc",
"cookies/site_for_cookies.h",
"cookies/static_cookie_policy.cc",
@@ -644,7 +647,6 @@ component("net") {
"http/webfonts_histogram.cc",
"http/webfonts_histogram.h",
"http2/platform/impl/http2_macros_impl.h",
- "http2/platform/impl/http2_string_utils_impl.h",
"log/file_net_log_observer.cc",
"log/file_net_log_observer.h",
"log/net_log.cc",
@@ -720,6 +722,7 @@ component("net") {
"proxy_resolution/pac_file_data.h",
"proxy_resolution/pac_file_decider.cc",
"proxy_resolution/pac_file_decider.h",
+ "proxy_resolution/pac_file_fetcher.cc",
"proxy_resolution/pac_file_fetcher.h",
"proxy_resolution/pac_file_fetcher_impl.cc",
"proxy_resolution/pac_file_fetcher_impl.h",
@@ -768,7 +771,6 @@ component("net") {
"quic/platform/impl/quic_hostname_utils_impl.cc",
"quic/platform/impl/quic_hostname_utils_impl.h",
"quic/platform/impl/quic_iovec_impl.h",
- "quic/platform/impl/quic_map_util_impl.h",
"quic/platform/impl/quic_mem_slice_impl.cc",
"quic/platform/impl/quic_mem_slice_impl.h",
"quic/platform/impl/quic_mem_slice_span_impl.cc",
@@ -834,7 +836,6 @@ component("net") {
"quic/web_transport_client.h",
"quic/web_transport_error.cc",
"quic/web_transport_error.h",
- "quiche/common/platform/impl/quiche_bug_tracker_impl.h",
"quiche/common/platform/impl/quiche_flag_utils_impl.h",
"quiche/common/platform/impl/quiche_flags_impl.cc",
"quiche/common/platform/impl/quiche_flags_impl.h",
@@ -850,6 +851,8 @@ component("net") {
"socket/client_socket_pool_manager_impl.h",
"socket/connect_job.cc",
"socket/connect_job.h",
+ "socket/connect_job_factory.cc",
+ "socket/connect_job_factory.h",
"socket/connection_attempts.h",
"socket/datagram_client_socket.h",
"socket/datagram_server_socket.h",
@@ -935,9 +938,6 @@ component("net") {
"spdy/multiplexed_http_stream.h",
"spdy/multiplexed_session.cc",
"spdy/multiplexed_session.h",
- "spdy/platform/impl/spdy_containers_impl.h",
- "spdy/platform/impl/spdy_string_utils_impl.cc",
- "spdy/platform/impl/spdy_string_utils_impl.h",
"spdy/server_push_delegate.h",
"spdy/spdy_buffer.cc",
"spdy/spdy_buffer.h",
@@ -1051,8 +1051,6 @@ component("net") {
"url_request/url_request_netlog_params.h",
"url_request/url_request_redirect_job.cc",
"url_request/url_request_redirect_job.h",
- "url_request/url_request_test_job.cc",
- "url_request/url_request_test_job.h",
"url_request/url_request_throttler_entry.cc",
"url_request/url_request_throttler_entry.h",
"url_request/url_request_throttler_entry_interface.h",
@@ -1394,6 +1392,14 @@ component("net") {
]
}
+ if (chrome_root_store_supported) {
+ sources += [
+ "cert/internal/trust_store_chrome.cc",
+ "cert/internal/trust_store_chrome.h",
+ ]
+ deps += [ "//net/data/ssl/chrome_root_store:gen_root_store_inc" ]
+ }
+
if (use_nss_certs) {
sources += [
"cert/internal/system_trust_store_nss.h",
@@ -1652,7 +1658,6 @@ source_set("net_deps") {
":preload_decoder",
"//base",
"//base/third_party/dynamic_annotations",
- "//base/util/type_safety:type_safety",
"//net/base/registry_controlled_domains",
"//third_party/protobuf:protobuf_lite",
"//third_party/zlib",
@@ -2057,6 +2062,8 @@ static_library("test_support") {
"base/mock_network_change_notifier.h",
"base/test_completion_callback.cc",
"base/test_completion_callback.h",
+ "base/test_data_stream.cc",
+ "base/test_data_stream.h",
"cert/mock_cert_verifier.cc",
"cert/mock_cert_verifier.h",
"cert/mock_client_cert_verifier.cc",
@@ -2167,6 +2174,8 @@ static_library("test_support") {
"test/url_request/url_request_mock_data_job.h",
"url_request/test_url_fetcher_factory.cc",
"url_request/test_url_fetcher_factory.h",
+ "url_request/url_request_test_job.cc",
+ "url_request/url_request_test_job.h",
"url_request/url_request_test_util.cc",
"url_request/url_request_test_util.h",
]
@@ -2194,6 +2203,7 @@ static_library("test_support") {
]
deps = [
+ ":quic_test_flags_utils",
":simple_quic_tools",
"//net/http:transport_security_state_unittest_data_default",
"//third_party/zlib",
@@ -2550,6 +2560,7 @@ source_set("quiche_test_tools") {
testonly = true
sources = [
"quiche/common/platform/impl/quiche_test_helpers_impl.h",
+ "quiche/common/platform/impl/quiche_test_impl.cc",
"quiche/common/platform/impl/quiche_test_impl.h",
]
deps = [
@@ -2563,6 +2574,15 @@ source_set("quiche_test_tools") {
[ "//net/third_party/quiche:quiche_test_tools_core" ]
}
+source_set("quic_test_flags_utils") {
+ testonly = true
+ sources = [
+ "quic/platform/impl/quic_test_flags_utils.cc",
+ "quic/platform/impl/quic_test_flags_utils.h",
+ ]
+ deps = [ ":net" ]
+}
+
source_set("quic_test_tools") {
testonly = true
sources = [
@@ -2605,7 +2625,10 @@ source_set("quic_test_tools") {
"//third_party/protobuf:protobuf_lite",
"//third_party/quic_trace:quic_trace_proto",
]
- public_deps = [ "//net/third_party/quiche:quic_test_tools_core" ]
+ public_deps = [
+ ":quic_test_flags_utils",
+ "//net/third_party/quiche:quic_test_tools_core",
+ ]
allow_circular_includes_from =
[ "//net/third_party/quiche:quic_test_tools_core" ]
}
@@ -4089,6 +4112,7 @@ test("net_unittests") {
"base/net_string_util_unittest.cc",
"base/network_activity_monitor_unittest.cc",
"base/network_change_notifier_unittest.cc",
+ "base/network_delegate_unittest.cc",
"base/network_interfaces_unittest.cc",
"base/network_isolation_key_unittest.cc",
"base/parse_number_unittest.cc",
@@ -4168,6 +4192,7 @@ test("net_unittests") {
"cookies/cookie_inclusion_status_unittest.cc",
"cookies/cookie_monster_unittest.cc",
"cookies/cookie_options_unittest.cc",
+ "cookies/cookie_partition_key_unittest.cc",
"cookies/cookie_util_unittest.cc",
"cookies/parsed_cookie_unittest.cc",
"cookies/site_for_cookies_unittest.cc",
@@ -4310,6 +4335,7 @@ test("net_unittests") {
"quic/test_quic_crypto_client_config_handle.h",
"socket/client_socket_pool_base_unittest.cc",
"socket/client_socket_pool_unittest.cc",
+ "socket/connect_job_factory_unittest.cc",
"socket/connect_job_test_util.cc",
"socket/connect_job_test_util.h",
"socket/connect_job_unittest.cc",
@@ -4742,6 +4768,11 @@ test("net_unittests") {
]
}
+ if (chrome_root_store_supported) {
+ sources += [ "cert/internal/trust_store_chrome_unittest.cc" ]
+ deps += [ "//net/data/ssl/chrome_root_store:gen_root_store_test_inc" ]
+ }
+
if (!disable_brotli_filter) {
sources += [ "filter/brotli_source_stream_unittest.cc" ]
}
@@ -5134,6 +5165,14 @@ fuzzer_test("net_canonical_cookie_fuzzer") {
seed_corpus = "data/fuzzer_data/net_canonical_cookie_fuzzer/"
}
+fuzzer_test("net_cookie_partition_key_fuzzer") {
+ sources = [ "cookies/cookie_partition_key_fuzzer.cc" ]
+ deps = [
+ ":net_fuzzer_test_support",
+ "//net",
+ ]
+}
+
fuzzer_test("net_parse_cookie_line_fuzzer") {
sources = [ "cookies/parse_cookie_line_fuzzer.cc" ]
deps = [
diff --git a/chromium/net/android/dummy_spnego_authenticator.cc b/chromium/net/android/dummy_spnego_authenticator.cc
index 3b5240ff19d..ad7c9544248 100644
--- a/chromium/net/android/dummy_spnego_authenticator.cc
+++ b/chromium/net/android/dummy_spnego_authenticator.cc
@@ -5,7 +5,7 @@
#include "base/android/jni_string.h"
#include "base/base64.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/net_test_jni_headers/DummySpnegoAuthenticator_jni.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/android/network_activation_request.h b/chromium/net/android/network_activation_request.h
index 8ce8edd7d81..590bffd6733 100644
--- a/chromium/net/android/network_activation_request.h
+++ b/chromium/net/android/network_activation_request.h
@@ -11,6 +11,7 @@
#include "base/sequenced_task_runner.h"
#include "net/base/net_export.h"
#include "net/base/network_change_notifier.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
namespace android {
diff --git a/chromium/net/android/network_change_notifier_android.cc b/chromium/net/android/network_change_notifier_android.cc
index e1bf77daaf5..93f920cc824 100644
--- a/chromium/net/android/network_change_notifier_android.cc
+++ b/chromium/net/android/network_change_notifier_android.cc
@@ -146,7 +146,6 @@ bool NetworkChangeNotifierAndroid::AreNetworkHandlesCurrentlySupported() const {
return force_network_handles_supported_for_testing_ ||
(base::android::BuildInfo::GetInstance()->sdk_int() >=
base::android::SDK_VERSION_LOLLIPOP &&
- !delegate_->IsProcessBoundToNetwork() &&
!delegate_->RegisterNetworkCallbackFailed());
}
diff --git a/chromium/net/android/network_change_notifier_delegate_android.cc b/chromium/net/android/network_change_notifier_delegate_android.cc
index ad9569ca791..4f6ec36eab0 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.cc
+++ b/chromium/net/android/network_change_notifier_delegate_android.cc
@@ -386,9 +386,4 @@ void NetworkChangeNotifierDelegateAndroid::FakeConnectionSubtypeChanged(
Java_NetworkChangeNotifier_fakeConnectionSubtypeChanged(env, subtype);
}
-bool NetworkChangeNotifierDelegateAndroid::IsProcessBoundToNetwork() {
- return Java_NetworkChangeNotifier_isProcessBoundToNetwork(
- base::android::AttachCurrentThread());
-}
-
} // namespace net
diff --git a/chromium/net/android/network_change_notifier_delegate_android.h b/chromium/net/android/network_change_notifier_delegate_android.h
index 905d2e6d53f..e6c73e0b0a5 100644
--- a/chromium/net/android/network_change_notifier_delegate_android.h
+++ b/chromium/net/android/network_change_notifier_delegate_android.h
@@ -6,7 +6,6 @@
#define NET_ANDROID_NETWORK_CHANGE_NOTIFIER_DELEGATE_ANDROID_H_
#include <map>
-#include <string>
#include "base/android/jni_android.h"
#include "base/memory/ref_counted.h"
@@ -128,9 +127,6 @@ class NET_EXPORT_PRIVATE NetworkChangeNotifierDelegateAndroid {
// Can only be called from the main (Java) thread.
NetworkChangeNotifier::ConnectionSubtype GetCurrentConnectionSubtype() const;
- // Is the current process bound to a specific network?
- bool IsProcessBoundToNetwork();
-
// Returns true if NetworkCallback failed to register, indicating that
// network-specific callbacks will not be issued.
bool RegisterNetworkCallbackFailed() const {
diff --git a/chromium/net/android/unittest_support/AndroidManifest.xml b/chromium/net/android/unittest_support/AndroidManifest.xml
index 4cbc0b9c219..29c12f9e767 100644
--- a/chromium/net/android/unittest_support/AndroidManifest.xml
+++ b/chromium/net/android/unittest_support/AndroidManifest.xml
@@ -26,11 +26,18 @@ found in the LICENSE file.
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+ <!-- Explicitly set the attribute requestLegacyExternalStorage to "true"
+ since it is "false" by default on apps targeting Android 10, and that
+ breaks test listing. See
+ https://developer.android.com/training/data-storage#scoped-storage and
+ https://developer.android.com/training/data-storage/compatibility. -->
<application android:label="NativeTests"
+ android:requestLegacyExternalStorage="true"
android:name="org.chromium.native_test.NativeTestApplication">
<activity android:name=".NativeUnitTestActivity"
android:label="NativeTest"
android:configChanges="orientation|keyboardHidden"
+ android:exported="true"
android:process=":test_process">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
diff --git a/chromium/net/base/address_list_unittest.cc b/chromium/net/base/address_list_unittest.cc
index 15c6770a39a..d44b7a014ec 100644
--- a/chromium/net/base/address_list_unittest.cc
+++ b/chromium/net/base/address_list_unittest.cc
@@ -4,7 +4,7 @@
#include "net/base/address_list.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "base/sys_byteorder.h"
#include "net/base/ip_address.h"
diff --git a/chromium/net/base/address_tracker_linux.cc b/chromium/net/base/address_tracker_linux.cc
index a7a6290ecc4..56597b04662 100644
--- a/chromium/net/base/address_tracker_linux.cc
+++ b/chromium/net/base/address_tracker_linux.cc
@@ -11,6 +11,7 @@
#include <utility>
#include "base/callback_helpers.h"
+#include "base/check.h"
#include "base/files/scoped_file.h"
#include "base/logging.h"
#include "base/posix/eintr_wrapper.h"
@@ -203,7 +204,7 @@ void AddressTrackerLinux::Init() {
// Request notifications.
struct sockaddr_nl addr = {};
addr.nl_family = AF_NETLINK;
- addr.nl_pid = getpid();
+ addr.nl_pid = 0; // Let the kernel select a unique value.
// TODO(szym): Track RTMGRP_LINK as well for ifi_type,
// http://crbug.com/113993
addr.nl_groups =
@@ -229,7 +230,7 @@ void AddressTrackerLinux::Init() {
request.header.nlmsg_len = NLMSG_LENGTH(sizeof(request.msg));
request.header.nlmsg_type = RTM_GETADDR;
request.header.nlmsg_flags = NLM_F_REQUEST | NLM_F_DUMP;
- request.header.nlmsg_pid = getpid();
+ request.header.nlmsg_pid = 0; // This field is opaque to netlink.
request.msg.rtgen_family = AF_UNSPEC;
rv = HANDLE_EINTR(
@@ -276,6 +277,11 @@ void AddressTrackerLinux::Init() {
}
}
+bool AddressTrackerLinux::DidTrackingInitSucceedForTesting() const {
+ CHECK(tracking_);
+ return watcher_ != nullptr;
+}
+
void AddressTrackerLinux::AbortAndForceOnline() {
watcher_.reset();
netlink_fd_.reset();
diff --git a/chromium/net/base/address_tracker_linux.h b/chromium/net/base/address_tracker_linux.h
index 8017b3ff5c8..c993318ed74 100644
--- a/chromium/net/base/address_tracker_linux.h
+++ b/chromium/net/base/address_tracker_linux.h
@@ -21,6 +21,7 @@
#include "base/compiler_specific.h"
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/files/scoped_file.h"
+#include "base/gtest_prod_util.h"
#include "base/synchronization/condition_variable.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
@@ -88,6 +89,11 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux {
private:
friend class AddressTrackerLinuxTest;
+ FRIEND_TEST_ALL_PREFIXES(AddressTrackerLinuxNetlinkTest,
+ TestInitializeTwoTrackers);
+ FRIEND_TEST_ALL_PREFIXES(AddressTrackerLinuxNetlinkTest,
+ TestInitializeTwoTrackersInPidNamespaces);
+ friend int ChildProcessInitializeTrackerForTesting();
// In tracking mode, holds |lock| while alive. In non-tracking mode,
// enforces single-threaded access.
@@ -146,6 +152,10 @@ class NET_EXPORT_PRIVATE AddressTrackerLinux {
// for |connection_type_initialized_cv_|.
int GetThreadsWaitingForConnectionTypeInitForTesting();
+ // Used by AddressTrackerLinuxNetlinkTest, returns true iff `Init` succeeded.
+ // Undefined for non-tracking mode.
+ bool DidTrackingInitSucceedForTesting() const;
+
// Gets the name of an interface given the interface index |interface_index|.
// May return empty string if it fails but should not return NULL. This is
// overridden by tests.
diff --git a/chromium/net/base/address_tracker_linux_unittest.cc b/chromium/net/base/address_tracker_linux_unittest.cc
index f90bedf3f57..9d853881a63 100644
--- a/chromium/net/base/address_tracker_linux_unittest.cc
+++ b/chromium/net/base/address_tracker_linux_unittest.cc
@@ -5,6 +5,7 @@
#include "net/base/address_tracker_linux.h"
#include <linux/if.h>
+#include <sched.h>
#include <memory>
#include <unordered_set>
@@ -12,13 +13,19 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/command_line.h"
+#include "base/files/file_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/synchronization/waitable_event.h"
+#include "base/test/multiprocess_test.h"
#include "base/test/spin_wait.h"
#include "base/test/task_environment.h"
+#include "base/test/test_simple_task_runner.h"
#include "base/threading/simple_thread.h"
#include "build/build_config.h"
#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "testing/multiprocess_func_list.h"
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
@@ -764,5 +771,172 @@ TEST_F(AddressTrackerLinuxTest, TunnelInterfaceName) {
} // namespace
+// This is a regression test for https://crbug.com/1224428.
+//
+// This test initializes two instances of `AddressTrackerLinux` in the same
+// process. The test will fail if the implementation reuses the value of
+// `sockaddr_nl::nl_pid`.
+//
+// Note: consumers generally should not need to create two tracking instances of
+// `AddressTrackerLinux` in the same process.
+TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackers) {
+#if defined(OS_ANDROID)
+ // Calling Init() on Android P+ isn't supported.
+ if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+ base::android::SDK_VERSION_P)
+ return;
+#endif
+ base::test::TaskEnvironment task_env(
+ base::test::TaskEnvironment::MainThreadType::IO);
+ AddressTrackerLinux tracker1(base::DoNothing(), base::DoNothing(),
+ base::DoNothing(), {});
+ AddressTrackerLinux tracker2(base::DoNothing(), base::DoNothing(),
+ base::DoNothing(), {});
+ tracker1.Init();
+ tracker2.Init();
+ EXPECT_TRUE(tracker1.DidTrackingInitSucceedForTesting());
+ EXPECT_TRUE(tracker2.DidTrackingInitSucceedForTesting());
+}
+
+// These tests use `base::LaunchOptions::clone_flags` for fine-grained control
+// over the clone syscall, but the field is only defined on Linux and ChromeOS.
+// Unfortunately, this means these tests do not have coverage on Android.
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+// These tests require specific flag values defined in <sched.h>.
+#if defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
+
+namespace {
+const char* const kSwitchParentWriteFd = "addresstrackerlinux_parent_write_fd";
+const char* const kSwitchReadFd = "addresstrackerlinux_read_fd";
+
+enum IPCMessage {
+ // Sent from child to parent once the child has initialized its tracker.
+ kChildInitializedAndWaiting,
+ // Sent from child to parent when it was unable to initialize its tracker.
+ kChildFailed,
+ // Sent from parent to child when all children are permitted to exit.
+ kChildMayExit,
+};
+
+base::File GetSwitchValueFile(const base::CommandLine* command_line,
+ base::StringPiece name) {
+ std::string value = command_line->GetSwitchValueASCII(name);
+ int fd;
+ CHECK(base::StringToInt(value, &fd));
+ return base::File(fd);
+}
+} // namespace
+
+// This is a regression test for https://crbug.com/1224428.
+//
+// This test creates multiple concurrent `AddressTrackerLinux` instances in
+// separate processes, each in their own PID namespaces.
+TEST(AddressTrackerLinuxNetlinkTest, TestInitializeTwoTrackersInPidNamespaces) {
+ // This test initializes `kNumChildren` instances of `AddressTrackerLinux` in
+ // tracking mode, each in their own child process running in a PID namespace.
+ // The test will fail if the implementation reuses the value of
+ // `sockaddr_nl::nl_pid`.
+ //
+ // The child processes use pipes to synchronize. Each child initializes a
+ // tracker, sends a message to the parent, and waits for the parent to
+ // respond, indicating that all children are done setting up. This ensures
+ // that the tracker objects have overlapping lifetimes, and thus that the
+ // underlying netlink sockets have overlapping lifetimes. This coexistence is
+ // necessary, but not sufficient, for a `sockaddr_nl::nl_pid` value collision.
+ constexpr size_t kNumChildren = 2;
+
+ base::ScopedFD parent_read_fd, parent_write_fd;
+ ASSERT_TRUE(base::CreatePipe(&parent_read_fd, &parent_write_fd));
+
+ struct Child {
+ base::ScopedFD read_fd;
+ base::ScopedFD write_fd;
+ base::Process process;
+ } children[kNumChildren];
+
+ for (Child& child : children) {
+ ASSERT_TRUE(base::CreatePipe(&child.read_fd, &child.write_fd));
+
+ // Since the child process will wipe its address space by calling execvp, we
+ // must share the file descriptors via its command line.
+ base::CommandLine command_line(
+ base::GetMultiProcessTestChildBaseCommandLine());
+ command_line.AppendSwitchASCII(kSwitchParentWriteFd,
+ base::NumberToString(parent_write_fd.get()));
+ command_line.AppendSwitchASCII(kSwitchReadFd,
+ base::NumberToString(child.read_fd.get()));
+
+ base::LaunchOptions options;
+ // Indicate that the child process requires these file descriptors.
+ // Otherwise, they will be closed. See `base::CloseSuperfluousFds`.
+ options.fds_to_remap = {{child.read_fd.get(), child.read_fd.get()},
+ {parent_write_fd.get(), parent_write_fd.get()}};
+ // Clone into a new PID namespace. Making it a new user namespace as well to
+ // skirt the CAP_SYS_ADMIN requirement.
+ options.clone_flags = CLONE_NEWPID | CLONE_NEWUSER;
+
+ child.process = base::SpawnMultiProcessTestChild(
+ "ChildProcessInitializeTrackerForTesting", command_line, options);
+ }
+
+ // Wait for all children to finish initializing their tracking
+ // AddressTrackerLinuxes.
+ base::File parent_reader(std::move(parent_read_fd));
+ for (const Child& child : children) {
+ ASSERT_TRUE(child.process.IsValid());
+
+ uint8_t message[] = {0};
+ ASSERT_TRUE(parent_reader.ReadAtCurrentPosAndCheck(message));
+ ASSERT_EQ(message[0], kChildInitializedAndWaiting);
+ }
+
+ // Tell children to exit and wait for them to exit.
+ for (Child& child : children) {
+ base::File child_writer(std::move(child.write_fd));
+ const uint8_t kMessage[] = {kChildMayExit};
+ ASSERT_TRUE(child_writer.WriteAtCurrentPosAndCheck(kMessage));
+
+ int exit_code = 0;
+ ASSERT_TRUE(child.process.WaitForExit(&exit_code));
+ ASSERT_EQ(exit_code, 0);
+ }
+}
+
+MULTIPROCESS_TEST_MAIN(ChildProcessInitializeTrackerForTesting) {
+ base::test::TaskEnvironment task_env(
+ base::test::TaskEnvironment::MainThreadType::IO);
+
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ base::File reader = GetSwitchValueFile(command_line, kSwitchReadFd);
+ base::File parent_writer =
+ GetSwitchValueFile(command_line, kSwitchParentWriteFd);
+
+ // Initialize an `AddressTrackerLinux` in tracking mode and ensure that it
+ // created a netlink socket.
+ AddressTrackerLinux tracker(base::DoNothing(), base::DoNothing(),
+ base::DoNothing(), {});
+ tracker.Init();
+ if (!tracker.DidTrackingInitSucceedForTesting()) {
+ const uint8_t kMessage[] = {kChildFailed};
+ parent_writer.WriteAtCurrentPosAndCheck(kMessage);
+ return 1;
+ }
+
+ // Signal to the parent that we have initialized the tracker.
+ const uint8_t kMessage[] = {kChildInitializedAndWaiting};
+ if (!parent_writer.WriteAtCurrentPosAndCheck(kMessage))
+ return 1;
+
+ // Block until the parent says all children have initialized their trackers.
+ uint8_t message[] = {0};
+ if (!reader.ReadAtCurrentPosAndCheck(message) || message[0] != kChildMayExit)
+ return 1;
+ return 0;
+}
+
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
+#endif // defined(CLONE_NEWUSER) && defined(CLONE_NEWPID)
+
} // namespace internal
} // namespace net
diff --git a/chromium/net/base/backoff_entry_serializer_unittest.cc b/chromium/net/base/backoff_entry_serializer_unittest.cc
index f6620595491..d2c37731269 100644
--- a/chromium/net/base/backoff_entry_serializer_unittest.cc
+++ b/chromium/net/base/backoff_entry_serializer_unittest.cc
@@ -141,8 +141,8 @@ TEST(BackoffEntrySerializerTest, SpecialCasesOfBackoffDuration) {
// Check that the serialized backoff duration matches our expectation.
double serialized_backoff_duration_double;
- EXPECT_TRUE(serialized.GetList()[2].GetAsDouble(
- &serialized_backoff_duration_double));
+ serialized_backoff_duration_double = serialized.GetList()[2].GetDouble();
+
base::TimeDelta serialized_backoff_duration =
base::TimeDelta::FromSecondsD(serialized_backoff_duration_double);
EXPECT_EQ(serialized_backoff_duration, test_case.expected_backoff_duration);
diff --git a/chromium/net/base/cache_type.h b/chromium/net/base/cache_type.h
index 3f2989be732..afb12b4f9ab 100644
--- a/chromium/net/base/cache_type.h
+++ b/chromium/net/base/cache_type.h
@@ -19,8 +19,11 @@ enum CacheType {
PNACL_CACHE, // Backing store the PNaCl translation cache
GENERATED_BYTE_CODE_CACHE, // Backing store for renderer generated data like
// bytecode for JavaScript.
- GENERATED_NATIVE_CODE_CACHE, // Backing store for renderer generated data
- // like native code for WebAssembly.
+ GENERATED_NATIVE_CODE_CACHE, // Backing store for renderer generated data
+ // like native code for WebAssembly.
+ GENERATED_WEBUI_BYTE_CODE_CACHE, // Backing store for renderer generated data
+ // like bytecode for JavaScript from WebUI
+ // pages.
};
// The types of disk cache backend, only used at backend instantiation.
diff --git a/chromium/net/base/chunked_upload_data_stream_unittest.cc b/chromium/net/base/chunked_upload_data_stream_unittest.cc
index 6f6a6dbebf9..63ff7130d7e 100644
--- a/chromium/net/base/chunked_upload_data_stream_unittest.cc
+++ b/chromium/net/base/chunked_upload_data_stream_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/test_completion_callback.h"
diff --git a/chromium/net/base/data_url.cc b/chromium/net/base/data_url.cc
index 82e1dbc4eea..99be85f41c2 100644
--- a/chromium/net/base/data_url.cc
+++ b/chromium/net/base/data_url.cc
@@ -9,7 +9,7 @@
#include "net/base/data_url.h"
#include "base/base64.h"
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/strings/escape.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
diff --git a/chromium/net/base/elements_upload_data_stream_unittest.cc b/chromium/net/base/elements_upload_data_stream_unittest.cc
index 3a02e9bf945..3e2f7160751 100644
--- a/chromium/net/base/elements_upload_data_stream_unittest.cc
+++ b/chromium/net/base/elements_upload_data_stream_unittest.cc
@@ -11,13 +11,13 @@
#include <vector>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
diff --git a/chromium/net/base/escape.cc b/chromium/net/base/escape.cc
index 9d28bf6c51a..f2d7eee0d1f 100644
--- a/chromium/net/base/escape.cc
+++ b/chromium/net/base/escape.cc
@@ -4,12 +4,15 @@
#include "net/base/escape.h"
+#include <ostream>
+
#include "base/check_op.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversion_utils.h"
#include "base/strings/utf_string_conversions.h"
#include "base/third_party/icu/icu_utf.h"
+#include "build/build_config.h"
namespace net {
diff --git a/chromium/net/base/features.cc b/chromium/net/base/features.cc
index 407919d15b7..c5cf07da5c7 100644
--- a/chromium/net/base/features.cc
+++ b/chromium/net/base/features.cc
@@ -6,6 +6,7 @@
#include <vector>
+#include "base/feature_list.h"
#include "build/build_config.h"
namespace net {
@@ -17,6 +18,9 @@ const base::Feature kAcceptLanguageHeader{"AcceptLanguageHeader",
const base::Feature kAlpsForHttp2{"AlpsForHttp2",
base::FEATURE_ENABLED_BY_DEFAULT};
+const base::Feature kAvoidH2Reprioritization{"AvoidH2Reprioritization",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
const base::Feature kCapReferrerToOriginOnCrossOrigin{
"CapReferrerToOriginOnCrossOrigin", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -57,9 +61,6 @@ const base::FeatureParam<std::string> kDnsHttpssvcControlDomains{
const base::FeatureParam<bool> kDnsHttpssvcControlDomainWildcard{
&kDnsHttpssvc, "DnsHttpssvcControlDomainWildcard", false};
-const base::Feature kAvoidH2Reprioritization{"AvoidH2Reprioritization",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
namespace dns_httpssvc_experiment {
base::TimeDelta GetExtraTimeAbsolute() {
DCHECK(base::FeatureList::IsEnabled(features::kDnsHttpssvc));
@@ -67,6 +68,24 @@ base::TimeDelta GetExtraTimeAbsolute() {
}
} // namespace dns_httpssvc_experiment
+const base::Feature kUseDnsHttpsSvcb{"UseDnsHttpsSvcb",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::FeatureParam<bool> kUseDnsHttpsSvcbHttpUpgrade{
+ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbHttpUpgrade", false};
+
+const base::FeatureParam<bool> kUseDnsHttpsSvcbEnforceSecureResponse{
+ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbEnforceSecureResponse", false};
+
+const base::FeatureParam<bool> kUseDnsHttpsSvcbEnableInsecure{
+ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbEnableInsecure", false};
+
+const base::FeatureParam<base::TimeDelta> kUseDnsHttpsSvcbExtraTimeAbsolute{
+ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbExtraTimeAbsolute", base::TimeDelta()};
+
+const base::FeatureParam<int> kUseDnsHttpsSvcbExtraTimePercent{
+ &kUseDnsHttpsSvcb, "UseDnsHttpsSvcbExtraTimePercent", 0};
+
const base::Feature kEnableTLS13EarlyData{"EnableTLS13EarlyData",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -130,12 +149,6 @@ const base::FeatureParam<std::string>
const base::Feature kNetUnusedIdleSocketTimeout{
"NetUnusedIdleSocketTimeout", base::FEATURE_DISABLED_BY_DEFAULT};
-const base::Feature kSameSiteByDefaultCookies{"SameSiteByDefaultCookies",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kCookiesWithoutSameSiteMustBeSecure{
- "CookiesWithoutSameSiteMustBeSecure", base::FEATURE_ENABLED_BY_DEFAULT};
-
const base::Feature kShortLaxAllowUnsafeThreshold{
"ShortLaxAllowUnsafeThreshold", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -166,6 +179,11 @@ const base::FeatureParam<int> kCertDualVerificationTrialCacheSize{
#endif /* defined(OS_MAC) */
#endif
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+const base::Feature kChromeRootStoreUsed{"ChromeRootStoreUsed",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+#endif /* BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) */
+
const base::Feature kTurnOffStreamingMediaCachingOnBattery{
"TurnOffStreamingMediaCachingOnBattery", base::FEATURE_DISABLED_BY_DEFAULT};
@@ -222,12 +240,6 @@ constexpr base::Feature kFirstPartySets{"FirstPartySets",
const base::FeatureParam<bool> kFirstPartySetsIsDogfooder{
&kFirstPartySets, "FirstPartySetsIsDogfooder", false};
-const base::Feature kSameSiteCookiesBugfix1166211{
- "SameSiteCookiesBugfix1166211", base::FEATURE_ENABLED_BY_DEFAULT};
-
-const base::Feature kNoCookieChangeNotificationOnLoad{
- "NoCookieChangeNotificationOnLoad", base::FEATURE_ENABLED_BY_DEFAULT};
-
#if BUILDFLAG(ENABLE_REPORTING)
const base::Feature kDocumentReporting{"DocumentReporting",
base::FEATURE_DISABLED_BY_DEFAULT};
@@ -236,11 +248,17 @@ const base::Feature kDocumentReporting{"DocumentReporting",
#if defined(OS_POSIX) || defined(OS_FUCHSIA)
const base::Feature kUdpSocketPosixAlwaysUpdateBytesReceived{
"UdpSocketPosixAlwaysUpdateBytesReceived",
- base::FEATURE_DISABLED_BY_DEFAULT};
+ base::FEATURE_ENABLED_BY_DEFAULT};
#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
const base::Feature kCookieSameSiteConsidersRedirectChain{
"CookieSameSiteConsidersRedirectChain", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kSamePartyCookiesConsideredFirstParty{
+ "SamePartyCookiesConsideredFirstParty", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kPartitionedCookies{"PartitionedCookies",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
} // namespace net
diff --git a/chromium/net/base/features.h b/chromium/net/base/features.h
index b97d7dd4ddf..ba47725877d 100644
--- a/chromium/net/base/features.h
+++ b/chromium/net/base/features.h
@@ -27,6 +27,9 @@ NET_EXPORT extern const base::Feature kAcceptLanguageHeader;
// https://vasilvv.github.io/httpbis-alps/draft-vvv-httpbis-alps.html.
NET_EXPORT extern const base::Feature kAlpsForHttp2;
+// Disable H2 reprioritization, in order to measure its impact.
+NET_EXPORT extern const base::Feature kAvoidH2Reprioritization;
+
// When kCapReferrerToOriginOnCrossOrigin is enabled, HTTP referrers on cross-
// origin requests are restricted to contain at most the source origin.
NET_EXPORT extern const base::Feature kCapReferrerToOriginOnCrossOrigin;
@@ -44,14 +47,14 @@ NET_EXPORT extern const base::FeatureParam<double>
NET_EXPORT extern const base::FeatureParam<base::TimeDelta>
kDnsMinTransactionTimeout;
-// Enables DNS queries for HTTPSSVC or INTEGRITY records, depending on feature
-// parameters. These queries will only be made over DoH. HTTPSSVC responses may
-// cause us to upgrade the URL to HTTPS and/or to attempt QUIC.
+// Enables DNS query-only experiments for HTTPSSVC or INTEGRITY records,
+// depending on feature parameters. Received responses never affect Chrome
+// behavior other than metrics.
+//
+// Not to be confused with `kUseDnsHttpsSvcb` which is querying HTTPS in order
+// to affect Chrome connection behavior.
NET_EXPORT extern const base::Feature kDnsHttpssvc;
-// Disable H2 reprioritization, in order to measure its impact.
-NET_EXPORT extern const base::Feature kAvoidH2Reprioritization;
-
// Determine which kind of record should be queried: HTTPSSVC or INTEGRITY. No
// more than one of these feature parameters should be enabled at once. In the
// event that both are enabled, |kDnsHttpssvcUseIntegrity| takes priority, and
@@ -101,6 +104,46 @@ namespace dns_httpssvc_experiment {
NET_EXPORT base::TimeDelta GetExtraTimeAbsolute();
} // namespace dns_httpssvc_experiment
+// Enables querying HTTPS DNS records that will affect results from HostResolver
+// and may be used to affect connection behavior. Whether or not those results
+// are used (e.g. to connect via ECH) may be controlled by separate features.
+//
+// Not to be confused with `kDnsHttpssvc` which is for experiment-only queries
+// where received HTTPS results do not affect Chrome behavior and are only used
+// for metrics.
+NET_EXPORT extern const base::Feature kUseDnsHttpsSvcb;
+
+// Param to control whether or not presence of an HTTPS record for an HTTP
+// request will force an HTTP->HTTPS upgrade redirect.
+NET_EXPORT extern const base::FeatureParam<bool> kUseDnsHttpsSvcbHttpUpgrade;
+
+// Param to control whether or not HostResolver, when using Secure DNS, will
+// fail the entire connection attempt when receiving an inconclusive response to
+// an HTTPS query (anything except transport error, timeout, or SERVFAIL). Used
+// to prevent certain downgrade attacks against ECH behavior.
+NET_EXPORT extern const base::FeatureParam<bool>
+ kUseDnsHttpsSvcbEnforceSecureResponse;
+
+// Param to control whether HTTPS queries will be allowed via Insecure DNS
+// (instead of just via Secure DNS).
+NET_EXPORT extern const base::FeatureParam<bool> kUseDnsHttpsSvcbEnableInsecure;
+
+// If we are still waiting for an HTTPS query after all the
+// other queries in a DnsTask have completed, we will compute a timeout for the
+// remaining query. The timeout will be the min of:
+// (a) `kUseDnsHttpsSvcbExtraTimeAbsolute.Get()`
+// (b) `kUseDnsHttpsSvcbExtraTimePercent.Get() / 100 * t`, where `t` is
+// the
+// time delta since the first query began.
+//
+// Either param is ignored if zero. If both are zero, there is no timeout
+// specific to HTTPS queries, only the regular DNS query timeout and server
+// fallback.
+NET_EXPORT extern const base::FeatureParam<base::TimeDelta>
+ kUseDnsHttpsSvcbExtraTimeAbsolute;
+NET_EXPORT extern const base::FeatureParam<int>
+ kUseDnsHttpsSvcbExtraTimePercent;
+
// Enables optimizing the network quality estimation algorithms in network
// quality estimator (NQE).
NET_EXPORT extern const base::Feature kNetworkQualityEstimator;
@@ -193,22 +236,6 @@ NET_EXPORT extern const base::FeatureParam<std::string>
// Changes the timeout after which unused sockets idle sockets are cleaned up.
NET_EXPORT extern const base::Feature kNetUnusedIdleSocketTimeout;
-// When enabled, makes cookies without a SameSite attribute behave like
-// SameSite=Lax cookies by default, and requires SameSite=None to be specified
-// in order to make cookies available in a third-party context. When disabled,
-// the default behavior for cookies without a SameSite attribute specified is no
-// restriction, i.e., available in a third-party context.
-// The "Lax-allow-unsafe" mitigation allows these cookies to be sent on
-// top-level cross-site requests with an unsafe (e.g. POST) HTTP method, if the
-// cookie is no more than 2 minutes old.
-NET_EXPORT extern const base::Feature kSameSiteByDefaultCookies;
-
-// When enabled, cookies without SameSite restrictions that don't specify the
-// Secure attribute will be rejected if set from an insecure context, or treated
-// as secure if set from a secure context. This ONLY has an effect if
-// SameSiteByDefaultCookies is also enabled.
-NET_EXPORT extern const base::Feature kCookiesWithoutSameSiteMustBeSecure;
-
// When enabled, the time threshold for Lax-allow-unsafe cookies will be lowered
// from 2 minutes to 10 seconds. This time threshold refers to the age cutoff
// for which cookies that default into SameSite=Lax, which are newer than the
@@ -241,7 +268,12 @@ NET_EXPORT extern const base::FeatureParam<int> kCertDualVerificationTrialImpl;
NET_EXPORT extern const base::FeatureParam<int>
kCertDualVerificationTrialCacheSize;
#endif /* defined(OS_MAC) */
-#endif /* BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED) */
+#endif /* BUILDFLAG(TRIAL_COMPARISON_CERT_VERIFIER_SUPPORTED) */
+
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+// When enabled, use the Chrome Root Store instead of the system root store
+NET_EXPORT extern const base::Feature kChromeRootStoreUsed;
+#endif /* BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED) */
// Turns off streaming media caching to disk when on battery power.
NET_EXPORT extern const base::Feature kTurnOffStreamingMediaCachingOnBattery;
@@ -318,20 +350,6 @@ NET_EXPORT extern const base::Feature kFirstPartySets;
// feature.
NET_EXPORT extern const base::FeatureParam<bool> kFirstPartySetsIsDogfooder;
-// Controls whether the fix for crbug.com/1166211 is enabled. When this is
-// enabled, SameSite=Lax cookies may only be accessed for cross-site requests if
-// they are top-level navigations. When it is disabled, the (incorrect) previous
-// behavior that allows SameSite=Lax cookies on cross-site, non-top-level
-// requests if all frame ancestors are same-site with the request URL is used
-// instead. This fix is implemented behind a flag (kill switch) due to potential
-// compatibility risk.
-NET_EXPORT extern const base::Feature kSameSiteCookiesBugfix1166211;
-
-// When this feature is enabled, no CookieChangeDispatcher notifications will be
-// sent when loading cookies from the persistent store. All other change
-// notifications are still dispatched as usual.
-NET_EXPORT extern const base::Feature kNoCookieChangeNotificationOnLoad;
-
#if BUILDFLAG(ENABLE_REPORTING)
// When enabled this feature will allow a new Reporting-Endpoints header to
// configure reporting endpoints for report delivery. This is used to support
@@ -356,6 +374,19 @@ NET_EXPORT extern const base::Feature kUdpSocketPosixAlwaysUpdateBytesReceived;
// See spec changes in https://github.com/httpwg/http-extensions/pull/1348
NET_EXPORT extern const base::Feature kCookieSameSiteConsidersRedirectChain;
+// When enabled, cookies with the SameParty attribute are treated as
+// "first-party" when in same-party contexts, for the purposes of third-party
+// cookie blocking. (Note that as a consequence, some cookies may be blocked
+// while others are allowed on a cross-site, same-party request. Additionally,
+// privacy mode is disabled in same-party contexts.)
+NET_EXPORT extern const base::Feature kSamePartyCookiesConsideredFirstParty;
+
+// When enabled, sites can opt-in to having their cookies partitioned by
+// top-level site with the Partitioned attribute. Partitioned cookies will only
+// be sent when the browser is on the same top-level site that it was on when
+// the cookie was set.
+NET_EXPORT extern const base::Feature kPartitionedCookies;
+
} // namespace features
} // namespace net
diff --git a/chromium/net/base/file_stream_unittest.cc b/chromium/net/base/file_stream_unittest.cc
index 94023cb5d82..e5ed3e62e3c 100644
--- a/chromium/net/base/file_stream_unittest.cc
+++ b/chromium/net/base/file_stream_unittest.cc
@@ -9,12 +9,12 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/macros.h"
#include "base/path_service.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/current_thread.h"
@@ -746,7 +746,7 @@ TEST_F(FileStreamTest, OpenAndDelete) {
base::Thread worker_thread("StreamTest");
ASSERT_TRUE(worker_thread.Start());
- bool prev = base::ThreadRestrictions::SetIOAllowed(false);
+ base::ScopedDisallowBlocking disallow_blocking;
std::unique_ptr<FileStream> stream(
new FileStream(worker_thread.task_runner()));
int flags = base::File::FLAG_OPEN | base::File::FLAG_WRITE |
@@ -770,7 +770,6 @@ TEST_F(FileStreamTest, OpenAndDelete) {
// open_callback won't be called.
base::RunLoop().RunUntilIdle();
EXPECT_FALSE(open_callback.have_result());
- base::ThreadRestrictions::SetIOAllowed(prev);
}
// Verify that Write() errors are mapped correctly.
diff --git a/chromium/net/base/hash_value.cc b/chromium/net/base/hash_value.cc
index ec440bbcc06..4a35bdafb1b 100644
--- a/chromium/net/base/hash_value.cc
+++ b/chromium/net/base/hash_value.cc
@@ -5,7 +5,9 @@
#include "net/base/hash_value.h"
#include <stdlib.h>
+
#include <algorithm>
+#include <ostream>
#include "base/base64.h"
#include "base/check_op.h"
diff --git a/chromium/net/base/host_mapping_rules.cc b/chromium/net/base/host_mapping_rules.cc
index 20edf5248bf..4ec3cc09ca1 100644
--- a/chromium/net/base/host_mapping_rules.cc
+++ b/chromium/net/base/host_mapping_rules.cc
@@ -8,11 +8,15 @@
#include "base/logging.h"
#include "base/strings/pattern.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/url_util.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
namespace net {
@@ -69,6 +73,36 @@ bool HostMappingRules::RewriteHost(HostPortPair* host_port) const {
return false;
}
+HostMappingRules::RewriteResult HostMappingRules::RewriteUrl(GURL& url) const {
+ // Must be a valid and standard URL. Otherwise, Chrome might not know how to
+ // find/replace the contained host or port.
+ DCHECK(url.is_valid());
+ DCHECK(url.IsStandard());
+ DCHECK(url.has_host());
+
+ HostPortPair host_port_pair = HostPortPair::FromURL(url);
+ if (!RewriteHost(&host_port_pair))
+ return RewriteResult::kNoMatchingRule;
+
+ url::Replacements<char> replacements;
+ std::string port_str = base::NumberToString(host_port_pair.port());
+ replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+ std::string host_str = host_port_pair.HostForURL();
+ replacements.SetHost(host_str.c_str(), url::Component(0, host_str.size()));
+ GURL new_url = url.ReplaceComponents(replacements);
+
+ if (!new_url.is_valid())
+ return RewriteResult::kInvalidRewrite;
+
+ DCHECK(new_url.IsStandard());
+ DCHECK(new_url.has_host());
+ DCHECK_EQ(url.EffectiveIntPort() == url::PORT_UNSPECIFIED,
+ new_url.EffectiveIntPort() == url::PORT_UNSPECIFIED);
+
+ url = std::move(new_url);
+ return RewriteResult::kRewritten;
+}
+
bool HostMappingRules::AddRuleFromString(base::StringPiece rule_string) {
std::vector<base::StringPiece> parts = base::SplitStringPiece(
base::TrimWhitespaceASCII(rule_string, base::TRIM_ALL), " ",
diff --git a/chromium/net/base/host_mapping_rules.h b/chromium/net/base/host_mapping_rules.h
index 4d9a7652a26..a8d7f95c241 100644
--- a/chromium/net/base/host_mapping_rules.h
+++ b/chromium/net/base/host_mapping_rules.h
@@ -11,22 +11,40 @@
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
+class GURL;
+
namespace net {
class HostPortPair;
class NET_EXPORT_PRIVATE HostMappingRules {
public:
+ enum class RewriteResult {
+ kRewritten,
+ kNoMatchingRule,
+ kInvalidRewrite,
+ };
+
HostMappingRules();
HostMappingRules(const HostMappingRules& host_mapping_rules);
~HostMappingRules();
HostMappingRules& operator=(const HostMappingRules& host_mapping_rules);
- // Modifies |*host_port| based on the current rules. Returns true if
- // |*host_port| was modified, false otherwise.
+ // Modifies `*host_port` based on the current rules. Returns true if
+ // `*host_port` was modified, false otherwise.
bool RewriteHost(HostPortPair* host_port) const;
+ // Modifies the host and port of `url` based on current rules. May only be
+ // called for URLs with a host and a scheme that is standard, and if the
+ // scheme does not allow ports, only the host will be rewritten.
+ //
+ // If `url` is rewritten, returns `kRewritten`. If no matching rule is found,
+ // returns `kNoMatchingRule` and `url` is not modified. If a matching rule is
+ // found but it results in an invalid URL, e.g. if the rule maps to
+ // "~NOTFOUND", returns `kInvalidRewrite` and `url` is not modified.
+ RewriteResult RewriteUrl(GURL& url) const;
+
// Adds a rule to this mapper. The format of the rule can be one of:
//
// "MAP" <hostname_pattern> <replacement_host> [":" <replacement_port>]
diff --git a/chromium/net/base/host_mapping_rules_unittest.cc b/chromium/net/base/host_mapping_rules_unittest.cc
index 8d8f7b1c746..82268586b23 100644
--- a/chromium/net/base/host_mapping_rules_unittest.cc
+++ b/chromium/net/base/host_mapping_rules_unittest.cc
@@ -4,8 +4,14 @@
#include "net/base/host_mapping_rules.h"
+#include <string.h>
+
#include "net/base/host_port_pair.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
+#include "url/url_util.h"
namespace net {
@@ -81,6 +87,108 @@ TEST(HostMappingRulesTest, ParseInvalidRules) {
EXPECT_FALSE(rules.AddRuleFromString("INCLUDE x :10"));
}
+TEST(HostMappingRulesTest, RewritesUrl) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ GURL url("http://initial.test:111");
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("http://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesUrlToIpv6Literal) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test [2345:6789::0abc]:1112");
+
+ GURL url("http://initial.test:111");
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("http://[2345:6789::0abc]:1112"));
+}
+
+TEST(HostMappingRulesTest, RewritesUrlPreservingScheme) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ GURL url("wss://initial.test:222");
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("wss://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesFileUrl) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ // Expect replacement port to be ignored because file URLs do not use port.
+ GURL url("file://initial.test/file.txt");
+ ASSERT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("file://replacement.test/file.txt"));
+ EXPECT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+}
+
+TEST(HostMappingRulesTest, RewritesAnyStandardUrlWithPort) {
+ const char kScheme[] = "foo";
+ url::ScopedSchemeRegistryForTests scoped_registry;
+ AddStandardScheme(kScheme, url::SCHEME_WITH_HOST_AND_PORT);
+ ASSERT_TRUE(url::IsStandard(kScheme, url::Component(0, strlen(kScheme))));
+
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ GURL url("foo://initial.test:100");
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("foo://replacement.test:1000"));
+}
+
+TEST(HostMappingRulesTest, RewritesAnyStandardUrlWithoutPort) {
+ const char kScheme[] = "foo";
+ url::ScopedSchemeRegistryForTests scoped_registry;
+ AddStandardScheme(kScheme, url::SCHEME_WITH_HOST);
+ ASSERT_TRUE(url::IsStandard(kScheme, url::Component(0, strlen(kScheme))));
+
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ // Expect replacement port to be ignored.
+ GURL url("foo://initial.test");
+ ASSERT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+ EXPECT_EQ(rules.RewriteUrl(url), HostMappingRules::RewriteResult::kRewritten);
+ EXPECT_EQ(url, GURL("foo://replacement.test"));
+ EXPECT_EQ(url.EffectiveIntPort(), url::PORT_UNSPECIFIED);
+}
+
+TEST(HostMappingRulesTest, IgnoresUnmappedUrls) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test replacement.test:1000");
+
+ GURL url("http://different.test:111");
+ EXPECT_EQ(rules.RewriteUrl(url),
+ HostMappingRules::RewriteResult::kNoMatchingRule);
+ EXPECT_EQ(url, GURL("http://different.test:111"));
+}
+
+TEST(HostMappingRulesTest, IgnoresInvalidReplacementUrls) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test invalid/url");
+
+ GURL url("http://initial.test");
+ EXPECT_EQ(rules.RewriteUrl(url),
+ HostMappingRules::RewriteResult::kInvalidRewrite);
+ EXPECT_EQ(url, GURL("http://initial.test"));
+}
+
+// Remapping to "~NOTFOUND" is documented as a special case for
+// MappedHostResolver usage. Ensure that it is handled as invalid as expected.
+TEST(HostMappingRulesTest, NotFoundIgnoredAsInvalidUrl) {
+ HostMappingRules rules;
+ rules.AddRuleFromString("MAP initial.test ~NOTFOUND");
+
+ GURL url("http://initial.test");
+ EXPECT_EQ(rules.RewriteUrl(url),
+ HostMappingRules::RewriteResult::kInvalidRewrite);
+ EXPECT_EQ(url, GURL("http://initial.test"));
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/base/host_port_pair.cc b/chromium/net/base/host_port_pair.cc
index f24ac7b0d34..efa039d35fd 100644
--- a/chromium/net/base/host_port_pair.cc
+++ b/chromium/net/base/host_port_pair.cc
@@ -15,13 +15,13 @@
#include "net/base/parse_number.h"
#include "net/base/port_util.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
namespace net {
HostPortPair::HostPortPair() : port_(0) {}
-HostPortPair::HostPortPair(const std::string& in_host, uint16_t in_port)
- : host_(in_host), port_(in_port) {
-}
+HostPortPair::HostPortPair(base::StringPiece in_host, uint16_t in_port)
+ : host_(in_host), port_(in_port) {}
// static
HostPortPair HostPortPair::FromURL(const GURL& url) {
@@ -30,6 +30,21 @@ HostPortPair HostPortPair::FromURL(const GURL& url) {
}
// static
+HostPortPair HostPortPair::FromSchemeHostPort(
+ const url::SchemeHostPort& scheme_host_port) {
+ DCHECK(scheme_host_port.IsValid());
+
+ // HostPortPair assumes hostnames do not have surrounding brackets (as is
+ // commonly used for IPv6 literals), so strip them if present.
+ base::StringPiece host = scheme_host_port.host();
+ if (host.size() >= 2 && host.front() == '[' && host.back() == ']') {
+ host = host.substr(1, host.size() - 2);
+ }
+
+ return HostPortPair(host, scheme_host_port.port());
+}
+
+// static
HostPortPair HostPortPair::FromIPEndPoint(const IPEndPoint& ipe) {
return HostPortPair(ipe.ToStringWithoutPort(), ipe.port());
}
diff --git a/chromium/net/base/host_port_pair.h b/chromium/net/base/host_port_pair.h
index 1efb721e103..2ac2aaf2ea2 100644
--- a/chromium/net/base/host_port_pair.h
+++ b/chromium/net/base/host_port_pair.h
@@ -10,10 +10,15 @@
#include <string>
#include <tuple>
+#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
class GURL;
+namespace url {
+class SchemeHostPort;
+} // namespace url
+
namespace net {
class IPEndPoint;
@@ -22,11 +27,14 @@ class NET_EXPORT HostPortPair {
public:
HostPortPair();
// If |in_host| represents an IPv6 address, it should not bracket the address.
- HostPortPair(const std::string& in_host, uint16_t in_port);
+ HostPortPair(base::StringPiece in_host, uint16_t in_port);
// Creates a HostPortPair for the origin of |url|.
static HostPortPair FromURL(const GURL& url);
+ static HostPortPair FromSchemeHostPort(
+ const url::SchemeHostPort& scheme_host_port);
+
// Creates a HostPortPair from an IPEndPoint.
static HostPortPair FromIPEndPoint(const IPEndPoint& ipe);
diff --git a/chromium/net/base/host_port_pair_unittest.cc b/chromium/net/base/host_port_pair_unittest.cc
index 1f9a9f90d0b..99e7c89261c 100644
--- a/chromium/net/base/host_port_pair_unittest.cc
+++ b/chromium/net/base/host_port_pair_unittest.cc
@@ -6,6 +6,8 @@
#include "net/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
using std::string;
@@ -112,6 +114,36 @@ TEST(HostPortPairTest, Equals) {
EXPECT_FALSE(new_a_10.Equals(b_11));
}
+TEST(HostPortPairTest, ParsesFromUrl) {
+ HostPortPair parsed = HostPortPair::FromURL(GURL("https://foo.test:1250"));
+ HostPortPair expected("foo.test", 1250);
+
+ EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromUrlWithIpv6Brackets) {
+ HostPortPair parsed = HostPortPair::FromURL(GURL("https://[::1]"));
+ HostPortPair expected("::1", 443);
+
+ EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromSchemeHostPort) {
+ HostPortPair parsed = HostPortPair::FromSchemeHostPort(
+ url::SchemeHostPort("ws", "bar.test", 111));
+ HostPortPair expected("bar.test", 111);
+
+ EXPECT_EQ(parsed, expected);
+}
+
+TEST(HostPortPairTest, ParsesFromSchemeHostPortWithIpv6Brackets) {
+ HostPortPair parsed = HostPortPair::FromSchemeHostPort(
+ url::SchemeHostPort("wss", "[::1022]", 112));
+ HostPortPair expected("::1022", 112);
+
+ EXPECT_EQ(parsed, expected);
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/base/interval.h b/chromium/net/base/interval.h
index 24f3853c4c8..8ac3b5e44d8 100644
--- a/chromium/net/base/interval.h
+++ b/chromium/net/base/interval.h
@@ -65,7 +65,6 @@
#include <algorithm>
#include <functional>
#include <ostream>
-#include <string>
#include <utility>
#include <vector>
diff --git a/chromium/net/base/ip_address.cc b/chromium/net/base/ip_address.cc
index fef6d40e6e0..ead7ef91d0e 100644
--- a/chromium/net/base/ip_address.cc
+++ b/chromium/net/base/ip_address.cc
@@ -9,8 +9,8 @@
#include "base/check_op.h"
#include "base/containers/stack_container.h"
+#include "base/cxx17_backports.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
diff --git a/chromium/net/base/ip_address_unittest.cc b/chromium/net/base/ip_address_unittest.cc
index 8a9b90022b1..e64c542feea 100644
--- a/chromium/net/base/ip_address_unittest.cc
+++ b/chromium/net/base/ip_address_unittest.cc
@@ -6,8 +6,8 @@
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/base/ip_endpoint.cc b/chromium/net/base/ip_endpoint.cc
index 749d872e0b5..f9e266aeafc 100644
--- a/chromium/net/base/ip_endpoint.cc
+++ b/chromium/net/base/ip_endpoint.cc
@@ -4,95 +4,43 @@
#include "net/base/ip_endpoint.h"
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include <winsock2.h>
-#include <ws2bth.h>
-#elif defined(OS_POSIX)
-#include <netinet/in.h>
-#endif
+#include <ostream>
#include <string.h>
-
#include <tuple>
#include "base/check.h"
+#include "base/check_op.h"
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_byteorder.h"
+#include "build/build_config.h"
#include "net/base/ip_address.h"
+#include "net/base/sys_addrinfo.h"
#if defined(OS_WIN)
-#include "net/base/winsock_util.h"
-#endif
-
-namespace net {
-
-namespace {
-
-// By definition, socklen_t is large enough to hold both sizes.
-const socklen_t kSockaddrInSize = sizeof(struct sockaddr_in);
-const socklen_t kSockaddrIn6Size = sizeof(struct sockaddr_in6);
-
-// Extracts the address and port portions of a sockaddr.
-bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
- socklen_t sock_addr_len,
- const uint8_t** address,
- size_t* address_len,
- uint16_t* port) {
- if (sock_addr->sa_family == AF_INET) {
- if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
- return false;
- const struct sockaddr_in* addr =
- reinterpret_cast<const struct sockaddr_in*>(sock_addr);
- *address = reinterpret_cast<const uint8_t*>(&addr->sin_addr);
- *address_len = IPAddress::kIPv4AddressSize;
- if (port)
- *port = base::NetToHost16(addr->sin_port);
- return true;
- }
-
- if (sock_addr->sa_family == AF_INET6) {
- if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6)))
- return false;
- const struct sockaddr_in6* addr =
- reinterpret_cast<const struct sockaddr_in6*>(sock_addr);
- *address = reinterpret_cast<const uint8_t*>(&addr->sin6_addr);
- *address_len = IPAddress::kIPv6AddressSize;
- if (port)
- *port = base::NetToHost16(addr->sin6_port);
- return true;
- }
+#include <winsock2.h>
+#include <ws2bth.h>
-#if defined(OS_WIN)
- if (sock_addr->sa_family == AF_BTH) {
- if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH)))
- return false;
- const SOCKADDR_BTH* addr = reinterpret_cast<const SOCKADDR_BTH*>(sock_addr);
- *address = reinterpret_cast<const uint8_t*>(&addr->btAddr);
- *address_len = kBluetoothAddressSize;
- if (port)
- *port = static_cast<uint16_t>(addr->port);
- return true;
- }
+#include "net/base/winsock_util.h" // For kBluetoothAddressSize
#endif
- return false; // Unrecognized |sa_family|.
-}
-
-} // namespace
+namespace net {
-IPEndPoint::IPEndPoint() : port_(0) {}
+IPEndPoint::IPEndPoint() = default;
IPEndPoint::~IPEndPoint() = default;
IPEndPoint::IPEndPoint(const IPAddress& address, uint16_t port)
: address_(address), port_(port) {}
-IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) {
- address_ = endpoint.address_;
- port_ = endpoint.port_;
+IPEndPoint::IPEndPoint(const IPEndPoint& endpoint) = default;
+
+uint16_t IPEndPoint::port() const {
+#if defined(OS_WIN)
+ DCHECK_NE(address_.size(), kBluetoothAddressSize);
+#endif
+ return port_;
}
AddressFamily IPEndPoint::GetFamily() const {
@@ -105,6 +53,10 @@ int IPEndPoint::GetSockAddrFamily() const {
return AF_INET;
case IPAddress::kIPv6AddressSize:
return AF_INET6;
+#if defined(OS_WIN)
+ case kBluetoothAddressSize:
+ return AF_BTH;
+#endif
default:
NOTREACHED() << "Bad IP address";
return AF_UNSPEC;
@@ -113,8 +65,17 @@ int IPEndPoint::GetSockAddrFamily() const {
bool IPEndPoint::ToSockAddr(struct sockaddr* address,
socklen_t* address_length) const {
+ // By definition, socklen_t is large enough to hold both sizes.
+ constexpr socklen_t kSockaddrInSize =
+ static_cast<socklen_t>(sizeof(struct sockaddr_in));
+ constexpr socklen_t kSockaddrIn6Size =
+ static_cast<socklen_t>(sizeof(struct sockaddr_in6));
+
DCHECK(address);
DCHECK(address_length);
+#if defined(OS_WIN)
+ DCHECK_NE(address_.size(), kBluetoothAddressSize);
+#endif
switch (address_.size()) {
case IPAddress::kIPv4AddressSize: {
if (*address_length < kSockaddrInSize)
@@ -150,25 +111,58 @@ bool IPEndPoint::ToSockAddr(struct sockaddr* address,
bool IPEndPoint::FromSockAddr(const struct sockaddr* sock_addr,
socklen_t sock_addr_len) {
DCHECK(sock_addr);
-
- const uint8_t* address;
- size_t address_len;
- uint16_t port;
- if (!GetIPAddressFromSockAddr(sock_addr, sock_addr_len, &address,
- &address_len, &port)) {
- return false;
+ switch (sock_addr->sa_family) {
+ case AF_INET: {
+ if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
+ return false;
+ const struct sockaddr_in* addr =
+ reinterpret_cast<const struct sockaddr_in*>(sock_addr);
+ *this = IPEndPoint(
+ IPAddress(reinterpret_cast<const uint8_t*>(&addr->sin_addr),
+ IPAddress::kIPv4AddressSize),
+ base::NetToHost16(addr->sin_port));
+ return true;
+ }
+ case AF_INET6: {
+ if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6)))
+ return false;
+ const struct sockaddr_in6* addr =
+ reinterpret_cast<const struct sockaddr_in6*>(sock_addr);
+ *this = IPEndPoint(
+ IPAddress(reinterpret_cast<const uint8_t*>(&addr->sin6_addr),
+ IPAddress::kIPv6AddressSize),
+ base::NetToHost16(addr->sin6_port));
+ return true;
+ }
+#if defined(OS_WIN)
+ case AF_BTH: {
+ if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH)))
+ return false;
+ const SOCKADDR_BTH* addr =
+ reinterpret_cast<const SOCKADDR_BTH*>(sock_addr);
+ *this = IPEndPoint();
+ address_ = IPAddress(reinterpret_cast<const uint8_t*>(&addr->btAddr),
+ kBluetoothAddressSize);
+ // Intentionally ignoring Bluetooth port. It is a ULONG, but
+ // `IPEndPoint::port_` is a uint16_t. See https://crbug.com/1231273.
+ return true;
+ }
+#endif
}
-
- address_ = net::IPAddress(address, address_len);
- port_ = port;
- return true;
+ return false; // Unrecognized |sa_family|.
}
std::string IPEndPoint::ToString() const {
+#if defined(OS_WIN)
+ DCHECK_NE(address_.size(), kBluetoothAddressSize);
+#endif
return IPAddressToStringWithPort(address_, port_);
}
std::string IPEndPoint::ToStringWithoutPort() const {
+#if defined(OS_WIN)
+ DCHECK_NE(address_.size(), kBluetoothAddressSize);
+#endif
return address_.ToString();
}
diff --git a/chromium/net/base/ip_endpoint.h b/chromium/net/base/ip_endpoint.h
index fd635b62432..01628dfcc5c 100644
--- a/chromium/net/base/ip_endpoint.h
+++ b/chromium/net/base/ip_endpoint.h
@@ -10,12 +10,22 @@
#include <string>
#include "base/compiler_specific.h"
+#include "build/build_config.h"
#include "net/base/address_family.h"
#include "net/base/ip_address.h"
#include "net/base/net_export.h"
-#include "net/base/sys_addrinfo.h"
+#if defined(OS_WIN)
+// Replicate these from Windows headers to avoid pulling net/sys_addrinfo.h.
+// Doing that transitively brings in windows.h. Including windows.h pollutes the
+// global namespace with thousands of macro definitions. This file is
+// transitively included in enough files that including windows.h potentially
+// impacts build performance.
struct sockaddr;
+typedef int socklen_t;
+#else
+#include "net/base/sys_addrinfo.h"
+#endif
namespace net {
@@ -30,23 +40,30 @@ class NET_EXPORT IPEndPoint {
IPEndPoint(const IPEndPoint& endpoint);
const IPAddress& address() const { return address_; }
- uint16_t port() const { return port_; }
- // Returns AddressFamily of the address.
+ // Returns the IPv4/IPv6 port if it has been set by the constructor or
+ // `FromSockAddr`. This function will crash if the IPEndPoint is for a
+ // Bluetooth socket.
+ uint16_t port() const;
+
+ // Returns AddressFamily of the address. Returns ADDRESS_FAMILY_UNSPECIFIED if
+ // this is the IPEndPoint for a Bluetooth socket.
AddressFamily GetFamily() const;
- // Returns the sockaddr family of the address, AF_INET or AF_INET6.
+ // Returns the sockaddr family of the address, AF_INET or AF_INET6. Returns
+ // AF_BTH if this is the IPEndPoint for a Bluetooth socket.
int GetSockAddrFamily() const;
- // Convert to a provided sockaddr struct.
+ // Convert to a provided sockaddr struct. This function will crash if the
+ // IPEndPoint is for a Bluetooth socket.
// |address| is the sockaddr to copy into. Should be at least
// sizeof(struct sockaddr_storage) bytes.
// |address_length| is an input/output parameter. On input, it is the
// size of data in |address| available. On output, it is the size of
// the address that was copied into |address|.
// Returns true on success, false on failure.
- bool ToSockAddr(struct sockaddr* address, socklen_t* address_length) const
- WARN_UNUSED_RESULT;
+ bool ToSockAddr(struct sockaddr* address,
+ socklen_t* address_length) const WARN_UNUSED_RESULT;
// Convert from a sockaddr struct.
// |address| is the address.
@@ -56,11 +73,13 @@ class NET_EXPORT IPEndPoint {
socklen_t address_length) WARN_UNUSED_RESULT;
// Returns value as a string (e.g. "127.0.0.1:80"). Returns the empty string
- // when |address_| is invalid (the port will be ignored).
+ // when |address_| is invalid (the port will be ignored). This function will
+ // crash if the IPEndPoint is for a Bluetooth socket.
std::string ToString() const;
// As above, but without port. Returns the empty string when address_ is
- // invalid.
+ // invalid. The function will crash if the IPEndPoint is for a Bluetooth
+ // socket.
std::string ToStringWithoutPort() const;
bool operator<(const IPEndPoint& that) const;
@@ -69,7 +88,7 @@ class NET_EXPORT IPEndPoint {
private:
IPAddress address_;
- uint16_t port_;
+ uint16_t port_ = 0;
};
} // namespace net
diff --git a/chromium/net/base/ip_endpoint_unittest.cc b/chromium/net/base/ip_endpoint_unittest.cc
index f0f7eabb227..6cc10dd73b5 100644
--- a/chromium/net/base/ip_endpoint_unittest.cc
+++ b/chromium/net/base/ip_endpoint_unittest.cc
@@ -4,22 +4,32 @@
#include "net/base/ip_endpoint.h"
-#include "build/build_config.h"
+#include <string.h>
-#if defined(OS_WIN)
-#include <winsock2.h>
-#elif defined(OS_POSIX)
-#include <netinet/in.h>
-#endif
+#include <string>
#include "base/check_op.h"
+#include "base/macros.h"
#include "base/notreached.h"
+#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_byteorder.h"
+#include "build/build_config.h"
+#include "net/base/ip_address.h"
#include "net/base/sockaddr_storage.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#if defined(OS_WIN)
+#include <winsock2.h>
+#include <ws2bth.h>
+
+#include "base/test/gtest_util.h" // For EXPECT_DCHECK_DEATH
+#include "net/base/winsock_util.h" // For kBluetoothAddressSize
+#elif defined(OS_POSIX)
+#include <netinet/in.h>
+#endif
+
namespace net {
namespace {
@@ -121,7 +131,6 @@ TEST_F(IPEndPointTest, ToFromSockAddr) {
EXPECT_EQ(expected_size, storage.addr_len);
EXPECT_EQ(ip_endpoint.port(), GetPortFromSockaddr(storage.addr,
storage.addr_len));
-
// And convert back to an IPEndPoint.
IPEndPoint ip_endpoint2;
EXPECT_TRUE(ip_endpoint2.FromSockAddr(storage.addr, storage.addr_len));
@@ -150,6 +159,158 @@ TEST_F(IPEndPointTest, FromSockAddrBufTooSmall) {
EXPECT_FALSE(ip_endpoint.FromSockAddr(sockaddr, sizeof(addr) - 1));
}
+#if defined(OS_WIN)
+
+namespace {
+constexpr uint8_t kBluetoothAddrBytes[kBluetoothAddressSize] = {1, 2, 3,
+ 4, 5, 6};
+constexpr uint8_t kBluetoothAddrBytes2[kBluetoothAddressSize] = {1, 2, 3,
+ 4, 5, 7};
+const IPAddress kBluetoothAddress(kBluetoothAddrBytes);
+const IPAddress kBluetoothAddress2(kBluetoothAddrBytes2);
+
+// Select a Bluetooth port that does not fit in a uint16_t.
+constexpr uint32_t kBluetoothPort = std::numeric_limits<uint16_t>::max() + 1;
+
+SOCKADDR_BTH BuildBluetoothSockAddr(const IPAddress& ip_address,
+ uint32_t port) {
+ SOCKADDR_BTH addr = {};
+ addr.addressFamily = AF_BTH;
+ DCHECK_LE(ip_address.bytes().size(), sizeof(addr.btAddr));
+ memcpy(&addr.btAddr, ip_address.bytes().data(), ip_address.bytes().size());
+ addr.port = port;
+ return addr;
+}
+} // namespace
+
+TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithSelf) {
+ IPEndPoint bt_endpoint;
+ SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
+ EXPECT_EQ(bt_endpoint.address(), kBluetoothAddress);
+ EXPECT_EQ(bt_endpoint.GetFamily(), AddressFamily::ADDRESS_FAMILY_UNSPECIFIED);
+ EXPECT_EQ(bt_endpoint.GetSockAddrFamily(), AF_BTH);
+ // Comparison functions should agree that `bt_endpoint` equals itself.
+ EXPECT_FALSE(bt_endpoint < bt_endpoint);
+ EXPECT_FALSE(bt_endpoint != bt_endpoint);
+ EXPECT_TRUE(bt_endpoint == bt_endpoint);
+ // Test that IPv4/IPv6-only methods crash.
+ EXPECT_DCHECK_DEATH(bt_endpoint.port());
+ SockaddrStorage storage;
+ EXPECT_DCHECK_DEATH(
+ ignore_result(bt_endpoint.ToSockAddr(storage.addr, &storage.addr_len)));
+ EXPECT_DCHECK_DEATH(bt_endpoint.ToString());
+ EXPECT_DCHECK_DEATH(bt_endpoint.ToStringWithoutPort());
+}
+
+TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithNonBluetooth) {
+ IPEndPoint bt_endpoint;
+ SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
+
+ // Compare `bt_endpoint` with non-Bluetooth endpoints.
+ for (const auto& test : tests) {
+ IPEndPoint endpoint(test.ip_address, 80);
+ if (test.ip_address.IsIPv4()) {
+ EXPECT_FALSE(bt_endpoint < endpoint);
+ } else {
+ EXPECT_TRUE(test.ip_address.IsIPv6());
+ EXPECT_TRUE(bt_endpoint < endpoint);
+ }
+ EXPECT_TRUE(bt_endpoint != endpoint);
+ EXPECT_FALSE(bt_endpoint == endpoint);
+ }
+}
+
+TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithCopy) {
+ IPEndPoint bt_endpoint;
+ SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
+
+ // Verify that a copy's accessors return the same values as the original's.
+ IPEndPoint bt_endpoint_other(bt_endpoint);
+ EXPECT_EQ(bt_endpoint.address(), bt_endpoint_other.address());
+ EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
+ EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
+ bt_endpoint_other.GetSockAddrFamily());
+ // Comparison functions should agree that the endpoints are equal.
+ EXPECT_FALSE(bt_endpoint < bt_endpoint_other);
+ EXPECT_FALSE(bt_endpoint != bt_endpoint_other);
+ EXPECT_TRUE(bt_endpoint == bt_endpoint_other);
+ // Test that IPv4/IPv6-only methods crash.
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
+ SockaddrStorage storage;
+ EXPECT_DCHECK_DEATH(ignore_result(
+ bt_endpoint_other.ToSockAddr(storage.addr, &storage.addr_len)));
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
+}
+
+TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithDifferentPort) {
+ IPEndPoint bt_endpoint;
+ SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
+
+ // Compare with another IPEndPoint that has a different port.
+ IPEndPoint bt_endpoint_other;
+ SOCKADDR_BTH addr2 =
+ BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort + 1);
+ EXPECT_TRUE(bt_endpoint_other.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr2), sizeof(addr2)));
+ EXPECT_EQ(bt_endpoint.address(), bt_endpoint_other.address());
+ EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
+ EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
+ bt_endpoint_other.GetSockAddrFamily());
+ // Comparison functions should agree that `bt_endpoint == bt_endpoint_other`
+ // because they have the same address and Bluetooth ports are not considered
+ // by comparison functions.
+ EXPECT_FALSE(bt_endpoint < bt_endpoint_other);
+ EXPECT_FALSE(bt_endpoint != bt_endpoint_other);
+ EXPECT_TRUE(bt_endpoint == bt_endpoint_other);
+ // Test that IPv4/IPv6-only methods crash.
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
+ SockaddrStorage storage;
+ EXPECT_DCHECK_DEATH(ignore_result(
+ bt_endpoint_other.ToSockAddr(storage.addr, &storage.addr_len)));
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
+}
+
+TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithDifferentAddress) {
+ IPEndPoint bt_endpoint;
+ SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
+
+ // Compare with another IPEndPoint that has a different address.
+ IPEndPoint bt_endpoint_other;
+ SOCKADDR_BTH addr2 =
+ BuildBluetoothSockAddr(kBluetoothAddress2, kBluetoothPort);
+ EXPECT_TRUE(bt_endpoint_other.FromSockAddr(
+ reinterpret_cast<const struct sockaddr*>(&addr2), sizeof(addr2)));
+ EXPECT_LT(bt_endpoint.address(), bt_endpoint_other.address());
+ EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
+ EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
+ bt_endpoint_other.GetSockAddrFamily());
+ // Comparison functions should agree that `bt_endpoint < bt_endpoint_other`
+ // due to lexicographic comparison of the address bytes.
+ EXPECT_TRUE(bt_endpoint < bt_endpoint_other);
+ EXPECT_TRUE(bt_endpoint != bt_endpoint_other);
+ EXPECT_FALSE(bt_endpoint == bt_endpoint_other);
+ // Test that IPv4/IPv6-only methods crash.
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
+ SockaddrStorage storage;
+ EXPECT_DCHECK_DEATH(ignore_result(
+ bt_endpoint_other.ToSockAddr(storage.addr, &storage.addr_len)));
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
+ EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
+}
+#endif
+
TEST_F(IPEndPointTest, Equality) {
uint16_t port = 0;
for (const auto& test : tests) {
diff --git a/chromium/net/base/isolation_info.cc b/chromium/net/base/isolation_info.cc
index 5cd54540daf..e5f3494e1f4 100644
--- a/chromium/net/base/isolation_info.cc
+++ b/chromium/net/base/isolation_info.cc
@@ -5,6 +5,8 @@
#include "net/base/isolation_info.h"
#include "base/check_op.h"
+#include "base/unguessable_token.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
@@ -41,15 +43,16 @@ bool IsConsistent(IsolationInfo::RequestType request_type,
const absl::optional<url::Origin>& frame_origin,
const SiteForCookies& site_for_cookies,
bool opaque_and_non_transient,
- absl::optional<std::set<SchemefulSite>> party_context) {
+ absl::optional<std::set<SchemefulSite>> party_context,
+ const base::UnguessableToken* nonce) {
// Check for the default-constructed case.
if (!top_frame_origin) {
return request_type == IsolationInfo::RequestType::kOther &&
- !frame_origin && site_for_cookies.IsNull() &&
+ !frame_origin && !nonce && site_for_cookies.IsNull() &&
!opaque_and_non_transient && !party_context;
}
- // |frame_origin| may only be nullopt is |top_frame_origin| is as well.
+ // |frame_origin| may only be nullopt if |top_frame_origin| is as well.
if (!frame_origin)
return false;
@@ -61,7 +64,7 @@ bool IsConsistent(IsolationInfo::RequestType request_type,
if (opaque_and_non_transient) {
return (request_type == IsolationInfo::RequestType::kOther &&
top_frame_origin->opaque() && top_frame_origin == frame_origin &&
- site_for_cookies.IsNull());
+ !nonce && site_for_cookies.IsNull());
}
switch (request_type) {
@@ -96,6 +99,7 @@ IsolationInfo::IsolationInfo()
absl::nullopt,
SiteForCookies(),
false /* opaque_and_non_transient */,
+ nullptr /* nonce */,
absl::nullopt) {}
IsolationInfo::IsolationInfo(const IsolationInfo&) = default;
@@ -109,6 +113,7 @@ IsolationInfo IsolationInfo::CreateForInternalRequest(
return IsolationInfo(RequestType::kOther, top_frame_origin, top_frame_origin,
SiteForCookies::FromOrigin(top_frame_origin),
false /* opaque_and_non_transient */,
+ nullptr /* nonce */,
std::set<SchemefulSite>() /* party_context */);
}
@@ -116,14 +121,14 @@ IsolationInfo IsolationInfo::CreateTransient() {
url::Origin opaque_origin;
return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin,
SiteForCookies(), false /* opaque_and_non_transient */,
- absl::nullopt /* party_context */);
+ nullptr /* nonce */, absl::nullopt /* party_context */);
}
IsolationInfo IsolationInfo::CreateOpaqueAndNonTransient() {
url::Origin opaque_origin;
return IsolationInfo(RequestType::kOther, opaque_origin, opaque_origin,
SiteForCookies(), true /* opaque_and_non_transient */,
- absl::nullopt /* party_context */);
+ nullptr /* nonce */, absl::nullopt /* party_context */);
}
IsolationInfo IsolationInfo::Create(
@@ -131,10 +136,11 @@ IsolationInfo IsolationInfo::Create(
const url::Origin& top_frame_origin,
const url::Origin& frame_origin,
const SiteForCookies& site_for_cookies,
- absl::optional<std::set<SchemefulSite>> party_context) {
+ absl::optional<std::set<SchemefulSite>> party_context,
+ const base::UnguessableToken* nonce) {
return IsolationInfo(request_type, top_frame_origin, frame_origin,
site_for_cookies, false /* opaque_and_non_transient */,
- std::move(party_context));
+ nonce, std::move(party_context));
}
IsolationInfo IsolationInfo::CreatePartial(
@@ -159,8 +165,13 @@ IsolationInfo IsolationInfo::CreatePartial(
frame_origin.opaque() &&
!network_isolation_key.IsTransient();
+ const base::UnguessableToken* nonce =
+ network_isolation_key.GetNonce()
+ ? &network_isolation_key.GetNonce().value()
+ : nullptr;
+
return IsolationInfo(request_type, top_frame_origin, frame_origin,
- SiteForCookies(), opaque_and_non_transient,
+ SiteForCookies(), opaque_and_non_transient, nonce,
absl::nullopt /* party_context */);
}
@@ -170,14 +181,15 @@ absl::optional<IsolationInfo> IsolationInfo::CreateIfConsistent(
const absl::optional<url::Origin>& frame_origin,
const SiteForCookies& site_for_cookies,
bool opaque_and_non_transient,
- absl::optional<std::set<SchemefulSite>> party_context) {
+ absl::optional<std::set<SchemefulSite>> party_context,
+ const base::UnguessableToken* nonce) {
if (!IsConsistent(request_type, top_frame_origin, frame_origin,
- site_for_cookies, opaque_and_non_transient,
- party_context)) {
+ site_for_cookies, opaque_and_non_transient, party_context,
+ nonce)) {
return absl::nullopt;
}
return IsolationInfo(request_type, top_frame_origin, frame_origin,
- site_for_cookies, opaque_and_non_transient,
+ site_for_cookies, opaque_and_non_transient, nonce,
std::move(party_context));
}
@@ -189,14 +201,16 @@ IsolationInfo IsolationInfo::CreateForRedirect(
if (request_type_ == RequestType::kSubFrame) {
return IsolationInfo(request_type_, top_frame_origin_, new_origin,
site_for_cookies_, opaque_and_non_transient_,
+ nonce_.has_value() ? &nonce_.value() : nullptr,
party_context_);
}
DCHECK_EQ(RequestType::kMainFrame, request_type_);
DCHECK(!party_context_ || party_context_->empty());
- return IsolationInfo(request_type_, new_origin, new_origin,
- SiteForCookies::FromOrigin(new_origin),
- opaque_and_non_transient_, party_context_);
+ return IsolationInfo(
+ request_type_, new_origin, new_origin,
+ SiteForCookies::FromOrigin(new_origin), opaque_and_non_transient_,
+ nonce_.has_value() ? &nonce_.value() : nullptr, party_context_);
}
bool IsolationInfo::IsEqualForTesting(const IsolationInfo& other) const {
@@ -205,6 +219,7 @@ bool IsolationInfo::IsEqualForTesting(const IsolationInfo& other) const {
frame_origin_ == other.frame_origin_ &&
network_isolation_key_ == other.network_isolation_key_ &&
opaque_and_non_transient_ == other.opaque_and_non_transient_ &&
+ nonce_ == other.nonce_ &&
site_for_cookies_.IsEquivalent(other.site_for_cookies_) &&
party_context_ == other.party_context_);
}
@@ -215,7 +230,7 @@ IsolationInfo IsolationInfo::ToDoUseTopFrameOriginAsWell(
RequestType::kOther, incorrectly_used_frame_origin,
incorrectly_used_frame_origin,
SiteForCookies::FromOrigin(incorrectly_used_frame_origin),
- false /* opaque_and_non_transient */,
+ false /* opaque_and_non_transient */, nullptr /* nonce */,
std::set<SchemefulSite>() /* party_context */);
}
@@ -225,6 +240,7 @@ IsolationInfo::IsolationInfo(
const absl::optional<url::Origin>& frame_origin,
const SiteForCookies& site_for_cookies,
bool opaque_and_non_transient,
+ const base::UnguessableToken* nonce,
absl::optional<std::set<SchemefulSite>> party_context)
: request_type_(request_type),
top_frame_origin_(top_frame_origin),
@@ -234,16 +250,18 @@ IsolationInfo::IsolationInfo(
? NetworkIsolationKey()
: NetworkIsolationKey(SchemefulSite(*top_frame_origin),
SchemefulSite(*frame_origin),
- opaque_and_non_transient)),
+ opaque_and_non_transient,
+ nonce)),
site_for_cookies_(site_for_cookies),
opaque_and_non_transient_(opaque_and_non_transient),
+ nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt),
party_context_(party_context.has_value() &&
party_context->size() > kPartyContextMaxSize
? absl::nullopt
: party_context) {
DCHECK(IsConsistent(request_type_, top_frame_origin_, frame_origin_,
site_for_cookies_, opaque_and_non_transient_,
- party_context_));
+ party_context_, nonce));
}
} // namespace net
diff --git a/chromium/net/base/isolation_info.h b/chromium/net/base/isolation_info.h
index 129d9c992ae..e8c5f93731a 100644
--- a/chromium/net/base/isolation_info.h
+++ b/chromium/net/base/isolation_info.h
@@ -7,6 +7,7 @@
#include <set>
+#include "base/unguessable_token.h"
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
#include "net/cookies/site_for_cookies.h"
@@ -107,7 +108,8 @@ class NET_EXPORT IsolationInfo {
// * If |request_type| is kOther, |top_frame_origin| and
// |frame_origin| must be first party with respect to |site_for_cookies|, or
// |site_for_cookies| must be null.
- // * If |party_context_| is not empty, |top_frame_origin| must not be null.
+ // * If |party_context| is not empty, |top_frame_origin| must not be null.
+ // * If |nonce| is specified, then |top_frame_origin| must not be null.
//
// Note that the |site_for_cookies| consistency checks are skipped when
// |site_for_cookies| is not HTTP/HTTPS.
@@ -116,7 +118,8 @@ class NET_EXPORT IsolationInfo {
const url::Origin& top_frame_origin,
const url::Origin& frame_origin,
const SiteForCookies& site_for_cookies,
- absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt);
+ absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt,
+ const base::UnguessableToken* nonce = nullptr);
// Create an IsolationInfos that may not be fully correct - in particular,
// the SiteForCookies will always set to null, and if the NetworkIsolationKey
@@ -142,7 +145,8 @@ class NET_EXPORT IsolationInfo {
const absl::optional<url::Origin>& frame_origin,
const SiteForCookies& site_for_cookies,
bool opaque_and_non_transient,
- absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt);
+ absl::optional<std::set<SchemefulSite>> party_context = absl::nullopt,
+ const base::UnguessableToken* nonce = nullptr);
// Create a new IsolationInfo for a redirect to the supplied origin. |this| is
// unmodified.
@@ -177,6 +181,8 @@ class NET_EXPORT IsolationInfo {
return network_isolation_key_;
}
+ const absl::optional<base::UnguessableToken>& nonce() const { return nonce_; }
+
// The value that should be consulted for the third-party cookie blocking
// policy, as defined in Section 2.1.1 and 2.1.2 of
// https://tools.ietf.org/html/draft-ietf-httpbis-cookie-same-site.
@@ -204,6 +210,7 @@ class NET_EXPORT IsolationInfo {
const absl::optional<url::Origin>& frame_origin,
const SiteForCookies& site_for_cookies,
bool opaque_and_non_transient,
+ const base::UnguessableToken* nonce,
absl::optional<std::set<SchemefulSite>> party_context);
RequestType request_type_;
@@ -219,6 +226,10 @@ class NET_EXPORT IsolationInfo {
bool opaque_and_non_transient_ = false;
+ // Having a nonce is a way to force a transient opaque `IsolationInfo`
+ // for non-opaque origins.
+ absl::optional<base::UnguessableToken> nonce_;
+
// This will hold the list of distinct sites in the form of SchemefulSite to
// be used for First-Party-Sets check.
//
diff --git a/chromium/net/base/isolation_info_unittest.cc b/chromium/net/base/isolation_info_unittest.cc
index e8d2cbf26bd..642bce7f142 100644
--- a/chromium/net/base/isolation_info_unittest.cc
+++ b/chromium/net/base/isolation_info_unittest.cc
@@ -4,6 +4,7 @@
#include "net/base/isolation_info.h"
+#include "base/unguessable_token.h"
#include "net/base/network_isolation_key.h"
#include "net/base/schemeful_site.h"
#include "net/cookies/site_for_cookies.h"
@@ -23,7 +24,9 @@ void DuplicateAndCompare(const IsolationInfo& isolation_info) {
isolation_info.request_type(), isolation_info.top_frame_origin(),
isolation_info.frame_origin(), isolation_info.site_for_cookies(),
isolation_info.opaque_and_non_transient(),
- isolation_info.party_context());
+ isolation_info.party_context(),
+ isolation_info.nonce().has_value() ? &isolation_info.nonce().value()
+ : nullptr);
ASSERT_TRUE(duplicate_isolation_info);
EXPECT_TRUE(isolation_info.IsEqualForTesting(*duplicate_isolation_info));
@@ -48,6 +51,9 @@ class IsolationInfoTest : public testing::Test {
std::set<net::SchemefulSite>{net::SchemefulSite(kOrigin2)};
const absl::optional<std::set<net::SchemefulSite>> kPartyContext3 =
std::set<net::SchemefulSite>{net::SchemefulSite(kOrigin3)};
+
+ const base::UnguessableToken kNonce1 = base::UnguessableToken::Create();
+ const base::UnguessableToken kNonce2 = base::UnguessableToken::Create();
};
TEST_F(IsolationInfoTest, RequestTypeMainFrame) {
@@ -66,6 +72,7 @@ TEST_F(IsolationInfoTest, RequestTypeMainFrame) {
isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContextEmpty, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce().has_value());
DuplicateAndCompare(isolation_info);
@@ -84,6 +91,7 @@ TEST_F(IsolationInfoTest, RequestTypeMainFrame) {
kOrigin3.GetURL()));
EXPECT_FALSE(redirected_isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContextEmpty, redirected_isolation_info.party_context());
+ EXPECT_FALSE(redirected_isolation_info.nonce().has_value());
}
TEST_F(IsolationInfoTest, RequestTypeSubFrame) {
@@ -102,6 +110,7 @@ TEST_F(IsolationInfoTest, RequestTypeSubFrame) {
isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContext1, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce().has_value());
DuplicateAndCompare(isolation_info);
@@ -120,6 +129,79 @@ TEST_F(IsolationInfoTest, RequestTypeSubFrame) {
kOrigin1.GetURL()));
EXPECT_FALSE(redirected_isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContext1, isolation_info.party_context());
+ EXPECT_FALSE(redirected_isolation_info.nonce().has_value());
+}
+
+TEST_F(IsolationInfoTest, RequestTypeMainFrameWithNonce) {
+ IsolationInfo isolation_info = IsolationInfo::Create(
+ IsolationInfo::RequestType::kMainFrame, kOrigin1, kOrigin1,
+ SiteForCookies::FromOrigin(kOrigin1), kPartyContextEmpty, &kNonce1);
+ EXPECT_EQ(IsolationInfo::RequestType::kMainFrame,
+ isolation_info.request_type());
+ EXPECT_EQ(kOrigin1, isolation_info.top_frame_origin());
+ EXPECT_EQ(kOrigin1, isolation_info.frame_origin());
+ EXPECT_TRUE(isolation_info.network_isolation_key().IsFullyPopulated());
+ EXPECT_TRUE(isolation_info.network_isolation_key().IsTransient());
+ EXPECT_EQ("", isolation_info.network_isolation_key().ToString());
+ EXPECT_TRUE(
+ isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
+ EXPECT_FALSE(isolation_info.opaque_and_non_transient());
+ EXPECT_EQ(kPartyContextEmpty, isolation_info.party_context());
+ EXPECT_EQ(kNonce1, isolation_info.nonce().value());
+
+ DuplicateAndCompare(isolation_info);
+
+ IsolationInfo redirected_isolation_info =
+ isolation_info.CreateForRedirect(kOrigin3);
+ EXPECT_EQ(IsolationInfo::RequestType::kMainFrame,
+ redirected_isolation_info.request_type());
+ EXPECT_EQ(kOrigin3, redirected_isolation_info.top_frame_origin());
+ EXPECT_EQ(kOrigin3, redirected_isolation_info.frame_origin());
+ EXPECT_TRUE(
+ redirected_isolation_info.network_isolation_key().IsFullyPopulated());
+ EXPECT_TRUE(redirected_isolation_info.network_isolation_key().IsTransient());
+ EXPECT_EQ("", redirected_isolation_info.network_isolation_key().ToString());
+ EXPECT_TRUE(redirected_isolation_info.site_for_cookies().IsFirstParty(
+ kOrigin3.GetURL()));
+ EXPECT_FALSE(redirected_isolation_info.opaque_and_non_transient());
+ EXPECT_EQ(kPartyContextEmpty, redirected_isolation_info.party_context());
+ EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value());
+}
+
+TEST_F(IsolationInfoTest, RequestTypeSubFrameWithNonce) {
+ IsolationInfo isolation_info = IsolationInfo::Create(
+ IsolationInfo::RequestType::kSubFrame, kOrigin1, kOrigin2,
+ SiteForCookies::FromOrigin(kOrigin1), kPartyContext1, &kNonce1);
+ EXPECT_EQ(IsolationInfo::RequestType::kSubFrame,
+ isolation_info.request_type());
+ EXPECT_EQ(kOrigin1, isolation_info.top_frame_origin());
+ EXPECT_EQ(kOrigin2, isolation_info.frame_origin());
+ EXPECT_TRUE(isolation_info.network_isolation_key().IsFullyPopulated());
+ EXPECT_TRUE(isolation_info.network_isolation_key().IsTransient());
+ EXPECT_EQ("", isolation_info.network_isolation_key().ToString());
+ EXPECT_TRUE(
+ isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
+ EXPECT_FALSE(isolation_info.opaque_and_non_transient());
+ EXPECT_EQ(kPartyContext1, isolation_info.party_context());
+ EXPECT_EQ(kNonce1, isolation_info.nonce().value());
+
+ DuplicateAndCompare(isolation_info);
+
+ IsolationInfo redirected_isolation_info =
+ isolation_info.CreateForRedirect(kOrigin3);
+ EXPECT_EQ(IsolationInfo::RequestType::kSubFrame,
+ redirected_isolation_info.request_type());
+ EXPECT_EQ(kOrigin1, redirected_isolation_info.top_frame_origin());
+ EXPECT_EQ(kOrigin3, redirected_isolation_info.frame_origin());
+ EXPECT_TRUE(
+ redirected_isolation_info.network_isolation_key().IsFullyPopulated());
+ EXPECT_TRUE(redirected_isolation_info.network_isolation_key().IsTransient());
+ EXPECT_EQ("", redirected_isolation_info.network_isolation_key().ToString());
+ EXPECT_TRUE(redirected_isolation_info.site_for_cookies().IsFirstParty(
+ kOrigin1.GetURL()));
+ EXPECT_FALSE(redirected_isolation_info.opaque_and_non_transient());
+ EXPECT_EQ(kPartyContext1, redirected_isolation_info.party_context());
+ EXPECT_EQ(kNonce1, redirected_isolation_info.nonce().value());
}
TEST_F(IsolationInfoTest, RequestTypeOther) {
@@ -131,6 +213,7 @@ TEST_F(IsolationInfoTest, RequestTypeOther) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -154,6 +237,7 @@ TEST_F(IsolationInfoTest, RequestTypeOtherWithSiteForCookies) {
isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContextEmpty, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -178,6 +262,7 @@ TEST_F(IsolationInfoTest, RequestTypeOtherWithEmptySiteForCookies) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContext2, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -196,6 +281,7 @@ TEST_F(IsolationInfoTest, CreateTransient) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -217,6 +303,7 @@ TEST_F(IsolationInfoTest, CreateOpaqueAndNonTransient) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_TRUE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -239,6 +326,7 @@ TEST_F(IsolationInfoTest, CreateForInternalRequest) {
isolation_info.site_for_cookies().IsFirstParty(kOrigin1.GetURL()));
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContextEmpty, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -260,6 +348,7 @@ TEST_F(IsolationInfoTest, CreatePartialUpdateTopFrame) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -277,6 +366,7 @@ TEST_F(IsolationInfoTest, CreatePartialUpdateFrameOnly) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -293,6 +383,7 @@ TEST_F(IsolationInfoTest, CreatePartialUpdateNothing) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -309,6 +400,7 @@ TEST_F(IsolationInfoTest, CreatePartialTransient) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -326,6 +418,7 @@ TEST_F(IsolationInfoTest, CreatePartialOpaqueAndNonTransient) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_TRUE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -340,6 +433,7 @@ TEST_F(IsolationInfoTest, CreatePartialEmpty) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsNull());
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_FALSE(isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
}
@@ -368,6 +462,7 @@ TEST_F(IsolationInfoTest, CustomSchemeRequestTypeOther) {
EXPECT_TRUE(isolation_info.site_for_cookies().IsFirstParty(kCustomOriginUrl));
EXPECT_FALSE(isolation_info.opaque_and_non_transient());
EXPECT_EQ(kPartyContext1, isolation_info.party_context());
+ EXPECT_FALSE(isolation_info.nonce());
DuplicateAndCompare(isolation_info);
@@ -423,6 +518,12 @@ TEST_F(IsolationInfoTest, CreateIfConsistentFails) {
IsolationInfo::RequestType::kOther, kOrigin1, kOrigin1, SiteForCookies(),
true /* opaque_and_non_transient */));
+ // |opaque_and_non_transient| with nonce.
+ EXPECT_FALSE(IsolationInfo::CreateIfConsistent(
+ IsolationInfo::RequestType::kOther, kOpaqueOrigin, kOpaqueOrigin,
+ SiteForCookies(), true /* opaque_and_non_transient */,
+ absl::nullopt /* party_context */, &kNonce1));
+
// Correctly have empty/non-empty origins:
EXPECT_TRUE(IsolationInfo::CreateIfConsistent(
IsolationInfo::RequestType::kOther, absl::nullopt, absl::nullopt,
@@ -461,6 +562,12 @@ TEST_F(IsolationInfoTest, CreateIfConsistentFails) {
IsolationInfo::RequestType::kOther, absl::nullopt, absl::nullopt,
SiteForCookies(), false /* opaque_and_non_transient */,
kPartyContextEmpty));
+
+ // No origins with non-null nonce.
+ EXPECT_FALSE(IsolationInfo::CreateIfConsistent(
+ IsolationInfo::RequestType::kOther, absl::nullopt, absl::nullopt,
+ SiteForCookies(), false /* opaque_and_non_transient */,
+ absl::nullopt /* party_context */, &kNonce1));
}
TEST_F(IsolationInfoTest, CreateForRedirectPartyContext) {
diff --git a/chromium/net/base/mime_sniffer.cc b/chromium/net/base/mime_sniffer.cc
index de8ad1c1fd7..78006760e07 100644
--- a/chromium/net/base/mime_sniffer.cc
+++ b/chromium/net/base/mime_sniffer.cc
@@ -91,7 +91,6 @@
#include "base/check_op.h"
#include "base/containers/span.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "url/gurl.h"
diff --git a/chromium/net/base/mime_util.cc b/chromium/net/base/mime_util.cc
index 0becb8b629e..f391fa9d729 100644
--- a/chromium/net/base/mime_util.cc
+++ b/chromium/net/base/mime_util.cc
@@ -13,7 +13,6 @@
#include "base/containers/span.h"
#include "base/lazy_instance.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
diff --git a/chromium/net/base/net_error_list.h b/chromium/net/base/net_error_list.h
index c18e34fbd7b..e73a28d6b16 100644
--- a/chromium/net/base/net_error_list.h
+++ b/chromium/net/base/net_error_list.h
@@ -996,3 +996,8 @@ NET_ERROR(DNS_SORT_ERROR, -806)
// Failed to resolve the hostname of a DNS-over-HTTPS server.
NET_ERROR(DNS_SECURE_RESOLVER_HOSTNAME_RESOLUTION_FAILED, -808)
+
+// DNS identified the request as disallowed for insecure connection (http/ws).
+// Error should be handled as if an HTTP redirect was received to redirect to
+// https or wss.
+NET_ERROR(DNS_NAME_HTTPS_ONLY, 809)
diff --git a/chromium/net/base/net_errors.cc b/chromium/net/base/net_errors.cc
index 06ba2d9174c..39890a98283 100644
--- a/chromium/net/base/net_errors.cc
+++ b/chromium/net/base/net_errors.cc
@@ -4,7 +4,11 @@
#include "net/base/net_errors.h"
+#include <string>
+
#include "base/check_op.h"
+#include "base/files/file.h"
+#include "base/logging.h"
#include "base/notreached.h"
#include "net/third_party/quiche/src/quic/core/quic_error_codes.h"
diff --git a/chromium/net/base/net_errors.h b/chromium/net/base/net_errors.h
index d2807f53999..e146fc40724 100644
--- a/chromium/net/base/net_errors.h
+++ b/chromium/net/base/net_errors.h
@@ -6,7 +6,6 @@
#define NET_BASE_NET_ERRORS_H__
#include <string>
-#include <vector>
#include "base/files/file.h"
#include "base/logging.h"
diff --git a/chromium/net/base/net_string_util_icu_alternatives_android.cc b/chromium/net/base/net_string_util_icu_alternatives_android.cc
index 1ee1893e084..246018078dd 100644
--- a/chromium/net/base/net_string_util_icu_alternatives_android.cc
+++ b/chromium/net/base/net_string_util_icu_alternatives_android.cc
@@ -24,6 +24,7 @@ ScopedJavaLocalRef<jstring> ConvertToJstring(base::StringPiece text,
ScopedJavaLocalRef<jobject> java_byte_buffer(
env,
env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
+ base::android::CheckException(env);
base::android::ScopedJavaLocalRef<jstring> java_charset =
base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
ScopedJavaLocalRef<jstring> java_result =
@@ -41,6 +42,7 @@ ScopedJavaLocalRef<jstring> ConvertToNormalizedJstring(base::StringPiece text,
ScopedJavaLocalRef<jobject> java_byte_buffer(
env,
env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
+ base::android::CheckException(env);
base::android::ScopedJavaLocalRef<jstring> java_charset =
base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
ScopedJavaLocalRef<jstring> java_result =
@@ -58,6 +60,7 @@ ScopedJavaLocalRef<jstring> ConvertToJstringWithSubstitutions(
ScopedJavaLocalRef<jobject> java_byte_buffer(
env,
env->NewDirectByteBuffer(const_cast<char*>(text.data()), text.length()));
+ base::android::CheckException(env);
base::android::ScopedJavaLocalRef<jstring> java_charset =
base::android::ConvertUTF8ToJavaString(env, base::StringPiece(charset));
ScopedJavaLocalRef<jstring> java_result =
diff --git a/chromium/net/base/network_change_notifier.cc b/chromium/net/base/network_change_notifier.cc
index be3a2578921..f57e96cf621 100644
--- a/chromium/net/base/network_change_notifier.cc
+++ b/chromium/net/base/network_change_notifier.cc
@@ -9,11 +9,11 @@
#include <unordered_set>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_checker.h"
diff --git a/chromium/net/base/network_change_notifier_fuchsia_unittest.cc b/chromium/net/base/network_change_notifier_fuchsia_unittest.cc
index 4c3eb222324..893bfa74836 100644
--- a/chromium/net/base/network_change_notifier_fuchsia_unittest.cc
+++ b/chromium/net/base/network_change_notifier_fuchsia_unittest.cc
@@ -78,9 +78,9 @@ std::vector<T> MakeSingleItemVec(T item) {
fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
fuchsia::hardware::network::DeviceClass device_class =
- fuchsia::hardware::network::DeviceClass::UNKNOWN) {
- // For most tests a live interface with an IPv4 address and an unknown class
- // is sufficient.
+ fuchsia::hardware::network::DeviceClass::ETHERNET) {
+ // For most tests a live interface with an IPv4 address and ethernet class is
+ // sufficient.
fuchsia::net::interfaces::Properties interface;
interface.set_id(kDefaultInterfaceId);
interface.set_online(true);
@@ -94,15 +94,15 @@ fuchsia::net::interfaces::Properties DefaultInterfaceProperties(
}
fuchsia::net::interfaces::Properties SecondaryInterfaceProperties() {
- // For most tests a live interface with an IPv4 address and an unknown class
- // is sufficient.
+ // For most tests a live interface with an IPv4 address and ethernet class is
+ // sufficient.
fuchsia::net::interfaces::Properties interface;
interface.set_id(kSecondaryInterfaceId);
interface.set_online(true);
interface.set_has_default_ipv4_route(false);
interface.set_has_default_ipv6_route(false);
interface.set_device_class(fuchsia::net::interfaces::DeviceClass::WithDevice(
- fuchsia::hardware::network::DeviceClass::UNKNOWN));
+ fuchsia::hardware::network::DeviceClass::ETHERNET));
interface.set_addresses(MakeSingleItemVec(
InterfaceAddressFrom(kSecondaryIPv4Address, kSecondaryIPv4Prefix)));
return interface;
@@ -240,13 +240,13 @@ class ResultReceiver {
};
// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
-class FakeConnectionTypeObserver
+class FakeConnectionTypeObserver final
: public NetworkChangeNotifier::ConnectionTypeObserver {
public:
FakeConnectionTypeObserver() {
NetworkChangeNotifier::AddConnectionTypeObserver(this);
}
- ~FakeConnectionTypeObserver() final {
+ ~FakeConnectionTypeObserver() override {
NetworkChangeNotifier::RemoveConnectionTypeObserver(this);
}
@@ -257,7 +257,7 @@ class FakeConnectionTypeObserver
// ConnectionTypeObserver implementation.
void OnConnectionTypeChanged(
- NetworkChangeNotifier::ConnectionType type) final {
+ NetworkChangeNotifier::ConnectionType type) override {
receiver_.AddEntry(type);
}
@@ -266,13 +266,13 @@ class FakeConnectionTypeObserver
};
// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
-class FakeNetworkChangeObserver
+class FakeNetworkChangeObserver final
: public NetworkChangeNotifier::NetworkChangeObserver {
public:
FakeNetworkChangeObserver() {
NetworkChangeNotifier::AddNetworkChangeObserver(this);
}
- ~FakeNetworkChangeObserver() final {
+ ~FakeNetworkChangeObserver() override {
NetworkChangeNotifier::RemoveNetworkChangeObserver(this);
}
@@ -282,7 +282,7 @@ class FakeNetworkChangeObserver
}
// NetworkChangeObserver implementation.
- void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) final {
+ void OnNetworkChanged(NetworkChangeNotifier::ConnectionType type) override {
receiver_.AddEntry(type);
}
@@ -291,10 +291,11 @@ class FakeNetworkChangeObserver
};
// Accumulates the list of ConnectionTypes notified via OnConnectionTypeChanged.
-class FakeIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
+class FakeIPAddressObserver final
+ : public NetworkChangeNotifier::IPAddressObserver {
public:
FakeIPAddressObserver() { NetworkChangeNotifier::AddIPAddressObserver(this); }
- ~FakeIPAddressObserver() final {
+ ~FakeIPAddressObserver() override {
NetworkChangeNotifier::RemoveIPAddressObserver(this);
EXPECT_EQ(ip_change_count_, 0u);
}
@@ -312,7 +313,7 @@ class FakeIPAddressObserver : public NetworkChangeNotifier::IPAddressObserver {
}
// IPAddressObserver implementation.
- void OnIPAddressChanged() final {
+ void OnIPAddressChanged() override {
ip_change_count_++;
if (quit_loop_ && ip_change_count_ >= expected_count_)
std::move(quit_loop_).Run();
@@ -433,7 +434,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, NoChange) {
// Set a live interface with an IP address and create the notifier.
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
// Push an event with no side-effects.
watcher_.PushEvent(MakeChangeEvent(kDefaultInterfaceId, [](auto*) {}));
@@ -476,7 +477,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPNoChange) {
TEST_F(NetworkChangeNotifierFuchsiaTest, IpChange) {
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(MakeChangeEvent(
@@ -495,7 +496,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, IpChangeV6) {
InterfaceAddressFrom(kDefaultIPv6Address, kDefaultIPv6Prefix)));
watcher_.SetInitial(std::move(props));
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(MakeChangeEvent(
@@ -515,7 +516,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
watcher_.SetInitial(std::move(props));
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(MakeChangeEvent(
@@ -535,7 +536,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, MultiV6IPChanged) {
TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(MakeChangeEvent(
@@ -555,7 +556,7 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, Ipv6AdditionalIpChange) {
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDown) {
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(MakeChangeEvent(
@@ -582,14 +583,14 @@ TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceUp) {
}));
EXPECT_TRUE(type_observer_->RunAndExpectConnectionTypes(
- {NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN}));
+ {NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET}));
EXPECT_TRUE(ip_observer_->RunAndExpectCallCount(1));
}
TEST_F(NetworkChangeNotifierFuchsiaTest, InterfaceDeleted) {
watcher_.SetInitial(DefaultInterfaceProperties());
CreateNotifier();
- EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
+ EXPECT_EQ(NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET,
notifier_->GetCurrentConnectionType());
watcher_.PushEvent(
diff --git a/chromium/net/base/network_config_watcher_mac.cc b/chromium/net/base/network_config_watcher_mac.cc
index a73f7a52666..85020208f9d 100644
--- a/chromium/net/base/network_config_watcher_mac.cc
+++ b/chromium/net/base/network_config_watcher_mac.cc
@@ -164,7 +164,6 @@ NetworkConfigWatcherMacThread::~NetworkConfigWatcherMacThread() {
}
void NetworkConfigWatcherMacThread::Init() {
- base::ThreadRestrictions::SetIOAllowed(true);
delegate_->Init();
// TODO(willchan): Look to see if there's a better signal for when it's ok to
diff --git a/chromium/net/base/network_delegate.cc b/chromium/net/base/network_delegate.cc
index 2f352781bc0..bd7e5dfdcca 100644
--- a/chromium/net/base/network_delegate.cc
+++ b/chromium/net/base/network_delegate.cc
@@ -7,10 +7,12 @@
#include <utility>
#include "base/logging.h"
+#include "base/ranges/algorithm.h"
#include "base/trace_event/trace_event.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/trace_constants.h"
+#include "net/cookies/cookie_util.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/url_request/url_request.h"
@@ -35,14 +37,13 @@ int NetworkDelegate::NotifyBeforeURLRequest(URLRequest* request,
int NetworkDelegate::NotifyBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
TRACE_EVENT0(NetTracingCategory(),
"NetworkDelegate::NotifyBeforeStartTransation");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(headers);
DCHECK(!callback.is_null());
- return OnBeforeStartTransaction(request, std::move(callback), headers);
+ return OnBeforeStartTransaction(request, headers, std::move(callback));
}
int NetworkDelegate::NotifyHeadersReceived(
@@ -100,11 +101,18 @@ void NetworkDelegate::NotifyPACScriptError(int line_number,
OnPACScriptError(line_number, error);
}
-bool NetworkDelegate::CanGetCookies(const URLRequest& request,
- bool allowed_from_caller) {
+bool NetworkDelegate::AnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
DCHECK_EQ(PrivacyMode::PRIVACY_MODE_DISABLED, request.privacy_mode());
- return OnCanGetCookies(request, allowed_from_caller);
+ bool allowed = OnAnnotateAndMoveUserBlockedCookies(
+ request, maybe_included_cookies, excluded_cookies, allowed_from_caller);
+ cookie_util::DCheckIncludedAndExcludedCookieLists(maybe_included_cookies,
+ excluded_cookies);
+ return allowed;
}
bool NetworkDelegate::CanSetCookie(const URLRequest& request,
@@ -119,10 +127,12 @@ bool NetworkDelegate::CanSetCookie(const URLRequest& request,
bool NetworkDelegate::ForcePrivacyMode(
const GURL& url,
const SiteForCookies& site_for_cookies,
- const absl::optional<url::Origin>& top_frame_origin) const {
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const {
TRACE_EVENT0(NetTracingCategory(), "NetworkDelegate::ForcePrivacyMode");
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- return OnForcePrivacyMode(url, site_for_cookies, top_frame_origin);
+ return OnForcePrivacyMode(url, site_for_cookies, top_frame_origin,
+ same_party_context_type);
}
bool NetworkDelegate::CancelURLRequestWithPolicyViolatingReferrerHeader(
@@ -158,4 +168,33 @@ bool NetworkDelegate::CanUseReportingClient(const url::Origin& origin,
return OnCanUseReportingClient(origin, endpoint);
}
+// static
+void NetworkDelegate::ExcludeAllCookies(
+ net::CookieInclusionStatus::ExclusionReason reason,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies) {
+ excluded_cookies.insert(
+ excluded_cookies.end(),
+ std::make_move_iterator(maybe_included_cookies.begin()),
+ std::make_move_iterator(maybe_included_cookies.end()));
+ maybe_included_cookies.clear();
+ // Add the ExclusionReason for all cookies.
+ for (net::CookieWithAccessResult& cookie : excluded_cookies) {
+ cookie.access_result.status.AddExclusionReason(reason);
+ }
+}
+
+// static
+void NetworkDelegate::MoveExcludedCookies(
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies) {
+ const auto to_be_moved = base::ranges::stable_partition(
+ maybe_included_cookies, [](const CookieWithAccessResult& cookie) {
+ return cookie.access_result.status.IsInclude();
+ });
+ excluded_cookies.insert(
+ excluded_cookies.end(), std::make_move_iterator(to_be_moved),
+ std::make_move_iterator(maybe_included_cookies.end()));
+ maybe_included_cookies.erase(to_be_moved, maybe_included_cookies.end());
+}
} // namespace net
diff --git a/chromium/net/base/network_delegate.h b/chromium/net/base/network_delegate.h
index d2427fb3313..54c57c9609b 100644
--- a/chromium/net/base/network_delegate.h
+++ b/chromium/net/base/network_delegate.h
@@ -16,6 +16,8 @@
#include "net/base/completion_once_callback.h"
#include "net/base/net_export.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_inclusion_status.h"
+#include "net/cookies/same_party_context.h"
#include "net/cookies/site_for_cookies.h"
#include "net/proxy_resolution/proxy_retry_info.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -55,9 +57,11 @@ class NET_EXPORT NetworkDelegate {
int NotifyBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url);
+ using OnBeforeStartTransactionCallback =
+ base::OnceCallback<void(int, const absl::optional<HttpRequestHeaders>&)>;
int NotifyBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers);
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback);
int NotifyHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
@@ -71,16 +75,19 @@ class NET_EXPORT NetworkDelegate {
void NotifyCompleted(URLRequest* request, bool started, int net_error);
void NotifyURLRequestDestroyed(URLRequest* request);
void NotifyPACScriptError(int line_number, const std::u16string& error);
- bool CanGetCookies(const URLRequest& request,
- bool allowed_from_caller);
+ bool AnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ CookieAccessResultList& maybe_included_cookies,
+ CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller);
bool CanSetCookie(const URLRequest& request,
const net::CanonicalCookie& cookie,
CookieOptions* options,
bool allowed_from_caller);
- bool ForcePrivacyMode(
- const GURL& url,
- const SiteForCookies& site_for_cookies,
- const absl::optional<url::Origin>& top_frame_origin) const;
+ bool ForcePrivacyMode(const GURL& url,
+ const SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const;
bool CancelURLRequestWithPolicyViolatingReferrerHeader(
const URLRequest& request,
@@ -97,9 +104,25 @@ class NET_EXPORT NetworkDelegate {
const GURL& endpoint) const;
protected:
+ // Adds the given ExclusionReason to all cookies in
+ // `mayble_included_cookies`, and moves the contents of
+ // `maybe_included_cookies` to `excluded_cookies`.
+ static void ExcludeAllCookies(
+ net::CookieInclusionStatus::ExclusionReason reason,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies);
+
+ // Moves any cookie in `maybe_included_cookies` that has an ExclusionReason
+ // into `excluded_cookies`.
+ static void MoveExcludedCookies(
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies);
+
THREAD_CHECKER(thread_checker_);
private:
+ FRIEND_TEST_ALL_PREFIXES(NetworkDelegateTest, ExcludeAllCookies);
+ FRIEND_TEST_ALL_PREFIXES(NetworkDelegateTest, MoveExcludedCookies);
// This is the interface for subclasses of NetworkDelegate to implement. These
// member functions will be called by the respective public notification
// member function, which will perform basic sanity checking.
@@ -132,7 +155,8 @@ class NET_EXPORT NetworkDelegate {
GURL* new_url) = 0;
// Called right before the network transaction starts. Allows the delegate to
- // read/write |headers| before they get sent out.
+ // read |headers| and modify them by passing a new copy to |callback| before
+ // they get sent out.
//
// Returns OK to continue with the request, ERR_IO_PENDING if the result is
// not ready yet, and any other status code to cancel the request. If
@@ -141,11 +165,11 @@ class NET_EXPORT NetworkDelegate {
// or OnCompleted. Once cancelled, |request| and |headers| become invalid and
// |callback| may not be called.
//
- // The default implementation returns OK (continue with request) without
- // modifying |headers|.
- virtual int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) = 0;
+ // The default implementation returns OK (continue with request).
+ virtual int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) = 0;
// Called for HTTP requests when the headers have been received.
// |original_response_headers| contains the headers as received over the
@@ -198,13 +222,17 @@ class NET_EXPORT NetworkDelegate {
const std::u16string& error) = 0;
// Called when reading cookies to allow the network delegate to block access
- // to the cookie. This method will never be invoked when
- // LOAD_DO_NOT_SEND_COOKIES is specified.
- // The |allowed_from_caller| param is used to pass whether this operation is
- // allowed from any higher level delegates (for example, in a
- // LayeredNetworkDelegate). Any custom logic should be ANDed with this bool.
- virtual bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) = 0;
+ // to individual cookies, by adding the appropriate ExclusionReason and moving
+ // them to the `excluded_cookies` list. This method will never be invoked
+ // when LOAD_DO_NOT_SEND_COOKIES is specified.
+ //
+ // Returns false if the delegate has blocked access to all cookies; true
+ // otherwise.
+ virtual bool OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) = 0;
// Called when a cookie is set to allow the network delegate to block access
// to the cookie. This method will never be invoked when
@@ -223,7 +251,8 @@ class NET_EXPORT NetworkDelegate {
virtual bool OnForcePrivacyMode(
const GURL& url,
const SiteForCookies& site_for_cookies,
- const absl::optional<url::Origin>& top_frame_origin) const = 0;
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_cookie_context_type) const = 0;
// Called when the |referrer_url| for requesting |target_url| during handling
// of the |request| is does not comply with the referrer policy (e.g. a
diff --git a/chromium/net/base/network_delegate_impl.cc b/chromium/net/base/network_delegate_impl.cc
index fedbd3c892a..6227858c3c2 100644
--- a/chromium/net/base/network_delegate_impl.cc
+++ b/chromium/net/base/network_delegate_impl.cc
@@ -5,6 +5,7 @@
#include "net/base/network_delegate_impl.h"
#include "net/base/net_errors.h"
+#include "net/cookies/same_party_context.h"
namespace net {
@@ -16,8 +17,8 @@ int NetworkDelegateImpl::OnBeforeURLRequest(URLRequest* request,
int NetworkDelegateImpl::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
return OK;
}
@@ -47,8 +48,14 @@ void NetworkDelegateImpl::OnURLRequestDestroyed(URLRequest* request) {
void NetworkDelegateImpl::OnPACScriptError(int line_number,
const std::u16string& error) {}
-bool NetworkDelegateImpl::OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) {
+bool NetworkDelegateImpl::OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) {
+ if (!allowed_from_caller)
+ ExcludeAllCookies(CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
+ maybe_included_cookies, excluded_cookies);
return allowed_from_caller;
}
@@ -62,7 +69,8 @@ bool NetworkDelegateImpl::OnCanSetCookie(const URLRequest& request,
bool NetworkDelegateImpl::OnForcePrivacyMode(
const GURL& url,
const SiteForCookies& site_for_cookies,
- const absl::optional<url::Origin>& top_frame_origin) const {
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const {
return false;
}
diff --git a/chromium/net/base/network_delegate_impl.h b/chromium/net/base/network_delegate_impl.h
index 4acc13af8e4..08b13d323bb 100644
--- a/chromium/net/base/network_delegate_impl.h
+++ b/chromium/net/base/network_delegate_impl.h
@@ -14,6 +14,7 @@
#include "net/base/net_export.h"
#include "net/base/network_delegate.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/same_party_context.h"
#include "net/proxy_resolution/proxy_retry_info.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -32,16 +33,20 @@ class URLRequest;
class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
public:
- ~NetworkDelegateImpl() override {}
+ NetworkDelegateImpl() = default;
+ NetworkDelegateImpl(const NetworkDelegateImpl&) = delete;
+ NetworkDelegateImpl& operator=(const NetworkDelegateImpl&) = delete;
+ ~NetworkDelegateImpl() override = default;
private:
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
@@ -61,8 +66,11 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
void OnPACScriptError(int line_number, const std::u16string& error) override;
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override;
+ bool OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) override;
bool OnCanSetCookie(const URLRequest& request,
const net::CanonicalCookie& cookie,
@@ -72,7 +80,8 @@ class NET_EXPORT NetworkDelegateImpl : public NetworkDelegate {
bool OnForcePrivacyMode(
const GURL& url,
const SiteForCookies& site_for_cookies,
- const absl::optional<url::Origin>& top_frame_origin) const override;
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const override;
bool OnCancelURLRequestWithPolicyViolatingReferrerHeader(
const URLRequest& request,
diff --git a/chromium/net/base/network_delegate_unittest.cc b/chromium/net/base/network_delegate_unittest.cc
new file mode 100644
index 00000000000..f9fcf8a0f0b
--- /dev/null
+++ b/chromium/net/base/network_delegate_unittest.cc
@@ -0,0 +1,129 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/base/network_delegate.h"
+
+#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/canonical_cookie_test_helpers.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+using testing::_;
+using testing::ElementsAre;
+using testing::IsEmpty;
+using testing::UnorderedElementsAre;
+
+namespace {
+
+constexpr char kURL[] = "example.test";
+
+CanonicalCookie MakeCookie(const std::string& name) {
+ return *CanonicalCookie::CreateUnsafeCookieForTesting(
+ name, "value", kURL, "/" /* path */, base::Time() /* creation */,
+ base::Time() /* expiration */, base::Time() /* last_access */,
+ true /* secure */, false /* httponly */, CookieSameSite::UNSPECIFIED,
+ CookiePriority::COOKIE_PRIORITY_DEFAULT, false /* same_party */);
+}
+
+CookieAccessResult Include() {
+ return {};
+}
+
+CookieAccessResult Exclude(CookieInclusionStatus::ExclusionReason reason) {
+ return CookieAccessResult(CookieInclusionStatus(reason));
+}
+
+} // namespace
+
+TEST(NetworkDelegateTest, ExcludeAllCookies) {
+ CookieAccessResultList maybe_included_cookies = {
+ {MakeCookie("1"), Include()}, {MakeCookie("2"), Include()}};
+
+ CookieAccessResultList excluded_cookies = {
+ {MakeCookie("3"),
+ Exclude(CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY)}};
+
+ NetworkDelegate::ExcludeAllCookies(
+ CookieInclusionStatus::ExclusionReason::EXCLUDE_USER_PREFERENCES,
+ maybe_included_cookies, excluded_cookies);
+
+ EXPECT_THAT(maybe_included_cookies, IsEmpty());
+ EXPECT_THAT(
+ excluded_cookies,
+ UnorderedElementsAre(
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("1"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("2"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("3"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_SECURE_ONLY,
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_USER_PREFERENCES}),
+ _, _, _))));
+}
+
+TEST(NetworkDelegateTest, MoveExcludedCookies) {
+ CookieAccessResultList maybe_included_cookies = {
+ {MakeCookie("1"), Include()},
+ {MakeCookie("2"),
+ Exclude(CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY)},
+ {MakeCookie("3"), Include()}};
+
+ CookieAccessResultList excluded_cookies = {{
+ MakeCookie("4"),
+ Exclude(CookieInclusionStatus::ExclusionReason::EXCLUDE_SECURE_ONLY),
+ }};
+
+ NetworkDelegate::MoveExcludedCookies(maybe_included_cookies,
+ excluded_cookies);
+
+ EXPECT_THAT(
+ maybe_included_cookies,
+ ElementsAre(MatchesCookieWithAccessResult(
+ MatchesCookieWithName("1"),
+ MatchesCookieAccessResult(IsInclude(), _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("3"),
+ MatchesCookieAccessResult(IsInclude(), _, _, _))));
+ EXPECT_THAT(
+ excluded_cookies,
+ UnorderedElementsAre(
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("2"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_SECURE_ONLY}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("4"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::ExclusionReason::
+ EXCLUDE_SECURE_ONLY}),
+ _, _, _))));
+}
+
+} // namespace net
diff --git a/chromium/net/base/network_interfaces_fuchsia.h b/chromium/net/base/network_interfaces_fuchsia.h
index eb95adcd765..3a0d7e234fc 100644
--- a/chromium/net/base/network_interfaces_fuchsia.h
+++ b/chromium/net/base/network_interfaces_fuchsia.h
@@ -11,6 +11,7 @@
#include "net/base/network_change_notifier.h"
#include "net/base/network_interfaces.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
namespace internal {
diff --git a/chromium/net/base/network_interfaces_linux_unittest.cc b/chromium/net/base/network_interfaces_linux_unittest.cc
index fe1984b22c8..ae026c2c7c3 100644
--- a/chromium/net/base/network_interfaces_linux_unittest.cc
+++ b/chromium/net/base/network_interfaces_linux_unittest.cc
@@ -11,7 +11,7 @@
#include <string>
#include <unordered_set>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "net/base/address_tracker_linux.h"
diff --git a/chromium/net/base/network_interfaces_unittest.cc b/chromium/net/base/network_interfaces_unittest.cc
index 145edf3efad..afd34188b5a 100644
--- a/chromium/net/base/network_interfaces_unittest.cc
+++ b/chromium/net/base/network_interfaces_unittest.cc
@@ -16,6 +16,8 @@
#if defined(OS_POSIX) && !defined(OS_ANDROID)
#include <net/if.h>
#elif defined(OS_WIN)
+#include <windows.h>
+
#include <iphlpapi.h>
#include <objbase.h>
#include "base/strings/string_util.h"
diff --git a/chromium/net/base/network_interfaces_win.cc b/chromium/net/base/network_interfaces_win.cc
index ceb459aa01a..f870733f12a 100644
--- a/chromium/net/base/network_interfaces_win.cc
+++ b/chromium/net/base/network_interfaces_win.cc
@@ -9,7 +9,6 @@
#include "base/files/file_path.h"
#include "base/lazy_instance.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
diff --git a/chromium/net/base/network_isolation_key.cc b/chromium/net/base/network_isolation_key.cc
index 09528d96cd3..e891bf68f57 100644
--- a/chromium/net/base/network_isolation_key.cc
+++ b/chromium/net/base/network_isolation_key.cc
@@ -4,9 +4,11 @@
#include <string>
+#include "base/unguessable_token.h"
#include "base/values.h"
#include "net/base/network_isolation_key.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
#include "url/url_constants.h"
@@ -22,16 +24,20 @@ std::string GetSiteDebugString(const absl::optional<SchemefulSite>& site) {
} // namespace
NetworkIsolationKey::NetworkIsolationKey(const SchemefulSite& top_frame_site,
- const SchemefulSite& frame_site)
+ const SchemefulSite& frame_site,
+ const base::UnguessableToken* nonce)
: NetworkIsolationKey(SchemefulSite(top_frame_site),
SchemefulSite(frame_site),
- false /* opaque_and_non_transient */) {}
+ false /* opaque_and_non_transient */,
+ nonce) {}
NetworkIsolationKey::NetworkIsolationKey(SchemefulSite&& top_frame_site,
- SchemefulSite&& frame_site)
+ SchemefulSite&& frame_site,
+ const base::UnguessableToken* nonce)
: NetworkIsolationKey(std::move(top_frame_site),
std::move(frame_site),
- false /* opaque_and_non_transient */) {}
+ false /* opaque_and_non_transient */,
+ nonce) {}
NetworkIsolationKey::NetworkIsolationKey(const url::Origin& top_frame_origin,
const url::Origin& frame_origin)
@@ -63,7 +69,8 @@ NetworkIsolationKey NetworkIsolationKey::CreateOpaqueAndNonTransient() {
SchemefulSite site_with_opaque_origin;
return NetworkIsolationKey(SchemefulSite(site_with_opaque_origin),
SchemefulSite(site_with_opaque_origin),
- true /* opaque_and_non_transient */);
+ true /* opaque_and_non_transient */,
+ nullptr /* nonce */);
}
NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite(
@@ -72,14 +79,10 @@ NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameSite(
return NetworkIsolationKey();
NetworkIsolationKey key(top_frame_site_.value(), new_frame_site);
key.opaque_and_non_transient_ = opaque_and_non_transient_;
+ key.nonce_ = nonce_;
return key;
}
-NetworkIsolationKey NetworkIsolationKey::CreateWithNewFrameOrigin(
- const url::Origin& new_frame_origin) const {
- return CreateWithNewFrameSite(SchemefulSite(new_frame_origin));
-}
-
std::string NetworkIsolationKey::ToString() const {
if (IsTransient())
return "";
@@ -114,6 +117,10 @@ std::string NetworkIsolationKey::ToDebugString() const {
return_string += " non-transient";
}
+ if (nonce_.has_value()) {
+ return_string += " (with nonce " + nonce_->ToString() + ")";
+ }
+
return return_string;
}
@@ -200,16 +207,22 @@ bool NetworkIsolationKey::IsEmpty() const {
NetworkIsolationKey::NetworkIsolationKey(SchemefulSite&& top_frame_site,
SchemefulSite&& frame_site,
- bool opaque_and_non_transient)
+ bool opaque_and_non_transient,
+ const base::UnguessableToken* nonce)
: opaque_and_non_transient_(opaque_and_non_transient),
top_frame_site_(std::move(top_frame_site)),
- frame_site_(std::move(frame_site)) {
+ frame_site_(std::move(frame_site)),
+ nonce_(nonce ? absl::make_optional(*nonce) : absl::nullopt) {
DCHECK(!opaque_and_non_transient || top_frame_site_->opaque());
DCHECK(!opaque_and_non_transient || frame_site.opaque());
+ DCHECK(!nonce || !nonce->is_empty());
+ // If there is a nonce, this is always transient.
+ DCHECK(!nonce || !opaque_and_non_transient);
}
bool NetworkIsolationKey::IsOpaque() const {
- return top_frame_site_->opaque() || frame_site_->opaque();
+ return top_frame_site_->opaque() || frame_site_->opaque() ||
+ nonce_.has_value();
}
absl::optional<std::string> NetworkIsolationKey::SerializeSiteWithNonce(
diff --git a/chromium/net/base/network_isolation_key.h b/chromium/net/base/network_isolation_key.h
index 855746ee616..167b8d2cf34 100644
--- a/chromium/net/base/network_isolation_key.h
+++ b/chromium/net/base/network_isolation_key.h
@@ -8,12 +8,15 @@
#include <string>
#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "base/values.h"
+#include "base/unguessable_token.h"
#include "net/base/net_export.h"
#include "net/base/schemeful_site.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+namespace base {
+class Value;
+}
+
namespace network {
namespace mojom {
class NetworkIsolationKeyDataView;
@@ -38,11 +41,13 @@ class NET_EXPORT NetworkIsolationKey {
// Full constructor. When a request is initiated by the top frame, it must
// also populate the |frame_site| parameter when calling this constructor.
NetworkIsolationKey(const SchemefulSite& top_frame_site,
- const SchemefulSite& frame_site);
+ const SchemefulSite& frame_site,
+ const base::UnguessableToken* nonce = nullptr);
// Alternative constructor that takes ownership of arguments, to save copies.
NetworkIsolationKey(SchemefulSite&& top_frame_site,
- SchemefulSite&& frame_site);
+ SchemefulSite&& frame_site,
+ const base::UnguessableToken* nonce = nullptr);
// Legacy constructor.
// TODO(https://crbug.com/1145294): Remove this in favor of above
@@ -77,18 +82,6 @@ class NET_EXPORT NetworkIsolationKey {
NetworkIsolationKey CreateWithNewFrameSite(
const SchemefulSite& new_frame_site) const;
- // Creates a new key using |top_frame_site_| and |new_frame_origin|.
- // TODO(https://crbug.com/1145294): Remove this in favor of above method.
- NetworkIsolationKey CreateWithNewFrameOrigin(
- const url::Origin& new_frame_origin) const;
-
- // Intended for temporary use in locations that should be using a non-empty
- // NetworkIsolationKey(), but are not yet. This both reduces the chance of
- // accidentally copying the lack of a NIK where one should be used, and
- // provides a reasonable way of locating callsites that need to have their
- // NetworkIsolationKey filled in.
- static NetworkIsolationKey Todo() { return NetworkIsolationKey(); }
-
// Intended for temporary use in locations that should be using main frame and
// frame origin, but are currently only using frame origin, because the
// creating object may be shared across main frame objects. Having a special
@@ -102,9 +95,10 @@ class NET_EXPORT NetworkIsolationKey {
// Compare keys for equality, true if all enabled fields are equal.
bool operator==(const NetworkIsolationKey& other) const {
- return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_) ==
+ return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_,
+ nonce_) ==
std::tie(other.top_frame_site_, other.frame_site_,
- other.opaque_and_non_transient_);
+ other.opaque_and_non_transient_, other.nonce_);
}
// Compare keys for inequality, true if any enabled field varies.
@@ -114,9 +108,10 @@ class NET_EXPORT NetworkIsolationKey {
// Provide an ordering for keys based on all enabled fields.
bool operator<(const NetworkIsolationKey& other) const {
- return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_) <
- std::tie(other.top_frame_site_, other.frame_site_,
- other.opaque_and_non_transient_);
+ return std::tie(top_frame_site_, frame_site_, opaque_and_non_transient_,
+ nonce_) < std::tie(other.top_frame_site_, other.frame_site_,
+ other.opaque_and_non_transient_,
+ other.nonce_);
}
// Returns the string representation of the key, which is the string
@@ -145,6 +140,11 @@ class NET_EXPORT NetworkIsolationKey {
return frame_site_;
}
+ // Getter for the nonce.
+ const absl::optional<base::UnguessableToken>& GetNonce() const {
+ return nonce_;
+ }
+
// Returns true if all parts of the key are empty.
bool IsEmpty() const;
@@ -169,8 +169,10 @@ class NET_EXPORT NetworkIsolationKey {
NetworkIsolationKey(SchemefulSite&& top_frame_site,
SchemefulSite&& frame_site,
- bool opaque_and_non_transient);
+ bool opaque_and_non_transient,
+ const base::UnguessableToken* nonce);
+ // Whether this key has opaque origins or a nonce.
bool IsOpaque() const;
// SchemefulSite::Serialize() is not const, as it may initialize the nonce.
@@ -187,6 +189,10 @@ class NET_EXPORT NetworkIsolationKey {
// The origin/etld+1 of the frame that initiates the request.
absl::optional<SchemefulSite> frame_site_;
+
+ // Having a nonce is a way to force a transient opaque `NetworkIsolationKey`
+ // for non-opaque origins.
+ absl::optional<base::UnguessableToken> nonce_;
};
} // namespace net
diff --git a/chromium/net/base/network_isolation_key_unittest.cc b/chromium/net/base/network_isolation_key_unittest.cc
index 5b558e2382c..6d6562edaa1 100644
--- a/chromium/net/base/network_isolation_key_unittest.cc
+++ b/chromium/net/base/network_isolation_key_unittest.cc
@@ -4,7 +4,8 @@
#include "net/base/network_isolation_key.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
+#include "base/unguessable_token.h"
#include "base/values.h"
#include "net/base/schemeful_site.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -38,6 +39,31 @@ TEST(NetworkIsolationKeyTest, NonEmptyKey) {
key.ToDebugString());
}
+TEST(NetworkIsolationKeyTest, KeyWithNonce) {
+ SchemefulSite site1 = SchemefulSite(GURL("http://a.test/"));
+ SchemefulSite site2 = SchemefulSite(GURL("http://b.test/"));
+ base::UnguessableToken nonce = base::UnguessableToken::Create();
+ NetworkIsolationKey key(site1, site2, &nonce);
+ EXPECT_TRUE(key.IsFullyPopulated());
+ EXPECT_EQ("", key.ToString());
+ EXPECT_TRUE(key.IsTransient());
+ EXPECT_EQ(site1.GetDebugString() + " " + site2.GetDebugString() +
+ " (with nonce " + nonce.ToString() + ")",
+ key.ToDebugString());
+
+ // Create another NetworkIsolationKey with the same input parameters, and
+ // check that it is equal.
+ NetworkIsolationKey same_key(site1, site2, &nonce);
+ EXPECT_EQ(key, same_key);
+
+ // Create another NetworkIsolationKey with a different nonce and check that
+ // it's different.
+ base::UnguessableToken nonce2 = base::UnguessableToken::Create();
+ NetworkIsolationKey key2(site1, site2, &nonce2);
+ EXPECT_NE(key, key2);
+ EXPECT_NE(key.ToDebugString(), key2.ToDebugString());
+}
+
TEST(NetworkIsolationKeyTest, OpaqueOriginKey) {
SchemefulSite site_data = SchemefulSite(GURL(kDataUrl));
NetworkIsolationKey key(site_data, site_data);
@@ -54,6 +80,10 @@ TEST(NetworkIsolationKeyTest, OpaqueOriginKey) {
}
TEST(NetworkIsolationKeyTest, Operators) {
+ base::UnguessableToken nonce1 = base::UnguessableToken::Create();
+ base::UnguessableToken nonce2 = base::UnguessableToken::Create();
+ if (nonce2 < nonce1)
+ std::swap(nonce1, nonce2);
// These are in ascending order.
const NetworkIsolationKey kKeys[] = {
NetworkIsolationKey(),
@@ -69,6 +99,10 @@ TEST(NetworkIsolationKeyTest, Operators) {
SchemefulSite(GURL("http://b.test/"))),
NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
SchemefulSite(GURL("https://a.test/"))),
+ NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
+ SchemefulSite(GURL("https://a.test/")), &nonce1),
+ NetworkIsolationKey(SchemefulSite(GURL("https://a.test/")),
+ SchemefulSite(GURL("https://a.test/")), &nonce2),
};
for (size_t first = 0; first < base::size(kKeys); ++first) {
diff --git a/chromium/net/base/port_util.cc b/chromium/net/base/port_util.cc
index 30518235a5b..d011599d865 100644
--- a/chromium/net/base/port_util.cc
+++ b/chromium/net/base/port_util.cc
@@ -20,45 +20,33 @@ namespace net {
namespace {
-// Records ports newly blocked in https://github.com/whatwg/fetch/pull/1148 for
-// "NAT Slipstreaming v2.0" vulnerability, plus 10080, to measure the breakage
-// from blocking them. Every other port is logged as kOther to provide a
-// baseline. See also https://samy.pl/slipstream/. Ports are logged regardless
-// of protocol and whether they are blocked or not.
-// TODO(ricea): Remove this in April 2021.
-void LogSlipstreamRestrictedPort(int port) {
- // These values are persisted to logs. Entries should not be renumbered and
- // numeric values should never be reused.
- enum class SlipstreamPort {
- kOther = 0,
- k69 = 1,
- k137 = 2,
- k161 = 3,
- k554 = 4,
- k1719 = 5,
- k1720 = 6,
- k1723 = 7,
- k6566 = 8,
- k10080 = 9,
- kMaxValue = k10080,
+// Records ports that may need blocking to mitigate the ALPACA vulnerability.
+// See https://alpaca-attack.com/ and https://github.com/whatwg/fetch/pull/1250.
+void LogAlpacaPort(int port) {
+ // Unlike the obsolete Net.Port.SlipStreamRestricted histogram, we don't
+ // record an "Other" category. Instead, historical data from
+ // Net.Port.SlipStreamRestricted can be used as a baseline for comparisons.
+ enum class AlpacaPort {
+ k26 = 0,
+ k989 = 1,
+ k990 = 2,
+ k2525 = 3,
+ kMaxValue = k2525,
};
- constexpr auto kMap = base::MakeFixedFlatMap<int, SlipstreamPort>({
- {69, SlipstreamPort::k69},
- {137, SlipstreamPort::k137},
- {161, SlipstreamPort::k161},
- {554, SlipstreamPort::k554},
- {1719, SlipstreamPort::k1719},
- {1720, SlipstreamPort::k1720},
- {1723, SlipstreamPort::k1723},
- {6566, SlipstreamPort::k6566},
- {10080, SlipstreamPort::k10080},
- });
-
- auto* it = kMap.find(port);
- SlipstreamPort as_enum =
- it == kMap.end() ? SlipstreamPort::kOther : it->second;
- base::UmaHistogramEnumeration("Net.Port.SlipstreamRestricted", as_enum);
+ constexpr std::pair<int, AlpacaPort> kMap[] = {
+ {26, AlpacaPort::k26},
+ {989, AlpacaPort::k989},
+ {990, AlpacaPort::k990},
+ {2525, AlpacaPort::k2525},
+ };
+
+ for (const auto& pair : kMap) {
+ if (pair.first == port) {
+ base::UmaHistogramEnumeration("Net.Port.Alpaca", pair.second);
+ return;
+ }
+ }
}
// The general list of blocked ports. Will be blocked unless a specific
@@ -125,6 +113,8 @@ const int kRestrictedPorts[] = {
587, // smtp (rfc6409)
601, // syslog-conn (rfc3195)
636, // ldap+ssl
+ 989, // ftps-data
+ 990, // ftps
993, // ldap+ssl
995, // pop3+ssl
1719, // h323gatestat
@@ -158,6 +148,10 @@ base::LazyInstance<std::multiset<int>>::Leaky g_explicitly_allowed_ports =
constexpr int kAllowablePorts[] = {
// TODO(https://crbug.com/1199642) Remove port 554 around 2021/10/15.
554,
+ // TODO(https://crbug.com/1220079) Remove ports 989 and 990 around
+ // 2022/02/01.
+ 989,
+ 990,
// TODO(https://crbig.com/1210779) Remove port 6566 around 2021/08/12.
6566,
// TODO(https://crbug.com/1196846) Remove port 10080 around 2022/04/01.
@@ -181,7 +175,7 @@ bool IsPortAllowedForScheme(int port, base::StringPiece url_scheme) {
if (!IsPortValid(port))
return false;
- LogSlipstreamRestrictedPort(port);
+ LogAlpacaPort(port);
// Allow explicitly allowed ports for any scheme.
if (g_explicitly_allowed_ports.Get().count(port) > 0)
diff --git a/chromium/net/base/port_util_unittest.cc b/chromium/net/base/port_util_unittest.cc
index 58f60628613..ddf2b5abd21 100644
--- a/chromium/net/base/port_util_unittest.cc
+++ b/chromium/net/base/port_util_unittest.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/base/priority_queue_unittest.cc b/chromium/net/base/priority_queue_unittest.cc
index ab9726fcf22..88974bcefe2 100644
--- a/chromium/net/base/priority_queue_unittest.cc
+++ b/chromium/net/base/priority_queue_unittest.cc
@@ -7,7 +7,6 @@
#include <cstddef>
#include "base/bind.h"
-#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/base/proxy_server_unittest.cc b/chromium/net/base/proxy_server_unittest.cc
index a38f8603d49..32e7e52e9d8 100644
--- a/chromium/net/base/proxy_server_unittest.cc
+++ b/chromium/net/base/proxy_server_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "net/base/proxy_server.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/base/schemeful_site.cc b/chromium/net/base/schemeful_site.cc
index 59067609bcd..528c0a08831 100644
--- a/chromium/net/base/schemeful_site.cc
+++ b/chromium/net/base/schemeful_site.cc
@@ -137,6 +137,11 @@ std::string SchemefulSite::Serialize() const {
return site_as_origin_.Serialize();
}
+std::string SchemefulSite::SerializeFileSiteWithHost() const {
+ DCHECK_EQ(url::kFileScheme, site_as_origin_.scheme());
+ return site_as_origin_.GetTupleOrPrecursorTupleIfOpaque().Serialize();
+}
+
std::string SchemefulSite::GetDebugString() const {
return site_as_origin_.GetDebugString();
}
diff --git a/chromium/net/base/schemeful_site.h b/chromium/net/base/schemeful_site.h
index 37f917e9b87..1e209703507 100644
--- a/chromium/net/base/schemeful_site.h
+++ b/chromium/net/base/schemeful_site.h
@@ -95,6 +95,12 @@ class NET_EXPORT SchemefulSite {
// with their associated nonce is necessary, see `SerializeWithNonce()`.
std::string Serialize() const;
+ // Serializes `site_as_origin_` in cases when it has a 'file' scheme but
+ // we want to preserve the Origin's host.
+ // This was added to serialize cookie partition keys, which may contain
+ // file origins with a host.
+ std::string SerializeFileSiteWithHost() const;
+
std::string GetDebugString() const;
// Gets the underlying site as a GURL. If the internal Origin is opaque,
diff --git a/chromium/net/base/schemeful_site_unittest.cc b/chromium/net/base/schemeful_site_unittest.cc
index 669dc147c1f..3fb45b500f1 100644
--- a/chromium/net/base/schemeful_site_unittest.cc
+++ b/chromium/net/base/schemeful_site_unittest.cc
@@ -234,6 +234,39 @@ TEST(SchemefulSiteTest, SerializationConsistent) {
}
}
+TEST(SchemefulSiteTest, SerializationFileSiteWithHost) {
+ const struct {
+ SchemefulSite site;
+ std::string expected;
+ } kTestCases[] = {
+ {SchemefulSite(GURL("file:///etc/passwd")), "file://"},
+ {SchemefulSite(GURL("file://example.com/etc/passwd")),
+ "file://example.com"},
+ {SchemefulSite(GURL("file://example.com")), "file://example.com"},
+ };
+
+ for (const auto& test_case : kTestCases) {
+ SCOPED_TRACE(test_case.site.GetDebugString());
+ std::string serialized_site = test_case.site.SerializeFileSiteWithHost();
+ EXPECT_EQ(test_case.expected, serialized_site);
+ absl::optional<SchemefulSite> deserialized_site =
+ SchemefulSite::Deserialize(serialized_site);
+ EXPECT_TRUE(deserialized_site);
+ EXPECT_EQ(test_case.site, deserialized_site);
+ }
+}
+
+TEST(SchemefulSiteTest, FileURLWithHostEquality) {
+ // Two file URLs with different hosts should result in unequal SchemefulSites.
+ SchemefulSite site1(GURL("file://foo/some/path.txt"));
+ SchemefulSite site2(GURL("file://bar/some/path.txt"));
+ EXPECT_NE(site1, site2);
+
+ // Two file URLs with the same host should result in equal SchemefulSites.
+ SchemefulSite site3(GURL("file://foo/another/path.pdf"));
+ EXPECT_EQ(site1, site3);
+}
+
TEST(SchemefulSiteTest, OpaqueSerialization) {
// List of origins which should all share a schemeful site.
SchemefulSite kTestSites[] = {
diff --git a/chromium/net/base/sys_addrinfo.h b/chromium/net/base/sys_addrinfo.h
index 4bd1eb638b7..a18921e2911 100644
--- a/chromium/net/base/sys_addrinfo.h
+++ b/chromium/net/base/sys_addrinfo.h
@@ -14,6 +14,11 @@
//
// Prefer including this file instead of directly writing the #if / #else,
// since it avoids duplicating the platform-specific selections.
+//
+// Note that this header transitively includes windows.h on Windows, which
+// pollutes the global namespace with thousands of macro definitions, so try to
+// avoid including this in headers. Including windows.h can also add significant
+// build overhead.
#ifndef NET_BASE_SYS_ADDRINFO_H_
#define NET_BASE_SYS_ADDRINFO_H_
diff --git a/chromium/net/base/test_data_stream.h b/chromium/net/base/test_data_stream.h
index 9432d3ef476..d51bf72564c 100644
--- a/chromium/net/base/test_data_stream.h
+++ b/chromium/net/base/test_data_stream.h
@@ -5,15 +5,12 @@
#ifndef NET_BASE_TEST_DATA_STREAM_H_
#define NET_BASE_TEST_DATA_STREAM_H_
-#include <string.h> // for memcpy().
-#include "net/base/net_export.h"
-
// This is a class for generating an infinite stream of data which can be
// verified independently to be the correct stream of data.
namespace net {
-class NET_EXPORT TestDataStream {
+class TestDataStream {
public:
TestDataStream();
diff --git a/chromium/net/base/url_util.cc b/chromium/net/base/url_util.cc
index f9e2c266769..339822020f2 100644
--- a/chromium/net/base/url_util.cc
+++ b/chromium/net/base/url_util.cc
@@ -288,6 +288,17 @@ std::string CanonicalizeHost(base::StringPiece host,
const url::Component raw_host_component(0, static_cast<int>(host.length()));
std::string canon_host;
url::StdStringCanonOutput canon_host_output(&canon_host);
+ // A url::StdStringCanonOutput starts off with a zero length buffer. The
+ // first time through Grow() immediately resizes it to 32 bytes, incurring
+ // a malloc. With libcxx a 22 byte or smaller request can be accommodated
+ // within the std::string itself (i.e. no malloc occurs). Start the buffer
+ // off at the max size to avoid a malloc on short strings.
+ // NOTE: To ensure the final size is correctly reflected, it's necessary
+ // to call Complete() which will adjust the size to the actual bytes written.
+ // This is handled below for success cases, while failure cases discard all
+ // the output.
+ const int kCxxMaxStringBufferSizeWithoutMalloc = 22;
+ canon_host_output.Resize(kCxxMaxStringBufferSizeWithoutMalloc);
url::CanonicalizeHostVerbose(host.data(), raw_host_component,
&canon_host_output, host_info);
diff --git a/chromium/net/base/winsock_util.cc b/chromium/net/base/winsock_util.cc
index 38cc61cf040..99adea3ef1a 100644
--- a/chromium/net/base/winsock_util.cc
+++ b/chromium/net/base/winsock_util.cc
@@ -5,6 +5,7 @@
#include "net/base/winsock_util.h"
#include "base/check.h"
+#include "base/debug/alias.h"
#include "net/base/net_errors.h"
namespace net {
@@ -24,6 +25,7 @@ void CheckEventWait(WSAEVENT hEvent, DWORD wait_rv, DWORD expected) {
DWORD err = ERROR_SUCCESS;
if (wait_rv == WAIT_FAILED)
err = GetLastError();
+ base::debug::Alias(&err);
CHECK(false); // Crash.
}
}
diff --git a/chromium/net/cert/asn1_util.cc b/chromium/net/cert/asn1_util.cc
index 633b47b6cd2..5142aa513ef 100644
--- a/chromium/net/cert/asn1_util.cc
+++ b/chromium/net/cert/asn1_util.cc
@@ -182,14 +182,6 @@ bool ExtractExtensionWithOID(base::StringPiece cert,
return true;
}
-bool HasExtensionWithOID(base::StringPiece cert, der::Input extension_oid) {
- bool extension_present;
- ParsedExtension extension;
- return ExtractExtensionWithOID(cert, extension_oid, &extension_present,
- &extension) &&
- extension_present;
-}
-
} // namespace
bool ExtractSubjectFromDERCert(base::StringPiece cert,
@@ -245,15 +237,6 @@ bool ExtractSubjectPublicKeyFromSPKI(base::StringPiece spki,
return true;
}
-bool HasTLSFeatureExtension(base::StringPiece cert) {
- // kTLSFeatureExtensionOID is the DER encoding of the OID for the
- // X.509 TLS Feature Extension.
- static const uint8_t kTLSFeatureExtensionOID[] = {0x2B, 0x06, 0x01, 0x05,
- 0x05, 0x07, 0x01, 0x18};
-
- return HasExtensionWithOID(cert, der::Input(kTLSFeatureExtensionOID));
-}
-
bool HasCanSignHttpExchangesDraftExtension(base::StringPiece cert) {
// kCanSignHttpExchangesDraftOid is the DER encoding of the OID for
// canSignHttpExchangesDraft defined in:
diff --git a/chromium/net/cert/asn1_util.h b/chromium/net/cert/asn1_util.h
index 03116e2280e..ec59393e70c 100644
--- a/chromium/net/cert/asn1_util.h
+++ b/chromium/net/cert/asn1_util.h
@@ -32,13 +32,6 @@ NET_EXPORT_PRIVATE bool ExtractSubjectPublicKeyFromSPKI(
base::StringPiece spki,
base::StringPiece* spk_out);
-// HasTLSFeatureExtension parses the DER encoded certificate in |cert|
-// and extracts the TLS feature extension
-// (https://tools.ietf.org/html/rfc7633) if present. Returns true if the
-// TLS feature extension was present, and false if the extension was not
-// present or if there was a parsing failure.
-NET_EXPORT_PRIVATE bool HasTLSFeatureExtension(base::StringPiece cert);
-
// HasCanSignHttpExchangesDraftExtension parses the DER encoded certificate
// in |cert| and extracts the canSignHttpExchangesDraft extension
// (https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html)
diff --git a/chromium/net/cert/cert_and_ct_verifier.h b/chromium/net/cert/cert_and_ct_verifier.h
index b64502e5cdd..cfcefaa1f86 100644
--- a/chromium/net/cert/cert_and_ct_verifier.h
+++ b/chromium/net/cert/cert_and_ct_verifier.h
@@ -45,6 +45,8 @@ class NET_EXPORT CertAndCTVerifier : public CertVerifier {
const NetLogWithSource& net_log,
int result);
+ // TODO(crbug.com/1211074): Expose CT log list as part of
+ // CertVerifier::Config.
std::unique_ptr<CertVerifier> cert_verifier_;
std::unique_ptr<CTVerifier> ct_verifier_;
};
diff --git a/chromium/net/cert/cert_database.cc b/chromium/net/cert/cert_database.cc
index d68c6bfc6a0..88f71c87aa2 100644
--- a/chromium/net/cert/cert_database.cc
+++ b/chromium/net/cert/cert_database.cc
@@ -6,6 +6,8 @@
#include "base/memory/singleton.h"
#include "base/observer_list_threadsafe.h"
+#include "net/log/net_log.h"
+#include "net/log/net_log_values.h"
namespace net {
@@ -26,6 +28,12 @@ void CertDatabase::RemoveObserver(Observer* observer) {
}
void CertDatabase::NotifyObserversCertDBChanged() {
+ // Log to NetLog as it may help debug issues like https://crbug.com/915463
+ // This isn't guarded with net::NetLog::Get()->IsCapturing()) because an
+ // AddGlobalEntry() call without much computation is really cheap.
+ net::NetLog::Get()->AddGlobalEntry(
+ NetLogEventType::CERTIFICATE_DATABASE_CHANGED);
+
observer_list_->Notify(FROM_HERE, &Observer::OnCertDBChanged);
}
diff --git a/chromium/net/cert/cert_verify_proc.cc b/chromium/net/cert/cert_verify_proc.cc
index 8cf304df9de..1b565ca5f86 100644
--- a/chromium/net/cert/cert_verify_proc.cc
+++ b/chromium/net/cert/cert_verify_proc.cc
@@ -12,7 +12,6 @@
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/scoped_blocking_call.h"
@@ -252,31 +251,6 @@ void BestEffortCheckOCSP(const std::string& raw_response,
kMaxRevocationLeafUpdateAge, &verify_result->response_status);
}
-// Records histograms indicating whether the certificate |cert|, which
-// is assumed to have been validated chaining to a private root,
-// contains the TLS Feature Extension (https://tools.ietf.org/html/rfc7633) and
-// has valid OCSP information stapled.
-void RecordTLSFeatureExtensionWithPrivateRoot(
- X509Certificate* cert,
- const OCSPVerifyResult& ocsp_result) {
- // This checks only for the presence of the TLS Feature Extension, but
- // does not check the feature list, and in particular does not verify that
- // its value is 'status_request' or 'status_request2'. In practice the
- // only use of the TLS feature extension is for OCSP stapling, so
- // don't bother to check the value.
- bool has_extension = asn1::HasTLSFeatureExtension(
- x509_util::CryptoBufferAsStringPiece(cert->cert_buffer()));
-
- UMA_HISTOGRAM_BOOLEAN("Net.Certificate.TLSFeatureExtensionWithPrivateRoot",
- has_extension);
- if (!has_extension)
- return;
-
- UMA_HISTOGRAM_BOOLEAN(
- "Net.Certificate.TLSFeatureExtensionWithPrivateRootHasOCSP",
- (ocsp_result.response_status != OCSPVerifyResult::MISSING));
-}
-
// Records details about the most-specific trust anchor in |hashes|, which is
// expected to be ordered with the leaf cert first and the root cert last.
// "Most-specific" refers to the case that it is not uncommon to have multiple
@@ -683,11 +657,6 @@ int CertVerifyProc::Verify(X509Certificate* cert,
rv = MapCertStatusToNetError(verify_result->cert_status);
}
- // Record a histogram for the presence of the TLS feature extension in
- // a certificate chaining to a private root.
- if (rv == OK && !verify_result->is_issued_by_known_root)
- RecordTLSFeatureExtensionWithPrivateRoot(cert, verify_result->ocsp_result);
-
// Record a histogram for per-verification usage of root certs.
if (rv == OK) {
RecordTrustAnchorHistogram(verify_result->public_key_hashes,
diff --git a/chromium/net/cert/cert_verify_proc_android_unittest.cc b/chromium/net/cert/cert_verify_proc_android_unittest.cc
index cdf678f325b..c0afde3812d 100644
--- a/chromium/net/cert/cert_verify_proc_android_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_android_unittest.cc
@@ -104,7 +104,8 @@ CreateMockRequestWithInvalidCertificate() {
"CERTIFICATE", &der);
if (!r)
return r;
- *result = X509Certificate::CreateFromBytes(der.data(), der.length());
+ *result =
+ X509Certificate::CreateFromBytes(base::as_bytes(base::make_span(der)));
if (!result) {
return ::testing::AssertionFailure()
<< "X509Certificate::CreateFromBytes() failed";
diff --git a/chromium/net/cert/cert_verify_proc_blocklist.inc b/chromium/net/cert/cert_verify_proc_blocklist.inc
index 51999c818a7..e5f2942337e 100644
--- a/chromium/net/cert/cert_verify_proc_blocklist.inc
+++ b/chromium/net/cert/cert_verify_proc_blocklist.inc
@@ -363,6 +363,18 @@ static constexpr uint8_t
{0xc5, 0x62, 0x17, 0xb7, 0xa8, 0x28, 0xc7, 0x34, 0x1c, 0x0a, 0xe7,
0xa5, 0x90, 0xd8, 0x79, 0x0d, 0x4d, 0xef, 0x53, 0x66, 0x52, 0xe6,
0x0a, 0xe5, 0xb8, 0xbd, 0xfa, 0x26, 0x97, 0x8f, 0xe0, 0x9c},
+ // 06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem
+ {0xe4, 0x7c, 0x5c, 0xd2, 0xdc, 0x8b, 0xab, 0xb4, 0xe5, 0x3f, 0x8a,
+ 0x49, 0x83, 0x92, 0x02, 0x75, 0xef, 0x6f, 0xfa, 0xac, 0xb0, 0x89,
+ 0xe8, 0x7a, 0x2c, 0x1f, 0xbe, 0x5a, 0x58, 0x5f, 0x05, 0xed},
+ // 0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem
+ {0x39, 0x73, 0x65, 0x88, 0xb9, 0x4a, 0x4c, 0xe7, 0x67, 0xf7, 0x31,
+ 0xca, 0xd5, 0x3f, 0x4c, 0xbe, 0x44, 0x13, 0x7e, 0x32, 0x1e, 0xad,
+ 0xca, 0xef, 0x8c, 0xe7, 0x9a, 0x22, 0x9b, 0xbc, 0xa9, 0x89},
+ // c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem
+ {0xea, 0x12, 0x70, 0x5d, 0xe7, 0xc4, 0x8f, 0x6f, 0xcc, 0xe2, 0xcb,
+ 0x8d, 0xbc, 0x54, 0x2e, 0x0f, 0xc3, 0x8a, 0xc3, 0x8e, 0x08, 0x88,
+ 0x0d, 0xd0, 0x4a, 0x02, 0xef, 0x67, 0xc9, 0x3a, 0xe1, 0x35},
};
// Hashes of SubjectPublicKeyInfos known to be used for interception by a
@@ -388,4 +400,16 @@ static constexpr uint8_t kKnownInterceptionList[][crypto::kSHA256Length] = {
{0xc5, 0x62, 0x17, 0xb7, 0xa8, 0x28, 0xc7, 0x34, 0x1c, 0x0a, 0xe7, 0xa5,
0x90, 0xd8, 0x79, 0x0d, 0x4d, 0xef, 0x53, 0x66, 0x52, 0xe6, 0x0a, 0xe5,
0xb8, 0xbd, 0xfa, 0x26, 0x97, 0x8f, 0xe0, 0x9c},
+ // 06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem
+ {0xe4, 0x7c, 0x5c, 0xd2, 0xdc, 0x8b, 0xab, 0xb4, 0xe5, 0x3f, 0x8a, 0x49,
+ 0x83, 0x92, 0x02, 0x75, 0xef, 0x6f, 0xfa, 0xac, 0xb0, 0x89, 0xe8, 0x7a,
+ 0x2c, 0x1f, 0xbe, 0x5a, 0x58, 0x5f, 0x05, 0xed},
+ // 0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem
+ {0x39, 0x73, 0x65, 0x88, 0xb9, 0x4a, 0x4c, 0xe7, 0x67, 0xf7, 0x31,
+ 0xca, 0xd5, 0x3f, 0x4c, 0xbe, 0x44, 0x13, 0x7e, 0x32, 0x1e, 0xad,
+ 0xca, 0xef, 0x8c, 0xe7, 0x9a, 0x22, 0x9b, 0xbc, 0xa9, 0x89},
+ // c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem
+ {0xea, 0x12, 0x70, 0x5d, 0xe7, 0xc4, 0x8f, 0x6f, 0xcc, 0xe2, 0xcb, 0x8d,
+ 0xbc, 0x54, 0x2e, 0x0f, 0xc3, 0x8a, 0xc3, 0x8e, 0x08, 0x88, 0x0d, 0xd0,
+ 0x4a, 0x02, 0xef, 0x67, 0xc9, 0x3a, 0xe1, 0x35},
};
diff --git a/chromium/net/cert/cert_verify_proc_builtin.cc b/chromium/net/cert/cert_verify_proc_builtin.cc
index b78515e0a89..948b77419f0 100644
--- a/chromium/net/cert/cert_verify_proc_builtin.cc
+++ b/chromium/net/cert/cert_verify_proc_builtin.cc
@@ -509,8 +509,7 @@ void MapPathBuilderErrorsToCertStatus(const CertPathErrors& errors,
bssl::UniquePtr<CRYPTO_BUFFER> CreateCertBuffers(
const scoped_refptr<ParsedCertificate>& certificate) {
return X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(certificate->der_cert().UnsafeData()),
- certificate->der_cert().Length());
+ certificate->der_cert().AsSpan());
}
// Creates a X509Certificate (chain) to return as the verified result.
diff --git a/chromium/net/cert/cert_verify_proc_builtin.h b/chromium/net/cert/cert_verify_proc_builtin.h
index eae8d61737e..d0a88f66ec2 100644
--- a/chromium/net/cert/cert_verify_proc_builtin.h
+++ b/chromium/net/cert/cert_verify_proc_builtin.h
@@ -9,6 +9,7 @@
#include "base/memory/ref_counted.h"
#include "base/supports_user_data.h"
+#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/der/parse_values.h"
diff --git a/chromium/net/cert/cert_verify_proc_unittest.cc b/chromium/net/cert/cert_verify_proc_unittest.cc
index 6f218940327..a316794eba8 100644
--- a/chromium/net/cert/cert_verify_proc_unittest.cc
+++ b/chromium/net/cert/cert_verify_proc_unittest.cc
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/message_loop/message_pump_type.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
@@ -90,10 +89,6 @@ namespace net {
namespace {
-const char kTLSFeatureExtensionHistogram[] =
- "Net.Certificate.TLSFeatureExtensionWithPrivateRoot";
-const char kTLSFeatureExtensionOCSPHistogram[] =
- "Net.Certificate.TLSFeatureExtensionWithPrivateRootHasOCSP";
const char kTrustAnchorVerifyHistogram[] = "Net.Certificate.TrustAnchor.Verify";
const char kTrustAnchorVerifyOutOfDateHistogram[] =
"Net.Certificate.TrustAnchor.VerifyOutOfDate";
@@ -1308,7 +1303,8 @@ class CertVerifyProcInspectSignatureAlgorithmsTest : public ::testing::Test {
// NOTE: The signature is NOT recomputed over TBSCertificate -- for these
// tests it isn't needed.
- return X509Certificate::CreateFromBytes(cert_der.data(), cert_der.size());
+ return X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(cert_der)));
}
static scoped_refptr<X509Certificate> CreateChain(
@@ -2114,7 +2110,6 @@ TEST_P(CertVerifyProcInternalTest,
if (base::Time::Now() > chain->valid_expiry()) {
FAIL() << "This test uses a certificate chain which is now expired. Please "
"disable and file a bug against mattm.";
- return;
}
std::string sct_list;
@@ -4493,114 +4488,6 @@ TEST_F(CertVerifyProcNameTest, DoesntMatchDnsSanTrailingDot) {
VerifyCertName(".test.example", false);
}
-// Tests that CertVerifyProc records a histogram correctly when a
-// certificate chaining to a private root contains the TLS feature
-// extension and does not have a stapled OCSP response.
-TEST(CertVerifyProcTest, HasTLSFeatureExtensionUMA) {
- base::HistogramTester histograms;
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem"));
- ASSERT_TRUE(cert);
- CertVerifyResult result;
- result.is_issued_by_known_root = false;
- scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result);
-
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
-
- int flags = 0;
- CertVerifyResult verify_result;
- int error = verify_proc->Verify(
- cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
- /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(),
- CertificateList(), &verify_result, NetLogWithSource());
- EXPECT_EQ(OK, error);
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1);
- histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1);
- histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, false, 1);
-}
-
-// Tests that CertVerifyProc records a histogram correctly when a
-// certificate chaining to a private root contains the TLS feature
-// extension and does have a stapled OCSP response.
-TEST(CertVerifyProcTest, HasTLSFeatureExtensionWithStapleUMA) {
- base::HistogramTester histograms;
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem"));
- ASSERT_TRUE(cert);
- CertVerifyResult result;
- result.is_issued_by_known_root = false;
- scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result);
-
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
-
- int flags = 0;
- CertVerifyResult verify_result;
- int error = verify_proc->Verify(
- cert.get(), "127.0.0.1", "dummy response", /*sct_list=*/std::string(),
- flags, CRLSet::BuiltinCRLSet().get(), CertificateList(), &verify_result,
- NetLogWithSource());
- EXPECT_EQ(OK, error);
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1);
- histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, true, 1);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 1);
- histograms.ExpectBucketCount(kTLSFeatureExtensionOCSPHistogram, true, 1);
-}
-
-// Tests that CertVerifyProc records a histogram correctly when a
-// certificate chaining to a private root does not contain the TLS feature
-// extension.
-TEST(CertVerifyProcTest, DoesNotHaveTLSFeatureExtensionUMA) {
- base::HistogramTester histograms;
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "ok_cert.pem"));
- ASSERT_TRUE(cert);
- CertVerifyResult result;
- result.is_issued_by_known_root = false;
- scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result);
-
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
-
- int flags = 0;
- CertVerifyResult verify_result;
- int error = verify_proc->Verify(
- cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
- /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(),
- CertificateList(), &verify_result, NetLogWithSource());
- EXPECT_EQ(OK, error);
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 1);
- histograms.ExpectBucketCount(kTLSFeatureExtensionHistogram, false, 1);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
-}
-
-// Tests that CertVerifyProc does not record a histogram when a
-// certificate contains the TLS feature extension but chains to a public
-// root.
-TEST(CertVerifyProcTest, HasTLSFeatureExtensionWithPublicRootUMA) {
- base::HistogramTester histograms;
- scoped_refptr<X509Certificate> cert(
- ImportCertFromFile(GetTestCertsDirectory(), "tls_feature_extension.pem"));
- ASSERT_TRUE(cert);
- CertVerifyResult result;
- result.is_issued_by_known_root = true;
- scoped_refptr<CertVerifyProc> verify_proc = new MockCertVerifyProc(result);
-
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
-
- int flags = 0;
- CertVerifyResult verify_result;
- int error = verify_proc->Verify(
- cert.get(), "127.0.0.1", /*ocsp_response=*/std::string(),
- /*sct_list=*/std::string(), flags, CRLSet::BuiltinCRLSet().get(),
- CertificateList(), &verify_result, NetLogWithSource());
- EXPECT_EQ(OK, error);
- histograms.ExpectTotalCount(kTLSFeatureExtensionHistogram, 0);
- histograms.ExpectTotalCount(kTLSFeatureExtensionOCSPHistogram, 0);
-}
-
// Test that trust anchors are appropriately recorded via UMA.
TEST(CertVerifyProcTest, HasTrustAnchorVerifyUMA) {
base::HistogramTester histograms;
diff --git a/chromium/net/cert/cert_verify_proc_win.cc b/chromium/net/cert/cert_verify_proc_win.cc
index be167e90abf..e5117c4f0de 100644
--- a/chromium/net/cert/cert_verify_proc_win.cc
+++ b/chromium/net/cert/cert_verify_proc_win.cc
@@ -9,9 +9,9 @@
#include <string>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/memory/free_deleter.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_local.h"
@@ -42,28 +42,6 @@ namespace net {
namespace {
-struct FreeChainEngineFunctor {
- void operator()(HCERTCHAINENGINE engine) const {
- if (engine)
- CertFreeCertificateChainEngine(engine);
- }
-};
-
-struct FreeCertChainContextFunctor {
- void operator()(PCCERT_CHAIN_CONTEXT chain_context) const {
- if (chain_context)
- CertFreeCertificateChain(chain_context);
- }
-};
-
-typedef crypto::ScopedCAPIHandle<HCERTCHAINENGINE, FreeChainEngineFunctor>
- ScopedHCERTCHAINENGINE;
-
-typedef std::unique_ptr<const CERT_CHAIN_CONTEXT, FreeCertChainContextFunctor>
- ScopedPCCERT_CHAIN_CONTEXT;
-
-//-----------------------------------------------------------------------------
-
int MapSecurityError(SECURITY_STATUS err) {
// There are numerous security error codes, but these are the ones we thus
// far find interesting.
@@ -765,7 +743,7 @@ CertDllVerifyRevocationWithCRLSet(DWORD encoding_type,
}
// Determine the issuer cert for the incoming cert
- ScopedPCCERT_CONTEXT issuer_cert;
+ crypto::ScopedPCCERT_CONTEXT issuer_cert;
if (local_params.pIssuerCert &&
CryptVerifyCertificateSignatureEx(
NULL, subject_cert->dwCertEncodingType,
@@ -883,8 +861,9 @@ int CertVerifyProcWin::VerifyInternal(
// CRLSet.
ScopedThreadLocalCRLSet thread_local_crlset(crl_set);
- ScopedPCCERT_CONTEXT cert_list = x509_util::CreateCertContextWithChain(
- cert, x509_util::InvalidIntermediateBehavior::kIgnore);
+ crypto::ScopedPCCERT_CONTEXT cert_list =
+ x509_util::CreateCertContextWithChain(
+ cert, x509_util::InvalidIntermediateBehavior::kIgnore);
if (!cert_list) {
verify_result->cert_status |= CERT_STATUS_INVALID;
return ERR_CERT_INVALID;
@@ -956,9 +935,9 @@ int CertVerifyProcWin::VerifyInternal(
// Root store used by TestRootCerts as changed, via CertControlStore with the
// CERT_STORE_CTRL_NOTIFY_CHANGE / CERT_STORE_CTRL_RESYNC, but that's more
// complexity for what is test-only code.
- ScopedHCERTCHAINENGINE chain_engine(NULL);
+ crypto::ScopedHCERTCHAINENGINE chain_engine;
if (TestRootCerts::HasInstance())
- chain_engine.reset(TestRootCerts::GetInstance()->GetChainEngine());
+ chain_engine = TestRootCerts::GetInstance()->GetChainEngine();
// Add stapled OCSP response data, which will be preferred over online checks
// and used when in cache-only mode.
@@ -1009,7 +988,7 @@ int CertVerifyProcWin::VerifyInternal(
// chain is rejected, then clear it from |chain_para| so that all subsequent
// calls will use the fallback path.
BOOL chain_result =
- CertGetCertificateChain(chain_engine, cert_list.get(),
+ CertGetCertificateChain(chain_engine.get(), cert_list.get(),
nullptr, // current system time
cert_list->hCertStore, &chain_para, chain_flags,
nullptr, // reserved
@@ -1026,7 +1005,7 @@ int CertVerifyProcWin::VerifyInternal(
chain_para.pStrongSignPara = nullptr;
chain_para.dwStrongSignFlags = 0;
chain_result =
- CertGetCertificateChain(chain_engine, cert_list.get(),
+ CertGetCertificateChain(chain_engine.get(), cert_list.get(),
nullptr, // current system time
cert_list->hCertStore, &chain_para, chain_flags,
nullptr, // reserved
@@ -1056,7 +1035,7 @@ int CertVerifyProcWin::VerifyInternal(
verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
CertFreeCertificateChain(chain_context);
- if (!CertGetCertificateChain(chain_engine, cert_list.get(),
+ if (!CertGetCertificateChain(chain_engine.get(), cert_list.get(),
nullptr, // current system time
cert_list->hCertStore, &chain_para,
chain_flags,
@@ -1075,7 +1054,7 @@ int CertVerifyProcWin::VerifyInternal(
chain_para.RequestedIssuancePolicy.Usage.cUsageIdentifier = 0;
chain_para.RequestedIssuancePolicy.Usage.rgpszUsageIdentifier = nullptr;
CertFreeCertificateChain(chain_context);
- if (!CertGetCertificateChain(chain_engine, cert_list.get(),
+ if (!CertGetCertificateChain(chain_engine.get(), cert_list.get(),
nullptr, // current system time
cert_list->hCertStore, &chain_para,
chain_flags,
@@ -1097,7 +1076,7 @@ int CertVerifyProcWin::VerifyInternal(
chain_flags &= ~CERT_CHAIN_REVOCATION_CHECK_CACHE_ONLY;
CertFreeCertificateChain(chain_context);
- if (!CertGetCertificateChain(chain_engine, cert_list.get(),
+ if (!CertGetCertificateChain(chain_engine.get(), cert_list.get(),
nullptr, // current system time
cert_list->hCertStore, &chain_para,
chain_flags,
@@ -1109,7 +1088,7 @@ int CertVerifyProcWin::VerifyInternal(
GetCertChainInfo(chain_context, verify_result);
}
- ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context);
+ crypto::ScopedPCCERT_CHAIN_CONTEXT scoped_chain_context(chain_context);
verify_result->cert_status |= MapCertChainErrorStatusToCertStatus(
chain_context->TrustStatus.dwErrorStatus);
diff --git a/chromium/net/cert/crl_set.cc b/chromium/net/cert/crl_set.cc
index 8190b540108..486fba1abc0 100644
--- a/chromium/net/cert/crl_set.cc
+++ b/chromium/net/cert/crl_set.cc
@@ -169,7 +169,7 @@ bool CopyHashToHashesMapFromHeader(
return true;
}
- for (const auto& i : dict->DictItems()) {
+ for (auto i : dict->DictItems()) {
if (!i.second.is_list()) {
return false;
}
diff --git a/chromium/net/cert/ct_log_verifier.cc b/chromium/net/cert/ct_log_verifier.cc
index 8d148de4eea..d280192933c 100644
--- a/chromium/net/cert/ct_log_verifier.cc
+++ b/chromium/net/cert/ct_log_verifier.cc
@@ -8,6 +8,7 @@
#include <vector>
+#include "base/bits.h"
#include "base/logging.h"
#include "base/notreached.h"
#include "base/strings/string_piece.h"
@@ -31,10 +32,6 @@ const unsigned char kSHA256EmptyStringHash[ct::kSthRootHashLength] = {
0xc8, 0x99, 0x6f, 0xb9, 0x24, 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b,
0x93, 0x4c, 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55};
-bool IsPowerOfTwo(uint64_t n) {
- return n != 0 && (n & (n - 1)) == 0;
-}
-
const EVP_MD* GetEvpAlg(ct::DigitallySigned::HashAlgorithm alg) {
switch (alg) {
case ct::DigitallySigned::HASH_ALGO_MD5:
@@ -178,7 +175,7 @@ bool CTLogVerifier::VerifyConsistencyProof(
// "consistency_path" array.
base::StringPiece first_proof_node = old_tree_hash;
auto iter = proof.nodes.begin();
- if (!IsPowerOfTwo(proof.first_tree_size)) {
+ if (!base::bits::IsPowerOfTwo(proof.first_tree_size)) {
if (iter == proof.nodes.end())
return false;
first_proof_node = *iter;
diff --git a/chromium/net/cert/ct_log_verifier_unittest.cc b/chromium/net/cert/ct_log_verifier_unittest.cc
index 4bbc080a1d6..42f63101e0b 100644
--- a/chromium/net/cert/ct_log_verifier_unittest.cc
+++ b/chromium/net/cert/ct_log_verifier_unittest.cc
@@ -10,8 +10,8 @@
#include <string>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "crypto/secure_hash.h"
diff --git a/chromium/net/cert/ct_objects_extractor_unittest.cc b/chromium/net/cert/ct_objects_extractor_unittest.cc
index 8dd553a104c..b5cec727784 100644
--- a/chromium/net/cert/ct_objects_extractor_unittest.cc
+++ b/chromium/net/cert/ct_objects_extractor_unittest.cc
@@ -28,8 +28,8 @@ class CTObjectsExtractorTest : public ::testing::Test {
ASSERT_EQ(2u, precert_chain_.size());
std::string der_test_cert(ct::GetDerEncodedX509Cert());
- test_cert_ = X509Certificate::CreateFromBytes(der_test_cert.data(),
- der_test_cert.length());
+ test_cert_ = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(test_cert_);
log_ = CTLogVerifier::Create(ct::GetTestPublicKey(), "testlog");
@@ -142,13 +142,12 @@ TEST_F(CTObjectsExtractorTest, ComplementarySCTVerifies) {
TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponse) {
std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
scoped_refptr<X509Certificate> subject_cert =
- X509Certificate::CreateFromBytes(der_subject_cert.data(),
- der_subject_cert.length());
+ X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_subject_cert)));
ASSERT_TRUE(subject_cert);
std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
- scoped_refptr<X509Certificate> issuer_cert =
- X509Certificate::CreateFromBytes(der_issuer_cert.data(),
- der_issuer_cert.length());
+ scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_issuer_cert)));
ASSERT_TRUE(issuer_cert);
std::string fake_sct_list = ct::GetFakeOCSPExtensionValue();
@@ -165,9 +164,8 @@ TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponse) {
// Test that the extractor honours serial number.
TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesSerial) {
std::string der_issuer_cert(ct::GetDerEncodedFakeOCSPResponseIssuerCert());
- scoped_refptr<X509Certificate> issuer_cert =
- X509Certificate::CreateFromBytes(der_issuer_cert.data(),
- der_issuer_cert.length());
+ scoped_refptr<X509Certificate> issuer_cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_issuer_cert)));
ASSERT_TRUE(issuer_cert);
std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
@@ -182,8 +180,8 @@ TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesSerial) {
TEST_F(CTObjectsExtractorTest, ExtractSCTListFromOCSPResponseMatchesIssuer) {
std::string der_subject_cert(ct::GetDerEncodedFakeOCSPResponseCert());
scoped_refptr<X509Certificate> subject_cert =
- X509Certificate::CreateFromBytes(der_subject_cert.data(),
- der_subject_cert.length());
+ X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_subject_cert)));
ASSERT_TRUE(subject_cert);
std::string ocsp_response = ct::GetDerEncodedFakeOCSPResponse();
diff --git a/chromium/net/cert/internal/parsed_certificate.h b/chromium/net/cert/internal/parsed_certificate.h
index 23f88dacf08..3496f8af6ca 100644
--- a/chromium/net/cert/internal/parsed_certificate.h
+++ b/chromium/net/cert/internal/parsed_certificate.h
@@ -15,6 +15,7 @@
#include "net/cert/internal/certificate_policies.h"
#include "net/cert/internal/parse_certificate.h"
#include "net/der/input.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/boringssl/src/include/openssl/base.h"
namespace net {
diff --git a/chromium/net/cert/internal/path_builder.h b/chromium/net/cert/internal/path_builder.h
index e7ef60dbb55..e4463fd7bd2 100644
--- a/chromium/net/cert/internal/path_builder.h
+++ b/chromium/net/cert/internal/path_builder.h
@@ -6,10 +6,10 @@
#define NET_CERT_INTERNAL_PATH_BUILDER_H_
#include <memory>
-#include <string>
#include <vector>
#include "base/supports_user_data.h"
+#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parsed_certificate.h"
diff --git a/chromium/net/cert/internal/revocation_checker.h b/chromium/net/cert/internal/revocation_checker.h
index cb26b874d9d..7472da6fef3 100644
--- a/chromium/net/cert/internal/revocation_checker.h
+++ b/chromium/net/cert/internal/revocation_checker.h
@@ -6,6 +6,7 @@
#define NET_CERT_INTERNAL_REVOCATION_CHECKER_H_
#include "base/strings/string_piece_forward.h"
+#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/cert/crl_set.h"
#include "net/cert/internal/parsed_certificate.h"
diff --git a/chromium/net/cert/internal/revocation_util.h b/chromium/net/cert/internal/revocation_util.h
index f39482c1a0e..61b77ad9b61 100644
--- a/chromium/net/cert/internal/revocation_util.h
+++ b/chromium/net/cert/internal/revocation_util.h
@@ -7,7 +7,6 @@
#include "base/compiler_specific.h"
#include "net/base/net_export.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace base {
class Time;
diff --git a/chromium/net/cert/internal/system_trust_store.cc b/chromium/net/cert/internal/system_trust_store.cc
index 981de2c639a..e5237077469 100644
--- a/chromium/net/cert/internal/system_trust_store.cc
+++ b/chromium/net/cert/internal/system_trust_store.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "net/cert/internal/system_trust_store.h"
+#include "net/net_buildflags.h"
#if defined(USE_NSS_CERTS)
#include "net/cert/internal/system_trust_store_nss.h"
@@ -44,6 +45,9 @@
#include "base/lazy_instance.h"
#include "third_party/boringssl/src/include/openssl/pool.h"
#endif
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+#include "net/cert/internal/trust_store_chrome.h"
+#endif // CHROME_ROOT_STORE_SUPPORTED
namespace net {
@@ -65,6 +69,35 @@ class DummySystemTrustStore : public SystemTrustStore {
} // namespace
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+class SystemTrustStoreChrome : public SystemTrustStore {
+ public:
+ explicit SystemTrustStoreChrome(
+ std::unique_ptr<TrustStoreChrome> trust_store_chrome,
+ std::unique_ptr<TrustStore> trust_store_system)
+ : trust_store_chrome_(std::move(trust_store_chrome)),
+ trust_store_system_(std::move(trust_store_system)) {
+ trust_store_collection_.AddTrustStore(trust_store_chrome_.get());
+ trust_store_collection_.AddTrustStore(trust_store_system_.get());
+ }
+
+ TrustStore* GetTrustStore() override { return &trust_store_collection_; }
+
+ bool UsesSystemTrustStore() const override { return true; }
+
+ // IsKnownRoot returns true if the given trust anchor is a standard one (as
+ // opposed to a user-installed root)
+ bool IsKnownRoot(const ParsedCertificate* trust_anchor) const override {
+ return trust_store_chrome_->Contains(trust_anchor);
+ }
+
+ private:
+ std::unique_ptr<TrustStoreChrome> trust_store_chrome_;
+ std::unique_ptr<TrustStore> trust_store_system_;
+ TrustStoreCollection trust_store_collection_;
+};
+#endif // CHROME_ROOT_STORE_SUPPORTED
+
#if defined(USE_NSS_CERTS)
namespace {
@@ -110,6 +143,23 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
std::make_unique<TrustStoreNSS>(trustSSL));
}
+#if BUILDFLAG(CHROME_ROOT_STORE_SUPPORTED)
+
+std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot() {
+ return std::make_unique<SystemTrustStoreChrome>(
+ std::make_unique<TrustStoreChrome>(),
+ std::make_unique<TrustStoreNSS>(
+ trustSSL, TrustStoreNSS::IgnoreSystemTrustSettings()));
+}
+
+#else
+
+std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot() {
+ return std::make_unique<DummySystemTrustStore>();
+}
+
+#endif // CHROME_ROOT_STORE_SUPPORTED
+
std::unique_ptr<SystemTrustStore>
CreateSslSystemTrustStoreNSSWithUserSlotRestriction(
crypto::ScopedPK11Slot user_slot) {
@@ -195,6 +245,10 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
return std::make_unique<SystemTrustStoreMac>();
}
+std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot() {
+ return std::make_unique<DummySystemTrustStore>();
+}
+
void InitializeTrustStoreMacCache() {
base::ThreadPool::PostTask(
FROM_HERE,
@@ -219,7 +273,8 @@ class FuchsiaSystemCerts {
}
CertificateList certs = X509Certificate::CreateCertificateListFromBytes(
- certs_file.data(), certs_file.length(), X509Certificate::FORMAT_AUTO);
+ base::as_bytes(base::make_span(certs_file)),
+ X509Certificate::FORMAT_AUTO);
for (const auto& cert : certs) {
CertErrors errors;
@@ -262,12 +317,20 @@ std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
return std::make_unique<SystemTrustStoreFuchsia>();
}
+std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot() {
+ return std::make_unique<DummySystemTrustStore>();
+}
+
#else
std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore() {
return std::make_unique<DummySystemTrustStore>();
}
+std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStoreChromeRoot() {
+ return std::make_unique<DummySystemTrustStore>();
+}
+
#endif
std::unique_ptr<SystemTrustStore> CreateEmptySystemTrustStore() {
diff --git a/chromium/net/cert/internal/system_trust_store.h b/chromium/net/cert/internal/system_trust_store.h
index 7474df47f5d..8375f9b1a93 100644
--- a/chromium/net/cert/internal/system_trust_store.h
+++ b/chromium/net/cert/internal/system_trust_store.h
@@ -38,6 +38,10 @@ class SystemTrustStore {
// unsupported platforms. In the case where this returns false, the trust
// store returned by GetTrustStore() is made up solely of the manually added
// trust anchors (via AddTrustAnchor()).
+ //
+ // TODO(hchao): Rename this to something more sensible now that we're
+ // introducing the idea of a Chrome Root Store that doesn't use all parts of a
+ // system's trust store.
virtual bool UsesSystemTrustStore() const = 0;
// IsKnownRoot() returns true if the given certificate originated from the
@@ -49,11 +53,28 @@ class SystemTrustStore {
// Creates an instance of SystemTrustStore that wraps the current platform's SSL
// trust store. This cannot return nullptr, even in the case where system trust
-// store integration is not supported. In this latter case, the SystemTrustStore
-// will only give access to the manually added trust anchors. This can be
-// inspected by testing whether UsesSystemTrustStore() returns false.
+// store integration is not supported.
+//
+// In cases where system trust store integration is not supported, the
+// SystemTrustStore will not give access to the platform's SSL trust store, to
+// avoid trusting a CA that the user has disabled on their system. In this
+// case, UsesSystemTrustStore() will return false, and only manually-added trust
+// anchors will be used.
NET_EXPORT std::unique_ptr<SystemTrustStore> CreateSslSystemTrustStore();
+// Creates an instance of SystemTrustStore that wraps the current platform's SSL
+// trust store for user added roots, but uses the Chrome Root Store trust
+// anchors. This cannot return nullptr, even in the case where system trust
+// store integration is not supported.
+//
+// In cases where system trust store integration is not supported, the
+// SystemTrustStore will not give access to the Chrome Root Store, to avoid
+// trusting a CA that the user has disabled on their system. In this case,
+// UsesSystemTrustStore() will return false, and only manually-added trust
+// anchors will be used.
+NET_EXPORT std::unique_ptr<SystemTrustStore>
+CreateSslSystemTrustStoreChromeRoot();
+
// Creates an instance of SystemTrustStore that initially does not have any
// trust roots. (This is the same trust store implementation that will be
// returned by CreateSslSystemTrustStore() on platforms where system trust
diff --git a/chromium/net/cert/internal/trust_store_chrome.cc b/chromium/net/cert/internal/trust_store_chrome.cc
new file mode 100644
index 00000000000..6c646ea4a78
--- /dev/null
+++ b/chromium/net/cert/internal/trust_store_chrome.cc
@@ -0,0 +1,70 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/internal/trust_store_chrome.h"
+#include "base/containers/span.h"
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/parsed_certificate.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "third_party/boringssl/src/include/openssl/pool.h"
+
+namespace net {
+
+struct ChromeRootCertInfo {
+ base::span<const uint8_t> root_cert_der;
+};
+
+namespace {
+
+#include "net/data/ssl/chrome_root_store/chrome-root-store-inc.cc"
+} // namespace
+
+TrustStoreChrome::TrustStoreChrome() : TrustStoreChrome(kChromeRootCertList) {}
+
+TrustStoreChrome::TrustStoreChrome(base::span<const ChromeRootCertInfo> certs) {
+ // TODO(hchao, sleevi): Explore keeping a CRYPTO_BUFFER of just the DER
+ // certificate and subject name. This would hopefully save memory compared
+ // to keeping the full parsed representation in memory, especially when
+ // there are multiple instances of TrustStoreChrome.
+ for (const auto& cert_info : certs) {
+ bssl::UniquePtr<CRYPTO_BUFFER> cert = x509_util::CreateCryptoBuffer(
+ cert_info.root_cert_der.data(), cert_info.root_cert_der.size());
+ CertErrors errors;
+ auto parsed = ParsedCertificate::Create(
+ std::move(cert), x509_util::DefaultParseCertificateOptions(), &errors);
+ DCHECK(parsed);
+ // TODO(hchao): Figure out how to fail gracefully when the Chrome Root Store
+ // gets a bad component update.
+ trust_store_.AddTrustAnchor(parsed);
+ }
+}
+
+TrustStoreChrome::~TrustStoreChrome() = default;
+
+void TrustStoreChrome::SyncGetIssuersOf(const ParsedCertificate* cert,
+ ParsedCertificateList* issuers) {
+ trust_store_.SyncGetIssuersOf(cert, issuers);
+}
+
+void TrustStoreChrome::GetTrust(const scoped_refptr<ParsedCertificate>& cert,
+ CertificateTrust* trust,
+ base::SupportsUserData* debug_data) const {
+ trust_store_.GetTrust(cert, trust, debug_data);
+}
+
+bool TrustStoreChrome::Contains(const ParsedCertificate* cert) const {
+ return trust_store_.Contains(cert);
+}
+
+// static
+std::unique_ptr<TrustStoreChrome> TrustStoreChrome::CreateTrustStoreForTesting(
+ base::span<const ChromeRootCertInfo> certs) {
+ // Note: wrap_unique is used because the constructor is private.
+ return base::WrapUnique(new TrustStoreChrome(certs));
+}
+
+} // namespace net
diff --git a/chromium/net/cert/internal/trust_store_chrome.h b/chromium/net/cert/internal/trust_store_chrome.h
new file mode 100644
index 00000000000..231b56d4287
--- /dev/null
+++ b/chromium/net/cert/internal/trust_store_chrome.h
@@ -0,0 +1,50 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
+#define NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
+
+#include "base/containers/span.h"
+#include "net/base/net_export.h"
+#include "net/cert/internal/trust_store.h"
+#include "net/cert/internal/trust_store_in_memory.h"
+
+namespace net {
+
+struct ChromeRootCertInfo;
+
+// TrustStoreChrome contains the Chrome Root Store, as described at
+// https://g.co/chrome/root-policy
+class NET_EXPORT TrustStoreChrome : public TrustStore {
+ public:
+ // Creates a ChromeTrustStore that uses a copy of `certs`, instead of the
+ // default Chrome Root Store.
+ static std::unique_ptr<TrustStoreChrome> CreateTrustStoreForTesting(
+ base::span<const ChromeRootCertInfo> certs);
+
+ TrustStoreChrome();
+ ~TrustStoreChrome() override;
+
+ TrustStoreChrome(const TrustStoreChrome& other) = delete;
+ TrustStoreChrome& operator=(const TrustStoreChrome& other) = delete;
+
+ // TrustStore implementation:
+ void SyncGetIssuersOf(const ParsedCertificate* cert,
+ ParsedCertificateList* issuers) override;
+ void GetTrust(const scoped_refptr<ParsedCertificate>& cert,
+ CertificateTrust* trust,
+ base::SupportsUserData* debug_data) const override;
+
+ // Returns true if the trust store contains the given ParsedCertificate
+ // (matches by DER).
+ bool Contains(const ParsedCertificate* cert) const;
+
+ private:
+ explicit TrustStoreChrome(base::span<const ChromeRootCertInfo> certs);
+ TrustStoreInMemory trust_store_;
+};
+
+} // namespace net
+
+#endif // NET_CERT_INTERNAL_TRUST_STORE_CHROME_H_
diff --git a/chromium/net/cert/internal/trust_store_chrome_unittest.cc b/chromium/net/cert/internal/trust_store_chrome_unittest.cc
new file mode 100644
index 00000000000..2502a56b202
--- /dev/null
+++ b/chromium/net/cert/internal/trust_store_chrome_unittest.cc
@@ -0,0 +1,99 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cert/internal/trust_store_chrome.h"
+
+#include "base/containers/span.h"
+#include "net/cert/internal/cert_errors.h"
+#include "net/cert/internal/parsed_certificate.h"
+#include "net/cert/x509_certificate.h"
+#include "net/cert/x509_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+struct ChromeRootCertInfo {
+ base::span<const uint8_t> root_cert_der;
+};
+
+namespace {
+
+#include "net/data/ssl/chrome_root_store/chrome-root-store-test-data-inc.cc"
+
+scoped_refptr<ParsedCertificate> ParseCertFromFile(base::FilePath dir_name,
+ std::string file_name) {
+ const scoped_refptr<X509Certificate> cert =
+ ImportCertFromFile(dir_name, file_name);
+ if (!cert) {
+ return nullptr;
+ }
+ CertErrors errors;
+ scoped_refptr<ParsedCertificate> parsed = ParsedCertificate::Create(
+ bssl::UpRef(cert->cert_buffer()),
+ x509_util::DefaultParseCertificateOptions(), &errors);
+ EXPECT_TRUE(parsed) << errors.ToDebugString();
+ return parsed;
+}
+
+const base::FilePath kCertDirPath = GetTestNetDataDirectory().AppendASCII(
+ "ssl/chrome_root_store/testdata/certs");
+
+const char kCertInStoreFile1[] =
+ "568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem";
+const char kCertInStoreFile2[] =
+ "6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem";
+const char kCertNotInStoreFile[] =
+ "c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem";
+
+TEST(TrustStoreChromeTestNoFixture, ContainsCert) {
+ std::unique_ptr<TrustStoreChrome> trust_store_chrome =
+ TrustStoreChrome::CreateTrustStoreForTesting(
+ base::span<const ChromeRootCertInfo>(kChromeRootCertList));
+
+ scoped_refptr<ParsedCertificate> trust_cert_1, trust_cert_2,
+ trust_cert_missing;
+ ASSERT_TRUE(trust_cert_1 =
+ ParseCertFromFile(kCertDirPath, kCertInStoreFile1));
+ ASSERT_TRUE(trust_store_chrome->Contains(trust_cert_1.get()));
+
+ ASSERT_TRUE(trust_cert_2 =
+ ParseCertFromFile(kCertDirPath, kCertInStoreFile2));
+ ASSERT_TRUE(trust_store_chrome->Contains(trust_cert_2.get()));
+
+ // Cert should not be in the trust store.
+ ASSERT_TRUE(trust_cert_missing =
+ ParseCertFromFile(kCertDirPath, kCertNotInStoreFile));
+ ASSERT_FALSE(trust_store_chrome->Contains(trust_cert_missing.get()));
+}
+
+TEST(TrustStoreChromeTestNoFixture, ContainsCerts) {
+ std::unique_ptr<TrustStoreChrome> trust_store_chrome =
+ TrustStoreChrome::CreateTrustStoreForTesting(
+ base::span<const ChromeRootCertInfo>(kChromeRootCertList));
+
+ CertificateTrust trust;
+ scoped_refptr<ParsedCertificate> trust_cert_1, trust_cert_2,
+ trust_cert_missing;
+
+ ASSERT_TRUE(trust_cert_1 =
+ ParseCertFromFile(kCertDirPath, kCertInStoreFile1));
+ trust_store_chrome->GetTrust(trust_cert_1, &trust, /*debug_data=*/nullptr);
+ EXPECT_EQ(CertificateTrustType::TRUSTED_ANCHOR, trust.type);
+
+ ASSERT_TRUE(trust_cert_2 =
+ ParseCertFromFile(kCertDirPath, kCertInStoreFile2));
+ trust_store_chrome->GetTrust(trust_cert_2, &trust, /*debug_data=*/nullptr);
+ EXPECT_EQ(CertificateTrustType::TRUSTED_ANCHOR, trust.type);
+
+ ASSERT_TRUE(trust_cert_missing =
+ ParseCertFromFile(kCertDirPath, kCertNotInStoreFile));
+ trust_store_chrome->GetTrust(trust_cert_missing, &trust,
+ /*debug_data=*/nullptr);
+ EXPECT_EQ(CertificateTrustType::UNSPECIFIED, trust.type);
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/cert/internal/trust_store_nss.cc b/chromium/net/cert/internal/trust_store_nss.cc
index 4b0ba6e5457..d69abc8ff42 100644
--- a/chromium/net/cert/internal/trust_store_nss.cc
+++ b/chromium/net/cert/internal/trust_store_nss.cc
@@ -11,6 +11,7 @@
#include "crypto/nss_util.h"
#include "net/cert/internal/cert_errors.h"
#include "net/cert/internal/parsed_certificate.h"
+#include "net/cert/known_roots_nss.h"
#include "net/cert/scoped_nss_types.h"
#include "net/cert/test_root_certs.h"
#include "net/cert/x509_util.h"
@@ -34,6 +35,13 @@ TrustStoreNSS::TrustStoreNSS(
DisallowTrustForCertsOnUserSlots disallow_trust_for_certs_on_user_slots)
: trust_type_(trust_type), filter_trusted_certs_by_slot_(true) {}
+TrustStoreNSS::TrustStoreNSS(
+ SECTrustType trust_type,
+ IgnoreSystemTrustSettings ignore_system_trust_settings)
+ : trust_type_(trust_type),
+ ignore_system_trust_settings_(true),
+ filter_trusted_certs_by_slot_(false) {}
+
TrustStoreNSS::~TrustStoreNSS() = default;
void TrustStoreNSS::SyncGetIssuersOf(const ParsedCertificate* cert,
@@ -118,9 +126,23 @@ void TrustStoreNSS::GetTrust(const scoped_refptr<ParsedCertificate>& cert,
}
// Determine if the certificate is a trust anchor.
+ //
+ // We may not use the result of this if it is a known root and we're ignoring
+ // system certs.
if ((trust_flags & CERTDB_TRUSTED_CA) == CERTDB_TRUSTED_CA) {
- *out_trust = CertificateTrust::ForTrustAnchor();
- return;
+ // If its a user root, or its a system root and we're not ignoring system
+ // roots than return root as trusted.
+ //
+ // TODO(hchao, sleevi): CERT_GetCertTrust combines the trust settings from
+ // all tokens and slots, meaning it doesn't allow us to distinguish between
+ // CKO_NSS_TRUST objects the user manually configured versus CKO_NSS_TRUST
+ // objects from the builtin token (system trust settings). Properly
+ // handling this may require iterating all the slots and manually computing
+ // the trust settings directly, rather than CERT_GetCertTrust.
+ if (!ignore_system_trust_settings_ || !IsKnownRoot(nss_cert.get())) {
+ *out_trust = CertificateTrust::ForTrustAnchor();
+ return;
+ }
}
// Trusted server certs (CERTDB_TERMINAL_RECORD + CERTDB_TRUSTED) are
diff --git a/chromium/net/cert/internal/trust_store_nss.h b/chromium/net/cert/internal/trust_store_nss.h
index 10e3df01d37..71c2b31c212 100644
--- a/chromium/net/cert/internal/trust_store_nss.h
+++ b/chromium/net/cert/internal/trust_store_nss.h
@@ -19,7 +19,12 @@ namespace net {
// anchors for path building. This TrustStore is thread-safe.
class NET_EXPORT TrustStoreNSS : public TrustStore {
public:
+ // TODO(hchao): this won't work when we try to get this working for ChromeOS
+ // as we will likely need to be able to specify multiple options (trust_type,
+ // user_slot, ignoring_system_certs_unless_distrusted), so we'll need to
+ // re-engineer to not get combinatorial explosion for constructors.
struct DisallowTrustForCertsOnUserSlots {};
+ struct IgnoreSystemTrustSettings {};
// Creates a TrustStoreNSS which will find anchors that are trusted for
// |trust_type|.
@@ -44,6 +49,15 @@ class NET_EXPORT TrustStoreNSS : public TrustStore {
SECTrustType trust_type,
DisallowTrustForCertsOnUserSlots disallow_trust_for_certs_on_user_slots);
+ // Creates a TrustStoreNSS which will find anchors that are trusted for
+ // |trust_type|.
+ // The created TrustStoreNSS will ignore system trust settings (but will
+ // respect user-added certs).
+ //
+ // TODO(hchao, sleevi): Only ignore builtin trust settings for these certs.
+ TrustStoreNSS(SECTrustType trust_type,
+ IgnoreSystemTrustSettings ignore_system_trust_settings);
+
~TrustStoreNSS() override;
// CertIssuerSource implementation:
@@ -60,6 +74,13 @@ class NET_EXPORT TrustStoreNSS : public TrustStore {
SECTrustType trust_type_;
+ // |ignore_system_certs_trust_settings_| specifies if the system trust
+ // settings should be considered when determining a cert's trustworthiness.
+ //
+ // TODO(hchao, sleevi): Figure out how to ignore built-in trust settings,
+ // while respecting user-configured trust settings, for these certificates.
+ const bool ignore_system_trust_settings_ = false;
+
// |filter_trusted_certs_by_slot_| and |user_slot_| together specify which
// slots certificates must be stored on to be allowed to be trusted. The
// possible combinations are:
diff --git a/chromium/net/cert/internal/trust_store_nss_unittest.cc b/chromium/net/cert/internal/trust_store_nss_unittest.cc
index 9eaa2dc765b..28edc26ff92 100644
--- a/chromium/net/cert/internal/trust_store_nss_unittest.cc
+++ b/chromium/net/cert/internal/trust_store_nss_unittest.cc
@@ -327,6 +327,36 @@ INSTANTIATE_TEST_SUITE_P(
SlotFilterType::kDoNotAllowUserSlots,
SlotFilterType::kAllowSpecifiedUserSlot));
+// Tests a TrustStoreNSS that ignores root certs
+class TrustStoreNSSTestIgnoreSystemCerts : public TrustStoreNSSTestBase {
+ public:
+ TrustStoreNSSTestIgnoreSystemCerts() = default;
+ ~TrustStoreNSSTestIgnoreSystemCerts() override = default;
+
+ std::unique_ptr<TrustStoreNSS> CreateTrustStoreNSS() override {
+ return std::make_unique<TrustStoreNSS>(
+ trustSSL, TrustStoreNSS::IgnoreSystemTrustSettings());
+ }
+};
+
+TEST_F(TrustStoreNSSTestIgnoreSystemCerts, UserRootTrusted) {
+ AddCertsToNSS();
+ TrustCert(newroot_.get());
+ EXPECT_TRUE(HasTrust({newroot_}, CertificateTrustType::TRUSTED_ANCHOR));
+}
+
+TEST_F(TrustStoreNSSTestIgnoreSystemCerts, UserRootDistrusted) {
+ AddCertsToNSS();
+ DistrustCert(newroot_.get());
+ EXPECT_TRUE(HasTrust({newroot_}, CertificateTrustType::DISTRUSTED));
+}
+
+TEST_F(TrustStoreNSSTestIgnoreSystemCerts, SystemRootCertsIgnored) {
+ scoped_refptr<ParsedCertificate> system_root = GetASSLTrustedBuiltinRoot();
+ ASSERT_TRUE(system_root);
+ EXPECT_TRUE(HasTrust({system_root}, CertificateTrustType::UNSPECIFIED));
+}
+
// Tests a TrustStoreNSS that does not filter which certificates
class TrustStoreNSSTestWithoutSlotFilter : public TrustStoreNSSTestBase {
public:
diff --git a/chromium/net/cert/merkle_tree_leaf_unittest.cc b/chromium/net/cert/merkle_tree_leaf_unittest.cc
index 691c1102e5e..b2bd82010d5 100644
--- a/chromium/net/cert/merkle_tree_leaf_unittest.cc
+++ b/chromium/net/cert/merkle_tree_leaf_unittest.cc
@@ -48,8 +48,8 @@ class MerkleTreeLeafTest : public ::testing::Test {
public:
void SetUp() override {
std::string der_test_cert(ct::GetDerEncodedX509Cert());
- test_cert_ = X509Certificate::CreateFromBytes(der_test_cert.data(),
- der_test_cert.length());
+ test_cert_ = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(test_cert_);
GetX509CertSCT(&x509_sct_);
diff --git a/chromium/net/cert/multi_log_ct_verifier.cc b/chromium/net/cert/multi_log_ct_verifier.cc
index dfd44a4e33f..bd503cf67c8 100644
--- a/chromium/net/cert/multi_log_ct_verifier.cc
+++ b/chromium/net/cert/multi_log_ct_verifier.cc
@@ -6,6 +6,8 @@
#include <vector>
+#include "base/bind.h"
+#include "base/callback.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/values.h"
@@ -52,15 +54,37 @@ void AddSCTAndLogStatus(scoped_refptr<ct::SignedCertificateTimestamp> sct,
} // namespace
-MultiLogCTVerifier::MultiLogCTVerifier() {}
+base::CallbackListSubscription
+MultiLogCTVerifier::CTLogProvider::RegisterLogsListCallback(
+ LogListCallbackList::CallbackType callback) {
+ return callback_list_.Add(std::move(callback));
+}
+
+void MultiLogCTVerifier::CTLogProvider::NotifyCallbacks(
+ const std::vector<scoped_refptr<const net::CTLogVerifier>>& log_verifiers) {
+ callback_list_.Notify(log_verifiers);
+}
+
+MultiLogCTVerifier::CTLogProvider::CTLogProvider() = default;
+MultiLogCTVerifier::CTLogProvider::~CTLogProvider() = default;
+
+MultiLogCTVerifier::MultiLogCTVerifier(CTLogProvider* notifier) {
+ // base::Unretained is safe since we are using a CallbackListSubscription that
+ // won't outlive |this|.
+ log_provider_subscription_ =
+ notifier->RegisterLogsListCallback(base::BindRepeating(
+ &MultiLogCTVerifier::SetLogs, base::Unretained(this)));
+}
MultiLogCTVerifier::~MultiLogCTVerifier() = default;
-void MultiLogCTVerifier::AddLogs(
+void MultiLogCTVerifier::SetLogs(
const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers) {
+ logs_.clear();
for (const auto& log_verifier : log_verifiers) {
VLOG(1) << "Adding CT log: " << log_verifier->description();
- logs_[log_verifier->key_id()] = log_verifier;
+ std::string key_id = log_verifier->key_id();
+ logs_[key_id] = log_verifier;
}
}
diff --git a/chromium/net/cert/multi_log_ct_verifier.h b/chromium/net/cert/multi_log_ct_verifier.h
index 0d603eb72f3..3d4818204d6 100644
--- a/chromium/net/cert/multi_log_ct_verifier.h
+++ b/chromium/net/cert/multi_log_ct_verifier.h
@@ -8,8 +8,11 @@
#include <map>
#include <string>
+#include "base/callback_forward.h"
+#include "base/callback_list.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
#include "net/cert/ct_verifier.h"
@@ -28,10 +31,30 @@ class CTLogVerifier;
// It must be initialized with a list of logs by calling AddLogs.
class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
public:
- MultiLogCTVerifier();
+ class NET_EXPORT CTLogProvider {
+ public:
+ using LogListCallbackList = base::RepeatingCallbackList<void(
+ const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers)>;
+
+ base::CallbackListSubscription RegisterLogsListCallback(
+ LogListCallbackList::CallbackType callback);
+
+ protected:
+ CTLogProvider();
+ ~CTLogProvider();
+
+ void NotifyCallbacks(
+ const std::vector<scoped_refptr<const net::CTLogVerifier>>&
+ log_verifiers);
+
+ private:
+ LogListCallbackList callback_list_;
+ };
+
+ explicit MultiLogCTVerifier(CTLogProvider* notifier);
~MultiLogCTVerifier() override;
- void AddLogs(
+ void SetLogs(
const std::vector<scoped_refptr<const CTLogVerifier>>& log_verifiers);
// CTVerifier implementation:
@@ -65,6 +88,8 @@ class NET_EXPORT MultiLogCTVerifier : public CTVerifier {
// of RFC6962.
std::map<std::string, scoped_refptr<const CTLogVerifier>> logs_;
+ base::CallbackListSubscription log_provider_subscription_;
+
DISALLOW_COPY_AND_ASSIGN(MultiLogCTVerifier);
};
diff --git a/chromium/net/cert/multi_log_ct_verifier_unittest.cc b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
index 006908b6bdb..ef3ae3179b4 100644
--- a/chromium/net/cert/multi_log_ct_verifier_unittest.cc
+++ b/chromium/net/cert/multi_log_ct_verifier_unittest.cc
@@ -41,6 +41,12 @@ namespace {
const char kHostname[] = "example.com";
const char kLogDescription[] = "somelog";
+class DoNothingLogProvider : public MultiLogCTVerifier::CTLogProvider {
+ public:
+ DoNothingLogProvider() = default;
+ ~DoNothingLogProvider() = default;
+};
+
class MultiLogCTVerifierTest : public ::testing::Test {
public:
void SetUp() override {
@@ -49,12 +55,12 @@ class MultiLogCTVerifierTest : public ::testing::Test {
ASSERT_TRUE(log);
log_verifiers_.push_back(log);
- verifier_ = std::make_unique<MultiLogCTVerifier>();
- verifier_->AddLogs(log_verifiers_);
+ DoNothingLogProvider notifier;
+ verifier_ = std::make_unique<MultiLogCTVerifier>(&notifier);
+ verifier_->SetLogs(log_verifiers_);
std::string der_test_cert(ct::GetDerEncodedX509Cert());
chain_ = X509Certificate::CreateFromBytes(
- der_test_cert.data(),
- der_test_cert.length());
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(chain_.get());
embedded_sct_chain_ =
@@ -241,6 +247,29 @@ TEST_F(MultiLogCTVerifierTest, CountsSingleEmbeddedSCTInOriginsHistogram) {
EXPECT_EQ(old_embedded_count + 1, NumEmbeddedSCTsInHistogram());
}
+TEST_F(MultiLogCTVerifierTest, SetLogsRemovesOldLogs) {
+ log_verifiers_.clear();
+ verifier_->SetLogs(log_verifiers_);
+ // Log list is now empty so verification should fail.
+ ASSERT_FALSE(CheckPrecertificateVerification(embedded_sct_chain_));
+}
+
+TEST_F(MultiLogCTVerifierTest, SetLogsAddsNewLogs) {
+ // Clear the log list.
+ log_verifiers_.clear();
+ verifier_->SetLogs(log_verifiers_);
+
+ // Add valid log again via SetLogs
+ scoped_refptr<const CTLogVerifier> log(
+ CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
+ ASSERT_TRUE(log);
+ log_verifiers_.push_back(log);
+ verifier_->SetLogs(log_verifiers_);
+
+ // Verification should now succeed.
+ ASSERT_TRUE(CheckPrecertificateVerification(embedded_sct_chain_));
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/cert/nss_cert_database_chromeos.cc b/chromium/net/cert/nss_cert_database_chromeos.cc
index 25487cd8159..1f11bbd24aa 100644
--- a/chromium/net/cert/nss_cert_database_chromeos.cc
+++ b/chromium/net/cert/nss_cert_database_chromeos.cc
@@ -13,8 +13,8 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/containers/cxx20_erase.h"
#include "base/location.h"
-#include "base/stl_util.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
diff --git a/chromium/net/cert/symantec_certs.cc b/chromium/net/cert/symantec_certs.cc
index bd8f2fb7fcd..4a540f5dda4 100644
--- a/chromium/net/cert/symantec_certs.cc
+++ b/chromium/net/cert/symantec_certs.cc
@@ -4,7 +4,7 @@
#include "net/cert/symantec_certs.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
namespace net {
diff --git a/chromium/net/cert/test_root_certs.cc b/chromium/net/cert/test_root_certs.cc
index fbee47a9ccd..10adc528919 100644
--- a/chromium/net/cert/test_root_certs.cc
+++ b/chromium/net/cert/test_root_certs.cc
@@ -33,7 +33,7 @@ CertificateList LoadCertificates(const base::FilePath& filename) {
}
return X509Certificate::CreateCertificateListFromBytes(
- raw_cert.data(), raw_cert.length(), X509Certificate::FORMAT_AUTO);
+ base::as_bytes(base::make_span(raw_cert)), X509Certificate::FORMAT_AUTO);
}
} // namespace
diff --git a/chromium/net/cert/test_root_certs.h b/chromium/net/cert/test_root_certs.h
index 80e26eefecf..afac81c7390 100644
--- a/chromium/net/cert/test_root_certs.h
+++ b/chromium/net/cert/test_root_certs.h
@@ -15,6 +15,7 @@
#if defined(OS_WIN)
#include <windows.h>
#include "base/win/wincrypt_shim.h"
+#include "crypto/scoped_capi_types.h"
#elif defined(OS_APPLE)
#include <CoreFoundation/CFArray.h>
#include <Security/SecTrust.h>
@@ -70,9 +71,8 @@ class NET_EXPORT TestRootCerts {
// Returns an HCERTCHAINENGINE suitable to be used for certificate
// validation routines, or NULL to indicate that the default system chain
- // engine is appropriate. The caller is responsible for freeing the
- // returned HCERTCHAINENGINE.
- HCERTCHAINENGINE GetChainEngine() const;
+ // engine is appropriate.
+ crypto::ScopedHCERTCHAINENGINE GetChainEngine() const;
#endif
TrustStore* test_trust_store() { return &test_trust_store_; }
diff --git a/chromium/net/cert/test_root_certs_win.cc b/chromium/net/cert/test_root_certs_win.cc
index 2c50876e88e..85632fbbc46 100644
--- a/chromium/net/cert/test_root_certs_win.cc
+++ b/chromium/net/cert/test_root_certs_win.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "crypto/scoped_capi_types.h"
#include "net/cert/test_root_certs.h"
#include <stdint.h>
@@ -164,9 +165,11 @@ void TestRootCerts::ClearImpl() {
CertDeleteCertificateFromStore(prev_cert);
}
-HCERTCHAINENGINE TestRootCerts::GetChainEngine() const {
- if (IsEmpty())
- return nullptr; // Default chain engine will suffice.
+crypto::ScopedHCERTCHAINENGINE TestRootCerts::GetChainEngine() const {
+ if (IsEmpty()) {
+ // Default chain engine will suffice.
+ return crypto::ScopedHCERTCHAINENGINE();
+ }
// Windows versions before 8 don't accept the struct size for later versions.
// We report the size of the old struct since we don't need the new members.
@@ -187,8 +190,10 @@ HCERTCHAINENGINE TestRootCerts::GetChainEngine() const {
engine_config.dwFlags =
CERT_CHAIN_ENABLE_CACHE_AUTO_UPDATE |
CERT_CHAIN_ENABLE_SHARE_STORE;
- HCERTCHAINENGINE chain_engine = nullptr;
- BOOL ok = CertCreateCertificateChainEngine(&engine_config, &chain_engine);
+ crypto::ScopedHCERTCHAINENGINE chain_engine;
+ BOOL ok = CertCreateCertificateChainEngine(
+ &engine_config,
+ crypto::ScopedHCERTCHAINENGINE::Receiver(chain_engine).get());
DCHECK(ok);
return chain_engine;
}
diff --git a/chromium/net/cert/trial_comparison_cert_verifier_unittest.cc b/chromium/net/cert/trial_comparison_cert_verifier_unittest.cc
index 531463f6030..6fa6acd4b57 100644
--- a/chromium/net/cert/trial_comparison_cert_verifier_unittest.cc
+++ b/chromium/net/cert/trial_comparison_cert_verifier_unittest.cc
@@ -42,7 +42,8 @@ namespace {
MATCHER_P(CertChainMatches, expected_cert, "") {
CertificateList actual_certs =
X509Certificate::CreateCertificateListFromBytes(
- arg.data(), arg.size(), X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+ base::as_bytes(base::make_span(arg)),
+ X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
if (actual_certs.empty()) {
*result_listener << "failed to parse arg";
return false;
diff --git a/chromium/net/cert/x509_certificate.cc b/chromium/net/cert/x509_certificate.cc
index b75554d9c6e..9a4cd2a2166 100644
--- a/chromium/net/cert/x509_certificate.cc
+++ b/chromium/net/cert/x509_certificate.cc
@@ -13,11 +13,12 @@
#include "base/base64.h"
#include "base/containers/contains.h"
+#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/pickle.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
@@ -116,14 +117,13 @@ bool GetNormalizedCertIssuer(CRYPTO_BUFFER* cert,
// Parses certificates from a PKCS#7 SignedData structure, appending them to
// |handles|.
void CreateCertBuffersFromPKCS7Bytes(
- const char* data,
- size_t length,
+ base::span<const uint8_t> data,
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>* handles) {
crypto::EnsureOpenSSLInit();
crypto::OpenSSLErrStackTracer err_cleaner(FROM_HERE);
CBS der_data;
- CBS_init(&der_data, reinterpret_cast<const uint8_t*>(data), length);
+ CBS_init(&der_data, data.data(), data.size());
STACK_OF(CRYPTO_BUFFER)* certs = sk_CRYPTO_BUFFER_new_null();
if (PKCS7_get_raw_certificates(certs, &der_data,
@@ -184,7 +184,7 @@ X509Certificate::CreateFromDERCertChainUnsafeOptions(
intermediate_ca_certs.reserve(der_certs.size() - 1);
for (size_t i = 1; i < der_certs.size(); i++) {
bssl::UniquePtr<CRYPTO_BUFFER> handle = CreateCertBufferFromBytes(
- const_cast<char*>(der_certs[i].data()), der_certs[i].size());
+ base::as_bytes(base::make_span(der_certs[i])));
if (!handle)
break;
intermediate_ca_certs.push_back(std::move(handle));
@@ -194,8 +194,8 @@ X509Certificate::CreateFromDERCertChainUnsafeOptions(
if (der_certs.size() - 1 != intermediate_ca_certs.size())
return nullptr;
- bssl::UniquePtr<CRYPTO_BUFFER> handle = CreateCertBufferFromBytes(
- const_cast<char*>(der_certs[0].data()), der_certs[0].size());
+ bssl::UniquePtr<CRYPTO_BUFFER> handle =
+ CreateCertBufferFromBytes(base::as_bytes(base::make_span(der_certs[0])));
if (!handle)
return nullptr;
@@ -205,18 +205,15 @@ X509Certificate::CreateFromDERCertChainUnsafeOptions(
// static
scoped_refptr<X509Certificate> X509Certificate::CreateFromBytes(
- const char* data,
- size_t length) {
- return CreateFromBytesUnsafeOptions(data, length, {});
+ base::span<const uint8_t> data) {
+ return CreateFromBytesUnsafeOptions(data, {});
}
// static
scoped_refptr<X509Certificate> X509Certificate::CreateFromBytesUnsafeOptions(
- const char* data,
- size_t length,
+ base::span<const uint8_t> data,
UnsafeCreateOptions options) {
- bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer =
- CreateCertBufferFromBytes(data, length);
+ bssl::UniquePtr<CRYPTO_BUFFER> cert_buffer = CreateCertBufferFromBytes(data);
if (!cert_buffer)
return nullptr;
@@ -252,15 +249,15 @@ scoped_refptr<X509Certificate> X509Certificate::CreateFromPickleUnsafeOptions(
// static
CertificateList X509Certificate::CreateCertificateListFromBytes(
- const char* data,
- size_t length,
+ base::span<const uint8_t> data,
int format) {
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> certificates;
// Check to see if it is in a PEM-encoded form. This check is performed
// first, as both OS X and NSS will both try to convert if they detect
// PEM encoding, except they don't do it consistently between the two.
- base::StringPiece data_string(data, length);
+ base::StringPiece data_string(reinterpret_cast<const char*>(data.data()),
+ data.size());
std::vector<std::string> pem_headers;
// To maintain compatibility with NSS/Firefox, CERTIFICATE is a universally
@@ -274,8 +271,10 @@ CertificateList X509Certificate::CreateCertificateListFromBytes(
std::string decoded(pem_tokenizer.data());
bssl::UniquePtr<CRYPTO_BUFFER> handle;
- if (format & FORMAT_PEM_CERT_SEQUENCE)
- handle = CreateCertBufferFromBytes(decoded.c_str(), decoded.size());
+ if (format & FORMAT_PEM_CERT_SEQUENCE) {
+ handle =
+ CreateCertBufferFromBytes(base::as_bytes(base::make_span(decoded)));
+ }
if (handle) {
// Parsed a DER encoded certificate. All PEM blocks that follow must
// also be DER encoded certificates wrapped inside of PEM blocks.
@@ -292,7 +291,8 @@ CertificateList X509Certificate::CreateCertificateListFromBytes(
certificates.empty() && i < base::size(kFormatDecodePriority); ++i) {
if (format & kFormatDecodePriority[i]) {
certificates = CreateCertBuffersFromBytes(
- decoded.c_str(), decoded.size(), kFormatDecodePriority[i]);
+ base::as_bytes(base::make_span(decoded)),
+ kFormatDecodePriority[i]);
}
}
}
@@ -310,8 +310,7 @@ CertificateList X509Certificate::CreateCertificateListFromBytes(
for (size_t i = 0;
certificates.empty() && i < base::size(kFormatDecodePriority); ++i) {
if (format & kFormatDecodePriority[i])
- certificates =
- CreateCertBuffersFromBytes(data, length, kFormatDecodePriority[i]);
+ certificates = CreateCertBuffersFromBytes(data, kFormatDecodePriority[i]);
}
CertificateList results;
@@ -669,42 +668,37 @@ void X509Certificate::GetPublicKeyInfo(const CRYPTO_BUFFER* cert_buffer,
// static
bssl::UniquePtr<CRYPTO_BUFFER> X509Certificate::CreateCertBufferFromBytes(
- const char* data,
- size_t length) {
+ base::span<const uint8_t> data) {
der::Input tbs_certificate_tlv;
der::Input signature_algorithm_tlv;
der::BitString signature_value;
// Do a bare minimum of DER parsing here to make sure the input is not
// completely crazy. (This is required for at least
// CreateCertificateListFromBytes with FORMAT_AUTO, if not more.)
- if (!ParseCertificate(
- der::Input(reinterpret_cast<const uint8_t*>(data), length),
- &tbs_certificate_tlv, &signature_algorithm_tlv, &signature_value,
- nullptr)) {
+ if (!ParseCertificate(der::Input(data.data(), data.size()),
+ &tbs_certificate_tlv, &signature_algorithm_tlv,
+ &signature_value, nullptr)) {
return nullptr;
}
- return x509_util::CreateCryptoBuffer(reinterpret_cast<const uint8_t*>(data),
- length);
+ return x509_util::CreateCryptoBuffer(data.data(), data.size());
}
// static
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>
-X509Certificate::CreateCertBuffersFromBytes(const char* data,
- size_t length,
+X509Certificate::CreateCertBuffersFromBytes(base::span<const uint8_t> data,
Format format) {
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> results;
switch (format) {
case FORMAT_SINGLE_CERTIFICATE: {
- bssl::UniquePtr<CRYPTO_BUFFER> handle =
- CreateCertBufferFromBytes(data, length);
+ bssl::UniquePtr<CRYPTO_BUFFER> handle = CreateCertBufferFromBytes(data);
if (handle)
results.push_back(std::move(handle));
break;
}
case FORMAT_PKCS7: {
- CreateCertBuffersFromPKCS7Bytes(data, length, &results);
+ CreateCertBuffersFromPKCS7Bytes(data, &results);
break;
}
default: {
diff --git a/chromium/net/cert/x509_certificate.h b/chromium/net/cert/x509_certificate.h
index 8d7ec012d7a..2090c5f65eb 100644
--- a/chromium/net/cert/x509_certificate.h
+++ b/chromium/net/cert/x509_certificate.h
@@ -11,6 +11,7 @@
#include <string>
#include <vector>
+#include "base/containers/span.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -109,14 +110,13 @@ class NET_EXPORT X509Certificate
// Create an X509Certificate from the DER-encoded representation.
// Returns NULL on failure.
- static scoped_refptr<X509Certificate> CreateFromBytes(const char* data,
- size_t length);
+ static scoped_refptr<X509Certificate> CreateFromBytes(
+ base::span<const uint8_t> data);
// Create an X509Certificate with non-standard parsing options.
// Do not use without consulting //net owners.
static scoped_refptr<X509Certificate> CreateFromBytesUnsafeOptions(
- const char* data,
- size_t length,
+ base::span<const uint8_t> data,
UnsafeCreateOptions options);
// Create an X509Certificate from the representation stored in the given
@@ -137,9 +137,9 @@ class NET_EXPORT X509Certificate
// bit-wise OR of Format, indicating the possible formats the
// certificates may have been serialized as. If an error occurs, an empty
// collection will be returned.
- static CertificateList CreateCertificateListFromBytes(const char* data,
- size_t length,
- int format);
+ static CertificateList CreateCertificateListFromBytes(
+ base::span<const uint8_t> data,
+ int format);
// Appends a representation of this object to the given pickle.
// The Pickle contains the certificate and any certificates that were
@@ -243,13 +243,13 @@ class NET_EXPORT X509Certificate
// checking to reject obviously invalid inputs.
// Returns NULL on failure.
static bssl::UniquePtr<CRYPTO_BUFFER> CreateCertBufferFromBytes(
- const char* data,
- size_t length);
+ base::span<const uint8_t> data);
// Creates all possible CRYPTO_BUFFERs from |data| encoded in a specific
// |format|. Returns an empty collection on failure.
- static std::vector<bssl::UniquePtr<CRYPTO_BUFFER>>
- CreateCertBuffersFromBytes(const char* data, size_t length, Format format);
+ static std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> CreateCertBuffersFromBytes(
+ base::span<const uint8_t> data,
+ Format format);
// Calculates the SHA-256 fingerprint of the certificate. Returns an empty
// (all zero) fingerprint on failure.
diff --git a/chromium/net/cert/x509_certificate_unittest.cc b/chromium/net/cert/x509_certificate_unittest.cc
index a4f99f7855f..38af8da0851 100644
--- a/chromium/net/cert/x509_certificate_unittest.cc
+++ b/chromium/net/cert/x509_certificate_unittest.cc
@@ -8,11 +8,11 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/hash/sha1.h"
#include "base/pickle.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -111,8 +111,7 @@ void CheckGoogleCert(const scoped_refptr<X509Certificate>& google_cert,
TEST(X509CertificateTest, GoogleCertParsing) {
scoped_refptr<X509Certificate> google_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+ X509Certificate::CreateFromBytes(google_der));
CheckGoogleCert(google_cert, google_fingerprint,
1238192407, // Mar 27 22:20:07 2009 GMT
@@ -120,8 +119,8 @@ TEST(X509CertificateTest, GoogleCertParsing) {
}
TEST(X509CertificateTest, WebkitCertParsing) {
- scoped_refptr<X509Certificate> webkit_cert(X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
+ scoped_refptr<X509Certificate> webkit_cert(
+ X509Certificate::CreateFromBytes(webkit_der));
ASSERT_NE(static_cast<X509Certificate*>(nullptr), webkit_cert.get());
@@ -171,8 +170,8 @@ TEST(X509CertificateTest, WebkitCertParsing) {
}
TEST(X509CertificateTest, ThawteCertParsing) {
- scoped_refptr<X509Certificate> thawte_cert(X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)));
+ scoped_refptr<X509Certificate> thawte_cert(
+ X509Certificate::CreateFromBytes(thawte_der));
ASSERT_NE(static_cast<X509Certificate*>(nullptr), thawte_cert.get());
@@ -358,8 +357,7 @@ TEST(X509CertificateTest, TeletexStringIsNotARealT61String) {
TEST(X509CertificateTest, SerialNumbers) {
scoped_refptr<X509Certificate> google_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+ X509Certificate::CreateFromBytes(google_der));
ASSERT_TRUE(google_cert);
static const uint8_t google_serial[16] = {
@@ -440,8 +438,8 @@ TEST(X509CertificateTest, SerialNumber37BytesLong) {
}
TEST(X509CertificateTest, SHA256FingerprintsCorrectly) {
- scoped_refptr<X509Certificate> google_cert(X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der)));
+ scoped_refptr<X509Certificate> google_cert(
+ X509Certificate::CreateFromBytes(google_der));
ASSERT_TRUE(google_cert);
const SHA256HashValue google_sha256_fingerprint = {
@@ -581,26 +579,6 @@ TEST(X509CertificateTest, ExtractSPKIFromDERCert) {
EXPECT_EQ(0, memcmp(hash, kNistSPKIHash, sizeof(hash)));
}
-TEST(X509CertificateTest, HasTLSFeatureExtension) {
- base::FilePath certs_dir = GetTestCertsDirectory();
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(certs_dir, "tls_feature_extension.pem");
- ASSERT_NE(static_cast<X509Certificate*>(nullptr), cert.get());
-
- EXPECT_TRUE(asn1::HasTLSFeatureExtension(
- x509_util::CryptoBufferAsStringPiece(cert->cert_buffer())));
-}
-
-TEST(X509CertificateTest, DoesNotHaveTLSFeatureExtension) {
- base::FilePath certs_dir = GetTestCertsDirectory();
- scoped_refptr<X509Certificate> cert =
- ImportCertFromFile(certs_dir, "ok_cert.pem");
- ASSERT_NE(static_cast<X509Certificate*>(nullptr), cert.get());
-
- EXPECT_FALSE(asn1::HasTLSFeatureExtension(
- x509_util::CryptoBufferAsStringPiece(cert->cert_buffer())));
-}
-
TEST(X509CertificateTest, HasCanSignHttpExchangesDraftExtension) {
base::FilePath certs_dir = GetTestCertsDirectory();
scoped_refptr<X509Certificate> cert = ImportCertFromFile(
@@ -673,16 +651,14 @@ TEST(X509CertificateTest, Cache) {
bssl::UniquePtr<CRYPTO_BUFFER> thawte_cert_handle;
// Add a single certificate to the certificate cache.
- google_cert_handle = X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ google_cert_handle = X509Certificate::CreateCertBufferFromBytes(google_der);
ASSERT_TRUE(google_cert_handle);
scoped_refptr<X509Certificate> cert1(
X509Certificate::CreateFromBuffer(std::move(google_cert_handle), {}));
ASSERT_TRUE(cert1);
// Add the same certificate, but as a new handle.
- google_cert_handle = X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ google_cert_handle = X509Certificate::CreateCertBufferFromBytes(google_der);
ASSERT_TRUE(google_cert_handle);
scoped_refptr<X509Certificate> cert2(
X509Certificate::CreateFromBuffer(std::move(google_cert_handle), {}));
@@ -698,10 +674,8 @@ TEST(X509CertificateTest, Cache) {
// Add the same certificate, but this time with an intermediate. This
// should result in the intermediate being cached. Note that this is not
// a legitimate chain, but is suitable for testing.
- google_cert_handle = X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
- thawte_cert_handle = X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
+ google_cert_handle = X509Certificate::CreateCertBufferFromBytes(google_der);
+ thawte_cert_handle = X509Certificate::CreateCertBufferFromBytes(thawte_der);
ASSERT_TRUE(google_cert_handle);
ASSERT_TRUE(thawte_cert_handle);
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
@@ -720,12 +694,10 @@ TEST(X509CertificateTest, Cache) {
TEST(X509CertificateTest, Pickle) {
bssl::UniquePtr<CRYPTO_BUFFER> google_cert_handle =
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ X509Certificate::CreateCertBufferFromBytes(google_der);
ASSERT_TRUE(google_cert_handle);
bssl::UniquePtr<CRYPTO_BUFFER> thawte_cert_handle =
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der));
+ X509Certificate::CreateCertBufferFromBytes(thawte_der);
ASSERT_TRUE(thawte_cert_handle);
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
@@ -754,19 +726,16 @@ TEST(X509CertificateTest, Pickle) {
TEST(X509CertificateTest, IntermediateCertificates) {
scoped_refptr<X509Certificate> webkit_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der)));
+ X509Certificate::CreateFromBytes(webkit_der));
ASSERT_TRUE(webkit_cert);
scoped_refptr<X509Certificate> thawte_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(thawte_der), sizeof(thawte_der)));
+ X509Certificate::CreateFromBytes(thawte_der));
ASSERT_TRUE(thawte_cert);
bssl::UniquePtr<CRYPTO_BUFFER> google_handle;
// Create object with no intermediates:
- google_handle = X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(google_der), sizeof(google_der));
+ google_handle = X509Certificate::CreateCertBufferFromBytes(google_der);
scoped_refptr<X509Certificate> cert1;
cert1 =
X509Certificate::CreateFromBuffer(bssl::UpRef(google_handle.get()), {});
diff --git a/chromium/net/cert/x509_util_ios.cc b/chromium/net/cert/x509_util_ios.cc
index 309964f8482..d21a90c6ef4 100644
--- a/chromium/net/cert/x509_util_ios.cc
+++ b/chromium/net/cert/x509_util_ios.cc
@@ -39,9 +39,8 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
if (!der_data)
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
- CFDataGetLength(der_data)));
+ X509Certificate::CreateCertBufferFromBytes(base::make_span(
+ CFDataGetBytePtr(der_data), CFDataGetLength(der_data))));
if (!cert_handle)
return nullptr;
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
@@ -52,9 +51,8 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
if (!der_data)
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(CFDataGetBytePtr(der_data)),
- CFDataGetLength(der_data)));
+ X509Certificate::CreateCertBufferFromBytes(base::make_span(
+ CFDataGetBytePtr(der_data), CFDataGetLength(der_data))));
if (!intermediate_cert_handle)
return nullptr;
intermediates.push_back(std::move(intermediate_cert_handle));
diff --git a/chromium/net/cert/x509_util_mac.cc b/chromium/net/cert/x509_util_mac.cc
index 6a17a2fadc8..9546a5bfec4 100644
--- a/chromium/net/cert/x509_util_mac.cc
+++ b/chromium/net/cert/x509_util_mac.cc
@@ -99,7 +99,7 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(der_data.Data), der_data.Length));
+ base::make_span(der_data.Data, der_data.Length)));
if (!cert_handle)
return nullptr;
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
@@ -110,7 +110,7 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromSecCertificate(
}
bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(der_data.Data), der_data.Length));
+ base::make_span(der_data.Data, der_data.Length)));
if (!intermediate_cert_handle)
return nullptr;
intermediates.push_back(std::move(intermediate_cert_handle));
diff --git a/chromium/net/cert/x509_util_nss.cc b/chromium/net/cert/x509_util_nss.cc
index 9ba26e3b967..98827784394 100644
--- a/chromium/net/cert/x509_util_nss.cc
+++ b/chromium/net/cert/x509_util_nss.cc
@@ -208,8 +208,8 @@ ScopedCERTCertificateList CreateCERTCertificateListFromX509Certificate(
ScopedCERTCertificateList CreateCERTCertificateListFromBytes(const char* data,
size_t length,
int format) {
- CertificateList certs =
- X509Certificate::CreateCertificateListFromBytes(data, length, format);
+ CertificateList certs = X509Certificate::CreateCertificateListFromBytes(
+ base::as_bytes(base::make_span(data, length)), format);
ScopedCERTCertificateList nss_chain;
nss_chain.reserve(certs.size());
for (const scoped_refptr<X509Certificate>& cert : certs) {
@@ -249,8 +249,7 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCERTCertificate(
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(nss_cert->derCert.data),
- nss_cert->derCert.len));
+ base::make_span(nss_cert->derCert.data, nss_cert->derCert.len)));
if (!cert_handle)
return nullptr;
@@ -260,9 +259,8 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCERTCertificate(
if (!nss_intermediate || !nss_intermediate->derCert.len)
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(nss_intermediate->derCert.data),
- nss_intermediate->derCert.len));
+ X509Certificate::CreateCertBufferFromBytes(base::make_span(
+ nss_intermediate->derCert.data, nss_intermediate->derCert.len)));
if (!intermediate_cert_handle)
return nullptr;
intermediates.push_back(std::move(intermediate_cert_handle));
diff --git a/chromium/net/cert/x509_util_nss_unittest.cc b/chromium/net/cert/x509_util_nss_unittest.cc
index b06bc023b32..f8375753566 100644
--- a/chromium/net/cert/x509_util_nss_unittest.cc
+++ b/chromium/net/cert/x509_util_nss_unittest.cc
@@ -4,9 +4,9 @@
#include "net/cert/x509_util_nss.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
-#include "base/stl_util.h"
#include "net/cert/scoped_nss_types.h"
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
@@ -45,13 +45,11 @@ TEST(X509UtilNSSTest, IsSameCertificate) {
ASSERT_TRUE(webkit_nss_cert);
scoped_refptr<X509Certificate> google_x509_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(google_der), base::size(google_der)));
+ X509Certificate::CreateFromBytes(google_der));
ASSERT_TRUE(google_x509_cert);
scoped_refptr<X509Certificate> webkit_x509_cert(
- X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), base::size(webkit_der)));
+ X509Certificate::CreateFromBytes(webkit_der));
ASSERT_TRUE(webkit_x509_cert);
EXPECT_TRUE(x509_util::IsSameCertificate(google_nss_cert.get(),
diff --git a/chromium/net/cert/x509_util_unittest.cc b/chromium/net/cert/x509_util_unittest.cc
index 37f5e47eae1..0029d384a31 100644
--- a/chromium/net/cert/x509_util_unittest.cc
+++ b/chromium/net/cert/x509_util_unittest.cc
@@ -37,7 +37,7 @@ TEST(X509UtilTest, CreateKeyAndSelfSigned) {
ASSERT_TRUE(private_key.get());
scoped_refptr<X509Certificate> cert(X509Certificate::CreateFromBytes(
- der_cert.data(), der_cert.size()));
+ base::as_bytes(base::make_span(der_cert))));
ASSERT_TRUE(cert.get());
EXPECT_EQ("subject", cert->subject().common_name);
@@ -146,8 +146,8 @@ TEST(X509UtilTest, CreateSelfSigned) {
base::Time::Now(), base::Time::Now() + base::TimeDelta::FromDays(1), {},
&der_cert));
- scoped_refptr<X509Certificate> cert =
- X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_cert)));
ASSERT_TRUE(cert.get());
EXPECT_EQ("subject", cert->subject().GetDisplayName());
@@ -219,9 +219,8 @@ TEST(X509UtilTest, CreateChannelBindings_SHA1) {
0x4c, 0x85, 0x62, 0x1b, 0x99, 0x83, 0x47, 0x5f, 0x95,
};
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(kCertificateDataDER),
- sizeof(kCertificateDataDER));
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(kCertificateDataDER);
ASSERT_TRUE(cert);
std::string channel_bindings;
@@ -328,9 +327,8 @@ TEST(X509UtilTest, CreateChannelBindings_SHA256) {
0x75, 0x57, 0x0e, 0xaf, 0xa3, 0x10, 0xbf, 0xf1, 0xbb,
};
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(kCertificateDataDER),
- sizeof(kCertificateDataDER));
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(kCertificateDataDER);
ASSERT_TRUE(cert);
std::string channel_bindings;
@@ -445,9 +443,8 @@ TEST(X509UtilTest, CreateChannelBindings_SHA384) {
0x7d, 0x7d, 0x18, 0xa8, 0xee, 0x80, 0x26, 0xb2, 0x1f,
};
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(kCertificateDataDER),
- sizeof(kCertificateDataDER));
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(kCertificateDataDER);
ASSERT_TRUE(cert);
std::string channel_bindings;
@@ -557,9 +554,8 @@ TEST(X509UtilTest, CreateChannelBindings_SHA512) {
0xaa, 0x65, 0x51, 0x51, 0x60, 0x4f, 0x58, 0x28,
};
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(kCertificateDataDER),
- sizeof(kCertificateDataDER));
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(kCertificateDataDER);
ASSERT_TRUE(cert);
std::string channel_bindings;
@@ -658,9 +654,8 @@ TEST(X509UtilTest, CreateChannelBindings_Unsupported_MD4) {
0xef, 0xba, 0x6d, 0x5e, 0x88, 0x01, 0xaf,
};
- scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(kCertificateDataDER),
- sizeof(kCertificateDataDER));
+ scoped_refptr<X509Certificate> cert =
+ X509Certificate::CreateFromBytes(kCertificateDataDER);
ASSERT_TRUE(cert);
std::string channel_bindings;
diff --git a/chromium/net/cert/x509_util_win.cc b/chromium/net/cert/x509_util_win.cc
index 0b2170c1ff7..ad819d986f6 100644
--- a/chromium/net/cert/x509_util_win.cc
+++ b/chromium/net/cert/x509_util_win.cc
@@ -15,14 +15,6 @@ namespace net {
namespace x509_util {
-namespace {
-
-using ScopedHCERTSTORE = crypto::ScopedCAPIHandle<
- HCERTSTORE,
- crypto::CAPIDestroyerWithFlags<HCERTSTORE, CertCloseStore, 0>>;
-
-} // namespace
-
scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
PCCERT_CONTEXT os_cert,
const std::vector<PCCERT_CONTEXT>& os_chain) {
@@ -37,8 +29,7 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> cert_handle(
X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(os_cert->pbCertEncoded),
- os_cert->cbCertEncoded));
+ base::make_span(os_cert->pbCertEncoded, os_cert->cbCertEncoded)));
if (!cert_handle)
return nullptr;
std::vector<bssl::UniquePtr<CRYPTO_BUFFER>> intermediates;
@@ -47,9 +38,8 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
!os_intermediate->cbCertEncoded)
return nullptr;
bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(os_intermediate->pbCertEncoded),
- os_intermediate->cbCertEncoded));
+ X509Certificate::CreateCertBufferFromBytes(base::make_span(
+ os_intermediate->pbCertEncoded, os_intermediate->cbCertEncoded)));
if (!intermediate_cert_handle)
return nullptr;
intermediates.push_back(std::move(intermediate_cert_handle));
@@ -60,20 +50,21 @@ scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
return result;
}
-ScopedPCCERT_CONTEXT CreateCertContextWithChain(const X509Certificate* cert) {
+crypto::ScopedPCCERT_CONTEXT CreateCertContextWithChain(
+ const X509Certificate* cert) {
return CreateCertContextWithChain(cert, InvalidIntermediateBehavior::kFail);
}
-ScopedPCCERT_CONTEXT CreateCertContextWithChain(
+crypto::ScopedPCCERT_CONTEXT CreateCertContextWithChain(
const X509Certificate* cert,
InvalidIntermediateBehavior invalid_intermediate_behavior) {
// Create an in-memory certificate store to hold the certificate and its
// intermediate certificates. The store will be referenced in the returned
// PCCERT_CONTEXT, and will not be freed until the PCCERT_CONTEXT is freed.
- ScopedHCERTSTORE store(
+ crypto::ScopedHCERTSTORE store(
CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL,
CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG, nullptr));
- if (!store.get())
+ if (!store.is_valid())
return nullptr;
PCCERT_CONTEXT primary_cert = nullptr;
@@ -84,7 +75,7 @@ ScopedPCCERT_CONTEXT CreateCertContextWithChain(
CERT_STORE_ADD_ALWAYS, &primary_cert);
if (!ok || !primary_cert)
return nullptr;
- ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
+ crypto::ScopedPCCERT_CONTEXT scoped_primary_cert(primary_cert);
for (const auto& intermediate : cert->intermediate_buffers()) {
ok = CertAddEncodedCertificateToStore(
diff --git a/chromium/net/cert/x509_util_win.h b/chromium/net/cert/x509_util_win.h
index c1c8f49a6c1..7d667797594 100644
--- a/chromium/net/cert/x509_util_win.h
+++ b/chromium/net/cert/x509_util_win.h
@@ -12,22 +12,13 @@
#include "base/memory/ref_counted.h"
#include "base/win/wincrypt_shim.h"
+#include "crypto/scoped_capi_types.h"
#include "net/base/hash_value.h"
#include "net/base/net_export.h"
#include "net/cert/x509_certificate.h"
namespace net {
-struct FreeCertContextFunctor {
- void operator()(PCCERT_CONTEXT context) const {
- if (context)
- CertFreeCertificateContext(context);
- }
-};
-
-using ScopedPCCERT_CONTEXT =
- std::unique_ptr<const CERT_CONTEXT, FreeCertContextFunctor>;
-
namespace x509_util {
// Creates an X509Certificate representing |os_cert| with intermediates
@@ -52,8 +43,8 @@ NET_EXPORT scoped_refptr<X509Certificate> CreateX509CertificateFromCertContexts(
// multiple threads if no further modifications happen, it is generally
// preferable for each thread that needs such a context to obtain its own,
// rather than risk thread-safety issues by sharing.
-NET_EXPORT ScopedPCCERT_CONTEXT
-CreateCertContextWithChain(const X509Certificate* cert);
+NET_EXPORT crypto::ScopedPCCERT_CONTEXT CreateCertContextWithChain(
+ const X509Certificate* cert);
// Specify behavior if an intermediate certificate fails CERT_CONTEXT parsing.
// kFail means the function should return a failure result immediately. kIgnore
@@ -62,7 +53,7 @@ enum class InvalidIntermediateBehavior { kFail, kIgnore };
// As CreateCertContextWithChain above, but |invalid_intermediate_behavior|
// specifies behavior if intermediates of |cert| could not be converted.
-NET_EXPORT ScopedPCCERT_CONTEXT CreateCertContextWithChain(
+NET_EXPORT crypto::ScopedPCCERT_CONTEXT CreateCertContextWithChain(
const X509Certificate* cert,
InvalidIntermediateBehavior invalid_intermediate_behavior);
diff --git a/chromium/net/cert_net/cert_net_fetcher_url_request_unittest.cc b/chromium/net/cert_net/cert_net_fetcher_url_request_unittest.cc
index 443615e6f8a..76c138de864 100644
--- a/chromium/net/cert_net/cert_net_fetcher_url_request_unittest.cc
+++ b/chromium/net/cert_net/cert_net_fetcher_url_request_unittest.cc
@@ -68,7 +68,7 @@ class RequestContext : public URLRequestContext {
std::make_unique<HttpServerProperties>());
storage_.set_quic_context(std::make_unique<QuicContext>());
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.host_resolver = host_resolver();
session_context.cert_verifier = cert_verifier();
session_context.transport_security_state = transport_security_state();
@@ -78,7 +78,7 @@ class RequestContext : public URLRequestContext {
session_context.http_server_properties = http_server_properties();
session_context.quic_context = quic_context();
storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
- HttpNetworkSession::Params(), session_context));
+ HttpNetworkSessionParams(), session_context));
storage_.set_http_transaction_factory(std::make_unique<HttpCache>(
storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
false /* is_main_cache */));
diff --git a/chromium/net/cookies/OWNERS b/chromium/net/cookies/OWNERS
index 2ddd82195da..76e5bbc884b 100644
--- a/chromium/net/cookies/OWNERS
+++ b/chromium/net/cookies/OWNERS
@@ -1,5 +1,3 @@
-chlily@chromium.org
-estark@chromium.org
+bingler@chromium.org
mkwst@chromium.org
-mmenke@chromium.org
morlovich@chromium.org
diff --git a/chromium/net/cookies/canonical_cookie.cc b/chromium/net/cookies/canonical_cookie.cc
index 83232c77be5..e9d0122b6c2 100644
--- a/chromium/net/cookies/canonical_cookie.cc
+++ b/chromium/net/cookies/canonical_cookie.cc
@@ -63,6 +63,7 @@
#include "net/base/url_util.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
+#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_util.h"
#include "net/cookies/parsed_cookie.h"
#include "url/gurl.h"
@@ -194,7 +195,7 @@ void ApplySameSiteCookieWarningToStatus(
CookieSameSite samesite,
CookieEffectiveSameSite effective_samesite,
bool is_secure,
- CookieOptions::SameSiteCookieContext same_site_context,
+ const CookieOptions::SameSiteCookieContext& same_site_context,
CookieInclusionStatus* status,
bool is_cookie_being_set) {
if (samesite == CookieSameSite::UNSPECIFIED &&
@@ -256,11 +257,77 @@ void ApplySameSiteCookieWarningToStatus(
}
}
- // If there are reasons to exclude the cookie other than the new SameSite
- // rules, don't warn about the cookie at all.
+ // Apply warning for whether inclusion was changed by considering redirects
+ // for the SameSite context calculation. This does not look at the actual
+ // inclusion or exclusion, but only at whether the inclusion differs between
+ // considering redirects and not.
+ using ContextDowngradeType = CookieOptions::SameSiteCookieContext::
+ ContextMetadata::ContextDowngradeType;
+ const auto& metadata = same_site_context.GetMetadataForCurrentSchemefulMode();
+ bool apply_cross_site_redirect_downgrade_warning = false;
+ switch (effective_samesite) {
+ case CookieEffectiveSameSite::STRICT_MODE:
+ // Strict contexts are all normalized to lax for cookie writes, so a
+ // strict-to-{lax,cross} downgrade cannot occur for response cookies.
+ apply_cross_site_redirect_downgrade_warning =
+ is_cookie_being_set ? metadata.cross_site_redirect_downgrade ==
+ ContextDowngradeType::kLaxToCross
+ : (metadata.cross_site_redirect_downgrade ==
+ ContextDowngradeType::kStrictToLax ||
+ metadata.cross_site_redirect_downgrade ==
+ ContextDowngradeType::kStrictToCross);
+ break;
+ case CookieEffectiveSameSite::LAX_MODE:
+ case CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
+ // Note that a lax-to-cross downgrade can only happen for response
+ // cookies, because a laxly same-site context only happens for a safe
+ // top-level cross-site request, which cannot be downgraded due to a
+ // cross-site redirect to a non-top-level or unsafe cross-site request.
+ apply_cross_site_redirect_downgrade_warning =
+ metadata.cross_site_redirect_downgrade ==
+ (is_cookie_being_set ? ContextDowngradeType::kLaxToCross
+ : ContextDowngradeType::kStrictToCross);
+ break;
+ default:
+ break;
+ }
+ if (apply_cross_site_redirect_downgrade_warning) {
+ status->AddWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
+ }
+
+ // If there are reasons to exclude the cookie other than SameSite, don't warn
+ // about the cookie at all.
status->MaybeClearSameSiteWarning();
}
+// These values are persisted to logs. Entries should not be renumbered and
+// numeric values should never be reused.
+enum class SameSiteNonePartyContextType {
+ // SameSite=None was required in order for the cookie to be included.
+ kSameSiteNoneRequired = 0,
+ // The cookie would have been included if it were SameParty (using only the
+ // top frame and resource URL).
+ kSamePartyTopResource = 1,
+ // The cookie would have been included if it were SameParty (using the
+ // resource URL and all frame ancestors).
+ kSamePartyAncestors = 2,
+ // The cookie would have been included if it were SameSite=Lax.
+ kSameSiteLax = 3,
+ // The cookie would have been included if it were SameSite=Strict.
+ kSameSiteStrict = 4,
+ kMaxValue = kSameSiteStrict
+};
+
+void RecordSameSiteNoneReadContextMetric(SameSiteNonePartyContextType type) {
+ UMA_HISTOGRAM_ENUMERATION("Cookie.SameSiteNone.PartyContext.Read", type);
+}
+
+void RecordSameSiteNoneWriteContextMetric(SameSiteNonePartyContextType type) {
+ UMA_HISTOGRAM_ENUMERATION("Cookie.SameSiteNone.PartyContext.Write", type);
+}
+
} // namespace
CookieAccessParams::CookieAccessParams(CookieAccessSemantics access_semantics,
@@ -274,24 +341,33 @@ CanonicalCookie::CanonicalCookie() = default;
CanonicalCookie::CanonicalCookie(const CanonicalCookie& other) = default;
-CanonicalCookie::CanonicalCookie(const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- const base::Time& last_access,
- bool secure,
- bool httponly,
- CookieSameSite same_site,
- CookiePriority priority,
- bool same_party,
- CookieSourceScheme source_scheme,
- int source_port)
- : name_(name),
- value_(value),
- domain_(domain),
- path_(path),
+CanonicalCookie::CanonicalCookie(CanonicalCookie&& other) = default;
+
+CanonicalCookie& CanonicalCookie::operator=(const CanonicalCookie& other) =
+ default;
+
+CanonicalCookie& CanonicalCookie::operator=(CanonicalCookie&& other) = default;
+
+CanonicalCookie::CanonicalCookie(
+ std::string name,
+ std::string value,
+ std::string domain,
+ std::string path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
+ bool secure,
+ bool httponly,
+ CookieSameSite same_site,
+ CookiePriority priority,
+ bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
+ CookieSourceScheme source_scheme,
+ int source_port)
+ : name_(std::move(name)),
+ value_(std::move(value)),
+ domain_(std::move(domain)),
+ path_(std::move(path)),
creation_date_(creation),
expiry_date_(expiration),
last_access_date_(last_access),
@@ -300,6 +376,7 @@ CanonicalCookie::CanonicalCookie(const std::string& name,
same_site_(same_site),
priority_(priority),
same_party_(same_party),
+ partition_key_(std::move(partition_key)),
source_scheme_(source_scheme) {
SetSourcePort(source_port);
}
@@ -382,6 +459,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
const std::string& cookie_line,
const base::Time& creation_time,
absl::optional<base::Time> server_time,
+ absl::optional<CookiePartitionKey> cookie_partition_key,
CookieInclusionStatus* status) {
// Put a pointer on the stack so the rest of the function can assign to it if
// the default nullptr is passed in.
@@ -391,12 +469,14 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
}
*status = CookieInclusionStatus();
- ParsedCookie parsed_cookie(cookie_line);
+ ParsedCookie parsed_cookie(cookie_line, status);
if (!parsed_cookie.IsValid()) {
DVLOG(net::cookie_util::kVlogSetCookies)
<< "WARNING: Couldn't parse cookie";
- status->AddExclusionReason(CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ DCHECK(status->HasExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE));
// Don't continue, because an invalid ParsedCookie doesn't have any
// attributes.
// TODO(chlily): Log metrics.
@@ -440,6 +520,20 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
if (parsed_cookie.IsSameParty())
base::UmaHistogramBoolean("Cookie.IsSamePartyValid", is_same_party_valid);
+ bool is_partitioned_valid = IsCookiePartitionedValid(parsed_cookie);
+ if (!is_partitioned_valid) {
+ status->AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED);
+ }
+
+ // Collect metrics on whether usage of the Partitioned attribute is correct.
+ if (parsed_cookie.IsPartitioned()) {
+ base::UmaHistogramBoolean("Cookie.IsPartitionedValid",
+ is_partitioned_valid);
+ } else {
+ cookie_partition_key = absl::nullopt;
+ }
+
if (!status->IsInclude())
return nullptr;
@@ -452,11 +546,14 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
// Get the port, this will get a default value if a port isn't provided.
int source_port = url.EffectiveIntPort();
+ // TODO(crbug.com/987177) Add partition key if Partitioned is present in the
+ // cookie line.
std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie(
parsed_cookie.Name(), parsed_cookie.Value(), cookie_domain, cookie_path,
creation_time, cookie_expires, creation_time, parsed_cookie.IsSecure(),
parsed_cookie.IsHttpOnly(), samesite, parsed_cookie.Priority(),
- parsed_cookie.IsSameParty(), source_scheme, source_port));
+ parsed_cookie.IsSameParty(), cookie_partition_key, source_scheme,
+ source_port));
// TODO(chlily): Log metrics.
if (!cc->IsCanonical()) {
@@ -475,7 +572,6 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::Create(
}
// static
-// TODO(crbug.com/957184): This should ideally return a CookieInclusionStatus.
std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie(
const GURL& url,
const std::string& name,
@@ -489,49 +585,94 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie(
bool http_only,
CookieSameSite same_site,
CookiePriority priority,
- bool same_party) {
+ bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
+ CookieInclusionStatus* status) {
+ // Put a pointer on the stack so the rest of the function can assign to it if
+ // the default nullptr is passed in.
+ CookieInclusionStatus blank_status;
+ if (status == nullptr) {
+ status = &blank_status;
+ }
+ *status = CookieInclusionStatus();
+
// Validate consistency of passed arguments.
if (ParsedCookie::ParseTokenString(name) != name ||
- ParsedCookie::ParseValueString(value) != value ||
- !ParsedCookie::IsValidCookieAttributeValue(name) ||
- !ParsedCookie::IsValidCookieAttributeValue(value) ||
- ParsedCookie::ParseValueString(domain) != domain ||
- ParsedCookie::ParseValueString(path) != path) {
- return nullptr;
+ !ParsedCookie::IsValidCookieAttributeValue(name)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ } else if (ParsedCookie::ParseValueString(value) != value ||
+ !ParsedCookie::IsValidCookieAttributeValue(value)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ } else if (ParsedCookie::ParseValueString(path) != path) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ } else if (name.empty() && value.empty()) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
}
- if (name.empty() && value.empty())
- return nullptr;
+ if (ParsedCookie::ParseValueString(domain) != domain) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
+ }
+ std::string cookie_domain;
// This validation step must happen before GetCookieDomainWithString, so it
// doesn't fail DCHECKs.
- if (!cookie_util::DomainIsHostOnly(url.host()))
- return nullptr;
-
- std::string cookie_domain;
- if (!cookie_util::GetCookieDomainWithString(url, domain, &cookie_domain))
- return nullptr;
+ if (!cookie_util::DomainIsHostOnly(url.host())) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
+ } else if (!cookie_util::GetCookieDomainWithString(url, domain,
+ &cookie_domain)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
+ }
- CookieSourceScheme source_scheme = url.SchemeIsCryptographic()
- ? CookieSourceScheme::kSecure
- : CookieSourceScheme::kNonSecure;
+ CookieSourceScheme source_scheme = CookieSourceScheme::kNonSecure;
+ // This validation step must happen before SchemeIsCryptographic, so it
+ // doesn't fail DCHECKs.
+ if (!url.is_valid()) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
+ } else {
+ source_scheme = url.SchemeIsCryptographic()
+ ? CookieSourceScheme::kSecure
+ : CookieSourceScheme::kNonSecure;
+ }
// Get the port, this will get a default value if a port isn't provided.
int source_port = url.EffectiveIntPort();
std::string cookie_path = CanonicalCookie::CanonPathWithString(url, path);
- if (!path.empty() && cookie_path != path)
- return nullptr;
+ if (!path.empty() && cookie_path != path) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ }
- if (!IsCookiePrefixValid(GetCookiePrefix(name), url, secure, domain,
- cookie_path)) {
- return nullptr;
+ CookiePrefix prefix = GetCookiePrefix(name);
+ if (!IsCookiePrefixValid(prefix, url, secure, domain, cookie_path)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX);
}
- if (!IsCookieSamePartyValid(same_party, secure, same_site))
- return nullptr;
+ if (!IsCookieSamePartyValid(same_party, secure, same_site)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY);
+ }
+ if (!IsCookiePartitionedValid(partition_key.has_value(), prefix,
+ same_party)) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED);
+ }
+
+ if (!last_access_time.is_null() && creation_time.is_null()) {
+ status->AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ }
- if (!last_access_time.is_null() && creation_time.is_null())
+ if (!status->IsInclude())
return nullptr;
// Canonicalize path again to make sure it escapes characters as needed.
@@ -546,7 +687,7 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie(
std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie(
name, value, cookie_domain, cookie_path, creation_time, expiration_time,
last_access_time, secure, http_only, same_site, priority, same_party,
- source_scheme, source_port));
+ partition_key, source_scheme, source_port));
DCHECK(cc->IsCanonical());
return cc;
@@ -554,23 +695,25 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateSanitizedCookie(
// static
std::unique_ptr<CanonicalCookie> CanonicalCookie::FromStorage(
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- const base::Time& last_access,
+ std::string name,
+ std::string value,
+ std::string domain,
+ std::string path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
bool secure,
bool httponly,
CookieSameSite same_site,
CookiePriority priority,
bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
CookieSourceScheme source_scheme,
int source_port) {
std::unique_ptr<CanonicalCookie> cc = base::WrapUnique(new CanonicalCookie(
- name, value, domain, path, creation, expiration, last_access, secure,
- httponly, same_site, priority, same_party, source_scheme, source_port));
+ std::move(name), std::move(value), std::move(domain), std::move(path),
+ creation, expiration, last_access, secure, httponly, same_site, priority,
+ same_party, partition_key, source_scheme, source_port));
if (!cc->IsCanonical())
return nullptr;
return cc;
@@ -590,11 +733,13 @@ std::unique_ptr<CanonicalCookie> CanonicalCookie::CreateUnsafeCookieForTesting(
CookieSameSite same_site,
CookiePriority priority,
bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
CookieSourceScheme source_scheme,
int source_port) {
return base::WrapUnique(new CanonicalCookie(
name, value, domain, path, creation, expiration, last_access, secure,
- httponly, same_site, priority, same_party, source_scheme, source_port));
+ httponly, same_site, priority, same_party, partition_key, source_scheme,
+ source_port));
}
std::string CanonicalCookie::DomainWithoutDot() const {
@@ -765,13 +910,11 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL(
break;
}
- // If both SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure
- // are enabled, non-SameSite cookies without the Secure attribute should be
- // ignored. This can apply to cookies which were created before the
- // experimental options were enabled (as non-SameSite, insecure cookies cannot
- // be set while the options are on).
+ // Unless legacy access semantics are in effect, SameSite=None cookies without
+ // the Secure attribute should be ignored. This can apply to cookies which
+ // were created before "SameSite=None requires Secure" was enabled (as
+ // SameSite=None insecure cookies cannot be set while the options are on).
if (params.access_semantics != CookieAccessSemantics::LEGACY &&
- cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled() &&
SameSite() == CookieSameSite::NO_RESTRICTION && !IsSecure()) {
status.AddExclusionReason(
CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE);
@@ -823,20 +966,59 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL(
break;
}
case CookieSamePartyStatus::kNoSamePartyEnforcement:
+ // Only apply SameSite-related warnings if SameParty is not in effect.
+ ApplySameSiteCookieWarningToStatus(
+ SameSite(), effective_same_site, IsSecure(),
+ options.same_site_cookie_context(), &status,
+ false /* is_cookie_being_set */);
break;
}
- // TODO(chlily): Apply warning if SameSite-by-default is enabled but
- // params.access_semantics is LEGACY?
- ApplySameSiteCookieWarningToStatus(SameSite(), effective_same_site,
- IsSecure(),
- options.same_site_cookie_context(),
- &status, false /* is_cookie_being_set */);
-
if (status.IsInclude()) {
UMA_HISTOGRAM_ENUMERATION("Cookie.IncludedRequestEffectiveSameSite",
effective_same_site,
CookieEffectiveSameSite::COUNT);
+
+ if (SameSite() == CookieSameSite::NO_RESTRICTION) {
+ SamePartyContext::Type top_resource =
+ options.same_party_context().top_resource_for_metrics_only();
+ SamePartyContext::Type ancestors =
+ options.same_party_context().ancestors_for_metrics_only();
+
+ if (top_resource == SamePartyContext::Type::kCrossParty) {
+ status.AddWarningReason(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED);
+ RecordSameSiteNoneReadContextMetric(
+ SameSiteNonePartyContextType::kSameSiteNoneRequired);
+ } else if (ancestors == SamePartyContext::Type::kCrossParty) {
+ status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE);
+ RecordSameSiteNoneReadContextMetric(
+ SameSiteNonePartyContextType::kSamePartyTopResource);
+ } else if (cookie_inclusion_context <
+ CookieOptions::SameSiteCookieContext::ContextType::
+ SAME_SITE_LAX) {
+ status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS);
+ RecordSameSiteNoneReadContextMetric(
+ SameSiteNonePartyContextType::kSamePartyAncestors);
+ } else if (cookie_inclusion_context <
+ CookieOptions::SameSiteCookieContext::ContextType::
+ SAME_SITE_STRICT) {
+ status.AddWarningReason(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX);
+ RecordSameSiteNoneReadContextMetric(
+ SameSiteNonePartyContextType::kSameSiteLax);
+ } else {
+ status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT);
+ RecordSameSiteNoneReadContextMetric(
+ SameSiteNonePartyContextType::kSameSiteStrict);
+ }
+ }
}
if (status.ShouldRecordDowngradeMetrics()) {
@@ -844,7 +1026,13 @@ CookieAccessResult CanonicalCookie::IncludeForRequestURL(
status.GetBreakingDowngradeMetricsEnumValue(url));
}
- // TODO(chlily): Log metrics.
+ if (status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION)) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Cookie.CrossSiteRedirectDowngradeChangesInclusion.Read", SameSite());
+ }
+
return CookieAccessResult(effective_same_site, status,
params.access_semantics,
is_allowed_to_access_secure_cookies);
@@ -901,11 +1089,9 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext(
CookieInclusionStatus::EXCLUDE_HTTP_ONLY);
}
- // If both SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure
- // are enabled, non-SameSite cookies without the Secure attribute will be
- // rejected.
+ // Unless legacy access semantics are in effect, SameSite=None cookies without
+ // the Secure attribute will be rejected.
if (params.access_semantics != CookieAccessSemantics::LEGACY &&
- cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled() &&
SameSite() == CookieSameSite::NO_RESTRICTION && !IsSecure()) {
DVLOG(net::cookie_util::kVlogSetCookies)
<< "SetCookie() rejecting insecure cookie with SameSite=None.";
@@ -1014,21 +1200,62 @@ CookieAccessResult CanonicalCookie::IsSetPermittedInContext(
break;
}
case CookieSamePartyStatus::kNoSamePartyEnforcement:
+ // Only apply SameSite-related warnings if SameParty is not in effect.
+ ApplySameSiteCookieWarningToStatus(
+ SameSite(), access_result.effective_same_site, IsSecure(),
+ options.same_site_cookie_context(), &access_result.status,
+ true /* is_cookie_being_set */);
break;
}
- ApplySameSiteCookieWarningToStatus(
- SameSite(), access_result.effective_same_site, IsSecure(),
- options.same_site_cookie_context(), &access_result.status,
- true /* is_cookie_being_set */);
-
if (access_result.status.IsInclude()) {
UMA_HISTOGRAM_ENUMERATION("Cookie.IncludedResponseEffectiveSameSite",
access_result.effective_same_site,
CookieEffectiveSameSite::COUNT);
+
+ if (SameSite() == CookieSameSite::NO_RESTRICTION) {
+ SamePartyContext::Type top_resource =
+ options.same_party_context().top_resource_for_metrics_only();
+ SamePartyContext::Type ancestors =
+ options.same_party_context().ancestors_for_metrics_only();
+
+ if (top_resource == SamePartyContext::Type::kCrossParty) {
+ access_result.status.AddWarningReason(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED);
+ RecordSameSiteNoneWriteContextMetric(
+ SameSiteNonePartyContextType::kSameSiteNoneRequired);
+ } else if (ancestors == SamePartyContext::Type::kCrossParty) {
+ access_result.status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE);
+ RecordSameSiteNoneWriteContextMetric(
+ SameSiteNonePartyContextType::kSamePartyTopResource);
+ } else if (cookie_inclusion_context <
+ CookieOptions::SameSiteCookieContext::ContextType::
+ SAME_SITE_LAX) {
+ access_result.status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS);
+ RecordSameSiteNoneWriteContextMetric(
+ SameSiteNonePartyContextType::kSamePartyAncestors);
+ } else {
+ // NB: unlike when sending a cookie, there's no distinction between
+ // SameSite=Lax and SameSite=Strict when setting a cookie.
+ access_result.status.AddWarningReason(
+ CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT);
+ RecordSameSiteNoneWriteContextMetric(
+ SameSiteNonePartyContextType::kSameSiteStrict);
+ }
+ }
}
- // TODO(chlily): Log metrics.
+ if (access_result.status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION)) {
+ UMA_HISTOGRAM_ENUMERATION(
+ "Cookie.CrossSiteRedirectDowngradeChangesInclusion.Write", SameSite());
+ }
return access_result;
}
@@ -1048,7 +1275,7 @@ bool CanonicalCookie::IsCanonical() const {
// Not checking domain or path against ParsedCookie as it may have
// come purely from the URL.
if (ParsedCookie::ParseTokenString(name_) != name_ ||
- ParsedCookie::ParseValueString(value_) != value_ ||
+ !ParsedCookie::ValueMatchesParsedValue(value_) ||
!ParsedCookie::IsValidCookieAttributeValue(name_) ||
!ParsedCookie::IsValidCookieAttributeValue(value_)) {
return false;
@@ -1072,7 +1299,8 @@ bool CanonicalCookie::IsCanonical() const {
if (path_.empty() || path_[0] != '/')
return false;
- switch (GetCookiePrefix(name_)) {
+ CookiePrefix prefix = GetCookiePrefix(name_);
+ switch (prefix) {
case COOKIE_PREFIX_HOST:
if (!secure_ || path_ != "/" || domain_.empty() || domain_[0] == '.')
return false;
@@ -1085,7 +1313,10 @@ bool CanonicalCookie::IsCanonical() const {
break;
}
- return IsCookieSamePartyValid(same_party_, secure_, same_site_);
+ if (!IsCookieSamePartyValid(same_party_, secure_, same_site_))
+ return false;
+
+ return IsCookiePartitionedValid(IsPartitioned(), prefix, same_party_);
}
bool CanonicalCookie::IsEffectivelySameSiteNone(
@@ -1185,24 +1416,16 @@ CookieEffectiveSameSite CanonicalCookie::GetEffectiveSameSite(
? kShortLaxAllowUnsafeMaxAge
: kLaxAllowUnsafeMaxAge);
- bool should_apply_same_site_lax_by_default =
- cookie_util::IsSameSiteByDefaultCookiesEnabled();
- if (access_semantics == CookieAccessSemantics::LEGACY) {
- should_apply_same_site_lax_by_default = false;
- } else if (access_semantics == CookieAccessSemantics::NONLEGACY) {
- should_apply_same_site_lax_by_default = true;
- }
-
switch (SameSite()) {
// If a cookie does not have a SameSite attribute, the effective SameSite
- // mode depends on the SameSiteByDefaultCookies setting and whether the
- // cookie is recently-created.
+ // mode depends on the access semantics and whether the cookie is
+ // recently-created.
case CookieSameSite::UNSPECIFIED:
- return should_apply_same_site_lax_by_default
- ? (IsRecentlyCreated(lax_allow_unsafe_threshold_age)
+ return (access_semantics == CookieAccessSemantics::LEGACY)
+ ? CookieEffectiveSameSite::NO_RESTRICTION
+ : (IsRecentlyCreated(lax_allow_unsafe_threshold_age)
? CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE
- : CookieEffectiveSameSite::LAX_MODE)
- : CookieEffectiveSameSite::NO_RESTRICTION;
+ : CookieEffectiveSameSite::LAX_MODE);
case CookieSameSite::NO_RESTRICTION:
return CookieEffectiveSameSite::NO_RESTRICTION;
case CookieSameSite::LAX_MODE:
@@ -1233,6 +1456,24 @@ bool CanonicalCookie::IsCookieSamePartyValid(bool is_same_party,
return is_secure && (same_site != CookieSameSite::STRICT_MODE);
}
+// static
+bool CanonicalCookie::IsCookiePartitionedValid(
+ const ParsedCookie& parsed_cookie) {
+ return IsCookiePartitionedValid(parsed_cookie.IsPartitioned(),
+ GetCookiePrefix(parsed_cookie.Name()),
+ parsed_cookie.IsSameParty());
+}
+
+// static
+bool CanonicalCookie::IsCookiePartitionedValid(
+ bool is_partitioned,
+ CanonicalCookie::CookiePrefix prefix,
+ bool is_same_party) {
+ if (!is_partitioned)
+ return true;
+ return prefix == CookiePrefix::COOKIE_PREFIX_HOST && !is_same_party;
+}
+
CookieAndLineWithAccessResult::CookieAndLineWithAccessResult() = default;
CookieAndLineWithAccessResult::CookieAndLineWithAccessResult(
diff --git a/chromium/net/cookies/canonical_cookie.h b/chromium/net/cookies/canonical_cookie.h
index f716ed3f17a..a8dd4c7a704 100644
--- a/chromium/net/cookies/canonical_cookie.h
+++ b/chromium/net/cookies/canonical_cookie.h
@@ -12,11 +12,13 @@
#include "base/gtest_prod_util.h"
#include "base/time/time.h"
+#include "net/base/features.h"
#include "net/base/net_export.h"
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
+#include "net/cookies/cookie_partition_key.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/third_party/mozilla/url_parse.h"
@@ -55,15 +57,18 @@ struct NET_EXPORT CookieAccessParams {
class NET_EXPORT CanonicalCookie {
public:
- using UniqueCookieKey = std::tuple<std::string, std::string, std::string>;
+ using UniqueCookieKey = std::tuple<absl::optional<CookiePartitionKey>,
+ std::string,
+ std::string,
+ std::string>;
CanonicalCookie();
CanonicalCookie(const CanonicalCookie& other);
-
+ CanonicalCookie(CanonicalCookie&& other);
+ CanonicalCookie& operator=(const CanonicalCookie& other);
+ CanonicalCookie& operator=(CanonicalCookie&& other);
~CanonicalCookie();
- // Supports the default copy constructor.
-
// Creates a new |CanonicalCookie| from the |cookie_line| and the
// |creation_time|. Canonicalizes inputs. May return nullptr if
// an attribute value is invalid. |url| must be valid. |creation_time| may
@@ -79,18 +84,29 @@ class NET_EXPORT CanonicalCookie {
// HttpOnly related parameters should be checked when setting the cookie in
// the CookieStore.
//
+ // The partition_key argument only needs to be present if the cookie line
+ // contains the Partitioned attribute. If the cookie line will never contain
+ // that attribute, you should use absl::nullopt to indicate you intend to
+ // always create an unpartitioned cookie. If partition_key has a value but the
+ // cookie line does not contain the Partitioned attribute, the resulting
+ // cookie will be unpartitioned. If the partition_key is null, then the cookie
+ // will be unpartitioned even when the cookie line has the Partitioned
+ // attribute.
+ //
// If a cookie is returned, |cookie->IsCanonical()| will be true.
static std::unique_ptr<CanonicalCookie> Create(
const GURL& url,
const std::string& cookie_line,
const base::Time& creation_time,
absl::optional<base::Time> server_time,
+ absl::optional<CookiePartitionKey> cookie_partition_key,
CookieInclusionStatus* status = nullptr);
// Create a canonical cookie based on sanitizing the passed inputs in the
// context of the passed URL. Returns a null unique pointer if the inputs
- // cannot be sanitized. If a cookie is created, |cookie->IsCanonical()|
- // will be true.
+ // cannot be sanitized. If `status` is provided it will have any relevant
+ // CookieInclusionStatus rejection reasons set. If a cookie is created,
+ // `cookie->IsCanonical()` will be true.
static std::unique_ptr<CanonicalCookie> CreateSanitizedCookie(
const GURL& url,
const std::string& name,
@@ -104,7 +120,9 @@ class NET_EXPORT CanonicalCookie {
bool http_only,
CookieSameSite same_site,
CookiePriority priority,
- bool same_party);
+ bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
+ CookieInclusionStatus* status = nullptr);
// FromStorage is a factory method which is meant for creating a new
// CanonicalCookie using properties of a previously existing cookie
@@ -114,18 +132,19 @@ class NET_EXPORT CanonicalCookie {
// Returns nullptr if the resulting cookie is not canonical,
// i.e. cc->IsCanonical() returns false.
static std::unique_ptr<CanonicalCookie> FromStorage(
- const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- const base::Time& last_access,
+ std::string name,
+ std::string value,
+ std::string domain,
+ std::string path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
bool secure,
bool httponly,
CookieSameSite same_site,
CookiePriority priority,
bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
CookieSourceScheme source_scheme,
int source_port);
@@ -144,6 +163,7 @@ class NET_EXPORT CanonicalCookie {
CookieSameSite same_site,
CookiePriority priority,
bool same_party,
+ absl::optional<CookiePartitionKey> partition_key = absl::nullopt,
CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
int source_port = url::PORT_UNSPECIFIED);
@@ -164,6 +184,28 @@ class NET_EXPORT CanonicalCookie {
CookieSameSite SameSite() const { return same_site_; }
CookiePriority Priority() const { return priority_; }
bool IsSameParty() const { return same_party_; }
+ bool IsPartitioned() const { return partition_key_.has_value(); }
+ const absl::optional<CookiePartitionKey>& PartitionKey() const {
+ return partition_key_;
+ }
+
+ // Methods for serializing and deserializing a partition key to/from a string.
+ // This will be used for Android, storing persistent partitioned cookies, and
+ // loading partitioned cookies into Java code.
+ //
+ // This function returns if the partition key is not opaque. We do not want
+ // to serialize cookies with opaque origins in their partition key to disk,
+ // because if the browser session ends we will not be able to attach the
+ // saved cookie to any future requests. This is because opaque origins' nonces
+ // are only stored in volatile memory.
+ bool SerializePartitionKey(std::string& out) const WARN_UNUSED_RESULT;
+ // Deserializes the result of the method above.
+ // If the result is abls::nullopt, the resulting cookie is not partitioned.
+ //
+ // Returns if the resulting partition key is valid.
+ static bool DeserializePartitionKey(const std::string& in,
+ absl::optional<SchemefulSite>& out)
+ WARN_UNUSED_RESULT;
// Returns an enum indicating the scheme of the origin that
// set this cookie. This is not part of the cookie spec but is being used to
@@ -192,18 +234,21 @@ class NET_EXPORT CanonicalCookie {
// For the case insensitive domain compare, we rely on the domain
// having been canonicalized (in
// GetCookieDomainWithString->CanonicalizeHost).
+ // If partitioned cookies are enabled, then we check the cookies have the same
+ // partition key in addition to the checks in RFC 2965.
bool IsEquivalent(const CanonicalCookie& ecc) const {
// It seems like it would make sense to take secure, httponly, and samesite
// into account, but the RFC doesn't specify this.
// NOTE: Keep this logic in-sync with TrimDuplicateCookiesForKey().
- return (name_ == ecc.Name() && domain_ == ecc.Domain()
- && path_ == ecc.Path());
+ return UniqueKey() == ecc.UniqueKey();
}
// Returns a key such that two cookies with the same UniqueKey() are
// guaranteed to be equivalent in the sense of IsEquivalent().
UniqueCookieKey UniqueKey() const {
- return std::make_tuple(name_, domain_, path_);
+ if (base::FeatureList::IsEnabled(features::kPartitionedCookies))
+ return std::make_tuple(partition_key_, name_, domain_, path_);
+ return std::make_tuple(absl::nullopt, name_, domain_, path_);
}
// Checks a looser set of equivalency rules than 'IsEquivalent()' in order
@@ -356,18 +401,19 @@ class NET_EXPORT CanonicalCookie {
// themselves.
// NOTE: Prefer using CreateSanitizedCookie() over directly using this
// constructor.
- CanonicalCookie(const std::string& name,
- const std::string& value,
- const std::string& domain,
- const std::string& path,
- const base::Time& creation,
- const base::Time& expiration,
- const base::Time& last_access,
+ CanonicalCookie(std::string name,
+ std::string value,
+ std::string domain,
+ std::string path,
+ base::Time creation,
+ base::Time expiration,
+ base::Time last_access,
bool secure,
bool httponly,
CookieSameSite same_site,
CookiePriority priority,
bool same_party,
+ absl::optional<CookiePartitionKey> partition_key,
CookieSourceScheme scheme_secure = CookieSourceScheme::kUnset,
int source_port = url::PORT_UNSPECIFIED);
@@ -401,9 +447,8 @@ class NET_EXPORT CanonicalCookie {
const std::string& path);
// Returns the effective SameSite mode to apply to this cookie. Depends on the
- // value of the given SameSite attribute and whether the
- // SameSiteByDefaultCookies feature is enabled, as well as the access
- // semantics of the cookie.
+ // value of the given SameSite attribute and the access semantics of the
+ // cookie.
// Note: If you are converting to a different representation of a cookie, you
// probably want to use SameSite() instead of this method. Otherwise, if you
// are considering using this method, consider whether you should use
@@ -423,6 +468,15 @@ class NET_EXPORT CanonicalCookie {
bool is_secure,
CookieSameSite same_site);
+ // Returns false iff the cookie is a partitioned cookie that violates the
+ // semantics of the Partitioned attribute:
+ // - Cannot be SameParty
+ // - Must have a __Host- prefix
+ static bool IsCookiePartitionedValid(const ParsedCookie& parsed_cookie);
+ static bool IsCookiePartitionedValid(bool is_partitioned,
+ CookiePrefix prefix,
+ bool is_same_party);
+
// Keep defaults here in sync with
// services/network/public/interfaces/cookie_manager.mojom.
std::string name_;
@@ -437,6 +491,12 @@ class NET_EXPORT CanonicalCookie {
CookieSameSite same_site_{CookieSameSite::NO_RESTRICTION};
CookiePriority priority_{COOKIE_PRIORITY_MEDIUM};
bool same_party_{false};
+ // This will be absl::nullopt for all cookies not set with the Partitioned
+ // attribute. If the value is non-null, then the cookie will only be delivered
+ // when the top-frame site matches the partition key.
+ // If the partition key is non-null and opaque, this means the Partitioned
+ // cookie was created on an opaque origin.
+ absl::optional<CookiePartitionKey> partition_key_;
CookieSourceScheme source_scheme_{CookieSourceScheme::kUnset};
// This can be [0,65535], PORT_UNSPECIFIED, or PORT_INVALID.
// PORT_UNSPECIFIED is used for cookies which already existed in the cookie
@@ -485,6 +545,18 @@ inline void PrintTo(const CookieWithAccessResult& cwar, std::ostream* os) {
PrintTo(cwar.access_result, os);
*os << " }";
}
+inline void PrintTo(const CookieAndLineWithAccessResult& calwar,
+ std::ostream* os) {
+ *os << "{ ";
+ if (calwar.cookie) {
+ PrintTo(*calwar.cookie, os);
+ } else {
+ *os << "nullopt";
+ }
+ *os << ", " << calwar.cookie_string << ", ";
+ PrintTo(calwar.access_result, os);
+ *os << " }";
+}
} // namespace net
diff --git a/chromium/net/cookies/canonical_cookie_fuzzer.cc b/chromium/net/cookies/canonical_cookie_fuzzer.cc
index 68a4d08c134..aa3bb25fa0f 100644
--- a/chromium/net/cookies/canonical_cookie_fuzzer.cc
+++ b/chromium/net/cookies/canonical_cookie_fuzzer.cc
@@ -53,12 +53,16 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
CookiePriority::COOKIE_PRIORITY_HIGH,
});
+ const auto partition_key = absl::make_optional<CookiePartitionKey>(
+ CookiePartitionKey::FromURLForTesting(
+ GURL(data_provider.ConsumeRandomLengthString(800))));
+
const std::unique_ptr<const CanonicalCookie> sanitized_cookie =
CanonicalCookie::CreateSanitizedCookie(
url, name, value, domain, path, creation, expiration, last_access,
data_provider.ConsumeBool() /* secure */,
data_provider.ConsumeBool() /* httponly */, same_site, priority,
- data_provider.ConsumeBool() /* same_party */);
+ data_provider.ConsumeBool() /* same_party */, partition_key);
if (sanitized_cookie) {
CHECK(sanitized_cookie->IsCanonical());
diff --git a/chromium/net/cookies/canonical_cookie_test_helpers.h b/chromium/net/cookies/canonical_cookie_test_helpers.h
index fe991278fe0..ab9908e4e17 100644
--- a/chromium/net/cookies/canonical_cookie_test_helpers.h
+++ b/chromium/net/cookies/canonical_cookie_test_helpers.h
@@ -7,7 +7,9 @@
#include <string>
+#include "base/strings/string_split.h"
#include "net/cookies/canonical_cookie.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
namespace net {
@@ -21,6 +23,133 @@ MATCHER_P(MatchesCookieLine, cookie_line, "") {
return false;
}
+// Matches a CanonicalCookie with the given name.
+MATCHER_P(MatchesCookieWithName, name, "") {
+ return testing::ExplainMatchResult(name, arg.Name(), result_listener);
+}
+
+MATCHER_P2(MatchesCookieNameValue, name, value, "") {
+ const CanonicalCookie& cookie = arg;
+ return testing::ExplainMatchResult(name, cookie.Name(), result_listener) &&
+ testing::ExplainMatchResult(value, cookie.Value(), result_listener);
+}
+
+MATCHER_P(MatchesCookieAccessWithName, name, "") {
+ return testing::ExplainMatchResult(MatchesCookieWithName(name), arg.cookie,
+ result_listener);
+}
+
+// Splits a string into key-value pairs, and executes the provided matcher on
+// the result.
+MATCHER_P3(WhenKVSplit, pair_delim, kv_delim, inner_matcher, "") {
+ std::vector<std::pair<std::string, std::string>> pairs;
+ // Ignore the return value of SplitStringIntoKeyValuePairs, to allow pairs
+ // with no associated value.
+ base::SplitStringIntoKeyValuePairs(arg, kv_delim, pair_delim, &pairs);
+ return testing::ExplainMatchResult(inner_matcher, pairs, result_listener);
+}
+
+// Splits a ';'-delimited string of Cookie 'name=value' or 'name' pairs, and
+// executes the provided matcher on the result.
+MATCHER_P(CookieStringIs, inner_matcher, "") {
+ return testing::ExplainMatchResult(WhenKVSplit(';', '=', inner_matcher), arg,
+ result_listener);
+}
+
+MATCHER_P2(MatchesCookieWithAccessResult, cookie, access_result, "") {
+ const CookieWithAccessResult& cwar = arg;
+ return testing::ExplainMatchResult(cookie, cwar.cookie, result_listener) &&
+ testing::ExplainMatchResult(access_result, cwar.access_result,
+ result_listener);
+}
+
+// Helper for checking that status.IsInclude() == true.
+MATCHER(IsInclude, "") {
+ const CookieInclusionStatus& status = arg;
+ return testing::ExplainMatchResult(true, status.IsInclude(), result_listener);
+}
+
+// Helper for checking that status.HasDowngradeWarning() == true.
+MATCHER(HasDowngradeWarning, "") {
+ CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(true, status.HasDowngradeWarning(),
+ result_listener);
+}
+
+// Helper for checking that status.HasWarningReason(reason) == true.
+MATCHER_P(HasWarningReason, reason, "") {
+ CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(true, status.HasWarningReason(reason),
+ result_listener);
+}
+
+// Helper for checking that status.HasExclusionReason(reason) == true.
+MATCHER_P(HasExclusionReason, reason, "") {
+ CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(true, status.HasExclusionReason(reason),
+ result_listener);
+}
+
+// Helper for checking that status.HasExactlyExclusionReasonsForTesting(reasons)
+// == true.
+MATCHER_P(HasExactlyExclusionReasonsForTesting, reasons, "") {
+ const CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(
+ true, status.HasExactlyExclusionReasonsForTesting(reasons),
+ result_listener);
+}
+
+// Helper for checking that status.HasExactlyWarningReasonsForTesting(reasons)
+// == true.
+MATCHER_P(HasExactlyWarningReasonsForTesting, reasons, "") {
+ const CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(
+ true, status.HasExactlyWarningReasonsForTesting(reasons),
+ result_listener);
+}
+
+MATCHER(ShouldWarn, "") {
+ net::CookieInclusionStatus status = arg;
+ return testing::ExplainMatchResult(true, status.ShouldWarn(),
+ result_listener);
+}
+
+// Helper for checking CookieAccessResults. Should be called with matchers (or
+// values) for each of the fields of a CookieAccessResult.
+MATCHER_P4(MatchesCookieAccessResult,
+ status,
+ effective_same_site,
+ access_semantics,
+ is_allowed_to_access_secure_cookies,
+ "") {
+ const CookieAccessResult& car = arg;
+ return testing::ExplainMatchResult(status, car.status, result_listener) &&
+ testing::ExplainMatchResult(
+ effective_same_site, car.effective_same_site, result_listener) &&
+ testing::ExplainMatchResult(access_semantics, car.access_semantics,
+ result_listener) &&
+ testing::ExplainMatchResult(is_allowed_to_access_secure_cookies,
+ car.is_allowed_to_access_secure_cookies,
+ result_listener);
+}
+
+MATCHER_P3(MatchesCookieAndLineWithAccessResult,
+ cookie,
+ line,
+ access_result,
+ "") {
+ const CookieAndLineWithAccessResult& cookie_and_line_with_access_result = arg;
+ return testing::ExplainMatchResult(cookie,
+ cookie_and_line_with_access_result.cookie,
+ result_listener) &&
+ testing::ExplainMatchResult(
+ line, cookie_and_line_with_access_result.cookie_string,
+ result_listener) &&
+ testing::ExplainMatchResult(
+ access_result, cookie_and_line_with_access_result.access_result,
+ result_listener);
+}
+
} // namespace net
#endif // NET_COOKIES_CANONICAL_COOKIE_TEST_HELPERS_H_
diff --git a/chromium/net/cookies/canonical_cookie_unittest.cc b/chromium/net/cookies/canonical_cookie_unittest.cc
index b21dada3ed9..55d49f245f1 100644
--- a/chromium/net/cookies/canonical_cookie_unittest.cc
+++ b/chromium/net/cookies/canonical_cookie_unittest.cc
@@ -8,6 +8,7 @@
#include "base/test/scoped_feature_list.h"
#include "build/build_config.h"
#include "net/base/features.h"
+#include "net/cookies/canonical_cookie_test_helpers.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
@@ -34,63 +35,6 @@ void MatchCookieLineToVector(
EXPECT_EQ(line, CanonicalCookie::BuildCookieLine(list));
}
-// Helper for checking CookieAccessResults. Should be called with matchers (or
-// values) for each of the fields of a CookieAccessResult.
-MATCHER_P4(MatchesCookieAccessResult,
- status,
- effective_same_site,
- access_semantics,
- is_allowed_to_access_secure_cookies,
- "") {
- return testing::ExplainMatchResult(
- testing::AllOf(
- testing::Field(&CookieAccessResult::status, status),
- testing::Field(&CookieAccessResult::effective_same_site,
- effective_same_site),
- testing::Field(&CookieAccessResult::access_semantics,
- access_semantics),
- testing::Field(
- &CookieAccessResult::is_allowed_to_access_secure_cookies,
- is_allowed_to_access_secure_cookies)),
- arg, result_listener);
-}
-
-// Helper for checking that status.HasDowngradeWarning() == true.
-MATCHER(HasDowngradeWarning, "") {
- CookieInclusionStatus status = arg;
- return testing::ExplainMatchResult(true, status.HasDowngradeWarning(),
- result_listener);
-}
-
-// Helper for checking that status.HasWarningReason(reason) == true.
-MATCHER_P(HasWarningReason, reason, "") {
- CookieInclusionStatus status = arg;
- return testing::ExplainMatchResult(true, status.HasWarningReason(reason),
- result_listener);
-}
-
-// Helper for checking that status.HasExclusionReason(reason) == true.
-MATCHER_P(HasExclusionReason, reason, "") {
- CookieInclusionStatus status = arg;
- return testing::ExplainMatchResult(true, status.HasExclusionReason(reason),
- result_listener);
-}
-
-// Helper for checking that status.HasExactlyExclusionReasonsForTesting(reasons)
-// == true.
-MATCHER_P(HasExactlyExclusionReasonsForTesting, reasons, "") {
- CookieInclusionStatus status = arg;
- return testing::ExplainMatchResult(
- true, status.HasExactlyExclusionReasonsForTesting(reasons),
- result_listener);
-}
-
-// Helper for checking that status.IsInclude() == true.
-MATCHER(IsInclude, "") {
- CookieInclusionStatus status = arg;
- return testing::ExplainMatchResult(true, status.IsInclude(), result_listener);
-}
-
} // namespace
using testing::_;
@@ -106,7 +50,8 @@ TEST(CanonicalCookieTest, Constructor) {
auto cookie1 = CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "2", "www.example.com", "/test", current_time, base::Time(),
base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false, CookieSourceScheme::kSecure, 443);
+ COOKIE_PRIORITY_DEFAULT, false, absl::nullopt,
+ CookieSourceScheme::kSecure, 443);
EXPECT_EQ("A", cookie1->Name());
EXPECT_EQ("2", cookie1->Value());
EXPECT_EQ("www.example.com", cookie1->Domain());
@@ -116,13 +61,17 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie1->SameSite());
EXPECT_EQ(CookiePriority::COOKIE_PRIORITY_DEFAULT, cookie1->Priority());
EXPECT_FALSE(cookie1->IsSameParty());
+ EXPECT_FALSE(cookie1->IsPartitioned());
EXPECT_EQ(cookie1->SourceScheme(), CookieSourceScheme::kSecure);
EXPECT_EQ(cookie1->SourcePort(), 443);
auto cookie2 = CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "2", ".www.example.com", "/", current_time, base::Time(),
base::Time(), false, false, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, true, CookieSourceScheme::kNonSecure, 65536);
+ COOKIE_PRIORITY_DEFAULT, true,
+ absl::make_optional(
+ CookiePartitionKey::FromURLForTesting(GURL("https://foo.com"))),
+ CookieSourceScheme::kNonSecure, 65536);
EXPECT_EQ("A", cookie2->Name());
EXPECT_EQ("2", cookie2->Value());
EXPECT_EQ(".www.example.com", cookie2->Domain());
@@ -132,6 +81,7 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie2->SameSite());
EXPECT_EQ(CookiePriority::COOKIE_PRIORITY_DEFAULT, cookie2->Priority());
EXPECT_TRUE(cookie2->IsSameParty());
+ EXPECT_TRUE(cookie2->IsPartitioned());
EXPECT_EQ(cookie2->SourceScheme(), CookieSourceScheme::kNonSecure);
// Because the port can be set explicitly in the constructor its value can be
// independent of the other parameters. In this case, test that an invalid
@@ -159,6 +109,7 @@ TEST(CanonicalCookieTest, Constructor) {
EXPECT_FALSE(cookie4->IsHttpOnly());
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie4->SameSite());
EXPECT_FALSE(cookie4->IsSameParty());
+ EXPECT_FALSE(cookie4->IsPartitioned());
EXPECT_EQ(cookie4->SourceScheme(), CookieSourceScheme::kUnset);
EXPECT_EQ(cookie4->SourcePort(), url::PORT_UNSPECIFIED);
@@ -166,7 +117,7 @@ TEST(CanonicalCookieTest, Constructor) {
auto cookie5 = CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "2", ".www.example.com", "/", current_time, base::Time(),
base::Time(), true /* secure */, false, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false, CookieSourceScheme::kUnset,
+ COOKIE_PRIORITY_DEFAULT, false, absl::nullopt, CookieSourceScheme::kUnset,
url::PORT_UNSPECIFIED);
EXPECT_EQ(cookie5->SourcePort(), url::PORT_UNSPECIFIED);
@@ -174,7 +125,7 @@ TEST(CanonicalCookieTest, Constructor) {
auto cookie6 = CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "2", ".www.example.com", "/", current_time, base::Time(),
base::Time(), true /* secure */, false, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false, CookieSourceScheme::kUnset,
+ COOKIE_PRIORITY_DEFAULT, false, absl::nullopt, CookieSourceScheme::kUnset,
url::PORT_INVALID);
EXPECT_EQ(cookie6->SourcePort(), url::PORT_INVALID);
}
@@ -186,26 +137,28 @@ TEST(CanonicalCookie, CreationCornerCases) {
// Space in name.
cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "A C=2", creation_time, server_time);
+ "A C=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_EQ("A C", cookie->Name());
// Semicolon in path.
cookie = CanonicalCookie::Create(GURL("http://fool/;/"), "*", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
// Control characters in name or value.
CookieInclusionStatus status;
- cookie =
- CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "\b=foo", creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ GURL("http://www.example.com/test/foo.html"), "\b=foo", creation_time,
+ server_time, absl::nullopt /* cookie_partition_key */, &status);
EXPECT_FALSE(cookie.get());
EXPECT_TRUE(status.HasExclusionReason(
CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE));
- cookie =
- CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "bar=\b", creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ GURL("http://www.example.com/test/foo.html"), "bar=\b", creation_time,
+ server_time, absl::nullopt /* cookie_partition_key */, &status);
EXPECT_FALSE(cookie.get());
EXPECT_TRUE(status.HasExclusionReason(
CookieInclusionStatus::ExclusionReason::EXCLUDE_FAILURE_TO_STORE));
@@ -219,7 +172,8 @@ TEST(CanonicalCookieTest, Create) {
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> cookie(
- CanonicalCookie::Create(url, "A=2", creation_time, server_time));
+ CanonicalCookie::Create(url, "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_EQ("A", cookie->Name());
EXPECT_EQ("2", cookie->Value());
EXPECT_EQ("www.example.com", cookie->Domain());
@@ -229,7 +183,8 @@ TEST(CanonicalCookieTest, Create) {
EXPECT_EQ(cookie->SourcePort(), 80);
GURL url2("http://www.foo.com");
- cookie = CanonicalCookie::Create(url2, "B=1", creation_time, server_time);
+ cookie = CanonicalCookie::Create(url2, "B=1", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ("B", cookie->Name());
EXPECT_EQ("1", cookie->Value());
EXPECT_EQ("www.foo.com", cookie->Domain());
@@ -241,103 +196,126 @@ TEST(CanonicalCookieTest, Create) {
// Test creating secure cookies. Secure scheme is not checked upon creation,
// so a URL of any scheme can create a Secure cookie.
cookie =
- CanonicalCookie::Create(url, "A=2; Secure", creation_time, server_time);
+ CanonicalCookie::Create(url, "A=2; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsSecure());
cookie = CanonicalCookie::Create(https_url, "A=2; Secure", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsSecure());
GURL url3("https://www.foo.com");
cookie =
- CanonicalCookie::Create(url3, "A=2; Secure", creation_time, server_time);
+ CanonicalCookie::Create(url3, "A=2; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsSecure());
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
- cookie = CanonicalCookie::Create(url3, "A=2", creation_time, server_time);
+ cookie = CanonicalCookie::Create(url3, "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_FALSE(cookie->IsSecure());
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
// Test creating cookie from localhost URL.
cookie = CanonicalCookie::Create(GURL("http://localhost/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
cookie = CanonicalCookie::Create(GURL("http://127.0.0.1/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
cookie = CanonicalCookie::Create(GURL("http://[::1]/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kNonSecure);
cookie = CanonicalCookie::Create(GURL("https://localhost/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
cookie = CanonicalCookie::Create(GURL("https://127.0.0.1/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
cookie = CanonicalCookie::Create(GURL("https://[::1]/path"), "A=2",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourceScheme(), CookieSourceScheme::kSecure);
// Test creating http only cookies. HttpOnly is not checked upon creation.
cookie =
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsHttpOnly());
cookie =
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsHttpOnly());
// Test creating SameSite cookies. SameSite is not checked upon creation.
cookie = CanonicalCookie::Create(url, "A=2; SameSite=Strict", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::STRICT_MODE, cookie->SameSite());
cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
cookie = CanonicalCookie::Create(url, "A=2; SameSite=Extended", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
- cookie = CanonicalCookie::Create(url, "A=2", creation_time, server_time);
+ cookie = CanonicalCookie::Create(url, "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
// Test creating cookies with different ports.
cookie = CanonicalCookie::Create(GURL("http://www.foo.com"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), 80);
cookie = CanonicalCookie::Create(GURL("http://www.foo.com:81"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), 81);
cookie = CanonicalCookie::Create(GURL("https://www.foo.com"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), 443);
cookie = CanonicalCookie::Create(GURL("https://www.foo.com:1234"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), 1234);
cookie = CanonicalCookie::Create(GURL("http://www.foo.com:443"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), 443);
// GURL's port parsing will handle any invalid ports, but let's still make
// sure we get the expected result anyway.
cookie = CanonicalCookie::Create(GURL("http://www.foo.com:70000"), "B=1",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(cookie->SourcePort(), url::PORT_INVALID);
}
@@ -349,12 +327,14 @@ TEST(CanonicalCookieTest, CreateNonStandardSameSite) {
// Non-standard value for the SameSite attribute.
cookie = CanonicalCookie::Create(url, "A=2; SameSite=NonStandard", now,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
// Omit value for the SameSite attribute.
- cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, server_time);
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite", now, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
}
@@ -369,13 +349,17 @@ TEST(CanonicalCookieTest, CreateSameSiteInCrossSiteContexts) {
// value (it is upon setting the cookie that the SameSiteContext comes into
// effect).
cookie =
- CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, server_time);
+ CanonicalCookie::Create(url, "A=2; SameSite=Strict", now, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
- cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, server_time);
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=Lax", now, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
- cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, server_time);
+ cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", now, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
- cookie = CanonicalCookie::Create(url, "A=2;", now, server_time);
+ cookie = CanonicalCookie::Create(url, "A=2;", now, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
}
@@ -386,8 +370,9 @@ TEST(CanonicalCookieTest, CreateHttpOnly) {
CookieInclusionStatus status;
// An HttpOnly cookie can be created.
- std::unique_ptr<CanonicalCookie> cookie =
- CanonicalCookie::Create(url, "A=2; HttpOnly", now, server_time, &status);
+ std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+ url, "A=2; HttpOnly", now, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
EXPECT_TRUE(cookie->IsHttpOnly());
EXPECT_TRUE(status.IsInclude());
}
@@ -399,7 +384,8 @@ TEST(CanonicalCookieTest, CreateWithInvalidDomain) {
CookieInclusionStatus status;
std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
- url, "A=2; Domain=wrongdomain.com", now, server_time, &status);
+ url, "A=2; Domain=wrongdomain.com", now, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
EXPECT_EQ(nullptr, cookie.get());
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
@@ -413,23 +399,26 @@ TEST(CanonicalCookieTest, CreateSameParty) {
CookieInclusionStatus status;
std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
- url, "A=2; SameParty; Secure", creation_time, server_time, &status);
+ url, "A=2; SameParty; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie.get());
EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(cookie->IsSameParty());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
- cookie = CanonicalCookie::Create(url, "A=2; SameParty; SameSite=None; Secure",
- creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ url, "A=2; SameParty; SameSite=None; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie.get());
EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(cookie->IsSameParty());
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
- cookie = CanonicalCookie::Create(url, "A=2; SameParty; SameSite=Lax; Secure",
- creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ url, "A=2; SameParty; SameSite=Lax; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie.get());
EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(cookie->IsSecure());
@@ -437,21 +426,71 @@ TEST(CanonicalCookieTest, CreateSameParty) {
EXPECT_EQ(CookieSameSite::LAX_MODE, cookie->SameSite());
// SameParty cookie with SameSite=Strict is invalid.
- cookie =
- CanonicalCookie::Create(url, "A=2; SameParty; SameSite=Strict; Secure",
- creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ url, "A=2; SameParty; SameSite=Strict; Secure", creation_time,
+ server_time, absl::nullopt /* cookie_partition_key */, &status);
EXPECT_FALSE(cookie.get());
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
// SameParty cookie without Secure is invalid.
- cookie = CanonicalCookie::Create(url, "A=2; SameParty; SameSite=Lax",
- creation_time, server_time, &status);
+ cookie = CanonicalCookie::Create(
+ url, "A=2; SameParty; SameSite=Lax", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status);
EXPECT_FALSE(cookie.get());
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
}
+TEST(CanonicalCookieTest, CreateWithPartitioned) {
+ GURL url("https://www.example.com/test/foo.html");
+ base::Time creation_time = base::Time::Now();
+ absl::optional<base::Time> server_time = absl::nullopt;
+ auto partition_key = absl::make_optional(
+ CookiePartitionKey::FromURLForTesting(GURL("https://toplevelsite.com")));
+ CookieInclusionStatus status;
+
+ // Valid Partitioned attribute
+ std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+ url, "__Host-A=2; Partitioned; Path=/; Secure", creation_time,
+ server_time, partition_key, &status);
+ ASSERT_TRUE(cookie.get());
+ EXPECT_TRUE(status.IsInclude());
+ EXPECT_TRUE(cookie->IsSecure());
+ EXPECT_TRUE(cookie->IsPartitioned());
+ EXPECT_EQ(partition_key, cookie->PartitionKey());
+ EXPECT_EQ(CookieSameSite::UNSPECIFIED, cookie->SameSite());
+
+ // Create() without Partitioned in the cookie line should not result in a
+ // partitioned cookie.
+ status = CookieInclusionStatus();
+ cookie =
+ CanonicalCookie::Create(url, "__Host-A=2; Path=/; Secure", creation_time,
+ server_time, partition_key, &status);
+ ASSERT_TRUE(cookie.get());
+ EXPECT_TRUE(status.IsInclude());
+ EXPECT_FALSE(cookie->IsPartitioned());
+ EXPECT_FALSE(cookie->PartitionKey());
+
+ // Invalid Partitioned attribute: no __Host- prefix.
+ status = CookieInclusionStatus();
+ cookie = CanonicalCookie::Create(url, "A=2; Partitioned; Path=/; Secure",
+ creation_time, server_time, partition_key,
+ &status);
+ EXPECT_FALSE(cookie.get());
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
+
+ // Invalid Partitioned attribute: SameParty cookie.
+ status = CookieInclusionStatus();
+ cookie = CanonicalCookie::Create(
+ url, "A=2; Partitioned; Path=/; Secure; SameParty", creation_time,
+ server_time, partition_key, &status);
+ EXPECT_FALSE(cookie.get());
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
+}
+
TEST(CanonicalCookieTest, CreateWithMaxAge) {
GURL url("http://www.example.com/test/foo.html");
base::Time creation_time = base::Time::Now();
@@ -459,7 +498,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Max-age with positive integer.
std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
- url, "A=1; max-age=60", creation_time, server_time);
+ url, "A=1; max-age=60", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -469,7 +509,7 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Max-age with expires (max-age should take precedence).
cookie = CanonicalCookie::Create(
url, "A=1; expires=01-Jan-1970, 00:00:00 GMT; max-age=60", creation_time,
- server_time);
+ server_time, absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -478,8 +518,9 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Max-age=0 should create an expired cookie with expiry equal to the earliest
// representable time.
- cookie = CanonicalCookie::Create(url, "A=1; max-age=0", creation_time,
- server_time);
+ cookie =
+ CanonicalCookie::Create(url, "A=1; max-age=0", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_TRUE(cookie->IsExpired(creation_time));
@@ -488,7 +529,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Negative max-age should create an expired cookie with expiry equal to the
// earliest representable time.
cookie = CanonicalCookie::Create(url, "A=1; max-age=-1", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_TRUE(cookie->IsExpired(creation_time));
@@ -496,7 +538,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Max-age with whitespace (should be trimmed out).
cookie = CanonicalCookie::Create(url, "A=1; max-age = 60 ; Secure",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -505,7 +548,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
// Max-age with non-integer should be ignored.
cookie = CanonicalCookie::Create(url, "A=1; max-age=abcd", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -516,7 +560,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
"max-age="
"9999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -528,7 +573,8 @@ TEST(CanonicalCookieTest, CreateWithMaxAge) {
"max-age=-"
"9999999999999999999999999999999999999999999"
"999999999999999999999999999999999999999999",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_TRUE(cookie->IsPersistent());
EXPECT_TRUE(cookie->IsExpired(creation_time));
@@ -543,7 +589,8 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
std::string cookie_line =
"ACSTM=20130308043820420042; path=/; domain=ipdl.inpit.go.jp; Expires=";
std::unique_ptr<CanonicalCookie> cookie(
- CanonicalCookie::Create(url, cookie_line, creation_time, server_time));
+ CanonicalCookie::Create(url, cookie_line, creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -551,8 +598,8 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a stale server time
server_time = creation_time - base::TimeDelta::FromHours(1);
- cookie =
- CanonicalCookie::Create(url, cookie_line, creation_time, server_time);
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -560,8 +607,8 @@ TEST(CanonicalCookieTest, EmptyExpiry) {
// With a future server time
server_time = creation_time + base::TimeDelta::FromHours(1);
- cookie =
- CanonicalCookie::Create(url, cookie_line, creation_time, server_time);
+ cookie = CanonicalCookie::Create(url, cookie_line, creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsPersistent());
EXPECT_FALSE(cookie->IsExpired(creation_time));
@@ -704,6 +751,77 @@ TEST(CanonicalCookieTest, IsEquivalent) {
EXPECT_FALSE(other_cookie->IsEquivalentForSecureCookieMatching(*cookie));
}
+class PartitionedCanonicalCookieTest : public testing::TestWithParam<bool> {
+ protected:
+ void SetUp() override {
+ if (PartitionedCookiesEnabled())
+ scoped_feature_list_.InitAndEnableFeature(features::kPartitionedCookies);
+ testing::TestWithParam<bool>::SetUp();
+ }
+
+ bool PartitionedCookiesEnabled() { return GetParam(); }
+
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(/* no label */,
+ PartitionedCanonicalCookieTest,
+ testing::Bool());
+
+TEST_P(PartitionedCanonicalCookieTest, IsEquivalent) {
+ const std::string name = "__Host-foo";
+ const std::string value = "bar";
+ const std::string domain = "";
+ const std::string path = "/";
+ const base::Time creation_time = base::Time();
+ const base::Time expiration_time = base::Time();
+ const base::Time last_accessed_time = base::Time();
+ const bool secure = true;
+ const bool http_only = false;
+ const CookieSameSite same_site = CookieSameSite::NO_RESTRICTION;
+ const CookiePriority cookie_priority = COOKIE_PRIORITY_DEFAULT;
+ const bool same_party = false;
+
+ const absl::optional<CookiePartitionKey> cookie_partition_key =
+ absl::make_optional(
+ CookiePartitionKey::FromURLForTesting(GURL("https://foo.com")));
+ const absl::optional<CookiePartitionKey> other_cookie_partition_key =
+ absl::make_optional(
+ CookiePartitionKey::FromURLForTesting(GURL("https://bar.com")));
+
+ auto unpartitioned_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+ name, value, domain, path, creation_time, expiration_time,
+ last_accessed_time, secure, http_only, same_site, cookie_priority,
+ same_party, absl::nullopt);
+ auto partitioned_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+ name, value, domain, path, creation_time, expiration_time,
+ last_accessed_time, secure, http_only, same_site, cookie_priority,
+ same_party, cookie_partition_key);
+
+ // Check that a cookie without a partition key is not equivalent to a cookie
+ // with one when partitioned cookie are enabled. If they are disabled the
+ // cookies should be equivalent.
+ EXPECT_NE(PartitionedCookiesEnabled(),
+ unpartitioned_cookie->IsEquivalent(*partitioned_cookie));
+
+ // Check that cookies with the same partition key are equivalent. This should
+ // be true regardless of the partitioned cookies setting.
+ auto other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+ name, value, domain, path, creation_time, expiration_time,
+ last_accessed_time, secure, http_only, same_site, cookie_priority,
+ same_party, cookie_partition_key);
+ EXPECT_TRUE(partitioned_cookie->IsEquivalent(*other_cookie));
+
+ // Check that cookies with different partition keys are not equivalent only
+ // when partitioned cookies are enabled.
+ other_cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
+ name, value, domain, path, creation_time, expiration_time,
+ last_accessed_time, secure, http_only, same_site, cookie_priority,
+ same_party, other_cookie_partition_key);
+ EXPECT_NE(PartitionedCookiesEnabled(),
+ partitioned_cookie->IsEquivalent(*other_cookie));
+}
+
TEST(CanonicalCookieTest, IsEquivalentForSecureCookieMatching) {
struct {
struct {
@@ -760,7 +878,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> cookie(
- CanonicalCookie::Create(url, "A=2", creation_time, server_time));
+ CanonicalCookie::Create(url, "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(cookie->IsHostCookie());
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -769,7 +888,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
cookie = CanonicalCookie::Create(url, "A=2; Domain=www.example.com",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsDomainCookie());
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
@@ -778,7 +898,8 @@ TEST(CanonicalCookieTest, IsDomainMatch) {
EXPECT_FALSE(cookie->IsDomainMatch("example.com"));
cookie = CanonicalCookie::Create(url, "A=2; Domain=.www.example.com",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("www.example.com"));
EXPECT_TRUE(cookie->IsDomainMatch("foo.www.example.com"));
@@ -791,7 +912,8 @@ TEST(CanonicalCookieTest, IsOnPath) {
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> cookie(CanonicalCookie::Create(
- GURL("http://www.example.com"), "A=2", creation_time, server_time));
+ GURL("http://www.example.com"), "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(cookie->IsOnPath("/"));
EXPECT_TRUE(cookie->IsOnPath("/test"));
EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
@@ -800,147 +922,94 @@ TEST(CanonicalCookieTest, IsOnPath) {
EXPECT_FALSE(cookie->IsOnPath(std::string()));
cookie = CanonicalCookie::Create(GURL("http://www.example.com/test/foo.html"),
- "A=2", creation_time, server_time);
+ "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_FALSE(cookie->IsOnPath("/"));
EXPECT_TRUE(cookie->IsOnPath("/test"));
EXPECT_TRUE(cookie->IsOnPath("/test/bar.html"));
EXPECT_TRUE(cookie->IsOnPath("/test/sample/bar.html"));
}
-struct EffectiveSameSiteTestCase {
- CookieSameSite same_site;
- CookieEffectiveSameSite effective_same_site;
- CookieAccessSemantics access_semantics;
-};
-
-void VerifyEffectiveSameSiteTestCases(
- base::Time creation_time,
- base::Time expiry_time,
- bool is_samesite_by_default_enabled,
- std::vector<EffectiveSameSiteTestCase> test_cases) {
- base::test::ScopedFeatureList feature_list;
- if (is_samesite_by_default_enabled) {
- feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
- } else {
- feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
- }
-
- for (const auto& test_case : test_cases) {
- auto cookie = CanonicalCookie::CreateUnsafeCookieForTesting(
- "A", "2", "example.test", "/", creation_time, expiry_time, base::Time(),
- true /* secure */, false /* httponly */, test_case.same_site,
- COOKIE_PRIORITY_DEFAULT, false);
- EXPECT_EQ(
- test_case.effective_same_site,
- cookie->GetEffectiveSameSiteForTesting(test_case.access_semantics));
- }
-}
-
TEST(CanonicalCookieTest, GetEffectiveSameSite) {
- // Test cases that are always the same, regardless of time or
- // SameSite-by-default feature status.
- const std::vector<EffectiveSameSiteTestCase> common_test_cases = {
+ struct {
+ CookieSameSite same_site;
+ CookieEffectiveSameSite expected_effective_same_site;
+ // nullopt for following members indicates same effective SameSite result
+ // for all possible values.
+ absl::optional<CookieAccessSemantics> access_semantics = absl::nullopt;
+ absl::optional<bool> is_cookie_recent = absl::nullopt;
+ } kTestCases[] = {
// Explicitly specified SameSite always has the same effective SameSite
// regardless of the access semantics.
- {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::UNKNOWN},
- {CookieSameSite::LAX_MODE, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::UNKNOWN},
- {CookieSameSite::STRICT_MODE, CookieEffectiveSameSite::STRICT_MODE,
- CookieAccessSemantics::UNKNOWN},
- {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::LEGACY},
- {CookieSameSite::LAX_MODE, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::LEGACY},
- {CookieSameSite::STRICT_MODE, CookieEffectiveSameSite::STRICT_MODE,
- CookieAccessSemantics::LEGACY},
- {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::NONLEGACY},
- {CookieSameSite::LAX_MODE, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::NONLEGACY},
- {CookieSameSite::STRICT_MODE, CookieEffectiveSameSite::STRICT_MODE,
- CookieAccessSemantics::NONLEGACY},
+ {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION},
+ {CookieSameSite::LAX_MODE, CookieEffectiveSameSite::LAX_MODE},
+ {CookieSameSite::STRICT_MODE, CookieEffectiveSameSite::STRICT_MODE},
+ {CookieSameSite::NO_RESTRICTION, CookieEffectiveSameSite::NO_RESTRICTION},
+
// UNSPECIFIED always maps to NO_RESTRICTION if LEGACY access semantics.
{CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::LEGACY}};
-
- // Test cases that differ based on access semantics, feature status, and
- // whether cookie is recently created:
+ CookieAccessSemantics::LEGACY},
- std::vector<EffectiveSameSiteTestCase> enabled_recent_test_cases = {
+ // UNSPECIFIED with non-LEGACY access semantics depends on whether cookie
+ // is recently created.
{CookieSameSite::UNSPECIFIED,
CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
- CookieAccessSemantics::UNKNOWN},
+ CookieAccessSemantics::NONLEGACY, true},
{CookieSameSite::UNSPECIFIED,
CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
- CookieAccessSemantics::NONLEGACY}};
-
- std::vector<EffectiveSameSiteTestCase> enabled_not_recent_test_cases = {
+ CookieAccessSemantics::UNKNOWN, true},
{CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::UNKNOWN},
+ CookieAccessSemantics::NONLEGACY, false},
{CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::NONLEGACY}};
+ CookieAccessSemantics::UNKNOWN, false},
+ };
- std::vector<EffectiveSameSiteTestCase> disabled_recent_test_cases = {
- {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::UNKNOWN},
- {CookieSameSite::UNSPECIFIED,
- CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
- CookieAccessSemantics::NONLEGACY}};
+ for (const auto& test : kTestCases) {
+ std::vector<std::unique_ptr<CanonicalCookie>> cookies;
+
+ base::Time now = base::Time::Now();
+ base::Time recent_creation_time = now - (kLaxAllowUnsafeMaxAge / 4);
+ base::Time not_recent_creation_time = now - (kLaxAllowUnsafeMaxAge * 4);
+ base::Time expiry_time = now + (kLaxAllowUnsafeMaxAge / 4);
+
+ if (!test.is_cookie_recent.has_value() || *test.is_cookie_recent) {
+ // Recent session cookie.
+ cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "2", "example.test", "/", recent_creation_time, base::Time(),
+ base::Time(), true /* secure */, false /* httponly */, test.same_site,
+ COOKIE_PRIORITY_DEFAULT, false));
+ // Recent persistent cookie.
+ cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "2", "example.test", "/", recent_creation_time, expiry_time,
+ base::Time(), true /* secure */, false /* httponly */, test.same_site,
+ COOKIE_PRIORITY_DEFAULT, false));
+ }
+ if (!test.is_cookie_recent.has_value() || !(*test.is_cookie_recent)) {
+ // Not-recent session cookie.
+ cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "2", "example.test", "/", not_recent_creation_time, base::Time(),
+ base::Time(), true /* secure */, false /* httponly */, test.same_site,
+ COOKIE_PRIORITY_DEFAULT, false));
+ // Not-recent persistent cookie.
+ cookies.push_back(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "2", "example.test", "/", not_recent_creation_time, expiry_time,
+ base::Time(), true /* secure */, false /* httponly */, test.same_site,
+ COOKIE_PRIORITY_DEFAULT, false));
+ }
- std::vector<EffectiveSameSiteTestCase> disabled_not_recent_test_cases = {
- {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::NO_RESTRICTION,
- CookieAccessSemantics::UNKNOWN},
- {CookieSameSite::UNSPECIFIED, CookieEffectiveSameSite::LAX_MODE,
- CookieAccessSemantics::NONLEGACY}};
+ std::vector<CookieAccessSemantics> access_semantics = {
+ CookieAccessSemantics::UNKNOWN, CookieAccessSemantics::LEGACY,
+ CookieAccessSemantics::NONLEGACY};
+ if (test.access_semantics.has_value())
+ access_semantics = {*test.access_semantics};
- // Test GetEffectiveSameSite for recently created cookies
- // Session cookie created less than kLaxAllowUnsafeMaxAge ago.
- base::Time now = base::Time::Now();
- base::Time creation_time = now - (kLaxAllowUnsafeMaxAge / 4);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), false,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), false,
- disabled_recent_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), true,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), true,
- enabled_recent_test_cases);
-
- // Persistent cookie with max age less than kLaxAllowUnsafeMaxAge.
- base::Time expiry_time = creation_time + (kLaxAllowUnsafeMaxAge / 4);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, false,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, false,
- disabled_recent_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, true,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, true,
- enabled_recent_test_cases);
-
- // Test GetEffectiveSameSite for not-recently-created cookies:
- // Session cookie created more than kLaxAllowUnsafeMaxAge ago.
- creation_time = now - (kLaxAllowUnsafeMaxAge * 4);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), false,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), false,
- disabled_not_recent_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), true,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, base::Time(), true,
- enabled_not_recent_test_cases);
-
- // Persistent cookie with max age more than kLaxAllowUnsafeMaxAge, created
- // more than kLaxAllowUnsafeMaxAge ago.
- expiry_time = creation_time + (kLaxAllowUnsafeMaxAge * 8);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, false,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, false,
- disabled_not_recent_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, true,
- common_test_cases);
- VerifyEffectiveSameSiteTestCases(creation_time, expiry_time, true,
- enabled_not_recent_test_cases);
+ for (const auto& cookie : cookies) {
+ for (const auto semantics : access_semantics) {
+ EXPECT_EQ(test.expected_effective_same_site,
+ cookie->GetEffectiveSameSiteForTesting(semantics));
+ }
+ }
+ }
}
TEST(CanonicalCookieTest, IncludeForRequestURL) {
@@ -950,7 +1019,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> cookie(
- CanonicalCookie::Create(url, "A=2", creation_time, server_time));
+ CanonicalCookie::Create(url, "A=2", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(cookie
->IncludeForRequestURL(
url, options,
@@ -997,7 +1067,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that cookie with a cookie path that does not match the url path are
// not included.
cookie = CanonicalCookie::Create(url, "A=2; Path=/foo/bar", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie
->IncludeForRequestURL(
url, options,
@@ -1020,7 +1091,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that a secure cookie is not included for a non secure URL.
GURL secure_url("https://www.example.com");
cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(cookie
->IncludeForRequestURL(
@@ -1043,7 +1115,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// Test that a delegate can make an exception, however, and ask for a
// non-secure URL to be treated as trustworthy... with a warning.
cookie =
- CanonicalCookie::Create(url, "A=2; Secure", creation_time, server_time);
+ CanonicalCookie::Create(url, "A=2; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie);
EXPECT_TRUE(cookie->IsSecure());
CookieAccessResult result = cookie->IncludeForRequestURL(
@@ -1058,7 +1131,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// The same happens for localhost even w/o delegate intervention.
GURL localhost_url("http://localhost/");
cookie = CanonicalCookie::Create(localhost_url, "A=2; Secure", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie);
EXPECT_TRUE(cookie->IsSecure());
result = cookie->IncludeForRequestURL(
@@ -1072,7 +1146,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// An unneeded exception doesn't add a warning, however.
cookie = CanonicalCookie::Create(secure_url, "A=2; Secure", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie);
EXPECT_TRUE(cookie->IsSecure());
result = cookie->IncludeForRequestURL(
@@ -1089,7 +1164,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURL) {
// is set on the cookie options.
options.set_include_httponly();
cookie =
- CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time);
+ CanonicalCookie::Create(url, "A=2; HttpOnly", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_TRUE(cookie->IsHttpOnly());
EXPECT_TRUE(cookie
->IncludeForRequestURL(
@@ -1121,22 +1197,15 @@ struct IncludeForRequestURLTestCase {
};
void VerifyIncludeForRequestURLTestCases(
- bool is_samesite_by_default_enabled,
CookieAccessSemantics access_semantics,
std::vector<IncludeForRequestURLTestCase> test_cases) {
GURL url("https://example.test");
for (const auto& test : test_cases) {
- base::test::ScopedFeatureList feature_list;
- if (is_samesite_by_default_enabled) {
- feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
- } else {
- feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
- }
-
base::Time creation_time = base::Time::Now() - test.creation_time_delta;
std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
- url, test.cookie_line, creation_time, absl::nullopt /* server_time */);
+ url, test.cookie_line, creation_time, absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
EXPECT_EQ(test.expected_samesite, cookie->SameSite());
CookieOptions request_options;
@@ -1151,7 +1220,8 @@ void VerifyIncludeForRequestURLTestCases(
CookieSamePartyStatus::kNoSamePartyEnforcement}),
MatchesCookieAccessResult(test.expected_inclusion_status,
test.expected_effective_samesite,
- access_semantics, true));
+ access_semantics, true))
+ << cookie->Name() << "=" << cookie->Value();
}
}
@@ -1214,21 +1284,25 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
{"Common=10;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=11;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=12;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=13;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
// Because NO_RESTRICTION cookies are always sent, the schemeful context
// downgrades shouldn't matter.
{"Common=14;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
@@ -1236,36 +1310,40 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
SameSiteCookieContext::ContextType::SAME_SITE_LAX),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=15;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=16;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
SameSiteCookieContext::ContextType::CROSS_SITE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=17;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX,
SameSiteCookieContext::ContextType::CROSS_SITE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
{"Common=18;SameSite=None;Secure", CookieSameSite::NO_RESTRICTION,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(
SameSiteCookieContext::ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
SameSiteCookieContext::ContextType::CROSS_SITE),
- CookieInclusionStatus()},
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED)},
};
- // Test cases where the default is None (either access semantics is LEGACY, or
- // semantics is UNKNOWN and SameSiteByDefaultCookies feature is disabled):
+ // Test cases where the unspecified-SameSite cookie defaults to SameSite=None
+ // due to LEGACY access semantics):
std::vector<IncludeForRequestURLTestCase> default_none_test_cases = {
- // Unspecified cookies (without SameSite-by-default):
{"DefaultNone=1", CookieSameSite::UNSPECIFIED,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(SameSiteCookieContext::ContextType::CROSS_SITE),
@@ -1281,6 +1359,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
std::vector<CookieInclusionStatus::ExclusionReason>(),
{CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT})},
+
{"DefaultNone=3", CookieSameSite::UNSPECIFIED,
CookieEffectiveSameSite::NO_RESTRICTION,
SameSiteCookieContext(SameSiteCookieContext::ContextType::SAME_SITE_LAX),
@@ -1291,9 +1370,7 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
SameSiteCookieContext::ContextType::SAME_SITE_STRICT),
CookieInclusionStatus()}};
- // Test cases where the default is Lax (either access semantics is NONLEGACY,
- // or access semantics is UNKNOWN and SameSiteByDefaultCookies feature is
- // enabled):
+ // Test cases where the unspecified-SameSite cookie defaults to SameSite=Lax:
std::vector<IncludeForRequestURLTestCase> default_lax_test_cases = {
// Unspecified recently-created cookies (with SameSite-by-default):
{"DefaultLax=1", CookieSameSite::UNSPECIFIED,
@@ -1457,29 +1534,17 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
auto SchemefulIndependentCases = [&]() {
// Run the test cases that are independent of Schemeful Same-Site.
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
common_test_cases);
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::UNKNOWN,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
default_lax_test_cases);
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
common_test_cases);
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::LEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
default_none_test_cases);
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
common_test_cases);
- VerifyIncludeForRequestURLTestCases(true, CookieAccessSemantics::NONLEGACY,
- default_lax_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
- common_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
- default_none_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
- common_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
- default_none_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
- common_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
default_lax_test_cases);
};
@@ -1490,11 +1555,11 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
SchemefulIndependentCases();
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
schemeful_disabled_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
schemeful_disabled_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
schemeful_disabled_test_cases);
}
{
@@ -1506,108 +1571,64 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameSite) {
// With LEGACY access the cases should act as if schemeful is disabled, even
// when it's not.
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::LEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::LEGACY,
schemeful_disabled_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::NONLEGACY,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::NONLEGACY,
schemeful_enabled_test_cases);
- VerifyIncludeForRequestURLTestCases(false, CookieAccessSemantics::UNKNOWN,
+ VerifyIncludeForRequestURLTestCases(CookieAccessSemantics::UNKNOWN,
schemeful_enabled_test_cases);
}
}
-// Test that non-SameSite, insecure cookies are excluded if both
-// SameSiteByDefaultCookies and CookiesWithoutSameSiteMustBeSecure are enabled.
+// Test that SameSite=None requires Secure.
TEST(CanonicalCookieTest, IncludeCookiesWithoutSameSiteMustBeSecure) {
GURL url("https://www.example.com");
base::Time creation_time = base::Time::Now();
absl::optional<base::Time> server_time = absl::nullopt;
CookieOptions options;
- std::unique_ptr<CanonicalCookie> cookie;
- // Create the cookie without the experimental options enabled.
- cookie = CanonicalCookie::Create(url, "A=2; SameSite=None", creation_time,
- server_time);
+ // Make a SameSite=None, *not* Secure cookie.
+ std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
+ url, "A=2; SameSite=None", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie.get());
EXPECT_FALSE(cookie->IsSecure());
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie->SameSite());
EXPECT_EQ(CookieEffectiveSameSite::NO_RESTRICTION,
cookie->GetEffectiveSameSiteForTesting());
- // Test SameSite=None must be Secure.
- // Features on:
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures(
- {features::kSameSiteByDefaultCookies,
- features::kCookiesWithoutSameSiteMustBeSecure} /* enabled_features */,
- {} /* disabled_features */);
-
- EXPECT_TRUE(
- cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::UNKNOWN,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
- EXPECT_TRUE(cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::LEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.IsInclude());
- EXPECT_TRUE(
- cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::NONLEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
- }
- // Features off:
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitWithFeatures(
- {} /* enabled_features */,
- {features::kSameSiteByDefaultCookies,
- features::
- kCookiesWithoutSameSiteMustBeSecure} /* disabled_features */);
-
- EXPECT_TRUE(cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::UNKNOWN,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.IsInclude());
- EXPECT_TRUE(cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::LEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.IsInclude());
- // If the semantics is Nonlegacy, only reject the cookie if the
- // SameSite=None-must-be-Secure feature is enabled.
- EXPECT_TRUE(cookie
- ->IncludeForRequestURL(
- url, options,
- CookieAccessParams{
- CookieAccessSemantics::NONLEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement})
- .status.IsInclude());
- }
+ // UKNOWN semantics results in modern behavior (requiring Secure).
+ EXPECT_TRUE(cookie
+ ->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams{
+ CookieAccessSemantics::UNKNOWN,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement})
+ .status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
+
+ // LEGACY semantics does not require Secure for SameSite=None cookies.
+ EXPECT_TRUE(cookie
+ ->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams{
+ CookieAccessSemantics::LEGACY,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement})
+ .status.IsInclude());
+
+ // NONLEGACY semantics results in modern behavior (requiring Secure).
+ EXPECT_TRUE(cookie
+ ->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams{
+ CookieAccessSemantics::NONLEGACY,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement})
+ .status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
}
TEST(CanonicalCookieTest, IncludeForRequestURLSameParty) {
@@ -1619,7 +1640,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameParty) {
// SameSite is not specified.
std::unique_ptr<CanonicalCookie> cookie_samesite_unspecified =
CanonicalCookie::Create(url, "A=2; SameParty; Secure", creation_time,
- server_time);
+ server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie_samesite_unspecified.get());
EXPECT_TRUE(cookie_samesite_unspecified->IsSecure());
EXPECT_EQ(CookieSameSite::UNSPECIFIED,
@@ -1631,7 +1653,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameParty) {
// SameSite=None.
std::unique_ptr<CanonicalCookie> cookie_samesite_none =
CanonicalCookie::Create(url, "A=2; SameSite=None; SameParty; Secure",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie_samesite_none.get());
EXPECT_TRUE(cookie_samesite_none->IsSecure());
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cookie_samesite_none->SameSite());
@@ -1642,7 +1665,8 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameParty) {
// SameSite=Lax.
std::unique_ptr<CanonicalCookie> cookie_samesite_lax =
CanonicalCookie::Create(url, "A=2; SameSite=Lax; SameParty; Secure",
- creation_time, server_time);
+ creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie_samesite_lax.get());
EXPECT_TRUE(cookie_samesite_lax->IsSecure());
EXPECT_EQ(CookieSameSite::LAX_MODE, cookie_samesite_lax->SameSite());
@@ -1680,6 +1704,300 @@ TEST(CanonicalCookieTest, IncludeForRequestURLSameParty) {
}
}
+TEST(CanonicalCookieTest, IncludeForRequestURL_SameSiteNone_Metrics) {
+ using SamePartyContextType = SamePartyContext::Type;
+
+ constexpr bool delegate_treats_url_as_trustworthy = false;
+ const base::Time now = base::Time::Now();
+ const auto make_cookie = [now](CookieSameSite same_site, bool same_party) {
+ return CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(),
+ true /* secure */, false /*httponly*/, same_site,
+ COOKIE_PRIORITY_DEFAULT, same_party);
+ };
+ GURL url("https://www.example.com/test");
+
+ const std::unique_ptr<CanonicalCookie> same_site_none_cookie =
+ make_cookie(CookieSameSite::NO_RESTRICTION, false /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_party_cookie =
+ make_cookie(CookieSameSite::NO_RESTRICTION, true /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_site_lax_cookie =
+ make_cookie(CookieSameSite::LAX_MODE, false /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_site_strict_cookie =
+ make_cookie(CookieSameSite::STRICT_MODE, false /* same_party */);
+ CookieOptions options;
+ options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
+ CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
+ // Same as default, but just to be explicit:
+ options.set_same_party_context(
+ SamePartyContext(SamePartyContext::Type::kCrossParty));
+
+ // Check that the most restrictive context is recognized and enforced.
+ EXPECT_THAT(
+ same_site_none_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kEnforceSamePartyExclude)),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Now tweak the context to allow a SameParty cookie (using the top&resource
+ // definition) and make sure we get the right warning. (Note: we make the
+ // "real" same-partyness value match the value computed for the metric, even
+ // though they would differ unless we changed the real definition.) Then
+ // check that if we modify the cookie as indicated, the set would be allowed,
+ // but the next-most-restrictive variation would still be blocked.
+ options.set_same_party_context(SamePartyContext(
+ SamePartyContextType::kSameParty, SamePartyContextType::kCrossParty,
+ SamePartyContextType::kSameParty));
+ EXPECT_THAT(
+ same_site_none_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kEnforceSamePartyInclude)),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Next: allow a SameParty cookie (using both definitions).
+ options.set_same_party_context(SamePartyContext::MakeInclusive());
+ EXPECT_THAT(
+ same_site_none_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Next: allow a SameSite=Lax cookie.
+ options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
+ CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
+ EXPECT_THAT(
+ same_site_none_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX}),
+ _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_strict_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Next: allow a SameSite=Strict cookie.
+ options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
+ CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_STRICT));
+ EXPECT_THAT(
+ same_site_none_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT}),
+ _, _, true));
+ EXPECT_THAT(
+ same_site_strict_cookie->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement)),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+}
+
+// Test that the CookieInclusionStatus warning for inclusion changed by
+// cross-site redirect context downgrade is applied correctly.
+TEST(CanonicalCookieTest, IncludeForRequestURL_RedirectDowngradeWarning) {
+ using Context = CookieOptions::SameSiteCookieContext;
+ using ContextType = Context::ContextType;
+
+ Context::ContextMetadata strict_lax_downgrade_metadata,
+ strict_cross_downgrade_metadata;
+ strict_lax_downgrade_metadata.cross_site_redirect_downgrade =
+ Context::ContextMetadata::ContextDowngradeType::kStrictToLax;
+ strict_cross_downgrade_metadata.cross_site_redirect_downgrade =
+ Context::ContextMetadata::ContextDowngradeType::kStrictToCross;
+
+ GURL url("https://www.example.test/test");
+ GURL insecure_url("http://www.example.test/test");
+
+ const struct {
+ ContextType context_type;
+ Context::ContextMetadata metadata;
+ CookieSameSite samesite;
+ bool expect_cross_site_redirect_warning;
+ } kTestCases[] = {
+ // Strict-to-lax downgrade.
+ {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
+ CookieSameSite::STRICT_MODE, true},
+ {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
+ CookieSameSite::STRICT_MODE, true},
+ {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
+ CookieSameSite::LAX_MODE, false},
+ {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
+ CookieSameSite::LAX_MODE, false},
+ {ContextType::SAME_SITE_STRICT, strict_lax_downgrade_metadata,
+ CookieSameSite::NO_RESTRICTION, false},
+ {ContextType::SAME_SITE_LAX, strict_lax_downgrade_metadata,
+ CookieSameSite::NO_RESTRICTION, false},
+
+ // Strict-to-cross downgrade.
+ {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
+ CookieSameSite::STRICT_MODE, true},
+ {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
+ CookieSameSite::STRICT_MODE, true},
+ {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
+ CookieSameSite::LAX_MODE, true},
+ {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
+ CookieSameSite::LAX_MODE, true},
+ {ContextType::SAME_SITE_STRICT, strict_cross_downgrade_metadata,
+ CookieSameSite::NO_RESTRICTION, false},
+ {ContextType::CROSS_SITE, strict_cross_downgrade_metadata,
+ CookieSameSite::NO_RESTRICTION, false},
+ };
+
+ for (bool consider_redirects : {true, false}) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(
+ features::kCookieSameSiteConsidersRedirectChain, consider_redirects);
+
+ for (CookieAccessSemantics semantics :
+ {CookieAccessSemantics::LEGACY, CookieAccessSemantics::NONLEGACY}) {
+ // There are no downgrade warnings for undowngraded contexts.
+ for (ContextType context_type :
+ {ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_LAX,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
+ ContextType::CROSS_SITE}) {
+ for (CookieSameSite samesite :
+ {CookieSameSite::UNSPECIFIED, CookieSameSite::NO_RESTRICTION,
+ CookieSameSite::LAX_MODE, CookieSameSite::STRICT_MODE}) {
+ std::unique_ptr<CanonicalCookie> cookie =
+ CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.test", "/test", base::Time::Now(),
+ base::Time(), base::Time(), /*secure=*/true,
+ /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT,
+ /*same_party=*/false);
+
+ CookieOptions options;
+ options.set_same_site_cookie_context(Context(context_type));
+
+ EXPECT_FALSE(
+ cookie
+ ->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement))
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
+ }
+ }
+
+ for (const auto& test : kTestCases) {
+ std::unique_ptr<CanonicalCookie> cookie =
+ CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.test", "/test", base::Time::Now(),
+ base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false,
+ test.samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false);
+
+ CookieOptions options;
+ options.set_same_site_cookie_context(
+ Context(test.context_type, test.context_type, test.metadata,
+ test.metadata));
+ EXPECT_EQ(
+ cookie
+ ->IncludeForRequestURL(
+ url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement))
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION),
+ test.expect_cross_site_redirect_warning);
+
+ // SameSite warnings not applied if other exclusion reasons apply (e.g.
+ // non-https with Secure attribute).
+ EXPECT_FALSE(
+ cookie
+ ->IncludeForRequestURL(
+ insecure_url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement))
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
+ }
+ }
+ }
+}
+
TEST(CanonicalCookieTest, MultipleExclusionReasons) {
GURL url("http://www.not-secure.com/foo");
base::Time creation_time = base::Time::Now();
@@ -1716,7 +2034,8 @@ TEST(CanonicalCookieTest, MultipleExclusionReasons) {
CookieInclusionStatus create_status;
auto cookie2 = CanonicalCookie::Create(
url, "__Secure-notactuallysecure=value;Domain=some-other-domain.com",
- creation_time, server_time, &create_status);
+ creation_time, server_time, absl::nullopt /* cookie_partition_key */,
+ &create_status);
ASSERT_FALSE(cookie2);
EXPECT_TRUE(create_status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
@@ -1724,7 +2043,8 @@ TEST(CanonicalCookieTest, MultipleExclusionReasons) {
// Test IsSetPermittedInContext()
auto cookie3 = CanonicalCookie::Create(
- url, "name=value;HttpOnly;SameSite=Lax", creation_time, server_time);
+ url, "name=value;HttpOnly;SameSite=Lax", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie3);
EXPECT_THAT(
cookie3->IsSetPermittedInContext(
@@ -1745,12 +2065,14 @@ TEST(CanonicalCookieTest, PartialCompare) {
base::Time creation_time = base::Time::Now();
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> cookie(
- CanonicalCookie::Create(url, "a=b", creation_time, server_time));
+ CanonicalCookie::Create(url, "a=b", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
std::unique_ptr<CanonicalCookie> cookie_different_path(
- CanonicalCookie::Create(url, "a=b; path=/foo", creation_time,
- server_time));
+ CanonicalCookie::Create(url, "a=b; path=/foo", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
std::unique_ptr<CanonicalCookie> cookie_different_value(
- CanonicalCookie::Create(url, "a=c", creation_time, server_time));
+ CanonicalCookie::Create(url, "a=c", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
// Cookie is equivalent to itself.
EXPECT_FALSE(cookie->PartialCompare(*cookie));
@@ -1776,29 +2098,36 @@ TEST(CanonicalCookieTest, SecureCookiePrefix) {
CookieInclusionStatus status;
// A __Secure- cookie must be Secure.
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B", creation_time,
- server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Secure-A=B", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B; httponly",
- creation_time, server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Secure-A=B; httponly", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
// (EXCLUDE_HTTP_ONLY would be fine, too)
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
// A typoed prefix does not have to be Secure.
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=B; Secure",
- creation_time, server_time));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__secure-A=C;", creation_time,
- server_time));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Secure",
- creation_time, server_time));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=C;", creation_time,
- server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__secure-A=B; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__secure-A=C;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__SecureA=B; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__SecureA=C;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
// A __Secure- cookie can't be set on a non-secure origin.
- EXPECT_FALSE(CanonicalCookie::Create(http_url, "__Secure-A=B; Secure",
- creation_time, server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ http_url, "__Secure-A=B; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
}
@@ -1812,71 +2141,79 @@ TEST(CanonicalCookieTest, HostCookiePrefix) {
CookieInclusionStatus status;
// A __Host- cookie must be Secure.
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
- server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
EXPECT_FALSE(CanonicalCookie::Create(
https_url, "__Host-A=B; Domain=" + domain + "; Path=/;", creation_time,
- server_time, &status));
+ server_time, absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/; Secure;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
// A __Host- cookie must be set from a secure scheme.
EXPECT_FALSE(CanonicalCookie::Create(
http_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, server_time, &status));
+ creation_time, server_time, absl::nullopt /* cookie_partition_key */,
+ &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure;",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/; Secure;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
// A __Host- cookie can't have a Domain.
EXPECT_FALSE(CanonicalCookie::Create(
https_url, "__Host-A=B; Domain=" + domain + "; Path=/; Secure;",
- creation_time, server_time, &status));
+ creation_time, server_time, absl::nullopt /* cookie_partition_key */,
+ &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
EXPECT_FALSE(CanonicalCookie::Create(
https_url, "__Host-A=B; Domain=" + domain + "; Secure;", creation_time,
- server_time, &status));
+ server_time, absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
// A __Host- cookie may have a domain if it's an IP address that matches the
// URL.
- EXPECT_TRUE(
- CanonicalCookie::Create(GURL("https://127.0.0.1"),
- "__Host-A=B; Domain=127.0.0.1; Path=/; Secure;",
- creation_time, server_time, &status));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ GURL("https://127.0.0.1"),
+ "__Host-A=B; Domain=127.0.0.1; Path=/; Secure;", creation_time,
+ server_time, absl::nullopt /* cookie_partition_key */, &status));
// A __Host- cookie with an IP address domain does not need the domain
// attribute specified explicitly (just like a normal domain).
- EXPECT_TRUE(CanonicalCookie::Create(GURL("https://127.0.0.1"),
- "__Host-A=B; Domain=; Path=/; Secure;",
- creation_time, server_time, &status));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ GURL("https://127.0.0.1"), "__Host-A=B; Domain=; Path=/; Secure;",
+ creation_time, server_time, absl::nullopt /* cookie_partition_key */,
+ &status));
// A __Host- cookie must have a Path of "/".
- EXPECT_FALSE(CanonicalCookie::Create(https_url,
- "__Host-A=B; Path=/foo; Secure;",
- creation_time, server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/foo; Secure;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure;",
- creation_time, server_time, &status));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Secure;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */, &status));
EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Secure; Path=/;",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Secure; Path=/;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
// Rules don't apply for a typoed prefix.
EXPECT_TRUE(CanonicalCookie::Create(
http_url, "__host-A=B; Domain=" + domain + "; Path=/;", creation_time,
- server_time));
+ server_time, absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(CanonicalCookie::Create(
https_url, "__HostA=B; Domain=" + domain + "; Secure;", creation_time,
- server_time));
+ server_time, absl::nullopt /* cookie_partition_key */));
}
TEST(CanonicalCookieTest, CanCreateSecureCookiesFromAnyScheme) {
@@ -1886,13 +2223,17 @@ TEST(CanonicalCookieTest, CanCreateSecureCookiesFromAnyScheme) {
absl::optional<base::Time> server_time = absl::nullopt;
std::unique_ptr<CanonicalCookie> http_cookie_no_secure(
- CanonicalCookie::Create(http_url, "a=b", creation_time, server_time));
+ CanonicalCookie::Create(http_url, "a=b", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
std::unique_ptr<CanonicalCookie> http_cookie_secure(CanonicalCookie::Create(
- http_url, "a=b; Secure", creation_time, server_time));
+ http_url, "a=b; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
std::unique_ptr<CanonicalCookie> https_cookie_no_secure(
- CanonicalCookie::Create(https_url, "a=b", creation_time, server_time));
+ CanonicalCookie::Create(https_url, "a=b", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
std::unique_ptr<CanonicalCookie> https_cookie_secure(CanonicalCookie::Create(
- https_url, "a=b; Secure", creation_time, server_time));
+ https_url, "a=b; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
EXPECT_TRUE(http_cookie_no_secure.get());
EXPECT_TRUE(http_cookie_secure.get());
@@ -2174,6 +2515,33 @@ TEST(CanonicalCookieTest, IsCanonical) {
base::Time(), true, false, CookieSameSite::STRICT_MODE,
COOKIE_PRIORITY_LOW, true)
->IsCanonical());
+
+ // Partitioned attribute used correctly (__Host- prefix, no SameParty).
+ EXPECT_TRUE(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-A", "B", "x.y", "/", base::Time(), base::Time(),
+ base::Time(), true, false, CookieSameSite::UNSPECIFIED,
+ COOKIE_PRIORITY_LOW, false,
+ absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))))
+ ->IsCanonical());
+
+ // Partitioned attribute invalid, no __Host- prefix.
+ EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "B", "x.y", "/", base::Time(), base::Time(),
+ base::Time(), true, false, CookieSameSite::UNSPECIFIED,
+ COOKIE_PRIORITY_LOW, false,
+ absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))))
+ ->IsCanonical());
+
+ // Partitioned attribute invalid, SameParty attribute also included.
+ EXPECT_FALSE(CanonicalCookie::CreateUnsafeCookieForTesting(
+ "__Host-A", "B", "x.y", "/", base::Time(), base::Time(),
+ base::Time(), true, false, CookieSameSite::UNSPECIFIED,
+ COOKIE_PRIORITY_LOW, true,
+ absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))))
+ ->IsCanonical());
}
TEST(CanonicalCookieTest, TestSetCreationDate) {
@@ -2195,42 +2563,48 @@ TEST(CanonicalCookieTest, TestPrefixHistograms) {
base::Time creation_time = base::Time::Now();
absl::optional<base::Time> server_time = absl::nullopt;
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Host-A=B;", creation_time,
- server_time));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Host-A=B;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Host-A=B; Path=/; Secure",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__Host-A=B; Path=/; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__HostA=B; Path=/; Secure",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__HostA=B; Path=/; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_HOST, 1);
- EXPECT_FALSE(CanonicalCookie::Create(https_url, "__Secure-A=B;",
- creation_time, server_time));
+ EXPECT_FALSE(CanonicalCookie::Create(
+ https_url, "__Secure-A=B;", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__Secure-A=B; Path=/; Secure",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__Secure-A=B; Path=/; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 1);
- EXPECT_TRUE(CanonicalCookie::Create(https_url, "__SecureA=B; Path=/; Secure",
- creation_time, server_time));
+ EXPECT_TRUE(CanonicalCookie::Create(
+ https_url, "__SecureA=B; Path=/; Secure", creation_time, server_time,
+ absl::nullopt /* cookie_partition_key */));
histograms.ExpectBucketCount(kCookiePrefixHistogram,
CanonicalCookie::COOKIE_PREFIX_SECURE, 2);
histograms.ExpectBucketCount(kCookiePrefixBlockedHistogram,
@@ -2244,21 +2618,26 @@ TEST(CanonicalCookieTest, BuildCookieLine) {
absl::optional<base::Time> server_time = absl::nullopt;
MatchCookieLineToVector("", cookies);
- cookies.push_back(CanonicalCookie::Create(url, "A=B", now, server_time));
+ cookies.push_back(CanonicalCookie::Create(
+ url, "A=B", now, server_time, absl::nullopt /* cookie_partition_key */));
MatchCookieLineToVector("A=B", cookies);
// Nameless cookies are sent back without a prefixed '='.
- cookies.push_back(CanonicalCookie::Create(url, "C", now, server_time));
+ cookies.push_back(CanonicalCookie::Create(
+ url, "C", now, server_time, absl::nullopt /* cookie_partition_key */));
MatchCookieLineToVector("A=B; C", cookies);
// Cookies separated by ';'.
- cookies.push_back(CanonicalCookie::Create(url, "D=E", now, server_time));
+ cookies.push_back(CanonicalCookie::Create(
+ url, "D=E", now, server_time, absl::nullopt /* cookie_partition_key */));
MatchCookieLineToVector("A=B; C; D=E", cookies);
// BuildCookieLine doesn't reorder the list, it relies on the caller to do so.
cookies.push_back(CanonicalCookie::Create(
- url, "F=G", now - base::TimeDelta::FromSeconds(1), server_time));
+ url, "F=G", now - base::TimeDelta::FromSeconds(1), server_time,
+ absl::nullopt /* cookie_partition_key */));
MatchCookieLineToVector("A=B; C; D=E; F=G", cookies);
// BuildCookieLine doesn't deduplicate.
cookies.push_back(CanonicalCookie::Create(
- url, "D=E", now - base::TimeDelta::FromSeconds(2), server_time));
+ url, "D=E", now - base::TimeDelta::FromSeconds(2), server_time,
+ absl::nullopt /* cookie_partition_key */));
MatchCookieLineToVector("A=B; C; D=E; F=G; D=E", cookies);
}
@@ -2268,13 +2647,15 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Inputs) {
base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
base::Time one_hour_from_now =
base::Time::Now() + base::TimeDelta::FromHours(1);
-
+ CookieInclusionStatus status;
std::unique_ptr<CanonicalCookie> cc;
+
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ("A", cc->Name());
EXPECT_EQ("B", cc->Value());
@@ -2288,88 +2669,118 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Inputs) {
EXPECT_EQ(CookieSameSite::NO_RESTRICTION, cc->SameSite());
EXPECT_EQ(COOKIE_PRIORITY_MEDIUM, cc->Priority());
EXPECT_FALSE(cc->IsSameParty());
+ EXPECT_FALSE(cc->IsPartitioned());
EXPECT_FALSE(cc->IsDomainCookie());
+ EXPECT_TRUE(status.IsInclude());
// Creation date
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
two_hours_ago, base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ(two_hours_ago, cc->CreationDate());
+ EXPECT_TRUE(status.IsInclude());
// Last access date
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
two_hours_ago, base::Time(), one_hour_ago, false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ(one_hour_ago, cc->LastAccessDate());
+ EXPECT_TRUE(status.IsInclude());
// Expiry
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ(one_hour_from_now, cc->ExpiryDate());
+ EXPECT_TRUE(status.IsInclude());
// Secure
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), true /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_TRUE(cc->IsSecure());
+ EXPECT_TRUE(status.IsInclude());
// Httponly
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
true /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_TRUE(cc->IsHttpOnly());
+ EXPECT_TRUE(status.IsInclude());
// Same site
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::LAX_MODE, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/);
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ(CookieSameSite::LAX_MODE, cc->SameSite());
+ EXPECT_TRUE(status.IsInclude());
// Priority
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
- false /*same_party*/);
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_EQ(COOKIE_PRIORITY_LOW, cc->Priority());
+ EXPECT_TRUE(status.IsInclude());
// Domain cookie
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", "www.foo.com", "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_TRUE(cc->IsDomainCookie());
+ EXPECT_TRUE(status.IsInclude());
// SameParty
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), true /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
- true /*same_party*/);
+ true /*same_party*/, absl::nullopt /*partition_key*/, &status);
EXPECT_TRUE(cc);
EXPECT_TRUE(cc->IsSameParty());
+ EXPECT_TRUE(status.IsInclude());
+
+ // Partitioned
+ cc = CanonicalCookie::CreateSanitizedCookie(
+ GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
+ base::Time(), base::Time(), base::Time(), true /*secure*/,
+ false /*httponly*/, CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_LOW,
+ false /*same_party*/,
+ absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))),
+ &status);
+ EXPECT_TRUE(cc);
+ EXPECT_TRUE(cc->IsPartitioned());
+ EXPECT_TRUE(status.IsInclude());
}
// Make sure sanitization and blocking of cookies works correctly.
@@ -2378,103 +2789,150 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) {
base::Time one_hour_ago = base::Time::Now() - base::TimeDelta::FromHours(1);
base::Time one_hour_from_now =
base::Time::Now() + base::TimeDelta::FromHours(1);
+ CookieInclusionStatus status;
// Simple path and domain variations.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", std::string(), "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/bar"), "C", "D", "www.foo.com", "/",
two_hours_ago, base::Time(), one_hour_ago, false /*secure*/,
true /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "E", "F", std::string(), std::string(),
base::Time(), base::Time(), base::Time(), true /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
// Test the file:// protocol.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("file:///"), "A", "B", std::string(), "/foo", one_hour_ago,
one_hour_from_now, base::Time(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("file:///home/user/foo.txt"), "A", "B", std::string(), "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("file:///home/user/foo.txt"), "A", "B", "home", "/foo", one_hour_ago,
one_hour_from_now, base::Time(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
// Test that malformed attributes fail to set the cookie.
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), " A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A;", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A=", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A\x07", "B", std::string(), "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", " B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "\x0fZ", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", "www.foo.com ", "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", "foo.ozzzzzzle", "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", std::string(), "foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", std::string(), "/foo ",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", "%2Efoo.com", "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://domaintest.%E3%81%BF%E3%82%93%E3%81%AA"), "A", "B",
"domaintest.%E3%81%BF%E3%82%93%E3%81%AA", "/foo", base::Time(),
base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
std::unique_ptr<CanonicalCookie> cc;
@@ -2484,133 +2942,169 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) {
GURL("http://www.foo.com/foo"), "A", "B", "www.foo.com", "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
ASSERT_TRUE(cc);
EXPECT_TRUE(cc->IsDomainCookie());
EXPECT_EQ(".www.foo.com", cc->Domain());
+ EXPECT_TRUE(status.IsInclude());
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", ".www.foo.com", "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
ASSERT_TRUE(cc);
EXPECT_TRUE(cc->IsDomainCookie());
EXPECT_EQ(".www.foo.com", cc->Domain());
+ EXPECT_TRUE(status.IsInclude());
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", ".foo.com", "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
ASSERT_TRUE(cc);
EXPECT_TRUE(cc->IsDomainCookie());
EXPECT_EQ(".foo.com", cc->Domain());
+ EXPECT_TRUE(status.IsInclude());
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com/foo"), "A", "B", ".www2.www.foo.com", "/foo",
one_hour_ago, one_hour_from_now, base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
EXPECT_FALSE(cc);
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
// Secure/URL Scheme mismatch.
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", std::string(), "/foo ",
base::Time(), base::Time(), base::Time(), true /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
// Null creation date/non-null last access date conflict.
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", std::string(), "/foo", base::Time(),
base::Time(), base::Time::Now(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
// Domain doesn't match URL
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", "www.bar.com", "/", base::Time(),
base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
// Path with unusual characters escaped.
cc = CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "A", "B", std::string(), "/foo",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false /*same_party*/);
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status);
ASSERT_TRUE(cc);
EXPECT_EQ("/foo%7F", cc->Path());
+ EXPECT_TRUE(status.IsInclude());
// Empty name and value.
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://www.foo.com"), "", "", std::string(), "/", base::Time(),
base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
// A __Secure- cookie must be Secure.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Secure-A", "B", ".www.foo.com", "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Secure-A", "B", ".www.foo.com", "/",
two_hours_ago, one_hour_from_now, one_hour_ago, false, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
// A __Host- cookie must be Secure.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
two_hours_ago, one_hour_from_now, one_hour_ago, false, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
// A __Host- cookie must have path "/".
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/foo",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
// A __Host- cookie must not specify a domain.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "__Host-A", "B", ".www.foo.com", "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PREFIX}));
+
// Without __Host- prefix, this is a valid host cookie because it does not
// specify a domain.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
+
// Without __Host- prefix, this is a valid domain (not host) cookie.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
// The __Host- prefix should not prevent otherwise-valid host cookies from
// being accepted.
@@ -2618,46 +3112,94 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) {
GURL("https://127.0.0.1"), "A", "B", std::string(), "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://127.0.0.1"), "__Host-A", "B", std::string(), "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
+
// Host cookies should not specify domain unless it is an IP address that
// matches the URL.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://127.0.0.1"), "A", "B", "127.0.0.1", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://127.0.0.1"), "__Host-A", "B", "127.0.0.1", "/",
two_hours_ago, one_hour_from_now, one_hour_ago, true, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- false));
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
// SameParty attribute requires Secure and forbids SameSite=Strict.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true /*secure*/, false,
CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- true /*same_party*/));
+ true /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, false /*secure*/, false,
CookieSameSite::LAX_MODE, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- true /*same_party*/));
+ true /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, true /*secure*/, false,
CookieSameSite::STRICT_MODE, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- true /*same_party*/));
+ true /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("https://www.foo.com"), "A", "B", ".www.foo.com", "/", two_hours_ago,
one_hour_from_now, one_hour_ago, false /*secure*/, false,
CookieSameSite::STRICT_MODE, CookiePriority::COOKIE_PRIORITY_DEFAULT,
- true /*same_party*/));
+ true /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
+
+ // Partitioned attribute requires __Host- and forbids SameParty.
+ status = CookieInclusionStatus();
+ EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
+ GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
+ two_hours_ago, one_hour_from_now, one_hour_ago, true /*secure*/, false,
+ CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/,
+ absl::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))),
+ &status));
+ EXPECT_TRUE(status.IsInclude());
+ // Invalid: no __Host- prefix
+ EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
+ GURL("https://www.foo.com"), "A", "B", std::string(), "/", two_hours_ago,
+ one_hour_from_now, one_hour_ago, true /*secure*/, false,
+ CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/,
+ absl::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))),
+ &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
+ status = CookieInclusionStatus();
+ // Invalid: SameParty attribute present.
+ EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
+ GURL("https://www.foo.com"), "__Host-A", "B", std::string(), "/",
+ two_hours_ago, one_hour_from_now, one_hour_ago, true /*secure*/, false,
+ CookieSameSite::NO_RESTRICTION, CookiePriority::COOKIE_PRIORITY_DEFAULT,
+ true /*same_party*/,
+ absl::optional<CookiePartitionKey>(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))),
+ &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_PARTITIONED}));
+ status = CookieInclusionStatus();
// Check that CreateSanitizedCookie can gracefully fail on inputs that would
// crash cookie_util::GetCookieDomainWithString due to failing
@@ -2667,36 +3209,62 @@ TEST(CanonicalCookieTest, CreateSanitizedCookie_Logic) {
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://..."), "A", "B", "...", "/", base::Time(), base::Time(),
base::Time(), false /*secure*/, false /*httponly*/,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://."), "A", "B", std::string(), "/", base::Time(),
base::Time(), base::Time(), false /*secure*/, false /*httponly*/,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
GURL("http://.chromium.org"), "A", "B", ".chromium.org", "/",
base::Time(), base::Time(), base::Time(), false /*secure*/,
false /*httponly*/, CookieSameSite::NO_RESTRICTION,
- COOKIE_PRIORITY_DEFAULT, false));
+ COOKIE_PRIORITY_DEFAULT, false /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
// Check that a file URL with an IPv6 host, and matching IPv6 domain, are
// valid.
EXPECT_TRUE(CanonicalCookie::CreateSanitizedCookie(
GURL("file://[A::]"), "A", "B", "[A::]", "", base::Time(), base::Time(),
base::Time(), false /*secure*/, false /*httponly*/,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false));
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.IsInclude());
// On Windows, URLs beginning with two backslashes are considered file
// URLs. On other platforms, they are invalid.
auto double_backslash_ipv6_cookie = CanonicalCookie::CreateSanitizedCookie(
GURL("\\\\[A::]"), "A", "B", "[A::]", "", base::Time(), base::Time(),
base::Time(), false /*secure*/, false /*httponly*/,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
+ false /*same_party*/, absl::nullopt /*partition_key*/, &status);
#if defined(OS_WIN)
EXPECT_TRUE(double_backslash_ipv6_cookie);
EXPECT_TRUE(double_backslash_ipv6_cookie->IsCanonical());
+ EXPECT_TRUE(status.IsInclude());
#else
EXPECT_FALSE(double_backslash_ipv6_cookie);
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN}));
#endif
+
+ // Confirm multiple error types can be set.
+ EXPECT_FALSE(CanonicalCookie::CreateSanitizedCookie(
+ GURL(""), "", "", "", "", base::Time(), base::Time(), base::Time::Now(),
+ true /*secure*/, true /*httponly*/, CookieSameSite::STRICT_MODE,
+ COOKIE_PRIORITY_DEFAULT, true /*same_party*/,
+ absl::nullopt /*partition_key*/, &status));
+ EXPECT_TRUE(status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE,
+ CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN,
+ CookieInclusionStatus::EXCLUDE_INVALID_SAMEPARTY}));
}
TEST(CanonicalCookieTest, FromStorage) {
@@ -2709,7 +3277,8 @@ TEST(CanonicalCookieTest, FromStorage) {
"A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
one_hour_ago, false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/, CookieSourceScheme::kSecure, 87);
+ false /*same_party*/, absl::nullopt /*partition_key*/,
+ CookieSourceScheme::kSecure, 87);
EXPECT_TRUE(cc);
EXPECT_EQ("A", cc->Name());
EXPECT_EQ("B", cc->Value());
@@ -2733,7 +3302,8 @@ TEST(CanonicalCookieTest, FromStorage) {
"A\n", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
one_hour_ago, false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/, CookieSourceScheme::kSecure, 80));
+ false /*same_party*/, absl::nullopt /*partition_key*/,
+ CookieSourceScheme::kSecure, 80));
// If the port information gets corrupted out of the valid range
// FromStorage() should result in a PORT_INVALID.
@@ -2741,7 +3311,8 @@ TEST(CanonicalCookieTest, FromStorage) {
"A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
one_hour_ago, false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/, CookieSourceScheme::kSecure, 80000);
+ false /*same_party*/, absl::nullopt /*partition_key*/,
+ CookieSourceScheme::kSecure, 80000);
EXPECT_EQ(cc2->SourcePort(), url::PORT_INVALID);
@@ -2750,7 +3321,8 @@ TEST(CanonicalCookieTest, FromStorage) {
"A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
one_hour_ago, false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/, CookieSourceScheme::kSecure, url::PORT_UNSPECIFIED);
+ false /*same_party*/, absl::nullopt /*partition_key*/,
+ CookieSourceScheme::kSecure, url::PORT_UNSPECIFIED);
EXPECT_EQ(cc3->SourcePort(), url::PORT_UNSPECIFIED);
// Test port edge cases: invalid.
@@ -2758,7 +3330,8 @@ TEST(CanonicalCookieTest, FromStorage) {
"A", "B", "www.foo.com", "/bar", two_hours_ago, one_hour_from_now,
one_hour_ago, false /*secure*/, false /*httponly*/,
CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT,
- false /*same_party*/, CookieSourceScheme::kSecure, url::PORT_INVALID);
+ false /*same_party*/, absl::nullopt /*partition_key*/,
+ CookieSourceScheme::kSecure, url::PORT_INVALID);
EXPECT_EQ(cc4->SourcePort(), url::PORT_INVALID);
}
@@ -3264,183 +3837,95 @@ TEST(CanonicalCookieTest, IsSetPermittedInContext) {
}
}
- // Behavior of UNSPECIFIED depends on an experiment and CookieAccessSemantics.
+ // Behavior of UNSPECIFIED depends on CookieAccessSemantics.
auto cookie_same_site_unspecified =
CanonicalCookie::CreateUnsafeCookieForTesting(
"A", "2", "www.example.com", "/test", current_time, base::Time(),
base::Time(), true /*secure*/, false /*httponly*/,
CookieSameSite::UNSPECIFIED, COOKIE_PRIORITY_DEFAULT, false);
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
-
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(
- HasExactlyExclusionReasonsForTesting(
- std::vector<CookieInclusionStatus::ExclusionReason>(
- {CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
- _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- }
-
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
-
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(
- HasExactlyExclusionReasonsForTesting(
- std::vector<CookieInclusionStatus::ExclusionReason>(
- {CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
- _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::UNKNOWN,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::LEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_cross_site,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(
- HasExactlyExclusionReasonsForTesting(
- std::vector<CookieInclusionStatus::ExclusionReason>(
- {CookieInclusionStatus::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
- _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_lax,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- EXPECT_THAT(
- cookie_same_site_unspecified->IsSetPermittedInContext(
- url, context_same_site_strict,
- CookieAccessParams(CookieAccessSemantics::NONLEGACY,
- false /* delegate_treats_url_as_trustworthy */,
- CookieSamePartyStatus::kNoSamePartyEnforcement),
- kCookieableSchemes),
- MatchesCookieAccessResult(IsInclude(), _, _, true));
- }
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_cross_site,
+ CookieAccessParams(CookieAccessSemantics::UNKNOWN,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>(
+ {CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
+ _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_lax,
+ CookieAccessParams(CookieAccessSemantics::UNKNOWN,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_strict,
+ CookieAccessParams(CookieAccessSemantics::UNKNOWN,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_cross_site,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_lax,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_strict,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_cross_site,
+ CookieAccessParams(CookieAccessSemantics::NONLEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>(
+ {CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX})),
+ _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_lax,
+ CookieAccessParams(CookieAccessSemantics::NONLEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
+ EXPECT_THAT(
+ cookie_same_site_unspecified->IsSetPermittedInContext(
+ url, context_same_site_strict,
+ CookieAccessParams(CookieAccessSemantics::NONLEGACY,
+ false /* delegate_treats_url_as_trustworthy */,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(IsInclude(), _, _, true));
}
TEST(CanonicalCookieTest, IsSetPermittedEffectiveSameSite) {
@@ -3627,14 +4112,163 @@ TEST(CanonicalCookieTest, IsSetPermitted_AllowedToAccessSecureCookies) {
}
}
+TEST(CanonicalCookieTest, IsSetPermitted_SameSiteNone_Metrics) {
+ using SamePartyContextType = SamePartyContext::Type;
+
+ constexpr bool delegate_treats_url_as_trustworthy = false;
+ const base::Time now = base::Time::Now();
+ const auto make_cookie = [now](CookieSameSite same_site, bool same_party) {
+ return CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.com", "/test", now, base::Time(), base::Time(),
+ true /* secure */, false /*httponly*/, same_site,
+ COOKIE_PRIORITY_DEFAULT, same_party);
+ };
+ GURL url("https://www.example.com/test");
+
+ const std::unique_ptr<CanonicalCookie> same_site_none_cookie =
+ make_cookie(CookieSameSite::NO_RESTRICTION, false /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_party_cookie =
+ make_cookie(CookieSameSite::NO_RESTRICTION, true /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_site_lax_cookie =
+ make_cookie(CookieSameSite::LAX_MODE, false /* same_party */);
+ const std::unique_ptr<CanonicalCookie> same_site_strict_cookie =
+ make_cookie(CookieSameSite::STRICT_MODE, false /* same_party */);
+ CookieOptions options;
+
+ options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
+ CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
+ // Same as default, but just to be explicit:
+ options.set_same_party_context(
+ SamePartyContext(SamePartyContext::Type::kCrossParty));
+ EXPECT_THAT(
+ same_site_none_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kEnforceSamePartyExclude),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Now tweak the context to allow a SameParty cookie (using the top&resource
+ // definition) and make sure we get the right warning. (Note: we make the
+ // "real" same-partyness value match the value computed for the metric, even
+ // though they would differ unless we changed the real definition.) Then
+ // check that if we modify the cookie as indicated, the set would be allowed.
+ options.set_same_party_context(SamePartyContext(
+ SamePartyContextType::kSameParty, SamePartyContextType::kCrossParty,
+ SamePartyContextType::kSameParty));
+ EXPECT_THAT(
+ same_site_none_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kEnforceSamePartyInclude),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Next: allow a SameParty cookie (using both definitions).
+ options.set_same_party_context(SamePartyContext::MakeInclusive());
+ EXPECT_THAT(
+ same_site_none_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS}),
+ _, _, true));
+ EXPECT_THAT(
+ same_party_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(Not(net::IsInclude()), _, _, true));
+
+ // Next: allow a SameSite=Lax or SameSite=Strict cookie.
+ options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
+ CookieOptions::SameSiteCookieContext::ContextType::SAME_SITE_LAX));
+ EXPECT_THAT(
+ same_site_none_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(
+ CookieInclusionStatus::MakeFromReasonsForTesting(
+ {}, {CookieInclusionStatus::
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT}),
+ _, _, true));
+ EXPECT_THAT(
+ same_site_lax_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+ EXPECT_THAT(
+ same_site_strict_cookie->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(CookieAccessSemantics::LEGACY,
+ delegate_treats_url_as_trustworthy,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes),
+ MatchesCookieAccessResult(net::IsInclude(), _, _, true));
+}
+
TEST(CanonicalCookieTest, IsSetPermitted_SameParty) {
GURL url("https://www.example.com/test");
base::Time current_time = base::Time::Now();
CookieOptions options;
options.set_same_site_cookie_context(CookieOptions::SameSiteCookieContext(
CookieOptions::SameSiteCookieContext::ContextType::CROSS_SITE));
- options.set_same_party_cookie_context_type(
- CookieOptions::SamePartyCookieContextType::kSameParty);
+ options.set_same_party_context(
+ SamePartyContext(SamePartyContext::Type::kSameParty));
{
bool delegate_treats_url_as_trustworthy = false;
@@ -3689,4 +4323,114 @@ TEST(CanonicalCookieTest, IsSetPermitted_SameParty) {
}
}
+// Test that the CookieInclusionStatus warning for inclusion changed by
+// cross-site redirect context downgrade is applied correctly.
+TEST(CanonicalCookieTest, IsSetPermittedInContext_RedirectDowngradeWarning) {
+ using Context = CookieOptions::SameSiteCookieContext;
+ using ContextType = Context::ContextType;
+
+ GURL url("https://www.example.test/test");
+ GURL insecure_url("http://www.example.test/test");
+
+ // Test cases to be used with a lax-to-cross context downgrade.
+ const struct {
+ ContextType context_type;
+ CookieSameSite samesite;
+ bool expect_cross_site_redirect_warning;
+ } kTestCases[] = {
+ {ContextType::SAME_SITE_LAX, CookieSameSite::STRICT_MODE, true},
+ {ContextType::CROSS_SITE, CookieSameSite::STRICT_MODE, true},
+ {ContextType::SAME_SITE_LAX, CookieSameSite::LAX_MODE, true},
+ {ContextType::CROSS_SITE, CookieSameSite::LAX_MODE, true},
+ {ContextType::SAME_SITE_LAX, CookieSameSite::NO_RESTRICTION, false},
+ {ContextType::CROSS_SITE, CookieSameSite::NO_RESTRICTION, false},
+ };
+
+ for (bool consider_redirects : {true, false}) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeatureState(
+ features::kCookieSameSiteConsidersRedirectChain, consider_redirects);
+
+ for (CookieAccessSemantics semantics :
+ {CookieAccessSemantics::LEGACY, CookieAccessSemantics::NONLEGACY}) {
+ // There are no downgrade warnings for undowngraded contexts.
+ for (ContextType context_type : {ContextType::SAME_SITE_LAX,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE,
+ ContextType::CROSS_SITE}) {
+ for (CookieSameSite samesite :
+ {CookieSameSite::UNSPECIFIED, CookieSameSite::NO_RESTRICTION,
+ CookieSameSite::LAX_MODE, CookieSameSite::STRICT_MODE}) {
+ std::unique_ptr<CanonicalCookie> cookie =
+ CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.test", "/test", base::Time::Now(),
+ base::Time(), base::Time(), /*secure=*/true,
+ /*httponly=*/false, samesite, COOKIE_PRIORITY_DEFAULT,
+ /*same_party=*/false);
+
+ CookieOptions options;
+ options.set_same_site_cookie_context(Context(context_type));
+
+ EXPECT_FALSE(
+ cookie
+ ->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes)
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
+ }
+ }
+
+ for (const auto& test : kTestCases) {
+ std::unique_ptr<CanonicalCookie> cookie =
+ CanonicalCookie::CreateUnsafeCookieForTesting(
+ "A", "1", "www.example.test", "/test", base::Time::Now(),
+ base::Time(), base::Time(), /*secure=*/true, /*httponly=*/false,
+ test.samesite, COOKIE_PRIORITY_DEFAULT, /*same_party=*/false);
+
+ Context::ContextMetadata lax_cross_downgrade_metadata;
+ lax_cross_downgrade_metadata.cross_site_redirect_downgrade =
+ Context::ContextMetadata::ContextDowngradeType::kLaxToCross;
+ CookieOptions options;
+ options.set_same_site_cookie_context(Context(
+ test.context_type, test.context_type, lax_cross_downgrade_metadata,
+ lax_cross_downgrade_metadata));
+
+ EXPECT_EQ(
+ cookie
+ ->IsSetPermittedInContext(
+ url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes)
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION),
+ test.expect_cross_site_redirect_warning);
+
+ // SameSite warnings not applied if other exclusion reasons apply (e.g.
+ // non-https with Secure attribute).
+ EXPECT_FALSE(
+ cookie
+ ->IsSetPermittedInContext(
+ insecure_url, options,
+ CookieAccessParams(
+ semantics,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement),
+ kCookieableSchemes)
+ .status.HasWarningReason(
+ CookieInclusionStatus::
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION));
+ }
+ }
+ }
+}
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_access_delegate.h b/chromium/net/cookies/cookie_access_delegate.h
index 70f8b488b3b..2c5715ef14e 100644
--- a/chromium/net/cookies/cookie_access_delegate.h
+++ b/chromium/net/cookies/cookie_access_delegate.h
@@ -9,6 +9,8 @@
#include "net/base/net_export.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/same_party_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -38,12 +40,12 @@ class NET_EXPORT CookieAccessDelegate {
const GURL& url,
const SiteForCookies& site_for_cookies) const = 0;
- // Returns whether `site` is same-party with `party_context` and
- // `top_frame_site`. If `top_frame_site` is nullopt, then `site` will be
- // checked only against `party_context`.
- virtual bool IsContextSamePartyWithSite(
+ // Returns the SamePartyContext indicating whether `site` is same-party
+ // with `party_context` and `top_frame_site`. If `top_frame_site` is nullptr,
+ // then `site` will be checked only against `party_context`.
+ virtual SamePartyContext ComputeSamePartyContext(
const net::SchemefulSite& site,
- const absl::optional<net::SchemefulSite>& top_frame_site,
+ const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const = 0;
// Returns whether `site` belongs to a non-singleton First-Party Set.
diff --git a/chromium/net/cookies/cookie_constants.cc b/chromium/net/cookies/cookie_constants.cc
index e6c5c429eb4..acb6142e961 100644
--- a/chromium/net/cookies/cookie_constants.cc
+++ b/chromium/net/cookies/cookie_constants.cc
@@ -349,4 +349,6 @@ CookieSourceSchemeName GetSchemeNameEnum(const GURL& url) {
return CookieSourceSchemeName::kOther;
}
+const char kEmptyCookiePartitionKey[] = "";
+
} // namespace net
diff --git a/chromium/net/cookies/cookie_constants.h b/chromium/net/cookies/cookie_constants.h
index ec821bd61a0..8e014241066 100644
--- a/chromium/net/cookies/cookie_constants.h
+++ b/chromium/net/cookies/cookie_constants.h
@@ -31,13 +31,17 @@ enum CookiePriority {
// information about same site cookie restrictions.
// These values are allowed for the SameSite field of a cookie. They mostly
// correspond to CookieEffectiveSameSite values.
-// Note: Don't renumber, as these values are persisted to a database.
+// Note: Don't renumber, as these values are persisted to a database and
+// recorded to histograms.
enum class CookieSameSite {
UNSPECIFIED = -1,
NO_RESTRICTION = 0,
LAX_MODE = 1,
STRICT_MODE = 2,
// Reserved 3 (was EXTENDED_MODE), next number is 4.
+
+ // Keep last, used for histograms.
+ kMaxValue = STRICT_MODE
};
// These are the enforcement modes that may be applied to a cookie when deciding
@@ -74,8 +78,22 @@ enum class CookieSameSiteString {
kMaxValue = kExtended
};
-// What rules to apply when determining whether access to a particular cookie is
-// allowed.
+// What SameSite rules to apply when determining whether access to a particular
+// cookie is allowed.
+//
+// At present, NONLEGACY semantics enforces the following:
+// 1) SameSite=Lax by default: A cookie that does not specify a SameSite
+// attribute will be treated as if it were Lax (except allowing unsafe
+// top-level requests for 2 minutes after its creation; see
+// "lax-allowing-unsafe" or "Lax+POST").
+// 2) SameSite=None requires Secure: A cookie specifying SameSite=None must
+// also specify Secure.
+// 3) Schemeful Same-Site: When determining what requests are considered
+// same-site or cross-site, a "site" is considered to be a registrable
+// domain with a scheme (as opposed to just a registrable domain).
+//
+// When the semantics is LEGACY, these three behaviors are disabled. When the
+// semantics is UNKNOWN, the behavior may or may not depend on base::Features.
enum class CookieAccessSemantics {
// Has not been checked yet or there is no way to check.
UNKNOWN = -1,
@@ -328,6 +346,13 @@ NET_EXPORT CookiePort ReducePortRangeForCookieHistogram(const int port);
// Returns the appropriate enum value for the scheme of the given GURL.
CookieSourceSchemeName GetSchemeNameEnum(const GURL& url);
+// This string is used to as a placeholder for the partition_key column in
+// the SQLite database. All cookies except those set with Partitioned will
+// have this value in their column.
+//
+// Empty string was chosen because it is the smallest, non-null value.
+NET_EXPORT extern const char kEmptyCookiePartitionKey[];
+
} // namespace net
#endif // NET_COOKIES_COOKIE_CONSTANTS_H_
diff --git a/chromium/net/cookies/cookie_deletion_info_unittest.cc b/chromium/net/cookies/cookie_deletion_info_unittest.cc
index 75686868906..d408ceeec83 100644
--- a/chromium/net/cookies/cookie_deletion_info_unittest.cc
+++ b/chromium/net/cookies/cookie_deletion_info_unittest.cc
@@ -507,56 +507,28 @@ TEST(CookieDeletionInfoTest, CookieDeletionInfoMatchesDomainList) {
// the IncludeForRequestURL call uses CookieOptions::MakeAllInclusive).
TEST(CookieDeletionInfoTest, MatchesWithCookieAccessSemantics) {
// Cookie with unspecified SameSite.
- auto cookie =
- CanonicalCookie::Create(GURL("https://www.example.com"), "cookie=1",
- base::Time::Now(), absl::nullopt);
-
- {
- // With SameSite features off.
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(features::kSameSiteByDefaultCookies);
-
- CookieDeletionInfo delete_info;
- delete_info.url = GURL("https://www.example.com/path");
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::UNKNOWN,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::LEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::NONLEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- }
- {
- // With SameSite features on.
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
-
- CookieDeletionInfo delete_info;
- delete_info.url = GURL("https://www.example.com/path");
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::UNKNOWN,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::LEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- EXPECT_TRUE(delete_info.Matches(
- *cookie,
- CookieAccessParams{CookieAccessSemantics::NONLEGACY,
- /*delegate_treats_url_as_trustworthy=*/false,
- CookieSamePartyStatus::kNoSamePartyEnforcement}));
- }
+ auto cookie = CanonicalCookie::Create(
+ GURL("https://www.example.com"), "cookie=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
+
+ CookieDeletionInfo delete_info;
+ delete_info.url = GURL("https://www.example.com/path");
+ EXPECT_TRUE(delete_info.Matches(
+ *cookie,
+ CookieAccessParams{CookieAccessSemantics::UNKNOWN,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement}));
+ EXPECT_TRUE(delete_info.Matches(
+ *cookie,
+ CookieAccessParams{CookieAccessSemantics::LEGACY,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement}));
+ EXPECT_TRUE(delete_info.Matches(
+ *cookie,
+ CookieAccessParams{CookieAccessSemantics::NONLEGACY,
+ /*delegate_treats_url_as_trustworthy=*/false,
+ CookieSamePartyStatus::kNoSamePartyEnforcement}));
}
} // namespace net
diff --git a/chromium/net/cookies/cookie_inclusion_status.cc b/chromium/net/cookies/cookie_inclusion_status.cc
index 688d692aaf2..0b70482c6cc 100644
--- a/chromium/net/cookies/cookie_inclusion_status.cc
+++ b/chromium/net/cookies/cookie_inclusion_status.cc
@@ -31,6 +31,9 @@ CookieInclusionStatus::CookieInclusionStatus(ExclusionReason reason,
: exclusion_reasons_(GetExclusionBitmask(reason)),
warning_reasons_(GetWarningBitmask(warning)) {}
+CookieInclusionStatus::CookieInclusionStatus(WarningReason warning)
+ : warning_reasons_(GetWarningBitmask(warning)) {}
+
bool CookieInclusionStatus::operator==(
const CookieInclusionStatus& other) const {
return exclusion_reasons_ == other.exclusion_reasons_ &&
@@ -85,24 +88,19 @@ void CookieInclusionStatus::MaybeClearSameSiteWarning() {
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
EXCLUDE_SAMESITE_NONE_INSECURE,
}) != 0u) {
- RemoveWarningReason(
- CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
- RemoveWarningReason(CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE);
- RemoveWarningReason(
- CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
+ RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT);
+ RemoveWarningReason(WARN_SAMESITE_NONE_INSECURE);
+ RemoveWarningReason(WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE);
}
if (!ShouldRecordDowngradeMetrics()) {
- RemoveWarningReason(
- CookieInclusionStatus::WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE);
- RemoveWarningReason(
- CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE);
- RemoveWarningReason(
- CookieInclusionStatus::WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE);
- RemoveWarningReason(
- CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE);
- RemoveWarningReason(
- CookieInclusionStatus::WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE);
+ RemoveWarningReason(WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE);
+ RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE);
+ RemoveWarningReason(WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE);
+ RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE);
+ RemoveWarningReason(WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE);
+
+ RemoveWarningReason(WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION);
}
}
@@ -199,45 +197,35 @@ CookieInclusionStatus::GetBreakingDowngradeMetricsEnumValue(
std::string CookieInclusionStatus::GetDebugString() const {
std::string out;
- // Inclusion/exclusion
if (IsInclude())
base::StrAppend(&out, {"INCLUDE, "});
- if (HasExclusionReason(EXCLUDE_UNKNOWN_ERROR))
- base::StrAppend(&out, {"EXCLUDE_UNKNOWN_ERROR, "});
- if (HasExclusionReason(EXCLUDE_HTTP_ONLY))
- base::StrAppend(&out, {"EXCLUDE_HTTP_ONLY, "});
- if (HasExclusionReason(EXCLUDE_SECURE_ONLY))
- base::StrAppend(&out, {"EXCLUDE_SECURE_ONLY, "});
- if (HasExclusionReason(EXCLUDE_DOMAIN_MISMATCH))
- base::StrAppend(&out, {"EXCLUDE_DOMAIN_MISMATCH, "});
- if (HasExclusionReason(EXCLUDE_NOT_ON_PATH))
- base::StrAppend(&out, {"EXCLUDE_NOT_ON_PATH, "});
- if (HasExclusionReason(EXCLUDE_SAMESITE_STRICT))
- base::StrAppend(&out, {"EXCLUDE_SAMESITE_STRICT, "});
- if (HasExclusionReason(EXCLUDE_SAMESITE_LAX))
- base::StrAppend(&out, {"EXCLUDE_SAMESITE_LAX, "});
- if (HasExclusionReason(EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX))
- base::StrAppend(&out, {"EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX, "});
- if (HasExclusionReason(EXCLUDE_SAMESITE_NONE_INSECURE))
- base::StrAppend(&out, {"EXCLUDE_SAMESITE_NONE_INSECURE, "});
- if (HasExclusionReason(EXCLUDE_USER_PREFERENCES))
- base::StrAppend(&out, {"EXCLUDE_USER_PREFERENCES, "});
- if (HasExclusionReason(EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT))
- base::StrAppend(&out, {"EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT, "});
- if (HasExclusionReason(EXCLUDE_FAILURE_TO_STORE))
- base::StrAppend(&out, {"EXCLUDE_FAILURE_TO_STORE, "});
- if (HasExclusionReason(EXCLUDE_NONCOOKIEABLE_SCHEME))
- base::StrAppend(&out, {"EXCLUDE_NONCOOKIEABLE_SCHEME, "});
- if (HasExclusionReason(EXCLUDE_OVERWRITE_SECURE))
- base::StrAppend(&out, {"EXCLUDE_OVERWRITE_SECURE, "});
- if (HasExclusionReason(EXCLUDE_OVERWRITE_HTTP_ONLY))
- base::StrAppend(&out, {"EXCLUDE_OVERWRITE_HTTP_ONLY, "});
- if (HasExclusionReason(EXCLUDE_INVALID_DOMAIN))
- base::StrAppend(&out, {"EXCLUDE_INVALID_DOMAIN, "});
- if (HasExclusionReason(EXCLUDE_INVALID_PREFIX))
- base::StrAppend(&out, {"EXCLUDE_INVALID_PREFIX, "});
- if (HasExclusionReason(EXCLUDE_INVALID_SAMEPARTY))
- base::StrAppend(&out, {"EXCLUDE_INVALID_SAMEPARTY, "});
+ for (const auto& reason :
+ std::initializer_list<std::pair<ExclusionReason, std::string>>{
+ {EXCLUDE_UNKNOWN_ERROR, "EXCLUDE_UNKNOWN_ERROR"},
+ {EXCLUDE_HTTP_ONLY, "EXCLUDE_HTTP_ONLY"},
+ {EXCLUDE_SECURE_ONLY, "EXCLUDE_SECURE_ONLY"},
+ {EXCLUDE_DOMAIN_MISMATCH, "EXCLUDE_DOMAIN_MISMATCH"},
+ {EXCLUDE_NOT_ON_PATH, "EXCLUDE_NOT_ON_PATH"},
+ {EXCLUDE_SAMESITE_STRICT, "EXCLUDE_SAMESITE_STRICT"},
+ {EXCLUDE_SAMESITE_LAX, "EXCLUDE_SAMESITE_LAX"},
+ {EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+ "EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX"},
+ {EXCLUDE_SAMESITE_NONE_INSECURE, "EXCLUDE_SAMESITE_NONE_INSECURE"},
+ {EXCLUDE_USER_PREFERENCES, "EXCLUDE_USER_PREFERENCES"},
+ {EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT,
+ "EXCLUDE_SAMEPARTY_CROSS_PARTY_CONTEXT"},
+ {EXCLUDE_FAILURE_TO_STORE, "EXCLUDE_FAILURE_TO_STORE"},
+ {EXCLUDE_NONCOOKIEABLE_SCHEME, "EXCLUDE_NONCOOKIEABLE_SCHEME"},
+ {EXCLUDE_OVERWRITE_SECURE, "EXCLUDE_OVERWRITE_SECURE"},
+ {EXCLUDE_OVERWRITE_HTTP_ONLY, "EXCLUDE_OVERWRITE_HTTP_ONLY"},
+ {EXCLUDE_INVALID_DOMAIN, "EXCLUDE_INVALID_DOMAIN"},
+ {EXCLUDE_INVALID_PREFIX, "EXCLUDE_INVALID_PREFIX"},
+ {EXCLUDE_INVALID_SAMEPARTY, "EXCLUDE_INVALID_SAMEPARTY"},
+ {EXCLUDE_INVALID_PARTITIONED, "EXCLUDE_INVALID_PARTITIONED"},
+ }) {
+ if (HasExclusionReason(reason.first))
+ base::StrAppend(&out, {reason.second, ", "});
+ }
// Add warning
if (!ShouldWarn()) {
@@ -245,31 +233,43 @@ std::string CookieInclusionStatus::GetDebugString() const {
return out;
}
- if (HasWarningReason(WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT))
- base::StrAppend(&out, {"WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT, "});
- if (HasWarningReason(WARN_SAMESITE_NONE_INSECURE))
- base::StrAppend(&out, {"WARN_SAMESITE_NONE_INSECURE, "});
- if (HasWarningReason(WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE))
- base::StrAppend(&out, {"WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE, "});
- if (HasWarningReason(WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE))
- base::StrAppend(&out, {"WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE, "});
- if (HasWarningReason(WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE))
- base::StrAppend(&out, {"WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE, "});
- if (HasWarningReason(WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE))
- base::StrAppend(&out, {"WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE, "});
- if (HasWarningReason(WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE))
- base::StrAppend(&out, {"WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE, "});
- if (HasWarningReason(WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE))
- base::StrAppend(&out, {"WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE, "});
- if (HasWarningReason(WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC))
- base::StrAppend(&out, {"WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC, "});
- if (HasWarningReason(WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE))
- base::StrAppend(&out, {"WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE, "});
- if (HasWarningReason(WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE))
- base::StrAppend(&out, {"WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE, "});
- if (HasWarningReason(WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211)) {
- base::StrAppend(&out,
- {"WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211, "});
+ for (const auto& reason :
+ std::initializer_list<std::pair<WarningReason, std::string>>{
+ {WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+ "WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT"},
+ {WARN_SAMESITE_NONE_INSECURE, "WARN_SAMESITE_NONE_INSECURE"},
+ {WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE,
+ "WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE"},
+ {WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE,
+ "WARN_STRICT_LAX_DOWNGRADE_STRICT_SAMESITE"},
+ {WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE,
+ "WARN_STRICT_CROSS_DOWNGRADE_STRICT_SAMESITE"},
+ {WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE,
+ "WARN_STRICT_CROSS_DOWNGRADE_LAX_SAMESITE"},
+ {WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE,
+ "WARN_LAX_CROSS_DOWNGRADE_STRICT_SAMESITE"},
+ {WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE,
+ "WARN_LAX_CROSS_DOWNGRADE_LAX_SAMESITE"},
+ {WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC,
+ "WARN_SECURE_ACCESS_GRANTED_NON_CRYPTOGRAPHIC"},
+ {WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE,
+ "WARN_SAMEPARTY_EXCLUSION_OVERRULED_SAMESITE"},
+ {WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE,
+ "WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE"},
+ {WARN_SAMESITE_NONE_REQUIRED, "WARN_SAMESITE_NONE_REQUIRED"},
+ {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE,
+ "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE"},
+ {WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS,
+ "WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS"},
+ {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX,
+ "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX"},
+ {WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT,
+ "WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT"},
+ {WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION,
+ "WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION"},
+ }) {
+ if (HasWarningReason(reason.first))
+ base::StrAppend(&out, {reason.second, ", "});
}
// Strip trailing comma and space.
diff --git a/chromium/net/cookies/cookie_inclusion_status.h b/chromium/net/cookies/cookie_inclusion_status.h
index 3247c6269f6..1ee8e9efc03 100644
--- a/chromium/net/cookies/cookie_inclusion_status.h
+++ b/chromium/net/cookies/cookie_inclusion_status.h
@@ -5,6 +5,7 @@
#ifndef NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
#define NET_COOKIES_COOKIE_INCLUSION_STATUS_H_
+#include <ostream>
#include <string>
#include <vector>
@@ -58,7 +59,9 @@ class NET_EXPORT CookieInclusionStatus {
// Statuses only applied when creating/setting cookies:
- // Cookie was malformed and could not be stored.
+ // Cookie was malformed and could not be stored, due to problem(s) while
+ // parsing.
+ // TODO(crbug.com/1228815): Use more specific reasons for parsing errors.
EXCLUDE_FAILURE_TO_STORE = 11,
// Attempted to set a cookie from a scheme that does not support cookies.
EXCLUDE_NONCOOKIEABLE_SCHEME = 12,
@@ -77,6 +80,10 @@ class NET_EXPORT CookieInclusionStatus {
// other attributes. (SameParty is invalid if Secure is not present, or if
// SameSite=Strict is present.)
EXCLUDE_INVALID_SAMEPARTY = 17,
+ /// Cookie was set with an invalid Partitioned attribute, which is only
+ // valid if the cookie has a __Host- prefix and does not have the SameParty
+ // attribute.
+ EXCLUDE_INVALID_PARTITIONED = 18,
// This should be kept last.
NUM_EXCLUSION_REASONS
@@ -169,12 +176,37 @@ class NET_EXPORT CookieInclusionStatus {
// contexts, for cookies that are 'SameParty; SameSite=Lax'.)
WARN_SAMEPARTY_INCLUSION_OVERRULED_SAMESITE = 11,
- // The cookie was SameSite=Lax (or unspecified-treated-as-lax) and was
- // excluded due to the fix for crbug.com/1166211, i.e. it was accessed by an
- // HTTP request which was not a main frame navigation, whose initiator was
- // cross-site and whose site-for-cookies was same-site with the request URL.
- // TODO(crbug.com/1166211): Remove when no longer needed.
- WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211 = 12,
+ // This cookie was SameSite=None and was included, but would have been
+ // excluded if it had been SameParty and the SameParty context had been
+ // computed using *either* top & current or the whole ancestor tree.
+ WARN_SAMESITE_NONE_REQUIRED = 12,
+ // This cookie was SameSite=None, was included, would have been included if
+ // it had been SameParty and the SameParty context type had been computed
+ // with only the top frame & resource URL, but would have been excluded if
+ // the SameParty context type had been computed using all ancestor frames.
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_TOP_RESOURCE = 13,
+ // This cookie was SameSite=None, was included, and would have been included
+ // if it had been SameParty and the SameParty context type had been computed
+ // using all ancestor frames.
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMEPARTY_ANCESTORS = 14,
+ // This cookie was SameSite=None, was included, and would have been included
+ // if it had been SameSite=Lax.
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_LAX = 15,
+ // This cookie was SameSite=None, was included, and would have been included
+ // if it had been SameSite=Strict.
+ WARN_SAMESITE_NONE_INCLUDED_BY_SAMESITE_STRICT = 16,
+
+ // The cookie would have been included prior to the spec change considering
+ // redirects in the SameSite context calculation
+ // (https://github.com/httpwg/http-extensions/pull/1348)
+ // but would have been excluded after the spec change, due to a cross-site
+ // redirect causing the SameSite context calculation to be downgraded.
+ // This is applied if and only if the cookie's inclusion was changed by
+ // considering redirect chains (and is applied regardless of which context
+ // was actually used for the inclusion decision). This is not applied if
+ // the context was downgraded but the cookie would have been
+ // included/excluded in both cases.
+ WARN_CROSS_SITE_REDIRECT_DOWNGRADE_CHANGES_INCLUSION = 17,
// This should be kept last.
NUM_WARNING_REASONS
@@ -214,6 +246,8 @@ class NET_EXPORT CookieInclusionStatus {
explicit CookieInclusionStatus(ExclusionReason reason);
// Makes a status that contains the given exclusion reason and warning.
CookieInclusionStatus(ExclusionReason reason, WarningReason warning);
+ // Makes a status that contains the given warning.
+ explicit CookieInclusionStatus(WarningReason warning);
bool operator==(const CookieInclusionStatus& other) const;
bool operator!=(const CookieInclusionStatus& other) const;
@@ -239,8 +273,8 @@ class NET_EXPORT CookieInclusionStatus {
void RemoveExclusionReasons(const std::vector<ExclusionReason>& reasons);
// If the cookie would have been excluded for reasons other than
- // SAMESITE_UNSPECIFIED_TREATED_AS_LAX or SAMESITE_NONE_INSECURE, don't bother
- // warning about it (clear the warning).
+ // SameSite-related reasons, don't bother warning about it (clear the
+ // warning).
void MaybeClearSameSiteWarning();
// Whether to record the breaking downgrade metrics if the cookie is included
diff --git a/chromium/net/cookies/cookie_monster.cc b/chromium/net/cookies/cookie_monster.cc
index 4183288fd5d..f13f2ce6133 100644
--- a/chromium/net/cookies/cookie_monster.cc
+++ b/chromium/net/cookies/cookie_monster.cc
@@ -50,6 +50,7 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/logging.h"
@@ -59,7 +60,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/ranges/algorithm.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -183,15 +183,6 @@ struct OrderByCreationTimeDesc {
}
};
-// Mozilla sorts on the path length (longest first), and then it
-// sorts by creation time (oldest first).
-// The RFC says the sort order for the domain attribute is undefined.
-bool CookieSorter(CanonicalCookie* cc1, CanonicalCookie* cc2) {
- if (cc1->Path().length() == cc2->Path().length())
- return cc1->CreationDate() < cc2->CreationDate();
- return cc1->Path().length() > cc2->Path().length();
-}
-
bool LRACookieSorter(const CookieMonster::CookieMap::iterator& it1,
const CookieMonster::CookieMap::iterator& it2) {
if (it1->second->LastAccessDate() != it2->second->LastAccessDate())
@@ -565,6 +556,17 @@ CookieMonster::~CookieMonster() {
net_log_.EndEvent(NetLogEventType::COOKIE_STORE_ALIVE);
}
+// static
+bool CookieMonster::CookieSorter(const CanonicalCookie* cc1,
+ const CanonicalCookie* cc2) {
+ // Mozilla sorts on the path length (longest first), and then it sorts by
+ // creation time (oldest first). The RFC says the sort order for the domain
+ // attribute is undefined.
+ if (cc1->Path().length() == cc2->Path().length())
+ return cc1->CreationDate() < cc2->CreationDate();
+ return cc1->Path().length() > cc2->Path().length();
+}
+
void CookieMonster::GetAllCookies(GetAllCookiesCallback callback) {
DCHECK(thread_checker_.CalledOnValidThread());
@@ -619,7 +621,6 @@ void CookieMonster::GetCookieListWithOptions(const GURL& url,
std::sort(cookie_ptrs.begin(), cookie_ptrs.end(), CookieSorter);
included_cookies.reserve(cookie_ptrs.size());
- std::vector<CanonicalCookie*> included_cookie_ptrs;
FilterCookiesWithOptions(url, options, &cookie_ptrs, &included_cookies,
&excluded_cookies);
}
@@ -794,16 +795,13 @@ void CookieMonster::StoreLoadedCookies(
// removed, and sync'd.
CookieItVector cookies_with_control_chars;
- bool dispatch_change = !base::FeatureList::IsEnabled(
- features::kNoCookieChangeNotificationOnLoad);
-
for (auto& cookie : cookies) {
CanonicalCookie* cookie_ptr = cookie.get();
CookieAccessResult access_result;
access_result.access_semantics = CookieAccessSemantics::UNKNOWN;
auto inserted = InternalInsertCookie(
GetKey(cookie_ptr->Domain()), std::move(cookie),
- false /* sync_to_store */, access_result, dispatch_change);
+ false /* sync_to_store */, access_result, false /* dispatch_change */);
const Time cookie_access_time(cookie_ptr->LastAccessDate());
if (earliest_access_time_.is_null() ||
cookie_access_time < earliest_access_time_) {
@@ -943,12 +941,14 @@ void CookieMonster::TrimDuplicateCookiesForKey(const std::string& key,
// duplicates.
dupes.erase(dupes.begin());
+ // TODO(crbug.com/1225444) Include cookie partition key in this log
+ // statement as well if needed.
LOG(ERROR) << base::StringPrintf(
"Found %d duplicate cookies for key='%s', "
"with {name='%s', domain='%s', path='%s'}",
static_cast<int>(dupes.size()), key.c_str(),
- std::get<0>(signature).c_str(), std::get<1>(signature).c_str(),
- std::get<2>(signature).c_str());
+ std::get<1>(signature).c_str(), std::get<2>(signature).c_str(),
+ std::get<3>(signature).c_str());
// Remove all the cookies identified by |dupes|. It is valid to delete our
// list of iterators one at a time, since |cookies_| is a multimap (they
diff --git a/chromium/net/cookies/cookie_monster.h b/chromium/net/cookies/cookie_monster.h
index ef391b3cb94..8439ba30a16 100644
--- a/chromium/net/cookies/cookie_monster.h
+++ b/chromium/net/cookies/cookie_monster.h
@@ -34,7 +34,6 @@
#include "net/cookies/cookie_monster_change_dispatcher.h"
#include "net/cookies/cookie_store.h"
#include "net/log/net_log_with_source.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -201,6 +200,10 @@ class NET_EXPORT CookieMonster : public CookieStore {
// before the CookieMap typedef.
static std::string GetKey(base::StringPiece domain);
+ // Exposes the comparison function used when sorting cookies.
+ static bool CookieSorter(const CanonicalCookie* cc1,
+ const CanonicalCookie* cc2);
+
// Triggers immediate recording of stats that are typically reported
// periodically.
bool DoRecordPeriodicStatsForTesting() { return DoRecordPeriodicStats(); }
diff --git a/chromium/net/cookies/cookie_monster_perftest.cc b/chromium/net/cookies/cookie_monster_perftest.cc
index c8ff8b5c826..61bb68fcadc 100644
--- a/chromium/net/cookies/cookie_monster_perftest.cc
+++ b/chromium/net/cookies/cookie_monster_perftest.cc
@@ -95,8 +95,9 @@ class SetCookieCallback : public CookieTestCallback {
void SetCookie(CookieMonster* cm,
const GURL& gurl,
const std::string& cookie_line) {
- auto cookie = CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ gurl, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(
std::move(cookie), gurl, options_,
base::BindOnce(&SetCookieCallback::Run, base::Unretained(this)));
diff --git a/chromium/net/cookies/cookie_monster_store_test.h b/chromium/net/cookies/cookie_monster_store_test.h
index 4f034827484..c925612720f 100644
--- a/chromium/net/cookies/cookie_monster_store_test.h
+++ b/chromium/net/cookies/cookie_monster_store_test.h
@@ -170,8 +170,7 @@ class MockSimplePersistentCookieStore
~MockSimplePersistentCookieStore() override;
private:
- typedef std::map<std::tuple<std::string, std::string, std::string>,
- CanonicalCookie>
+ typedef std::map<CanonicalCookie::UniqueCookieKey, CanonicalCookie>
CanonicalCookieMap;
CanonicalCookieMap cookies_;
diff --git a/chromium/net/cookies/cookie_monster_unittest.cc b/chromium/net/cookies/cookie_monster_unittest.cc
index 4c7ed97862c..23c3f2e783a 100644
--- a/chromium/net/cookies/cookie_monster_unittest.cc
+++ b/chromium/net/cookies/cookie_monster_unittest.cc
@@ -64,8 +64,6 @@ namespace net {
using base::Time;
using base::TimeDelta;
using CookieDeletionInfo = net::CookieDeletionInfo;
-using features::kCookiesWithoutSameSiteMustBeSecure;
-using features::kSameSiteByDefaultCookies;
namespace {
@@ -173,7 +171,8 @@ class CookieMonsterTestBase : public CookieStoreTest<T> {
ResultSavingCookieCallback<CookieAccessResult> callback;
cm->SetCanonicalCookieAsync(
CanonicalCookie::Create(url, cookie_line, creation_time,
- absl::nullopt /* server_time */),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */),
url, CookieOptions::MakeAllInclusive(), callback.MakeCallback());
callback.WaitUntilDone();
return callback.result().status.IsInclude();
@@ -1038,7 +1037,8 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
ResultSavingCookieCallback<CookieAccessResult> call1;
cookie_monster_->SetCanonicalCookieAsync(
CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
- absl::nullopt /* server_time */),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */),
http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
call1.MakeCallback());
base::RunLoop().RunUntilIdle();
@@ -1052,7 +1052,8 @@ TEST_F(DeferredCookieTaskTest, DeferredSetCookie) {
ResultSavingCookieCallback<CookieAccessResult> call2;
cookie_monster_->SetCanonicalCookieAsync(
CanonicalCookie::Create(http_www_foo_.url(), "X=Y", base::Time::Now(),
- absl::nullopt /* server_time */),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */),
http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
call2.MakeCallback());
ASSERT_TRUE(call2.was_run());
@@ -1337,7 +1338,8 @@ TEST_F(DeferredCookieTaskTest, DeferredTaskOrder) {
cookie_monster_->SetCanonicalCookieAsync(
CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
- absl::nullopt /* server_time */),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */),
http_www_foo_.url(), CookieOptions::MakeAllInclusive(),
set_cookies_callback.MakeCallback());
@@ -1623,39 +1625,47 @@ TEST_F(CookieMonsterTest, SetCookieableSchemes) {
absl::optional<base::Time> server_time = absl::nullopt;
EXPECT_TRUE(
CreateAndSetCookieReturnStatus(cm.get(), http_url, "x=1").IsInclude());
- EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
- cm.get(),
- CanonicalCookie::Create(http_url, "y=1", now, server_time),
- http_url, false /*modify_httponly*/)
- .status.IsInclude());
+ EXPECT_TRUE(
+ SetCanonicalCookieReturnAccessResult(
+ cm.get(),
+ CanonicalCookie::Create(http_url, "y=1", now, server_time,
+ absl::nullopt /* cookie_partition_key */),
+ http_url, false /*modify_httponly*/)
+ .status.IsInclude());
EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm.get(), foo_url, "x=1")
.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
- EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
- cm.get(),
- CanonicalCookie::Create(foo_url, "y=1", now, server_time),
- foo_url, false /*modify_httponly*/)
- .status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
+ EXPECT_TRUE(
+ SetCanonicalCookieReturnAccessResult(
+ cm.get(),
+ CanonicalCookie::Create(foo_url, "y=1", now, server_time,
+ absl::nullopt /* cookie_partition_key */),
+ foo_url, false /*modify_httponly*/)
+ .status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
EXPECT_TRUE(
CreateAndSetCookieReturnStatus(cm_foo.get(), foo_url, "x=1").IsInclude());
- EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
- cm_foo.get(),
- CanonicalCookie::Create(foo_url, "y=1", now, server_time),
- foo_url, false /*modify_httponly*/)
- .status.IsInclude());
+ EXPECT_TRUE(
+ SetCanonicalCookieReturnAccessResult(
+ cm_foo.get(),
+ CanonicalCookie::Create(foo_url, "y=1", now, server_time,
+ absl::nullopt /* cookie_partition_key */),
+ foo_url, false /*modify_httponly*/)
+ .status.IsInclude());
EXPECT_TRUE(CreateAndSetCookieReturnStatus(cm_foo.get(), http_url, "x=1")
.HasExactlyExclusionReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
- EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
- cm_foo.get(),
- CanonicalCookie::Create(http_url, "y=1", now, server_time),
- http_url, false /*modify_httponly*/)
- .status.HasExactlyExclusionReasonsForTesting(
- {CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
+ EXPECT_TRUE(
+ SetCanonicalCookieReturnAccessResult(
+ cm_foo.get(),
+ CanonicalCookie::Create(http_url, "y=1", now, server_time,
+ absl::nullopt /* cookie_partition_key */),
+ http_url, false /*modify_httponly*/)
+ .status.HasExactlyExclusionReasonsForTesting(
+ {CookieInclusionStatus::EXCLUDE_NONCOOKIEABLE_SCHEME}));
}
TEST_F(CookieMonsterTest, GetAllCookiesForURL) {
@@ -2366,8 +2376,9 @@ TEST_F(CookieMonsterTest, WhileLoadingLoadCompletesBeforeKeyLoadCompletes) {
store->set_store_load_commands(true);
std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_));
- auto cookie = CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ kUrl, "a=b", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback;
cm->SetCanonicalCookieAsync(std::move(cookie), kUrl,
CookieOptions::MakeAllInclusive(),
@@ -2428,8 +2439,9 @@ TEST_F(CookieMonsterTest, WhileLoadingDeleteAllGetForURL) {
std::vector<std::unique_ptr<CanonicalCookie>> cookies;
// When passed to the CookieMonster, it takes ownership of the pointed to
// cookies.
- cookies.push_back(CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(),
- absl::nullopt /* server_time */));
+ cookies.push_back(CanonicalCookie::Create(
+ kUrl, "a=b", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
ASSERT_TRUE(cookies[0]);
store->TakeCallbackAt(0).Run(std::move(cookies));
@@ -2454,8 +2466,9 @@ TEST_F(CookieMonsterTest, WhileLoadingGetAllSetGetAll) {
GetAllCookiesCallback get_cookies_callback1;
cm->GetAllCookiesAsync(get_cookies_callback1.MakeCallback());
- auto cookie = CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ kUrl, "a=b", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback;
cm->SetCanonicalCookieAsync(std::move(cookie), kUrl,
CookieOptions::MakeAllInclusive(),
@@ -2501,8 +2514,9 @@ TEST_F(CookieMonsterTest, CheckOrderOfCookieTaskQueueWhenLoadingCompletes) {
std::unique_ptr<CookieMonster> cm(new CookieMonster(store.get(), &net_log_));
// Get all cookies task that queues a task to set a cookie when executed.
- auto cookie = CanonicalCookie::Create(kUrl, "a=b", base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ kUrl, "a=b", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
ResultSavingCookieCallback<CookieAccessResult> set_cookie_callback;
cm->GetAllCookiesAsync(base::BindOnce(
&RunClosureOnAllCookiesReceived,
@@ -2715,7 +2729,8 @@ TEST_F(CookieMonsterTest, InvalidExpiryTime) {
std::string(kValidCookieLine) + "; expires=Blarg arg arg";
std::unique_ptr<CanonicalCookie> cookie(
CanonicalCookie::Create(http_www_foo_.url(), cookie_line, Time::Now(),
- absl::nullopt /* server_time */));
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
ASSERT_FALSE(cookie->IsPersistent());
}
@@ -2918,16 +2933,25 @@ TEST_F(CookieMonsterTest, NumKeysHistogram) {
scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies;
initial_cookies.push_back(CanonicalCookie::Create(
- GURL("http://domain1.test"), "A=1", base::Time::Now(), absl::nullopt));
+ GURL("http://domain1.test"), "A=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
+ initial_cookies.push_back(CanonicalCookie::Create(
+ GURL("http://domain2.test"), "A=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
initial_cookies.push_back(CanonicalCookie::Create(
- GURL("http://domain2.test"), "A=1", base::Time::Now(), absl::nullopt));
- initial_cookies.push_back(
- CanonicalCookie::Create(GURL("http://sub.domain2.test"), "A=1",
- base::Time::Now(), absl::nullopt));
+ GURL("http://sub.domain2.test"), "A=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
initial_cookies.push_back(CanonicalCookie::Create(
- GURL("http://domain3.test"), "A=1", base::Time::Now(), absl::nullopt));
+ GURL("http://domain3.test"), "A=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
initial_cookies.push_back(CanonicalCookie::Create(
- GURL("http://domain3.test"), "B=1", base::Time::Now(), absl::nullopt));
+ GURL("http://domain3.test"), "B=1", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
store->SetLoadExpectation(true /* return_value */,
std::move(initial_cookies));
auto cm = std::make_unique<CookieMonster>(store.get(), &net_log_);
@@ -3009,9 +3033,10 @@ TEST_F(CookieMonsterTest, SecureCookieLocalhost) {
// Insecure localhost can set secure cookie, and warning is attached to
// status.
{
- auto cookie = CanonicalCookie::Create(insecure_localhost,
- "from_insecure_localhost=1; Secure",
- base::Time::Now(), absl::nullopt);
+ auto cookie = CanonicalCookie::Create(
+ insecure_localhost, "from_insecure_localhost=1; Secure",
+ base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie);
CookieInclusionStatus status =
SetCanonicalCookieReturnAccessResult(cm.get(), std::move(cookie),
@@ -3025,9 +3050,10 @@ TEST_F(CookieMonsterTest, SecureCookieLocalhost) {
// Secure localhost can set secure cookie, and warning is not attached to
// status.
{
- auto cookie = CanonicalCookie::Create(insecure_localhost,
- "from_secure_localhost=1; Secure",
- base::Time::Now(), absl::nullopt);
+ auto cookie = CanonicalCookie::Create(
+ insecure_localhost, "from_secure_localhost=1; Secure",
+ base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
ASSERT_TRUE(cookie);
CookieInclusionStatus status =
SetCanonicalCookieReturnAccessResult(cm.get(), std::move(cookie),
@@ -3078,7 +3104,8 @@ TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) {
// Set a secure, httponly cookie from a secure origin
auto preexisting_cookie = CanonicalCookie::Create(
https_www_foo_.url(), "A=B;Secure;HttpOnly", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
CookieAccessResult access_result = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(preexisting_cookie), https_www_foo_.url(),
true /* can_modify_httponly */);
@@ -3096,7 +3123,8 @@ TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) {
// equivalent to the pre-existing Secure cookie.
auto bad_cookie =
CanonicalCookie::Create(http_www_foo_.url(), "A=D", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
// Allow modifying HttpOnly, so that we don't skip preexisting cookies for
// being HttpOnly.
access_result = SetCanonicalCookieReturnAccessResult(
@@ -3127,7 +3155,8 @@ TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) {
// trying to shadow a secure cookie.
bad_cookie = CanonicalCookie::Create(
http_www_foo_.url(), "A=E; path=/some/path", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
// Allow modifying HttpOnly, so that we don't skip preexisting cookies for
// being HttpOnly.
access_result = SetCanonicalCookieReturnAccessResult(
@@ -3155,9 +3184,10 @@ TEST_F(CookieMonsterTest, MaybeDeleteEquivalentCookieAndUpdateStatus) {
net_log_.Clear();
// Test skipping equivalent cookie for HttpOnly only.
- bad_cookie = CanonicalCookie::Create(https_www_foo_.url(), "A=E; Secure",
- base::Time::Now(),
- absl::nullopt /* server_time */);
+ bad_cookie = CanonicalCookie::Create(
+ https_www_foo_.url(), "A=E; Secure", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
access_result = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(bad_cookie), https_www_foo_.url(),
false /* can_modify_httponly */);
@@ -3181,7 +3211,8 @@ TEST_F(CookieMonsterTest, SkipDontOverwriteForMultipleReasons) {
// Set a secure, httponly cookie from a secure origin
auto preexisting_cookie = CanonicalCookie::Create(
https_www_foo_.url(), "A=B;Secure;HttpOnly", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
CookieAccessResult access_result = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(preexisting_cookie), https_www_foo_.url(),
true /* can_modify_httponly */);
@@ -3191,7 +3222,8 @@ TEST_F(CookieMonsterTest, SkipDontOverwriteForMultipleReasons) {
// Httponly from an insecure scheme.
auto cookie =
CanonicalCookie::Create(http_www_foo_.url(), "A=B", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
access_result = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(cookie), http_www_foo_.url(),
false /* can_modify_httponly */);
@@ -3216,7 +3248,8 @@ TEST_F(CookieMonsterTest, DontDeleteEquivalentCookieIfSetIsRejected) {
auto preexisting_cookie = CanonicalCookie::Create(
http_www_foo_.url(), "cookie=foo", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
CookieAccessResult access_result = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(preexisting_cookie), http_www_foo_.url(),
false /* can_modify_httponly */);
@@ -3224,7 +3257,8 @@ TEST_F(CookieMonsterTest, DontDeleteEquivalentCookieIfSetIsRejected) {
auto bad_cookie = CanonicalCookie::Create(
http_www_foo_.url(), "cookie=bar;secure", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
CookieAccessResult access_result2 = SetCanonicalCookieReturnAccessResult(
cm.get(), std::move(bad_cookie), http_www_foo_.url(),
false /* can_modify_httponly */);
@@ -3891,7 +3925,8 @@ TEST_F(CookieMonsterTest, SetCanonicalCookieDoesNotBlockForLoadAll) {
GURL cookie_url("http://a.com/");
cm.SetCanonicalCookieAsync(
CanonicalCookie::Create(cookie_url, "A=B", base::Time::Now(),
- absl::nullopt /* server_time */),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */),
cookie_url, CookieOptions::MakeAllInclusive(),
callback_set.MakeCallback());
@@ -3969,17 +4004,20 @@ TEST_F(CookieMonsterTest, DeleteCookieWithInheritedTimestamps) {
std::string cookie_line = "foo=bar";
CookieOptions options = CookieOptions::MakeAllInclusive();
absl::optional<base::Time> server_time = absl::nullopt;
+ absl::optional<CookiePartitionKey> partition_key = absl::nullopt;
CookieMonster cm(nullptr, nullptr);
// Write a cookie created at |t1|.
- auto cookie = CanonicalCookie::Create(url, cookie_line, t1, server_time);
+ auto cookie =
+ CanonicalCookie::Create(url, cookie_line, t1, server_time, partition_key);
ResultSavingCookieCallback<CookieAccessResult> set_callback_1;
cm.SetCanonicalCookieAsync(std::move(cookie), url, options,
set_callback_1.MakeCallback());
set_callback_1.WaitUntilDone();
// Overwrite the cookie at |t2|.
- cookie = CanonicalCookie::Create(url, cookie_line, t2, server_time);
+ cookie =
+ CanonicalCookie::Create(url, cookie_line, t2, server_time, partition_key);
ResultSavingCookieCallback<CookieAccessResult> set_callback_2;
cm.SetCanonicalCookieAsync(std::move(cookie), url, options,
set_callback_2.MakeCallback());
@@ -3987,7 +4025,8 @@ TEST_F(CookieMonsterTest, DeleteCookieWithInheritedTimestamps) {
// The second cookie overwrites the first one but it will inherit the creation
// timestamp |t1|. Test that deleting the new cookie still works.
- cookie = CanonicalCookie::Create(url, cookie_line, t2, server_time);
+ cookie =
+ CanonicalCookie::Create(url, cookie_line, t2, server_time, partition_key);
ResultSavingCookieCallback<unsigned int> delete_callback;
cm.DeleteCanonicalCookieAsync(*cookie, delete_callback.MakeCallback());
delete_callback.WaitUntilDone();
@@ -4006,9 +4045,9 @@ TEST_F(CookieMonsterTest, RejectCreatedSameSiteCookieOnSet) {
CookieInclusionStatus status;
// Cookie can be created successfully; SameSite is not checked on Creation.
- auto cookie =
- CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */, &status);
+ auto cookie = CanonicalCookie::Create(
+ url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie != nullptr);
ASSERT_TRUE(status.IsInclude());
@@ -4029,9 +4068,9 @@ TEST_F(CookieMonsterTest, RejectCreatedSecureCookieOnSet) {
CookieInclusionStatus status;
// Cookie can be created successfully from an any url. Secure is not checked
// on Create.
- auto cookie =
- CanonicalCookie::Create(http_url, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */, &status);
+ auto cookie = CanonicalCookie::Create(
+ http_url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie != nullptr);
ASSERT_TRUE(status.IsInclude());
@@ -4053,9 +4092,9 @@ TEST_F(CookieMonsterTest, RejectCreatedHttpOnlyCookieOnSet) {
CookieMonster cm(nullptr, nullptr);
CookieInclusionStatus status;
// Cookie can be created successfully; HttpOnly is not checked on Create.
- auto cookie =
- CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */, &status);
+ auto cookie = CanonicalCookie::Create(
+ url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */, &status);
ASSERT_TRUE(cookie != nullptr);
ASSERT_TRUE(status.IsInclude());
@@ -4075,14 +4114,12 @@ TEST_F(CookieMonsterTest, RejectCreatedHttpOnlyCookieOnSet) {
{CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
}
-// Test the CookiesWithoutSameSiteMustBeSecure experimental option (in
-// conjunction with SameSiteByDefaultCookies, which it depends upon).
+// Test that SameSite=None requires Secure.
TEST_F(CookieMonsterTest, CookiesWithoutSameSiteMustBeSecure) {
const base::TimeDelta kLongAge = kLaxAllowUnsafeMaxAge * 4;
const base::TimeDelta kShortAge = kLaxAllowUnsafeMaxAge / 4;
struct TestCase {
- bool is_cookies_without_samesite_must_be_secure_enabled;
bool is_url_secure;
std::string cookie_line;
CookieInclusionStatus expected_set_cookie_result;
@@ -4093,67 +4130,39 @@ TEST_F(CookieMonsterTest, CookiesWithoutSameSiteMustBeSecure) {
} test_cases[] = {
// Feature enabled:
// Cookie set from a secure URL with SameSite enabled is not rejected.
- {true, true, "A=B; SameSite=Lax", CookieInclusionStatus(),
+ {true, "A=B; SameSite=Lax", CookieInclusionStatus(),
CookieEffectiveSameSite::LAX_MODE},
// Cookie set from a secure URL which is defaulted into Lax is not
// rejected.
- {true, true, "A=B", // recently-set session cookie.
+ {true, "A=B", // recently-set session cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
kShortAge},
- {true, true, "A=B", // not-recently-set session cookie.
+ {true, "A=B", // not-recently-set session cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge},
// Cookie set from a secure URL with SameSite=None and Secure is set.
- {true, true, "A=B; SameSite=None; Secure", CookieInclusionStatus(),
+ {true, "A=B; SameSite=None; Secure",
+ CookieInclusionStatus(
+ CookieInclusionStatus::WARN_SAMESITE_NONE_REQUIRED),
CookieEffectiveSameSite::NO_RESTRICTION},
// Cookie set from a secure URL with SameSite=None but not specifying
// Secure is rejected.
- {true, true, "A=B; SameSite=None",
+ {true, "A=B; SameSite=None",
CookieInclusionStatus(
CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE,
CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE)},
// Cookie set from an insecure URL which defaults into LAX_MODE is not
// rejected.
- {true, false, "A=B", // recently-set session cookie.
+ {false, "A=B", // recently-set session cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
kShortAge},
- {true, false, "A=B", // not-recently-set session cookie.
+ {false, "A=B", // not-recently-set session cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge},
- {true, false, "A=B; Max-Age=1000000", // recently-set persistent cookie.
+ {false, "A=B; Max-Age=1000000", // recently-set persistent cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
kShortAge},
- {true, false,
+ {false,
"A=B; Max-Age=1000000", // not-recently-set persistent cookie.
CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge},
-
- // Feature not enabled (but SameSiteByDefaultCookies is still enabled):
- // Cookie set from a secure URL with SameSite enabled is not rejected.
- {false, true, "A=B; SameSite=Lax", CookieInclusionStatus(),
- CookieEffectiveSameSite::LAX_MODE},
- // Cookie set from a secure URL which is defaulted into Lax is not
- // rejected.
- {false, true, "A=B", // recently-set session cookie.
- CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
- kShortAge},
- {false, true, "A=B", // not-recently-set session cookie.
- CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge},
- // Cookie set from a secure URL with SameSite=None and Secure is set.
- {false, true, "A=B; SameSite=None; Secure", CookieInclusionStatus(),
- CookieEffectiveSameSite::NO_RESTRICTION},
- // Cookie set from an insecure URL with SameSite=None (which can't ever be
- // secure because it's an insecure URL) is NOT rejected, because
- // CookiesWithoutSameSiteMustBeSecure is not enabled.
- {false, false, "A=B; SameSite=None",
- CookieInclusionStatus::MakeFromReasonsForTesting(
- std::vector<CookieInclusionStatus::ExclusionReason>(),
- {CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE}),
- CookieEffectiveSameSite::NO_RESTRICTION},
- // Cookie set from an insecure URL which is defaulted into Lax is not
- // rejected.
- {false, false, "A=B", // recently-set session cookie.
- CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
- kShortAge},
- {false, false, "A=B", // not-recently-set session cookie.
- CookieInclusionStatus(), CookieEffectiveSameSite::LAX_MODE, kLongAge},
};
auto cm = std::make_unique<CookieMonster>(nullptr, nullptr);
@@ -4164,24 +4173,12 @@ TEST_F(CookieMonsterTest, CookiesWithoutSameSiteMustBeSecure) {
for (int i = 0; i < length; ++i) {
TestCase test = test_cases[i];
base::test::ScopedFeatureList feature_list;
- if (test.is_cookies_without_samesite_must_be_secure_enabled) {
- feature_list.InitWithFeatures(
- {kSameSiteByDefaultCookies,
- kCookiesWithoutSameSiteMustBeSecure} /* enabled_features */,
- {} /* disabled_features */);
- } else {
- feature_list.InitWithFeatures(
- {kSameSiteByDefaultCookies} /* enabled_features */,
- {kCookiesWithoutSameSiteMustBeSecure} /* disabled_features */);
- }
- ASSERT_TRUE(cookie_util::IsSameSiteByDefaultCookiesEnabled());
- ASSERT_EQ(test.is_cookies_without_samesite_must_be_secure_enabled,
- cookie_util::IsCookiesWithoutSameSiteMustBeSecureEnabled());
GURL url = test.is_url_secure ? secure_url : insecure_url;
base::Time creation_time = base::Time::Now() - test.creation_time_delta;
- auto cookie = CanonicalCookie::Create(url, test.cookie_line, creation_time,
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ url, test.cookie_line, creation_time, absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
// Make a copy so we can delete it after the test.
CanonicalCookie cookie_copy = *cookie;
CookieAccessResult result = SetCanonicalCookieReturnAccessResult(
@@ -4227,58 +4224,8 @@ void RecordCookieChanges(std::vector<CanonicalCookie>* out_cookies,
out_causes->push_back(change.cause);
}
-TEST_F(CookieMonsterNotificationTest, GlobalNotBroadcast) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndDisableFeature(
- features::kNoCookieChangeNotificationOnLoad);
-
- // Create a persistent store that will not synchronously satisfy the
- // loading requirement.
- scoped_refptr<MockPersistentCookieStore> store(new MockPersistentCookieStore);
- store->set_store_load_commands(true);
-
- // Bind it to a CookieMonster
- auto monster = std::make_unique<CookieMonster>(store.get(), nullptr);
-
- // Trigger load dispatch and confirm it.
- monster->GetAllCookiesAsync(CookieStore::GetAllCookiesCallback());
- ASSERT_EQ(1u, store->commands().size());
- EXPECT_EQ(CookieStoreCommand::LOAD, store->commands()[0].type);
-
- // Attach a change subscription.
- std::vector<CanonicalCookie> cookies;
- std::vector<CookieChangeCause> causes;
- std::unique_ptr<CookieChangeSubscription> subscription =
- monster->GetChangeDispatcher().AddCallbackForAllChanges(
- base::BindRepeating(&RecordCookieChanges, &cookies, &causes));
-
- // Set up a set of cookies with a duplicate.
- std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies;
- AddCookieToList(GURL("http://www.foo.com"), "X=1; path=/",
- base::Time::Now() + base::TimeDelta::FromDays(3),
- &initial_cookies);
-
- AddCookieToList(GURL("http://www.foo.com"), "X=2; path=/",
- base::Time::Now() + base::TimeDelta::FromDays(1),
- &initial_cookies);
-
- // Execute the load
- store->TakeCallbackAt(0).Run(std::move(initial_cookies));
- base::RunLoop().RunUntilIdle();
-
- // We should see two insertions, no deletions, and only one cookie in the
- // monster.
- // TODO(rdsmith): Why yes, this is an internally inconsistent interface.
- ASSERT_EQ(2U, cookies.size());
- EXPECT_EQ("X", cookies[0].Name());
- EXPECT_EQ(CookieChangeCause::INSERTED, causes[0]);
- EXPECT_EQ("X", cookies[1].Name());
- EXPECT_EQ(CookieChangeCause::INSERTED, causes[1]);
- EXPECT_EQ(1u, this->GetAllCookies(monster.get()).size());
-}
-
-// Tests that there are no changes emitted for cookie loading when the feature
-// kNoCookieChangeNotificationOnLoad is enabled.
+// Tests that there are no changes emitted for cookie loading, but there are
+// changes emitted for other operations.
TEST_F(CookieMonsterNotificationTest, NoNotificationOnLoad) {
// Create a persistent store that will not synchronously satisfy the
// loading requirement.
@@ -4300,38 +4247,50 @@ TEST_F(CookieMonsterNotificationTest, NoNotificationOnLoad) {
monster->GetChangeDispatcher().AddCallbackForAllChanges(
base::BindRepeating(&RecordCookieChanges, &cookies, &causes));
- // Set up initial cookie.
+ // Set up some initial cookies, including duplicates.
std::vector<std::unique_ptr<CanonicalCookie>> initial_cookies;
GURL url("http://www.foo.com");
initial_cookies.push_back(CanonicalCookie::Create(
- url, "X=1; path=/", base::Time::Now(), absl::nullopt));
+ url, "X=1; path=/", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
+ initial_cookies.push_back(CanonicalCookie::Create(
+ url, "Y=1; path=/", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
+ initial_cookies.push_back(CanonicalCookie::Create(
+ url, "Y=2; path=/", base::Time::Now() + base::TimeDelta::FromDays(1),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
// Execute the load
store->TakeCallbackAt(0).Run(std::move(initial_cookies));
base::RunLoop().RunUntilIdle();
- // There should be no notifications because kNoCookieChangeNotificationOnLoad
- // is enabled. (The above GlobalNotBroadcast test shows that there would be
- // notifications without the feature enabled.)
+ // We should see no insertions (because loads do not cause notifications to be
+ // dispatched), no deletions (because overwriting a duplicate cookie on load
+ // does not trigger a notification), and two cookies in the monster.
EXPECT_EQ(0u, cookies.size());
EXPECT_EQ(0u, causes.size());
- // But there should still be a cookie in the CookieMonster.
- EXPECT_EQ(1u, this->GetAllCookies(monster.get()).size());
+ EXPECT_EQ(2u, this->GetAllCookies(monster.get()).size());
- // Change the cookie again to make sure that other changes do emit
+ // Change the cookies again to make sure that other changes do emit
// notifications.
this->CreateAndSetCookie(monster.get(), url, "X=2; path=/",
CookieOptions::MakeAllInclusive());
+ this->CreateAndSetCookie(monster.get(), url, "Y=3; path=/; max-age=0",
+ CookieOptions::MakeAllInclusive());
base::RunLoop().RunUntilIdle();
- ASSERT_EQ(2u, cookies.size());
- ASSERT_EQ(2u, causes.size());
+ ASSERT_EQ(3u, cookies.size());
+ ASSERT_EQ(3u, causes.size());
EXPECT_EQ("X", cookies[0].Name());
EXPECT_EQ("1", cookies[0].Value());
EXPECT_EQ(CookieChangeCause::OVERWRITE, causes[0]);
EXPECT_EQ("X", cookies[1].Name());
EXPECT_EQ("2", cookies[1].Value());
EXPECT_EQ(CookieChangeCause::INSERTED, causes[1]);
+ EXPECT_EQ("Y", cookies[2].Name());
+ EXPECT_EQ("2", cookies[2].Value());
+ EXPECT_EQ(CookieChangeCause::EXPIRED_OVERWRITE, causes[2]);
}
class CookieMonsterLegacyCookieAccessTest : public CookieMonsterTest {
@@ -4350,48 +4309,19 @@ class CookieMonsterLegacyCookieAccessTest : public CookieMonsterTest {
std::make_unique<TestCookieAccessDelegate>();
access_delegate_ = access_delegate.get();
cm_->SetCookieAccessDelegate(std::move(access_delegate));
-
- feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
}
- ~CookieMonsterLegacyCookieAccessTest() override {}
-
- void SetFeatures(bool is_same_site_by_default_cookies_enabled,
- bool is_cookies_without_samesite_must_be_secure_enabled) {
- feature_list_ = std::make_unique<base::test::ScopedFeatureList>();
-
- std::vector<base::Feature> enabled;
- std::vector<base::Feature> disabled;
-
- if (is_same_site_by_default_cookies_enabled) {
- enabled.push_back(kSameSiteByDefaultCookies);
- } else {
- disabled.push_back(kSameSiteByDefaultCookies);
- }
-
- if (is_cookies_without_samesite_must_be_secure_enabled) {
- enabled.push_back(kCookiesWithoutSameSiteMustBeSecure);
- } else {
- disabled.push_back(kCookiesWithoutSameSiteMustBeSecure);
- }
-
- feature_list_->InitWithFeatures(enabled, disabled);
- }
+ ~CookieMonsterLegacyCookieAccessTest() override = default;
protected:
const std::string kDomain = "example.test";
const GURL kHttpsUrl = GURL("https://example.test");
const GURL kHttpUrl = GURL("http://example.test");
- // The FeatureList must be before the CookieMonster because the CookieMonster
- // destructor expects the state of the features to be the same as when it's in
- // use.
- std::unique_ptr<base::test::ScopedFeatureList> feature_list_;
std::unique_ptr<CookieMonster> cm_;
TestCookieAccessDelegate* access_delegate_;
};
TEST_F(CookieMonsterLegacyCookieAccessTest, SetLegacyNoSameSiteCookie) {
- SetFeatures(true, true);
// Check that setting unspecified-SameSite cookie from cross-site context
// fails if not set to Legacy semantics, but succeeds if set to legacy.
EXPECT_FALSE(CreateAndSetCookie(cm_.get(), kHttpUrl, "cookie=chocolate_chip",
@@ -4411,22 +4341,17 @@ TEST_F(CookieMonsterLegacyCookieAccessTest, SetLegacyNoSameSiteCookie) {
}
TEST_F(CookieMonsterLegacyCookieAccessTest, GetLegacyNoSameSiteCookie) {
- // Set an unspecified-SameSite cookie with SameSite features turned off.
- // Getting the cookie will succeed.
- SetFeatures(false, false);
+ // Set a cookie with no SameSite attribute.
ASSERT_TRUE(CreateAndSetCookie(cm_.get(), kHttpUrl, "cookie=chocolate_chip",
- CookieOptions()));
- EXPECT_EQ("cookie=chocolate_chip",
- GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
- // Turn on the features. Now getting the cookie fails.
- SetFeatures(true, true);
+ CookieOptions::MakeAllInclusive()));
+
+ // Getting the cookie fails unless semantics is legacy.
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::UNKNOWN);
EXPECT_EQ("", GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::NONLEGACY);
EXPECT_EQ("", GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
- // Set the access semantics to legacy, to be able to get the cookie.
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::LEGACY);
EXPECT_EQ("cookie=chocolate_chip",
@@ -4435,7 +4360,6 @@ TEST_F(CookieMonsterLegacyCookieAccessTest, GetLegacyNoSameSiteCookie) {
TEST_F(CookieMonsterLegacyCookieAccessTest,
SetLegacySameSiteNoneInsecureCookie) {
- SetFeatures(true, true);
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::UNKNOWN);
EXPECT_FALSE(CreateAndSetCookie(cm_.get(), kHttpsUrl,
@@ -4458,46 +4382,26 @@ TEST_F(CookieMonsterLegacyCookieAccessTest,
TEST_F(CookieMonsterLegacyCookieAccessTest,
GetLegacySameSiteNoneInsecureCookie) {
- // Set an SameSite=None insecure cookie with SameSite features turned off.
- // Getting the cookie will succeed.
- SetFeatures(false, false);
+ // Need to inject such a cookie under legacy semantics.
+ access_delegate_->SetExpectationForCookieDomain(
+ kDomain, CookieAccessSemantics::LEGACY);
ASSERT_TRUE(CreateAndSetCookie(cm_.get(), kHttpUrl,
"cookie=oatmeal_raisin; SameSite=None",
- CookieOptions()));
- EXPECT_EQ("cookie=oatmeal_raisin",
- GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
- // Turn on the features. Now getting the cookie fails.
- SetFeatures(true, true);
+ CookieOptions::MakeAllInclusive()));
+ // Getting a SameSite=None but non-Secure cookie fails unless semantics is
+ // legacy.
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::UNKNOWN);
EXPECT_EQ("", GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::NONLEGACY);
EXPECT_EQ("", GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
- // Set the access semantics to legacy, to be able to get the cookie.
access_delegate_->SetExpectationForCookieDomain(
kDomain, CookieAccessSemantics::LEGACY);
EXPECT_EQ("cookie=oatmeal_raisin",
GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
}
-TEST_F(CookieMonsterLegacyCookieAccessTest, NonlegacyCookie) {
- // Nonlegacy cookie will have default as Lax.
- SetFeatures(false, false);
- access_delegate_->SetExpectationForCookieDomain(
- kDomain, CookieAccessSemantics::NONLEGACY);
- EXPECT_FALSE(CreateAndSetCookie(cm_.get(), kHttpUrl, "cookie=chocolate_chip",
- CookieOptions()));
-
- // The SameSite=None-must-be-Secure rule will only only activate if the
- // feature is on, even if access semantics is Nonlegacy.
- EXPECT_TRUE(CreateAndSetCookie(cm_.get(), kHttpUrl,
- "cookie=oatmeal_raisin; SameSite=None",
- CookieOptions()));
- EXPECT_EQ("cookie=oatmeal_raisin",
- GetCookiesWithOptions(cm_.get(), kHttpUrl, CookieOptions()));
-}
-
TEST_F(CookieMonsterTest, IsCookieSentToSamePortThatSetIt) {
// Note: `IsCookieSentToSamePortThatSetIt()` only uses the source_scheme if
// the port is valid, specified, and doesn't match the url's port. So for test
@@ -4724,7 +4628,8 @@ TEST_F(CookieMonsterTest, CookiePortReadDiffersFromSetHistogram) {
auto unspecified_cookie = CanonicalCookie::Create(
GURL("https://www.foo.com/withoutport"), "C=D; Path=/withoutport",
- base::Time::Now(), absl::nullopt);
+ base::Time::Now(), /* server_time */ absl::nullopt,
+ /* cookie_partition_key */ absl::nullopt);
// Force to be unspecified.
unspecified_cookie->SetSourcePort(url::PORT_UNSPECIFIED);
EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
@@ -4735,7 +4640,8 @@ TEST_F(CookieMonsterTest, CookiePortReadDiffersFromSetHistogram) {
auto invalid_cookie = CanonicalCookie::Create(
GURL("https://www.foo.com/invalidport"), "E=F; Path=/invalidport",
- base::Time::Now(), absl::nullopt);
+ base::Time::Now(), /* server_time */ absl::nullopt,
+ /* cookie_partition_key */ absl::nullopt);
// Force to be invalid.
invalid_cookie->SetSourcePort(99999);
EXPECT_TRUE(SetCanonicalCookieReturnAccessResult(
diff --git a/chromium/net/cookies/cookie_options.cc b/chromium/net/cookies/cookie_options.cc
index aa708aa771b..685647c8ff9 100644
--- a/chromium/net/cookies/cookie_options.cc
+++ b/chromium/net/cookies/cookie_options.cc
@@ -8,6 +8,7 @@
#include "base/metrics/histogram_functions.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/same_party_context.h"
namespace net {
@@ -33,29 +34,24 @@ CookieOptions::SameSiteCookieContext::GetContextForCookieInclusion() const {
return context_;
}
-bool CookieOptions::SameSiteCookieContext::AffectedByBugfix1166211() const {
- return cookie_util::IsSchemefulSameSiteEnabled()
- ? schemeful_affected_by_bugfix_1166211_
- : affected_by_bugfix_1166211_;
+const CookieOptions::SameSiteCookieContext::ContextMetadata&
+CookieOptions::SameSiteCookieContext::GetMetadataForCurrentSchemefulMode()
+ const {
+ return cookie_util::IsSchemefulSameSiteEnabled() ? schemeful_metadata()
+ : metadata();
}
-void CookieOptions::SameSiteCookieContext::
- MaybeApplyBugfix1166211WarningToStatusAndLogHistogram(
- CookieInclusionStatus& status) const {
- DCHECK(AffectedByBugfix1166211());
- bool changed =
- status.HasOnlyExclusionReason(
- CookieInclusionStatus::ExclusionReason::EXCLUDE_SAMESITE_LAX) ||
- status.HasOnlyExclusionReason(
- CookieInclusionStatus::ExclusionReason::
- EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX);
- if (changed) {
- status.AddWarningReason(
- CookieInclusionStatus::WarningReason::
- WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211);
- }
- base::UmaHistogramBoolean(
- "Cookie.SameSiteCookieInclusionChangedByBugfix1166211", changed);
+void CookieOptions::SameSiteCookieContext::SetContextTypesForTesting(
+ ContextType context_type,
+ ContextType schemeful_context_type) {
+ context_ = context_type;
+ schemeful_context_ = schemeful_context_type;
+}
+
+bool CookieOptions::SameSiteCookieContext::CompleteEquivalenceForTesting(
+ const SameSiteCookieContext& other) const {
+ return (*this == other) && (metadata() == other.metadata()) &&
+ (schemeful_metadata() == other.schemeful_metadata());
}
bool operator==(const CookieOptions::SameSiteCookieContext& lhs,
@@ -69,13 +65,23 @@ bool operator!=(const CookieOptions::SameSiteCookieContext& lhs,
return !(lhs == rhs);
}
-// Keep default values in sync with content/public/common/cookie_manager.mojom.
+bool operator==(
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& lhs,
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& rhs) {
+ return lhs.cross_site_redirect_downgrade == rhs.cross_site_redirect_downgrade;
+}
+
+bool operator!=(
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& lhs,
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& rhs) {
+ return !(lhs == rhs);
+}
+
+// Keep default values in sync with
+// services/network/public/mojom/cookie_manager.mojom.
CookieOptions::CookieOptions()
- : exclude_httponly_(true),
- same_site_cookie_context_(SameSiteCookieContext(
- SameSiteCookieContext::ContextType::CROSS_SITE)),
- update_access_time_(true),
- return_excluded_cookies_(false) {}
+ : same_site_cookie_context_(SameSiteCookieContext(
+ SameSiteCookieContext::ContextType::CROSS_SITE)) {}
CookieOptions::CookieOptions(const CookieOptions& other) = default;
CookieOptions::CookieOptions(CookieOptions&& other) = default;
@@ -90,8 +96,7 @@ CookieOptions CookieOptions::MakeAllInclusive() {
options.set_include_httponly();
options.set_same_site_cookie_context(SameSiteCookieContext::MakeInclusive());
options.set_do_not_update_access_time();
- options.set_same_party_cookie_context_type(
- SamePartyCookieContextType::kSameParty);
+ options.set_same_party_context(SamePartyContext::MakeInclusive());
options.set_is_in_nontrivial_first_party_set(true);
return options;
}
diff --git a/chromium/net/cookies/cookie_options.h b/chromium/net/cookies/cookie_options.h
index e0783435edc..76d3b23dde4 100644
--- a/chromium/net/cookies/cookie_options.h
+++ b/chromium/net/cookies/cookie_options.h
@@ -13,7 +13,7 @@
#include "net/base/net_export.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "net/cookies/same_party_context.h"
#include "url/gurl.h"
namespace net {
@@ -37,16 +37,71 @@ class NET_EXPORT CookieOptions {
COUNT
};
+ // Holds metadata about the factors that went into deciding the ContextType.
+ //
+ // These values may be used for recording histograms or
+ // CookieInclusionStatus warnings, but SHOULD NOT be relied
+ // upon for cookie inclusion decisions. Use only the ContextTypes for that.
+ //
+ // When adding a field, also update CompleteEquivalenceForTesting.
+ struct NET_EXPORT ContextMetadata {
+ // Possible "downgrades" for the SameSite context type, e.g. from a more
+ // trusted context to a less trusted context, as a result of some behavior
+ // change affecting the same-site calculation.
+ enum class ContextDowngradeType {
+ // Context not downgraded.
+ kNoDowngrade,
+ // Context was originally strictly same-site, was downgraded to laxly
+ // same-site.
+ kStrictToLax,
+ // Context was originally strictly same-site, was downgraded to
+ // cross-site.
+ kStrictToCross,
+ // Context was originally laxly same-site, was downgraded to cross-site.
+ kLaxToCross,
+ };
+
+ // Records the type of any context downgrade due to a cross-site redirect,
+ // i.e. whether the spec change in
+ // https://github.com/httpwg/http-extensions/pull/1348 changed the result
+ // of the context calculation. Note that a lax-to-cross downgrade can only
+ // happen for response cookies, because a laxly same-site context only
+ // happens for a top-level cross-site request, which cannot be downgraded
+ // due to a cross-site redirect to a non-top-level cross-site request.
+ // This only records whether the context was downgraded, not whether the
+ // cookie's inclusion result was changed.
+ ContextDowngradeType cross_site_redirect_downgrade =
+ ContextDowngradeType::kNoDowngrade;
+ };
+
+ // The following three constructors apply default values for the metadata
+ // members.
SameSiteCookieContext()
: SameSiteCookieContext(ContextType::CROSS_SITE,
ContextType::CROSS_SITE) {}
+
explicit SameSiteCookieContext(ContextType same_site_context)
: SameSiteCookieContext(same_site_context, same_site_context) {}
SameSiteCookieContext(ContextType same_site_context,
ContextType schemeful_same_site_context)
+ : SameSiteCookieContext(same_site_context,
+ schemeful_same_site_context,
+ ContextMetadata(),
+ ContextMetadata()) {}
+
+ // Schemeful and schemeless context types are consistency-checked against
+ // each other, but the metadata is stored as-is (i.e. the values in
+ // `metadata` and `schemeful_metadata` may be logically inconsistent), as
+ // the metadata is not relied upon for correctness.
+ SameSiteCookieContext(ContextType same_site_context,
+ ContextType schemeful_same_site_context,
+ ContextMetadata metadata,
+ ContextMetadata schemeful_metadata)
: context_(same_site_context),
- schemeful_context_(schemeful_same_site_context) {
+ schemeful_context_(schemeful_same_site_context),
+ metadata_(metadata),
+ schemeful_metadata_(schemeful_metadata) {
DCHECK_LE(schemeful_context_, context_);
}
@@ -61,37 +116,38 @@ class NET_EXPORT CookieOptions {
// Returns the context for determining SameSite cookie inclusion.
ContextType GetContextForCookieInclusion() const;
+ // Returns the metadata describing how this context was calculated, under
+ // the currently applicable schemeful/schemeless mode.
+ // TODO(chlily): Should take the CookieAccessSemantics as well, to
+ // accurately account for the context actually used for a given cookie.
+ const ContextMetadata& GetMetadataForCurrentSchemefulMode() const;
+
// If you're just trying to determine if a cookie is accessible you likely
// want to use GetContextForCookieInclusion() which will return the correct
// context regardless the status of same-site features.
ContextType context() const { return context_; }
- void set_context(ContextType context) { context_ = context; }
- void set_context(std::pair<ContextType, bool> context) {
- context_ = context.first;
- affected_by_bugfix_1166211_ = context.second;
- }
-
ContextType schemeful_context() const { return schemeful_context_; }
- void set_schemeful_context(ContextType schemeful_context) {
- schemeful_context_ = schemeful_context;
- }
- void set_schemeful_context(std::pair<ContextType, bool> schemeful_context) {
- schemeful_context_ = schemeful_context.first;
- schemeful_affected_by_bugfix_1166211_ = schemeful_context.second;
+
+ // You probably want to use GetMetadataForCurrentSchemefulMode() instead of
+ // these getters, since that takes into account the applicable schemeful
+ // mode.
+ const ContextMetadata& metadata() const { return metadata_; }
+ const ContextMetadata& schemeful_metadata() const {
+ return schemeful_metadata_;
}
- // Whether the request was affected by the bugfix, either schemefully or
- // schemelessly.
- // TODO(crbug.com/1166211): Remove once no longer needed.
- bool AffectedByBugfix1166211() const;
+ // Sets context types. Does not check for consistency between context and
+ // schemeful context. Does not touch the metadata.
+ void SetContextTypesForTesting(ContextType context_type,
+ ContextType schemeful_context_type);
- // If the cookie was excluded solely due to the bugfix, this applies a
- // warning to the status that will show up in the netlog. Also logs a
- // histogram showing whether the warning was applied.
- // TODO(crbug.com/1166211): Remove once no longer needed.
- void MaybeApplyBugfix1166211WarningToStatusAndLogHistogram(
- CookieInclusionStatus& status) const;
+ // Returns whether the context types and all fields of the metadata structs
+ // are the same.
+ bool CompleteEquivalenceForTesting(
+ const SameSiteCookieContext& other) const;
+ // Equality operators disregard any metadata! (Only the context types are
+ // compared, not how they were computed.)
NET_EXPORT friend bool operator==(
const CookieOptions::SameSiteCookieContext& lhs,
const CookieOptions::SameSiteCookieContext& rhs);
@@ -103,25 +159,8 @@ class NET_EXPORT CookieOptions {
ContextType context_;
ContextType schemeful_context_;
- // Record whether the ContextType calculation was affected by the bugfix for
- // crbug.com/1166211. These are for the purpose of recording histograms and
- // adding warnings to CookieInclusionStatus.
- // Note: These are not preserved when serializing/deserializing for mojo, as
- // these are only used in URLRequestHttpJob, which does not make mojo calls
- // with this struct (it is only relevant for HTTP requests).
- // TODO(crbug.com/1166211): Remove once no longer needed.
- bool affected_by_bugfix_1166211_ = false;
- bool schemeful_affected_by_bugfix_1166211_ = false;
- };
-
- // Computed in URLRequestHttpJob for every cookie access attempt but is only
- // relevant for SameParty cookies.
- enum class SamePartyCookieContextType {
- // The opposite to kSameParty. Should be the default value.
- kCrossParty = 0,
- // If the request URL is in the same First-Party Sets as the top-frame site
- // and each member of the isolation_info.party_context.
- kSameParty = 1,
+ ContextMetadata metadata_;
+ ContextMetadata schemeful_metadata_;
};
// Creates a CookieOptions object which:
@@ -152,11 +191,11 @@ class NET_EXPORT CookieOptions {
// How trusted is the current browser environment when it comes to accessing
// SameSite cookies. Default is not trusted, e.g. CROSS_SITE.
- void set_same_site_cookie_context(SameSiteCookieContext context) {
+ void set_same_site_cookie_context(const SameSiteCookieContext& context) {
same_site_cookie_context_ = context;
}
- SameSiteCookieContext same_site_cookie_context() const {
+ const SameSiteCookieContext& same_site_cookie_context() const {
return same_site_cookie_context_;
}
@@ -168,14 +207,11 @@ class NET_EXPORT CookieOptions {
void unset_return_excluded_cookies() { return_excluded_cookies_ = false; }
bool return_excluded_cookies() const { return return_excluded_cookies_; }
- // How trusted is the current browser environment when it comes to accessing
- // SameParty cookies. Default is not trusted, e.g. kCrossParty.
- void set_same_party_cookie_context_type(
- SamePartyCookieContextType context_type) {
- same_party_cookie_context_type_ = context_type;
+ void set_same_party_context(const SamePartyContext& context) {
+ same_party_context_ = context;
}
- SamePartyCookieContextType same_party_cookie_context_type() const {
- return same_party_cookie_context_type_;
+ const SamePartyContext& same_party_context() const {
+ return same_party_context_;
}
// Getter/setter of |full_party_context_size_| for logging purposes.
@@ -200,13 +236,15 @@ class NET_EXPORT CookieOptions {
static CookieOptions MakeAllInclusive();
private:
- bool exclude_httponly_;
+ // Keep default values in sync with
+ // content/public/common/cookie_manager.mojom.
+ bool exclude_httponly_ = true;
SameSiteCookieContext same_site_cookie_context_;
- bool update_access_time_;
+ bool update_access_time_ = true;
bool return_excluded_cookies_ = false;
- SamePartyCookieContextType same_party_cookie_context_type_ =
- SamePartyCookieContextType::kCrossParty;
+ SamePartyContext same_party_context_;
+
// The size of the isolation_info.party_context plus the top-frame site.
// Stored for logging purposes.
uint32_t full_party_context_size_ = 0;
@@ -219,6 +257,13 @@ class NET_EXPORT CookieOptions {
bool is_in_nontrivial_first_party_set_ = false;
};
+NET_EXPORT bool operator==(
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& lhs,
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& rhs);
+NET_EXPORT bool operator!=(
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& lhs,
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& rhs);
+
// Allows gtest to print more helpful error messages instead of printing hex.
// (No need to null-check `os` because we can assume gtest will properly pass a
// non-null pointer, and it is dereferenced immediately anyway.)
@@ -227,12 +272,25 @@ inline void PrintTo(CookieOptions::SameSiteCookieContext::ContextType ct,
*os << static_cast<int>(ct);
}
+inline void PrintTo(
+ const CookieOptions::SameSiteCookieContext::ContextMetadata& m,
+ std::ostream* os) {
+ *os << "{";
+ *os << " cross_site_redirect_downgrade: "
+ << static_cast<int>(m.cross_site_redirect_downgrade);
+ *os << " }";
+}
+
inline void PrintTo(const CookieOptions::SameSiteCookieContext& sscc,
std::ostream* os) {
*os << "{ context: ";
PrintTo(sscc.context(), os);
*os << ", schemeful_context: ";
PrintTo(sscc.schemeful_context(), os);
+ *os << ", metadata: ";
+ PrintTo(sscc.metadata(), os);
+ *os << ", schemeful_metadata: ";
+ PrintTo(sscc.schemeful_metadata(), os);
*os << " }";
}
diff --git a/chromium/net/cookies/cookie_options_unittest.cc b/chromium/net/cookies/cookie_options_unittest.cc
index 22a1720de88..eedd89ed740 100644
--- a/chromium/net/cookies/cookie_options_unittest.cc
+++ b/chromium/net/cookies/cookie_options_unittest.cc
@@ -35,18 +35,52 @@ TEST(CookieOptionsTest, SameSiteCookieContext) {
SameSiteCookieContext::ContextType::SAME_SITE_LAX,
SameSiteCookieContext::ContextType::CROSS_SITE);
- EXPECT_EQ("{ context: 0, schemeful_context: 0 }",
- ::testing::PrintToString(cross_cross));
- EXPECT_EQ("{ context: 2, schemeful_context: 2 }",
- ::testing::PrintToString(lax_lax));
- EXPECT_EQ("{ context: 3, schemeful_context: 3 }",
- ::testing::PrintToString(strict_strict));
- EXPECT_EQ("{ context: 3, schemeful_context: 0 }",
- ::testing::PrintToString(strict_cross));
- EXPECT_EQ("{ context: 3, schemeful_context: 2 }",
- ::testing::PrintToString(strict_lax));
- EXPECT_EQ("{ context: 2, schemeful_context: 0 }",
- ::testing::PrintToString(lax_cross));
+ SameSiteCookieContext::ContextMetadata metadata1;
+ metadata1.cross_site_redirect_downgrade = SameSiteCookieContext::
+ ContextMetadata::ContextDowngradeType::kStrictToLax;
+ SameSiteCookieContext::ContextMetadata metadata2;
+ metadata2.cross_site_redirect_downgrade = SameSiteCookieContext::
+ ContextMetadata::ContextDowngradeType::kStrictToLax;
+ SameSiteCookieContext context_with_metadata(
+ SameSiteCookieContext::ContextType::SAME_SITE_STRICT,
+ SameSiteCookieContext::ContextType::SAME_SITE_STRICT, metadata1,
+ metadata2);
+
+ EXPECT_EQ(
+ "{ context: 0, schemeful_context: 0, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(cross_cross));
+ EXPECT_EQ(
+ "{ context: 2, schemeful_context: 2, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(lax_lax));
+ EXPECT_EQ(
+ "{ context: 3, schemeful_context: 3, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(strict_strict));
+ EXPECT_EQ(
+ "{ context: 3, schemeful_context: 0, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(strict_cross));
+ EXPECT_EQ(
+ "{ context: 3, schemeful_context: 2, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(strict_lax));
+ EXPECT_EQ(
+ "{ context: 2, schemeful_context: 0, "
+ "metadata: { cross_site_redirect_downgrade: 0 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 0 } }",
+ ::testing::PrintToString(lax_cross));
+ EXPECT_EQ(
+ "{ context: 3, schemeful_context: 3, "
+ "metadata: { cross_site_redirect_downgrade: 1 }, "
+ "schemeful_metadata: { cross_site_redirect_downgrade: 1 } }",
+ ::testing::PrintToString(context_with_metadata));
}
} // namespace
diff --git a/chromium/net/cookies/cookie_partition_key.cc b/chromium/net/cookies/cookie_partition_key.cc
new file mode 100644
index 00000000000..055866802c3
--- /dev/null
+++ b/chromium/net/cookies/cookie_partition_key.cc
@@ -0,0 +1,87 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cookies/cookie_partition_key.h"
+
+#include "base/feature_list.h"
+#include "net/base/features.h"
+#include "net/cookies/cookie_constants.h"
+
+namespace net {
+
+CookiePartitionKey::CookiePartitionKey() = default;
+
+CookiePartitionKey::CookiePartitionKey(const SchemefulSite& site)
+ : site_(site) {}
+
+CookiePartitionKey::CookiePartitionKey(const GURL& url)
+ : site_(SchemefulSite(url)) {}
+
+CookiePartitionKey::CookiePartitionKey(const CookiePartitionKey& other) =
+ default;
+
+CookiePartitionKey::CookiePartitionKey(CookiePartitionKey&& other) = default;
+
+CookiePartitionKey& CookiePartitionKey::operator=(
+ const CookiePartitionKey& other) = default;
+
+CookiePartitionKey& CookiePartitionKey::operator=(CookiePartitionKey&& other) =
+ default;
+
+CookiePartitionKey::~CookiePartitionKey() = default;
+
+bool CookiePartitionKey::operator==(const CookiePartitionKey& other) const {
+ return site_ == other.site_;
+}
+
+bool CookiePartitionKey::operator<(const CookiePartitionKey& other) const {
+ return site_ < other.site_;
+}
+
+// static
+bool CookiePartitionKey::Serialize(const absl::optional<CookiePartitionKey>& in,
+ std::string& out) {
+ if (!in) {
+ out = kEmptyCookiePartitionKey;
+ return true;
+ }
+ if (in->site_.GetURL().SchemeIsFile()) {
+ out = in->site_.SerializeFileSiteWithHost();
+ return true;
+ }
+ if (in->site_.opaque())
+ return false;
+ out = in->site_.Serialize();
+ return true;
+}
+
+// static
+bool CookiePartitionKey::Deserialize(const std::string& in,
+ absl::optional<CookiePartitionKey>& out) {
+ if (in == kEmptyCookiePartitionKey) {
+ out = absl::nullopt;
+ return true;
+ }
+ auto schemeful_site = SchemefulSite::Deserialize(in);
+ // SchemfulSite is opaque if the input is invalid.
+ if (schemeful_site.opaque())
+ return false;
+ out = absl::make_optional(CookiePartitionKey(schemeful_site));
+ return true;
+}
+
+absl::optional<CookiePartitionKey> CookiePartitionKey::FromNetworkIsolationKey(
+ const NetworkIsolationKey& network_isolation_key) {
+ if (!base::FeatureList::IsEnabled(features::kPartitionedCookies))
+ return absl::nullopt;
+ // TODO(crbug.com/1225444): Check if the top frame site is in a First-Party
+ // Set or if it is an extension URL.
+ absl::optional<net::SchemefulSite> top_frame_site =
+ network_isolation_key.GetTopFrameSite();
+ if (!top_frame_site)
+ return absl::nullopt;
+ return absl::make_optional(net::CookiePartitionKey(top_frame_site.value()));
+}
+
+} // namespace net
diff --git a/chromium/net/cookies/cookie_partition_key.h b/chromium/net/cookies/cookie_partition_key.h
new file mode 100644
index 00000000000..5f8207f727e
--- /dev/null
+++ b/chromium/net/cookies/cookie_partition_key.h
@@ -0,0 +1,89 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_COOKIES_COOKIE_PARTITION_KEY_H_
+#define NET_COOKIES_COOKIE_PARTITION_KEY_H_
+
+#include <string>
+
+#include "net/base/net_export.h"
+#include "net/base/network_isolation_key.h"
+#include "net/base/schemeful_site.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+
+namespace network {
+namespace mojom {
+class CookiePartitionKeyDataView;
+} // namespace mojom
+} // namespace network
+
+namespace mojo {
+template <typename DataViewType, typename T>
+struct StructTraits;
+} // namespace mojo
+
+namespace net {
+
+class NET_EXPORT CookiePartitionKey {
+ public:
+ CookiePartitionKey();
+ explicit CookiePartitionKey(const SchemefulSite& site);
+ CookiePartitionKey(const CookiePartitionKey& other);
+ CookiePartitionKey(CookiePartitionKey&& other);
+ CookiePartitionKey& operator=(const CookiePartitionKey& other);
+ CookiePartitionKey& operator=(CookiePartitionKey&& other);
+ ~CookiePartitionKey();
+
+ bool operator==(const CookiePartitionKey& other) const;
+ bool operator<(const CookiePartitionKey& other) const;
+
+ // Methods for serializing and deserializing a partition key to/from a string.
+ // This will be used for Android, storing persistent partitioned cookies, and
+ // loading partitioned cookies into Java code.
+ //
+ // This function returns true if the partition key is not opaque. We do not
+ // want to serialize cookies with opaque origins in their partition key to
+ // disk, because if the browser session ends we will not be able to attach the
+ // saved cookie to any future requests. This is because opaque origins' nonces
+ // are only stored in volatile memory.
+ //
+ // TODO(crbug.com/1225444) Investigate ways to persist partition keys with
+ // opaque origins if a browser session is restored.
+ static bool Serialize(const absl::optional<CookiePartitionKey>& in,
+ std::string& out) WARN_UNUSED_RESULT;
+ // Deserializes the result of the method above.
+ // If the result is absl::nullopt, the resulting cookie is not partitioned.
+ //
+ // Returns if the resulting partition key is valid.
+ static bool Deserialize(const std::string& in,
+ absl::optional<CookiePartitionKey>& out)
+ WARN_UNUSED_RESULT;
+
+ static CookiePartitionKey FromURLForTesting(const GURL& url) {
+ return CookiePartitionKey(url);
+ }
+
+ // Create a cookie partition key from a request's NetworkIsolationKey.
+ //
+ static absl::optional<CookiePartitionKey> FromNetworkIsolationKey(
+ const NetworkIsolationKey& network_isolation_key);
+
+ // Temporary method, used to mark the places where we need to supply the
+ // cookie partition key to CanonicalCookie::Create.
+ static absl::optional<CookiePartitionKey> Todo() { return absl::nullopt; }
+
+ private:
+ explicit CookiePartitionKey(const GURL& url);
+
+ // IPC needs access to internal site.
+ friend struct mojo::StructTraits<network::mojom::CookiePartitionKeyDataView,
+ CookiePartitionKey>;
+
+ SchemefulSite site_;
+};
+
+} // namespace net
+
+#endif // NET_COOKIES_COOKIE_PARTITION_KEY_H_
diff --git a/chromium/net/cookies/cookie_partition_key_fuzzer.cc b/chromium/net/cookies/cookie_partition_key_fuzzer.cc
new file mode 100644
index 00000000000..ddc089acd53
--- /dev/null
+++ b/chromium/net/cookies/cookie_partition_key_fuzzer.cc
@@ -0,0 +1,42 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include <fuzzer/FuzzedDataProvider.h>
+
+#include "net/cookies/cookie_partition_key.h"
+
+namespace net {
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
+ FuzzedDataProvider data_provider(data, size);
+
+ std::string url_str = data_provider.ConsumeRandomLengthString(800);
+ GURL url(url_str);
+ if (!url.is_valid())
+ return 0;
+
+ SchemefulSite site(url::Origin::Create(url));
+ absl::optional<CookiePartitionKey> partition_key =
+ absl::make_optional(CookiePartitionKey(site));
+
+ bool result = CookiePartitionKey::Deserialize(url_str, partition_key);
+ if (site.opaque())
+ CHECK(!result);
+ else
+ CHECK(result);
+
+ std::string tmp;
+ result = CookiePartitionKey::Serialize(partition_key, tmp);
+ if (site.opaque())
+ CHECK(!result);
+ else
+ CHECK(result);
+
+ return 0;
+}
+
+} // namespace net
diff --git a/chromium/net/cookies/cookie_partition_key_unittest.cc b/chromium/net/cookies/cookie_partition_key_unittest.cc
new file mode 100644
index 00000000000..7f83ba7ccb9
--- /dev/null
+++ b/chromium/net/cookies/cookie_partition_key_unittest.cc
@@ -0,0 +1,115 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_COOKIES_COOKIE_PARTITION_KEY_UNITTEST_H_
+#define NET_COOKIES_COOKIE_PARTITION_KEY_UNITTEST_H_
+
+#include "net/cookies/cookie_partition_key.h"
+#include "base/test/scoped_feature_list.h"
+#include "net/base/features.h"
+#include "net/cookies/cookie_constants.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class CookiePartitionKeyTest : public testing::TestWithParam<bool> {
+ protected:
+ // testing::Test
+ void SetUp() override {
+ if (PartitionedCookiesEnabled())
+ scoped_feature_list_.InitAndEnableFeature(features::kPartitionedCookies);
+ testing::TestWithParam<bool>::SetUp();
+ }
+
+ bool PartitionedCookiesEnabled() { return GetParam(); }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(/* no label */,
+ CookiePartitionKeyTest,
+ testing::Bool());
+
+TEST_P(CookiePartitionKeyTest, Serialization) {
+ struct {
+ absl::optional<CookiePartitionKey> input;
+ bool expected_ret;
+ std::string expected_output;
+ } cases[] = {
+ // No partition key
+ {absl::nullopt, true, kEmptyCookiePartitionKey},
+ // Partition key present
+ {absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com"))),
+ true, "https://toplevelsite.com"},
+ // Local file URL
+ {absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("file:///path/to/file.txt"))),
+ true, "file://"},
+ // File URL with host
+ {absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("file://toplevelsite.com/path/to/file.pdf"))),
+ true, "file://toplevelsite.com"},
+ // Opaque origin
+ {absl::make_optional(CookiePartitionKey::FromURLForTesting(GURL())),
+ false, ""},
+ // Invalid partition key
+ {absl::make_optional(
+ CookiePartitionKey::FromURLForTesting(GURL("abc123foobar!!"))),
+ false, ""},
+ };
+
+ for (const auto& tc : cases) {
+ std::string got;
+ EXPECT_EQ(tc.expected_ret, CookiePartitionKey::Serialize(tc.input, got));
+ EXPECT_EQ(tc.expected_output, got);
+ }
+}
+
+TEST_P(CookiePartitionKeyTest, Deserialization) {
+ struct {
+ std::string input;
+ bool expected_ret;
+ absl::optional<CookiePartitionKey> expected_output;
+ } cases[] = {
+ {kEmptyCookiePartitionKey, true, absl::nullopt},
+ {"https://toplevelsite.com", true,
+ absl::make_optional(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com")))},
+ {"abc123foobar!!", false, absl::nullopt},
+ };
+
+ for (const auto& tc : cases) {
+ absl::optional<CookiePartitionKey> got;
+ EXPECT_EQ(tc.expected_ret, CookiePartitionKey::Deserialize(tc.input, got));
+ if (tc.expected_output.has_value()) {
+ EXPECT_TRUE(got.has_value());
+ EXPECT_EQ(tc.expected_output.value(), got.value());
+ } else {
+ EXPECT_FALSE(got.has_value());
+ }
+ }
+}
+
+TEST_P(CookiePartitionKeyTest, FromNetworkIsolationKey) {
+ EXPECT_FALSE(
+ CookiePartitionKey::FromNetworkIsolationKey(NetworkIsolationKey()));
+
+ SchemefulSite top_level_site =
+ SchemefulSite(GURL("https://toplevelsite.com"));
+ absl::optional<CookiePartitionKey> got =
+ CookiePartitionKey::FromNetworkIsolationKey(NetworkIsolationKey(
+ top_level_site, SchemefulSite(GURL("https://cookiesite.com"))));
+
+ bool partitioned_cookies_enabled = PartitionedCookiesEnabled();
+ EXPECT_EQ(partitioned_cookies_enabled, got.has_value());
+ if (partitioned_cookies_enabled) {
+ EXPECT_EQ(CookiePartitionKey(top_level_site), got.value());
+ }
+}
+
+} // namespace net
+
+#endif // NET_COOKIES_COOKIE_PARTITION_KEY_UNITTEST_H_
diff --git a/chromium/net/cookies/cookie_store.h b/chromium/net/cookies/cookie_store.h
index afa99e255bd..0642e632ded 100644
--- a/chromium/net/cookies/cookie_store.h
+++ b/chromium/net/cookies/cookie_store.h
@@ -20,7 +20,6 @@
#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_deletion_info.h"
#include "net/cookies/cookie_options.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
diff --git a/chromium/net/cookies/cookie_store_test_callbacks.h b/chromium/net/cookies/cookie_store_test_callbacks.h
index b3195c20aca..71597d999a9 100644
--- a/chromium/net/cookies/cookie_store_test_callbacks.h
+++ b/chromium/net/cookies/cookie_store_test_callbacks.h
@@ -5,7 +5,6 @@
#ifndef NET_COOKIES_COOKIE_STORE_TEST_CALLBACKS_H_
#define NET_COOKIES_COOKIE_STORE_TEST_CALLBACKS_H_
-#include <string>
#include <vector>
#include "base/bind.h"
diff --git a/chromium/net/cookies/cookie_store_test_helpers.h b/chromium/net/cookies/cookie_store_test_helpers.h
index ec0ab7b2030..63182daf15e 100644
--- a/chromium/net/cookies/cookie_store_test_helpers.h
+++ b/chromium/net/cookies/cookie_store_test_helpers.h
@@ -16,7 +16,6 @@
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/log/net_log_with_source.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
diff --git a/chromium/net/cookies/cookie_store_unittest.h b/chromium/net/cookies/cookie_store_unittest.h
index de52e7baad4..1631f1667dd 100644
--- a/chromium/net/cookies/cookie_store_unittest.h
+++ b/chromium/net/cookies/cookie_store_unittest.h
@@ -20,12 +20,14 @@
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "build/build_config.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_store_test_callbacks.h"
#include "net/cookies/cookie_store_test_helpers.h"
#include "net/cookies/test_cookie_access_delegate.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#if defined(OS_IOS)
@@ -198,7 +200,8 @@ class CookieStoreTest : public testing::Test {
absl::optional<base::Time> server_time = absl::nullopt,
absl::optional<base::Time> system_time = absl::nullopt) {
auto cookie = CanonicalCookie::Create(
- url, cookie_line, system_time.value_or(base::Time::Now()), server_time);
+ url, cookie_line, system_time.value_or(base::Time::Now()), server_time,
+ absl::nullopt /* cookie_partition_key */);
if (!cookie)
return false;
@@ -269,9 +272,9 @@ class CookieStoreTest : public testing::Test {
const GURL& url,
const std::string& cookie_line) {
CookieInclusionStatus create_status;
- auto cookie = CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */,
- &create_status);
+ auto cookie = CanonicalCookie::Create(
+ url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */, &create_status);
if (!cookie)
return create_status;
@@ -438,7 +441,8 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) {
std::unique_ptr<CanonicalCookie> cc(CanonicalCookie::CreateSanitizedCookie(
this->www_foo_foo_.url(), "A", "B", std::string(), "/foo", one_hour_ago,
one_hour_from_now, base::Time(), false, false,
- CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false));
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false,
+ absl::nullopt));
ASSERT_TRUE(cc);
EXPECT_TRUE(this->SetCanonicalCookie(
cs, std::move(cc), this->www_foo_foo_.url(), true /*modify_httponly*/));
@@ -448,7 +452,8 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) {
cc = CanonicalCookie::CreateSanitizedCookie(
this->www_foo_bar_.url(), "C", "D", this->www_foo_bar_.domain(), "/bar",
two_hours_ago, base::Time(), one_hour_ago, false, true,
- CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false);
+ CookieSameSite::STRICT_MODE, COOKIE_PRIORITY_DEFAULT, false,
+ absl::nullopt);
ASSERT_TRUE(cc);
EXPECT_TRUE(this->SetCanonicalCookie(
cs, std::move(cc), this->www_foo_bar_.url(), true /*modify_httponly*/));
@@ -460,7 +465,8 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) {
cc = CanonicalCookie::CreateSanitizedCookie(
this->http_www_foo_.url(), "E", "F", std::string(), std::string(),
base::Time(), base::Time(), base::Time(), true, false,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false,
+ absl::nullopt);
ASSERT_TRUE(cc);
EXPECT_FALSE(this->SetCanonicalCookie(
cs, std::move(cc), this->http_www_foo_.url(), true /*modify_httponly*/));
@@ -468,7 +474,8 @@ TYPED_TEST_P(CookieStoreTest, FilterTest) {
cc = CanonicalCookie::CreateSanitizedCookie(
this->https_www_foo_.url(), "E", "F", std::string(), std::string(),
base::Time(), base::Time(), base::Time(), true, false,
- CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false);
+ CookieSameSite::NO_RESTRICTION, COOKIE_PRIORITY_DEFAULT, false,
+ absl::nullopt);
ASSERT_TRUE(cc);
EXPECT_TRUE(this->SetCanonicalCookie(
cs, std::move(cc), this->https_www_foo_.url(), true /*modify_httponly*/));
@@ -595,7 +602,8 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) {
CookieInclusionStatus status;
auto cookie = CanonicalCookie::Create(
this->http_www_foo_.url(), "foo=1; Secure", base::Time::Now(),
- absl::nullopt /* server_time */, &status);
+ absl::nullopt /* server_time */, absl::nullopt /* cookie_partition_key */,
+ &status);
EXPECT_TRUE(cookie->IsSecure());
EXPECT_TRUE(status.IsInclude());
EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
@@ -644,7 +652,8 @@ TYPED_TEST_P(CookieStoreTest, SetCanonicalCookieTest) {
CookieInclusionStatus create_status;
auto c = CanonicalCookie::Create(
this->http_www_foo_.url(), "bar=1; HttpOnly", base::Time::Now(),
- absl::nullopt /* server_time */, &create_status);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */, &create_status);
EXPECT_TRUE(c->IsHttpOnly());
EXPECT_TRUE(create_status.IsInclude());
EXPECT_TRUE(this->SetCanonicalCookieReturnAccessResult(
diff --git a/chromium/net/cookies/cookie_util.cc b/chromium/net/cookies/cookie_util.cc
index 5300a577980..8033226d032 100644
--- a/chromium/net/cookies/cookie_util.cc
+++ b/chromium/net/cookies/cookie_util.cc
@@ -6,11 +6,11 @@
#include <cstdio>
#include <cstdlib>
-#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
@@ -27,6 +27,9 @@
#include "net/base/url_util.h"
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_monster.h"
+#include "net/cookies/cookie_options.h"
+#include "net/cookies/same_party_context.h"
#include "net/http/http_util.h"
#include "url/gurl.h"
#include "url/url_constants.h"
@@ -37,6 +40,7 @@ namespace cookie_util {
namespace {
using ContextType = CookieOptions::SameSiteCookieContext::ContextType;
+using ContextMetadata = CookieOptions::SameSiteCookieContext::ContextMetadata;
base::Time MinNonNullTime() {
return base::Time::FromInternalValue(1);
@@ -85,6 +89,19 @@ bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded,
return false;
}
+struct ComputeSameSiteContextResult {
+ ContextType context_type = ContextType::CROSS_SITE;
+ ContextMetadata metadata;
+};
+
+CookieOptions::SameSiteCookieContext MakeSameSiteCookieContext(
+ const ComputeSameSiteContextResult& result,
+ const ComputeSameSiteContextResult& schemeful_result) {
+ return CookieOptions::SameSiteCookieContext(
+ result.context_type, schemeful_result.context_type, result.metadata,
+ schemeful_result.metadata);
+}
+
// This function consolidates the common logic for computing SameSite cookie
// access context in various situations (HTTP vs JS; get vs set).
//
@@ -95,14 +112,9 @@ bool SaturatedTimeFromUTCExploded(const base::Time::Exploded& exploded,
// schemeful_context, i.e. whether scheme should be considered when comparing
// two sites.
//
-// The bool in the return value is whether the ContextType return value was
-// affected by bugfix 1166211, used for CookieInclusionStatus warnings and
-// histogramming.
-// TODO(crbug.com/1166211): Remove when no longer needed.
-//
// See documentation of `ComputeSameSiteContextForRequest` for explanations of
// other parameters.
-std::pair<ContextType, bool> ComputeSameSiteContext(
+ComputeSameSiteContextResult ComputeSameSiteContext(
const std::vector<GURL>& url_chain,
const SiteForCookies& site_for_cookies,
const absl::optional<url::Origin>& initiator,
@@ -128,8 +140,11 @@ std::pair<ContextType, bool> ComputeSameSiteContext(
site_for_cookies.IsNull());
DCHECK(!is_main_frame_navigation || !request_url.SchemeIsWSOrWSS());
+ // Defaults to a cross-site context type.
+ ComputeSameSiteContextResult result;
+
if (!site_for_cookies_is_same_site)
- return {ContextType::CROSS_SITE, false};
+ return result;
// Create a SiteForCookies object from the initiator so that we can reuse
// IsFirstPartyWithSchemefulMode().
@@ -146,26 +161,66 @@ std::pair<ContextType, bool> ComputeSameSiteContext(
url_chain.size() == 1u ||
base::ranges::all_of(url_chain, is_same_site_with_site_for_cookies);
- if (same_site_initiator &&
- (!base::FeatureList::IsEnabled(
- features::kCookieSameSiteConsidersRedirectChain) ||
- same_site_redirect_chain)) {
- return {ContextType::SAME_SITE_STRICT, false};
+ // Whether the context would be SAME_SITE_STRICT if not considering redirect
+ // chains, but is different after considering redirect chains.
+ bool cross_site_redirect_downgraded_from_strict = false;
+ // Allows the kCookieSameSiteConsidersRedirectChain feature to override the
+ // result and use SAME_SITE_STRICT.
+ bool use_strict = false;
+
+ if (same_site_initiator) {
+ if (same_site_redirect_chain) {
+ result.context_type = ContextType::SAME_SITE_STRICT;
+ return result;
+ }
+ cross_site_redirect_downgraded_from_strict = true;
+ // If we are not supposed to consider redirect chains, record that the
+ // context result should ultimately be strictly same-site. We cannot
+ // just return early from here because we don't yet know what the context
+ // gets downgraded to, so we can't return with the correct metadata until we
+ // go through the rest of the logic below to determine that.
+ use_strict = !base::FeatureList::IsEnabled(
+ features::kCookieSameSiteConsidersRedirectChain);
}
- if (is_http) {
- base::UmaHistogramBoolean("Cookie.SameSiteContextAffectedByBugfix1166211",
- !is_main_frame_navigation);
+ if (!is_http || is_main_frame_navigation) {
+ if (cross_site_redirect_downgraded_from_strict) {
+ result.metadata.cross_site_redirect_downgrade =
+ ContextMetadata::ContextDowngradeType::kStrictToLax;
+ }
+ result.context_type =
+ use_strict ? ContextType::SAME_SITE_STRICT : ContextType::SAME_SITE_LAX;
+ return result;
}
- // Preserve old behavior if the bugfix is disabled.
- if (!base::FeatureList::IsEnabled(features::kSameSiteCookiesBugfix1166211))
- return {ContextType::SAME_SITE_LAX, false};
-
- if (!is_http || is_main_frame_navigation)
- return {ContextType::SAME_SITE_LAX, false};
-
- return {ContextType::CROSS_SITE, true};
+ if (cross_site_redirect_downgraded_from_strict) {
+ result.metadata.cross_site_redirect_downgrade =
+ ContextMetadata::ContextDowngradeType::kStrictToCross;
+ }
+ result.context_type =
+ use_strict ? ContextType::SAME_SITE_STRICT : ContextType::CROSS_SITE;
+
+ return result;
+}
+
+// Setting any SameSite={Strict,Lax} cookie only requires a LAX context, so
+// normalize any strictly same-site contexts to Lax for cookie writes.
+void NormalizeStrictToLaxForSet(ComputeSameSiteContextResult& result) {
+ if (result.context_type == ContextType::SAME_SITE_STRICT)
+ result.context_type = ContextType::SAME_SITE_LAX;
+
+ switch (result.metadata.cross_site_redirect_downgrade) {
+ case ContextMetadata::ContextDowngradeType::kStrictToLax:
+ result.metadata.cross_site_redirect_downgrade =
+ ContextMetadata::ContextDowngradeType::kNoDowngrade;
+ break;
+ case ContextMetadata::ContextDowngradeType::kStrictToCross:
+ result.metadata.cross_site_redirect_downgrade =
+ ContextMetadata::ContextDowngradeType::kLaxToCross;
+ break;
+ default:
+ break;
+ }
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet(
@@ -176,21 +231,22 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSet(
bool is_main_frame_navigation) {
CookieOptions::SameSiteCookieContext same_site_context;
- same_site_context.set_context(ComputeSameSiteContext(
+ ComputeSameSiteContextResult result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
- false /* compute_schemefully */));
- same_site_context.set_schemeful_context(ComputeSameSiteContext(
+ false /* compute_schemefully */);
+ ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, is_http, is_main_frame_navigation,
- true /* compute_schemefully */));
+ true /* compute_schemefully */);
+
+ NormalizeStrictToLaxForSet(result);
+ NormalizeStrictToLaxForSet(schemeful_result);
- // Setting any SameSite={Strict,Lax} cookie only requires a LAX context, so
- // normalize any strictly same-site contexts to Lax for cookie writes.
- if (same_site_context.context() == ContextType::SAME_SITE_STRICT)
- same_site_context.set_context(ContextType::SAME_SITE_LAX);
- if (same_site_context.schemeful_context() == ContextType::SAME_SITE_STRICT)
- same_site_context.set_schemeful_context(ContextType::SAME_SITE_LAX);
+ return MakeSameSiteCookieContext(result, schemeful_result);
+}
- return same_site_context;
+bool CookieWithAccessResultSorter(const CookieWithAccessResult& a,
+ const CookieWithAccessResult& b) {
+ return CookieMonster::CookieSorter(&a.cookie, &b.cookie);
}
} // namespace
@@ -570,28 +626,23 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForRequest(
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusive();
- CookieOptions::SameSiteCookieContext same_site_context;
-
- same_site_context.set_context(ComputeSameSiteContext(
+ ComputeSameSiteContextResult result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, true /* is_http */,
- is_main_frame_navigation, false /* compute_schemefully */));
- same_site_context.set_schemeful_context(ComputeSameSiteContext(
+ is_main_frame_navigation, false /* compute_schemefully */);
+ ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
url_chain, site_for_cookies, initiator, true /* is_http */,
- is_main_frame_navigation, true /* compute_schemefully */));
+ is_main_frame_navigation, true /* compute_schemefully */);
// If the method is safe, the context is Lax. Otherwise, make a note that
// the method is unsafe.
if (!net::HttpUtil::IsMethodSafe(http_method)) {
- if (same_site_context.context() == ContextType::SAME_SITE_LAX) {
- same_site_context.set_context(ContextType::SAME_SITE_LAX_METHOD_UNSAFE);
- }
- if (same_site_context.schemeful_context() == ContextType::SAME_SITE_LAX) {
- same_site_context.set_schemeful_context(
- ContextType::SAME_SITE_LAX_METHOD_UNSAFE);
- }
+ if (result.context_type == ContextType::SAME_SITE_LAX)
+ result.context_type = ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
+ if (schemeful_result.context_type == ContextType::SAME_SITE_LAX)
+ schemeful_result.context_type = ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
}
- return same_site_context;
+ return MakeSameSiteCookieContext(result, schemeful_result);
}
NET_EXPORT CookieOptions::SameSiteCookieContext
@@ -602,18 +653,16 @@ ComputeSameSiteContextForScriptGet(const GURL& url,
if (force_ignore_site_for_cookies)
return CookieOptions::SameSiteCookieContext::MakeInclusive();
- CookieOptions::SameSiteCookieContext same_site_context;
-
// We don't check the redirect chain for script access to cookies (only the
// URL itself).
- same_site_context.set_context(ComputeSameSiteContext(
+ ComputeSameSiteContextResult result = ComputeSameSiteContext(
{url}, site_for_cookies, initiator, false /* is_http */,
- false /* is_main_frame_navigation */, false /* compute_schemefully */));
- same_site_context.set_schemeful_context(ComputeSameSiteContext(
+ false /* is_main_frame_navigation */, false /* compute_schemefully */);
+ ComputeSameSiteContextResult schemeful_result = ComputeSameSiteContext(
{url}, site_for_cookies, initiator, false /* is_http */,
- false /* is_main_frame_navigation */, true /* compute_schemefully */));
+ false /* is_main_frame_navigation */, true /* compute_schemefully */);
- return same_site_context;
+ return MakeSameSiteCookieContext(result, schemeful_result);
}
CookieOptions::SameSiteCookieContext ComputeSameSiteContextForResponse(
@@ -683,16 +732,6 @@ CookieOptions::SameSiteCookieContext ComputeSameSiteContextForSubresource(
return CookieOptions::SameSiteCookieContext::MakeInclusive();
}
-bool IsSameSiteByDefaultCookiesEnabled() {
- return base::FeatureList::IsEnabled(features::kSameSiteByDefaultCookies);
-}
-
-bool IsCookiesWithoutSameSiteMustBeSecureEnabled() {
- return IsSameSiteByDefaultCookiesEnabled() &&
- base::FeatureList::IsEnabled(
- features::kCookiesWithoutSameSiteMustBeSecure);
-}
-
bool IsSchemefulSameSiteEnabled() {
return base::FeatureList::IsEnabled(features::kSchemefulSameSite);
}
@@ -705,23 +744,23 @@ bool IsFirstPartySetsEnabled() {
// 1) `isolation_info` is not fully populated.
// 2) `isolation_info.party_context` is null.
// 3) `cookie_access_delegate.IsContextSamePartyWithSite` returns false.
-CookieOptions::SamePartyCookieContextType ComputeSamePartyContext(
+SamePartyContext ComputeSamePartyContext(
const SchemefulSite& request_site,
const IsolationInfo& isolation_info,
const CookieAccessDelegate* cookie_access_delegate,
bool force_ignore_top_frame_party) {
if (!isolation_info.IsEmpty() && isolation_info.party_context().has_value() &&
- cookie_access_delegate &&
- cookie_access_delegate->IsContextSamePartyWithSite(
- request_site,
- force_ignore_top_frame_party
- ? absl::nullopt
- : isolation_info.network_isolation_key().GetTopFrameSite(),
- isolation_info.party_context().value())) {
- return CookieOptions::SamePartyCookieContextType::kSameParty;
+ cookie_access_delegate) {
+ return cookie_access_delegate->ComputeSamePartyContext(
+ request_site,
+ force_ignore_top_frame_party
+ ? nullptr
+ : base::OptionalOrNullptr(
+ isolation_info.network_isolation_key().GetTopFrameSite()),
+ isolation_info.party_context().value());
}
- return CookieOptions::SamePartyCookieContextType::kCrossParty;
+ return SamePartyContext();
}
CookieSamePartyStatus GetSamePartyStatus(const CanonicalCookie& cookie,
@@ -731,10 +770,10 @@ CookieSamePartyStatus GetSamePartyStatus(const CanonicalCookie& cookie,
return CookieSamePartyStatus::kNoSamePartyEnforcement;
}
- switch (options.same_party_cookie_context_type()) {
- case CookieOptions::SamePartyCookieContextType::kCrossParty:
+ switch (options.same_party_context().context_type()) {
+ case SamePartyContext::Type::kCrossParty:
return CookieSamePartyStatus::kEnforceSamePartyExclude;
- case CookieOptions::SamePartyCookieContextType::kSameParty:
+ case SamePartyContext::Type::kSameParty:
return CookieSamePartyStatus::kEnforceSamePartyInclude;
};
}
@@ -793,5 +832,24 @@ NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url) {
}
}
+NET_EXPORT void DCheckIncludedAndExcludedCookieLists(
+ const CookieAccessResultList& included_cookies,
+ const CookieAccessResultList& excluded_cookies) {
+ // Check that all elements of `included_cookies` really should be included,
+ // and that all elements of `excluded_cookies` really should be excluded.
+ DCHECK(base::ranges::all_of(included_cookies,
+ [](const net::CookieWithAccessResult& cookie) {
+ return cookie.access_result.status.IsInclude();
+ }));
+ DCHECK(base::ranges::none_of(excluded_cookies,
+ [](const net::CookieWithAccessResult& cookie) {
+ return cookie.access_result.status.IsInclude();
+ }));
+
+ // Check that the included cookies are still in the correct order.
+ DCHECK(
+ base::ranges::is_sorted(included_cookies, CookieWithAccessResultSorter));
+}
+
} // namespace cookie_util
} // namespace net
diff --git a/chromium/net/cookies/cookie_util.h b/chromium/net/cookies/cookie_util.h
index 94e7dbf52c9..0a6884cdb65 100644
--- a/chromium/net/cookies/cookie_util.h
+++ b/chromium/net/cookies/cookie_util.h
@@ -17,6 +17,7 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/site_for_cookies.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/origin.h"
class GURL;
@@ -235,26 +236,20 @@ ComputeSameSiteContextForSubresource(const GURL& url,
const SiteForCookies& site_for_cookies,
bool force_ignore_site_for_cookies);
-// Returns whether the respective SameSite feature is enabled.
-NET_EXPORT bool IsSameSiteByDefaultCookiesEnabled();
-NET_EXPORT bool IsCookiesWithoutSameSiteMustBeSecureEnabled();
+// Returns whether the respective feature is enabled.
NET_EXPORT bool IsSchemefulSameSiteEnabled();
-
NET_EXPORT bool IsFirstPartySetsEnabled();
-// Compute SameParty context, determines which of the cookies for `request_site`
-// can be accessed. Returns either kCrossParty or kSameParty. `isolation_info`
-// must be fully populated. In Chrome, all requests with credentials enabled
-// have a fully populated IsolationInfo. But that might not be true for other
-// embedders yet (including cast, WebView, etc). Also not sure about iOS. If
+// Computes the SameParty context bundle, determining which of the cookies for
+// `request_site` can be accessed. `isolation_info` must be fully populated. If
// `force_ignore_top_frame_party` is true, the top frame from `isolation_info`
// will be assumed to be same-party with `request_site`, regardless of what it
// is.
-NET_EXPORT CookieOptions::SamePartyCookieContextType ComputeSamePartyContext(
- const SchemefulSite& request_site,
- const IsolationInfo& isolation_info,
- const CookieAccessDelegate* cookie_access_delegate,
- bool force_ignore_top_frame_party);
+NET_EXPORT SamePartyContext
+ComputeSamePartyContext(const SchemefulSite& request_site,
+ const IsolationInfo& isolation_info,
+ const CookieAccessDelegate* cookie_access_delegate,
+ bool force_ignore_top_frame_party);
NET_EXPORT FirstPartySetsContextType ComputeFirstPartySetsContextType(
const SchemefulSite& request_site,
@@ -285,6 +280,15 @@ StripAccessResults(const CookieAccessResultList& cookie_access_result_list);
// Records port related metrics from Omnibox navigations.
NET_EXPORT void RecordCookiePortOmniboxHistograms(const GURL& url);
+// Checks invariants that should be upheld w.r.t. the included and excluded
+// cookies. Namely: the included cookies should be elements of
+// `included_cookies`; excluded cookies should be elements of
+// `excluded_cookies`; and included cookies should be in the correct sorted
+// order.
+NET_EXPORT void DCheckIncludedAndExcludedCookieLists(
+ const CookieAccessResultList& included_cookies,
+ const CookieAccessResultList& excluded_cookies);
+
} // namespace cookie_util
} // namespace net
diff --git a/chromium/net/cookies/cookie_util_unittest.cc b/chromium/net/cookies/cookie_util_unittest.cc
index e41c75566a2..91d5558b289 100644
--- a/chromium/net/cookies/cookie_util_unittest.cc
+++ b/chromium/net/cookies/cookie_util_unittest.cc
@@ -15,7 +15,9 @@
#include "base/time/time.h"
#include "net/base/features.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/same_party_context.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -305,13 +307,18 @@ TEST(CookieUtilTest, SimulatedCookieSource) {
for (const auto& test : kTests) {
std::vector<std::unique_ptr<CanonicalCookie>> cookies;
// It shouldn't depend on the cookie's secureness or actual source scheme.
- cookies.push_back(CanonicalCookie::Create(
- insecure_url, test.cookie, base::Time::Now(), absl::nullopt));
- cookies.push_back(CanonicalCookie::Create(
- secure_url, test.cookie, base::Time::Now(), absl::nullopt));
cookies.push_back(
- CanonicalCookie::Create(secure_url, test.cookie + "; Secure",
- base::Time::Now(), absl::nullopt));
+ CanonicalCookie::Create(insecure_url, test.cookie, base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
+ cookies.push_back(
+ CanonicalCookie::Create(secure_url, test.cookie, base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
+ cookies.push_back(CanonicalCookie::Create(
+ secure_url, test.cookie + "; Secure", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */));
for (const auto& cookie : cookies) {
GURL simulated_source =
cookie_util::SimulatedCookieSource(*cookie, test.source_scheme);
@@ -348,10 +355,44 @@ TEST(CookieUtilTest, TestIsDomainMatch) {
EXPECT_FALSE(cookie_util::IsDomainMatch(".example.de", "example.de.vu"));
}
+using ::testing::AllOf;
+using SameSiteCookieContext = CookieOptions::SameSiteCookieContext;
+using ContextType = CookieOptions::SameSiteCookieContext::ContextType;
+
MATCHER_P2(ContextTypeIsWithSchemefulMode, context_type, schemeful, "") {
return context_type == (schemeful ? arg.schemeful_context() : arg.context());
}
+// Checks for the expected metadata related to context downgrades from
+// cross-site redirects.
+MATCHER_P3(CrossSiteRedirectMetadataCorrectWithSchemefulMode,
+ context_type_without_chain,
+ context_type_with_chain,
+ schemeful,
+ "") {
+ using ContextDowngradeType = CookieOptions::SameSiteCookieContext::
+ ContextMetadata::ContextDowngradeType;
+
+ const auto& metadata = schemeful ? arg.schemeful_metadata() : arg.metadata();
+ switch (metadata.cross_site_redirect_downgrade) {
+ case ContextDowngradeType::kNoDowngrade:
+ return context_type_without_chain == context_type_with_chain;
+ case ContextDowngradeType::kStrictToLax:
+ return context_type_without_chain == ContextType::SAME_SITE_STRICT &&
+ (context_type_with_chain == ContextType::SAME_SITE_LAX ||
+ context_type_with_chain ==
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE);
+ case ContextDowngradeType::kStrictToCross:
+ return context_type_without_chain == ContextType::SAME_SITE_STRICT &&
+ context_type_with_chain == ContextType::CROSS_SITE;
+ case ContextDowngradeType::kLaxToCross:
+ return (context_type_without_chain == ContextType::SAME_SITE_LAX ||
+ context_type_without_chain ==
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE) &&
+ context_type_with_chain == ContextType::CROSS_SITE;
+ }
+}
+
std::string UrlChainToString(const std::vector<GURL>& url_chain) {
std::string s;
for (const GURL& url : url_chain) {
@@ -362,38 +403,27 @@ std::string UrlChainToString(const std::vector<GURL>& url_chain) {
// Tests for the various ComputeSameSiteContextFor*() functions. The first
// boolean test param is whether the results of the computations are evaluated
-// schemefully. The second boolean test param is whether the fix for
-// crbug.com/1166211 is enabled. The third boolean param is whether SameSite
-// considers redirect chains.
+// schemefully. The second boolean param is whether SameSite considers redirect
+// chains.
class CookieUtilComputeSameSiteContextTest
- : public ::testing::TestWithParam<std::tuple<bool, bool, bool>> {
+ : public ::testing::TestWithParam<std::tuple<bool, bool>> {
public:
CookieUtilComputeSameSiteContextTest() {
- std::vector<base::Feature> enabled_features;
- std::vector<base::Feature> disabled_features;
- // No need to explicitly enable the Bugfix1166211 feature because it
- // is enabled by default.
- if (!IsBugfix1166211Enabled())
- disabled_features.push_back(features::kSameSiteCookiesBugfix1166211);
- // No need to explicitly disable the redirect chain feature because it
- // is disabled by default.
if (DoesSameSiteConsiderRedirectChain()) {
- enabled_features.push_back(
+ feature_list_.InitAndEnableFeature(
features::kCookieSameSiteConsidersRedirectChain);
+ } else {
+ // No need to explicitly disable the redirect chain feature because it
+ // is disabled by default.
+ feature_list_.Init();
}
- feature_list_.InitWithFeatures(enabled_features, disabled_features);
}
~CookieUtilComputeSameSiteContextTest() override = default;
- using SameSiteCookieContext = CookieOptions::SameSiteCookieContext;
- using ContextType = CookieOptions::SameSiteCookieContext::ContextType;
-
bool IsSchemeful() const { return std::get<0>(GetParam()); }
- bool IsBugfix1166211Enabled() const { return std::get<1>(GetParam()); }
-
bool DoesSameSiteConsiderRedirectChain() const {
- return std::get<2>(GetParam());
+ return std::get<1>(GetParam());
}
// Returns the proper gtest matcher to use for the schemeless/schemeful mode.
@@ -401,6 +431,13 @@ class CookieUtilComputeSameSiteContextTest
return ContextTypeIsWithSchemefulMode(context_type, IsSchemeful());
}
+ auto CrossSiteRedirectMetadataCorrect(
+ ContextType context_type_without_chain,
+ ContextType context_type_with_chain) const {
+ return CrossSiteRedirectMetadataCorrectWithSchemefulMode(
+ context_type_without_chain, context_type_with_chain, IsSchemeful());
+ }
+
// The following methods return the sets of URLs/SiteForCookies/initiators/URL
// chains that are same-site or cross-site with respect to kSiteUrl.
@@ -807,32 +844,13 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest) {
}
// For non-main-frame-navigation requests, the context should be
- // cross-site, or (if the old incorrect behavior is in effect) lax or
- // lax-unsafe.
- if (IsBugfix1166211Enabled()) {
- for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
- EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, {url}, site_for_cookies, initiator,
- false /* is_main_frame_navigation */,
- false /* force_ignore_site_for_cookies */),
- ContextTypeIs(ContextType::CROSS_SITE));
- }
- } else {
- for (const std::string& method : {"GET", "HEAD"}) {
- EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
- method, {url}, site_for_cookies, initiator,
- false /* is_main_frame_navigation */,
- false /* force_ignore_site_for_cookies */),
- ContextTypeIs(ContextType::SAME_SITE_LAX));
- }
- for (const std::string& method : {"POST", "PUT"}) {
- EXPECT_THAT(
- cookie_util::ComputeSameSiteContextForRequest(
- method, {url}, site_for_cookies, initiator,
- false /* is_main_frame_navigation */,
- false /* force_ignore_site_for_cookies */),
- ContextTypeIs(ContextType::SAME_SITE_LAX_METHOD_UNSAFE));
- }
+ // cross-site.
+ for (const std::string& method : {"GET", "POST", "PUT", "HEAD"}) {
+ EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
+ method, {url}, site_for_cookies, initiator,
+ false /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */),
+ ContextTypeIs(ContextType::CROSS_SITE));
}
}
}
@@ -865,14 +883,12 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
// Schemefully same-site URL and site-for-cookies with cross-scheme
// initiator.
for (bool is_main_frame_navigation : {false, true}) {
- ContextType lax_if_main_frame =
- is_main_frame_navigation || !IsBugfix1166211Enabled()
- ? ContextType::SAME_SITE_LAX
- : ContextType::CROSS_SITE;
+ ContextType lax_if_main_frame = is_main_frame_navigation
+ ? ContextType::SAME_SITE_LAX
+ : ContextType::CROSS_SITE;
ContextType lax_unsafe_if_main_frame =
- is_main_frame_navigation || !IsBugfix1166211Enabled()
- ? ContextType::SAME_SITE_LAX_METHOD_UNSAFE
- : ContextType::CROSS_SITE;
+ is_main_frame_navigation ? ContextType::SAME_SITE_LAX_METHOD_UNSAFE
+ : ContextType::CROSS_SITE;
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_STRICT, lax_if_main_frame),
@@ -903,43 +919,31 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_SchemefulDowngrade) {
// Cross-scheme URL and site-for-cookies with cross-site initiator.
// (The request cannot be a main frame navigation if the site-for-cookies is
// not schemefully same-site).
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
- ContextType incorrectly_lax_unsafe =
- IsBugfix1166211Enabled() ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
- EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
"GET", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
- EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForRequest(
"GET", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
- EXPECT_EQ(
- SameSiteCookieContext(incorrectly_lax_unsafe, ContextType::CROSS_SITE),
- cookie_util::ComputeSameSiteContextForRequest(
- "POST", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
- false /* is_main_frame_navigation */,
- false /* force_ignore_site_for_cookies */));
- EXPECT_EQ(
- SameSiteCookieContext(incorrectly_lax_unsafe, ContextType::CROSS_SITE),
- cookie_util::ComputeSameSiteContextForRequest(
- "POST", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
- false /* is_main_frame_navigation */,
- false /* force_ignore_site_for_cookies */));
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
+ cookie_util::ComputeSameSiteContextForRequest(
+ "POST", {kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
+ false /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */));
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
+ cookie_util::ComputeSameSiteContextForRequest(
+ "POST", {kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
+ false /* is_main_frame_navigation */,
+ false /* force_ignore_site_for_cookies */));
}
TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_WebSocketSchemes) {
// wss/https and http/ws are considered the same for schemeful purposes.
// (ws/wss requests cannot be main frame navigations.)
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
-
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
"GET", {kWssUrl}, kSecureSiteForCookies, kSecureSiteInitiator,
false /* is_main_frame_navigation */,
@@ -950,7 +954,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_WebSocketSchemes) {
"GET", {kWssUrl}, kSecureSiteForCookies, kSecureCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(incorrectly_lax));
+ ContextTypeIs(ContextType::CROSS_SITE));
EXPECT_THAT(cookie_util::ComputeSameSiteContextForRequest(
"GET", {kWsUrl}, kSiteForCookies, kSiteInitiator,
@@ -961,19 +965,13 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_WebSocketSchemes) {
"GET", {kWsUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(incorrectly_lax));
+ ContextTypeIs(ContextType::CROSS_SITE));
}
// Test cases where the URL chain contains multiple members, where the last
// member (current request URL) is same-site to kSiteUrl. (Everything is listed
// as same-site or cross-site relative to kSiteUrl.)
TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
- ContextType incorrectly_lax_unsafe =
- IsBugfix1166211Enabled() ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX_METHOD_UNSAFE;
struct {
std::string method;
bool url_chain_is_same_site;
@@ -991,8 +989,9 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
{"GET", true, true, true, ContextType::SAME_SITE_STRICT,
ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
ContextType::SAME_SITE_STRICT},
- {"GET", true, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
- incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {"GET", true, true, false, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX},
{"GET", true, false, true, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE,
ContextType::CROSS_SITE},
@@ -1002,10 +1001,12 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
// If the url chain is cross-site, then the result will differ depending
// on whether the redirect chain is considered, when the site-for-cookies
// and initiator are both same-site.
- {"GET", false, true, true, incorrectly_lax, ContextType::SAME_SITE_LAX,
- ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT},
- {"GET", false, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
- incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {"GET", false, true, true, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_STRICT,
+ ContextType::SAME_SITE_STRICT},
+ {"GET", false, true, false, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX},
{"GET", false, false, true, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE,
ContextType::CROSS_SITE},
@@ -1017,8 +1018,8 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
{"POST", true, true, true, ContextType::SAME_SITE_STRICT,
ContextType::SAME_SITE_STRICT, ContextType::SAME_SITE_STRICT,
ContextType::SAME_SITE_STRICT},
- {"POST", true, true, false, incorrectly_lax_unsafe,
- ContextType::SAME_SITE_LAX_METHOD_UNSAFE, incorrectly_lax_unsafe,
+ {"POST", true, true, false, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::CROSS_SITE,
ContextType::SAME_SITE_LAX_METHOD_UNSAFE},
{"POST", true, false, true, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE,
@@ -1029,11 +1030,11 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
// If the url chain is cross-site, then the result will differ depending
// on whether the redirect chain is considered, when the site-for-cookies
// and initiator are both same-site.
- {"POST", false, true, true, incorrectly_lax_unsafe,
+ {"POST", false, true, true, ContextType::CROSS_SITE,
ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::SAME_SITE_STRICT,
ContextType::SAME_SITE_STRICT},
- {"POST", false, true, false, incorrectly_lax_unsafe,
- ContextType::SAME_SITE_LAX_METHOD_UNSAFE, incorrectly_lax_unsafe,
+ {"POST", false, true, false, ContextType::CROSS_SITE,
+ ContextType::SAME_SITE_LAX_METHOD_UNSAFE, ContextType::CROSS_SITE,
ContextType::SAME_SITE_LAX_METHOD_UNSAFE},
{"POST", false, false, true, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE},
@@ -1067,7 +1068,10 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
test_case.method, url_chain, site_for_cookies,
initiator, false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(expected_context_type))
+ AllOf(ContextTypeIs(expected_context_type),
+ CrossSiteRedirectMetadataCorrect(
+ test_case.expected_context_type_without_chain,
+ test_case.expected_context_type)))
<< UrlChainToString(url_chain) << " "
<< site_for_cookies.ToDebugString() << " "
<< (initiator ? initiator->Serialize() : "nullopt");
@@ -1078,7 +1082,14 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForRequest_Redirect) {
test_case.method, url_chain, site_for_cookies, initiator,
true /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(expected_context_type_for_main_frame_navigation))
+ AllOf(
+ ContextTypeIs(
+ expected_context_type_for_main_frame_navigation),
+ CrossSiteRedirectMetadataCorrect(
+ test_case
+ .expected_context_type_for_main_frame_navigation_without_chain,
+ test_case
+ .expected_context_type_for_main_frame_navigation)))
<< UrlChainToString(url_chain) << " "
<< site_for_cookies.ToDebugString() << " "
<< (initiator ? initiator->Serialize() : "nullopt");
@@ -1149,8 +1160,7 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
}
// For non-main-frame-navigation requests, the context should be lax iff
- // the initiator is same-site, and cross-site otherwise. If the old
- // (incorrect) behavior is in effect, it is always lax.
+ // the initiator is same-site, and cross-site otherwise.
for (const absl::optional<url::Origin>& initiator :
GetSameSiteInitiators()) {
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
@@ -1161,14 +1171,11 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse) {
}
for (const absl::optional<url::Origin>& initiator :
GetCrossSiteInitiators()) {
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
{url}, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(incorrectly_lax));
+ ContextTypeIs(ContextType::CROSS_SITE));
}
}
}
@@ -1195,15 +1202,12 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
// With cross-site initiator:
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
- EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
{kSiteUrl}, kSecureSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */));
- EXPECT_EQ(SameSiteCookieContext(incorrectly_lax, ContextType::CROSS_SITE),
+ EXPECT_EQ(SameSiteCookieContext(ContextType::CROSS_SITE),
cookie_util::ComputeSameSiteContextForResponse(
{kSecureSiteUrl}, kSiteForCookies, kCrossSiteInitiator,
false /* is_main_frame_navigation */,
@@ -1212,10 +1216,9 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_SchemefulDowngrade) {
// Schemefully same-site URL and site-for-cookies with cross-scheme
// initiator.
for (bool is_main_frame_navigation : {false, true}) {
- ContextType lax_if_main_frame =
- is_main_frame_navigation || !IsBugfix1166211Enabled()
- ? ContextType::SAME_SITE_LAX
- : ContextType::CROSS_SITE;
+ ContextType lax_if_main_frame = is_main_frame_navigation
+ ? ContextType::SAME_SITE_LAX
+ : ContextType::CROSS_SITE;
EXPECT_EQ(
SameSiteCookieContext(ContextType::SAME_SITE_LAX, lax_if_main_frame),
cookie_util::ComputeSameSiteContextForResponse(
@@ -1246,14 +1249,11 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_WebSocketSchemes) {
// Cross-site initiators.
for (const absl::optional<url::Origin>& initiator :
GetCrossSiteInitiators()) {
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
EXPECT_THAT(cookie_util::ComputeSameSiteContextForResponse(
{kWsUrl}, kSiteForCookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(incorrectly_lax));
+ ContextTypeIs(ContextType::CROSS_SITE));
}
}
@@ -1261,9 +1261,6 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_WebSocketSchemes) {
// member (current request URL) is same-site to kSiteUrl. (Everything is listed
// as same-site or cross-site relative to kSiteUrl.)
TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
- ContextType incorrectly_lax = IsBugfix1166211Enabled()
- ? ContextType::CROSS_SITE
- : ContextType::SAME_SITE_LAX;
struct {
bool url_chain_is_same_site;
bool site_for_cookies_is_same_site;
@@ -1279,8 +1276,8 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
// without considering the redirect chain.
{true, true, true, ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX,
ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX},
- {true, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
- incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {true, true, false, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
+ ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX},
{true, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE},
{true, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
@@ -1288,10 +1285,10 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
// If the url chain is cross-site, then the result will differ depending
// on whether the redirect chain is considered, when the site-for-cookies
// and initiator are both same-site.
- {false, true, true, incorrectly_lax, ContextType::SAME_SITE_LAX,
+ {false, true, true, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
ContextType::SAME_SITE_LAX, ContextType::SAME_SITE_LAX},
- {false, true, false, incorrectly_lax, ContextType::SAME_SITE_LAX,
- incorrectly_lax, ContextType::SAME_SITE_LAX},
+ {false, true, false, ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX,
+ ContextType::CROSS_SITE, ContextType::SAME_SITE_LAX},
{false, false, true, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
ContextType::CROSS_SITE, ContextType::CROSS_SITE},
{false, false, false, ContextType::CROSS_SITE, ContextType::CROSS_SITE,
@@ -1323,7 +1320,10 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
url_chain, site_for_cookies, initiator,
false /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(expected_context_type))
+ AllOf(ContextTypeIs(expected_context_type),
+ CrossSiteRedirectMetadataCorrect(
+ test_case.expected_context_type_without_chain,
+ test_case.expected_context_type)))
<< UrlChainToString(url_chain) << " "
<< site_for_cookies.ToDebugString() << " "
<< (initiator ? initiator->Serialize() : "nullopt");
@@ -1334,7 +1334,14 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForResponse_Redirect) {
url_chain, site_for_cookies, initiator,
true /* is_main_frame_navigation */,
false /* force_ignore_site_for_cookies */),
- ContextTypeIs(expected_context_type_for_main_frame_navigation))
+ AllOf(
+ ContextTypeIs(
+ expected_context_type_for_main_frame_navigation),
+ CrossSiteRedirectMetadataCorrect(
+ test_case
+ .expected_context_type_for_main_frame_navigation_without_chain,
+ test_case
+ .expected_context_type_for_main_frame_navigation)))
<< UrlChainToString(url_chain) << " "
<< site_for_cookies.ToDebugString() << " "
<< (initiator ? initiator->Serialize() : "nullopt");
@@ -1439,7 +1446,6 @@ TEST_P(CookieUtilComputeSameSiteContextTest, ForceIgnoreSiteForCookies) {
INSTANTIATE_TEST_SUITE_P(/* no label */,
CookieUtilComputeSameSiteContextTest,
::testing::Combine(::testing::Bool(),
- ::testing::Bool(),
::testing::Bool()));
TEST(CookieUtilTest, AdaptCookieAccessResultToBool) {
@@ -1483,9 +1489,9 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotInSet) {
CookieSameSite::STRICT_MODE,
CookieSameSite::UNSPECIFIED,
}) {
- for (CookieOptions::SamePartyCookieContextType party_context_type : {
- CookieOptions::SamePartyCookieContextType::kCrossParty,
- CookieOptions::SamePartyCookieContextType::kSameParty,
+ for (SamePartyContext::Type party_context_type : {
+ SamePartyContext::Type::kCrossParty,
+ SamePartyContext::Type::kSameParty,
}) {
base::Time now = base::Time::Now();
std::unique_ptr<CanonicalCookie> cookie =
@@ -1494,7 +1500,8 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotInSet) {
secure, httponly, same_site,
CookiePriority::COOKIE_PRIORITY_DEFAULT, same_party);
- options.set_same_party_cookie_context_type(party_context_type);
+ options.set_same_party_context(
+ SamePartyContext(party_context_type));
EXPECT_EQ(CookieSamePartyStatus::kNoSamePartyEnforcement,
cookie_util::GetSamePartyStatus(*cookie, options));
}
@@ -1519,9 +1526,9 @@ TEST(CookieUtilTest, GetSamePartyStatus_FeatureDisabled) {
CookieSameSite::STRICT_MODE,
CookieSameSite::UNSPECIFIED,
}) {
- for (CookieOptions::SamePartyCookieContextType party_context_type : {
- CookieOptions::SamePartyCookieContextType::kCrossParty,
- CookieOptions::SamePartyCookieContextType::kSameParty,
+ for (SamePartyContext::Type party_context_type : {
+ SamePartyContext::Type::kCrossParty,
+ SamePartyContext::Type::kSameParty,
}) {
base::Time now = base::Time::Now();
std::unique_ptr<CanonicalCookie> cookie =
@@ -1530,7 +1537,8 @@ TEST(CookieUtilTest, GetSamePartyStatus_FeatureDisabled) {
secure, httponly, same_site,
CookiePriority::COOKIE_PRIORITY_DEFAULT, same_party);
- options.set_same_party_cookie_context_type(party_context_type);
+ options.set_same_party_context(
+ SamePartyContext(party_context_type));
EXPECT_EQ(CookieSamePartyStatus::kNoSamePartyEnforcement,
cookie_util::GetSamePartyStatus(*cookie, options));
}
@@ -1554,9 +1562,9 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotSameParty) {
CookieSameSite::STRICT_MODE,
CookieSameSite::UNSPECIFIED,
}) {
- for (CookieOptions::SamePartyCookieContextType party_context_type : {
- CookieOptions::SamePartyCookieContextType::kCrossParty,
- CookieOptions::SamePartyCookieContextType::kSameParty,
+ for (SamePartyContext::Type party_context_type : {
+ SamePartyContext::Type::kCrossParty,
+ SamePartyContext::Type::kSameParty,
}) {
base::Time now = base::Time::Now();
std::unique_ptr<CanonicalCookie> cookie =
@@ -1565,7 +1573,7 @@ TEST(CookieUtilTest, GetSamePartyStatus_NotSameParty) {
httponly, same_site, CookiePriority::COOKIE_PRIORITY_DEFAULT,
false /* same_party */);
- options.set_same_party_cookie_context_type(party_context_type);
+ options.set_same_party_context(SamePartyContext(party_context_type));
EXPECT_EQ(CookieSamePartyStatus::kNoSamePartyEnforcement,
cookie_util::GetSamePartyStatus(*cookie, options));
}
@@ -1622,13 +1630,13 @@ TEST(CookieUtilTest, GetSamePartyStatus_SamePartySemantics) {
CookiePriority::COOKIE_PRIORITY_DEFAULT,
true /* same_party */);
- options.set_same_party_cookie_context_type(
- CookieOptions::SamePartyCookieContextType::kCrossParty);
+ options.set_same_party_context(
+ SamePartyContext(SamePartyContext::Type::kCrossParty));
EXPECT_EQ(CookieSamePartyStatus::kEnforceSamePartyExclude,
cookie_util::GetSamePartyStatus(*cookie, options));
- options.set_same_party_cookie_context_type(
- CookieOptions::SamePartyCookieContextType::kSameParty);
+ options.set_same_party_context(
+ SamePartyContext(SamePartyContext::Type::kSameParty));
EXPECT_EQ(CookieSamePartyStatus::kEnforceSamePartyInclude,
cookie_util::GetSamePartyStatus(*cookie, options));
}
diff --git a/chromium/net/cookies/parse_cookie_line_fuzzer.cc b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
index 037662209c2..830a8bfc078 100644
--- a/chromium/net/cookies/parse_cookie_line_fuzzer.cc
+++ b/chromium/net/cookies/parse_cookie_line_fuzzer.cc
@@ -25,7 +25,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
// Call zero or one of ParsedCookie's mutator methods. Should not call
// anything other than SetName/SetValue when !IsValid().
- const uint8_t action = data_provider.ConsumeIntegralInRange(0, 11);
+ const uint8_t action = data_provider.ConsumeIntegralInRange(0, 12);
switch (action) {
case 1:
parsed_cookie.SetName(GetArbitraryString(&data_provider));
@@ -65,6 +65,9 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
case 11:
parsed_cookie.SetIsSameParty(data_provider.ConsumeBool());
break;
+ case 12:
+ parsed_cookie.SetIsPartitioned(data_provider.ConsumeBool());
+ break;
}
}
diff --git a/chromium/net/cookies/parsed_cookie.cc b/chromium/net/cookies/parsed_cookie.cc
index 4fc5a19184e..a8a449c1a99 100644
--- a/chromium/net/cookies/parsed_cookie.cc
+++ b/chromium/net/cookies/parsed_cookie.cc
@@ -48,6 +48,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/strings/string_util.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/http/http_util.h"
namespace {
@@ -61,11 +62,12 @@ const char kHttpOnlyTokenName[] = "httponly";
const char kSameSiteTokenName[] = "samesite";
const char kPriorityTokenName[] = "priority";
const char kSamePartyTokenName[] = "sameparty";
+const char kPartitionedTokenName[] = "partitioned";
const char kTerminator[] = "\n\r\0";
const int kTerminatorLen = sizeof(kTerminator) - 1;
const char kWhitespace[] = " \t";
-const char kValueSeparator[] = ";";
+const char kValueSeparator = ';';
const char kTokenSeparator[] = ";=";
// Returns true if |c| occurs in |chars|
@@ -73,6 +75,17 @@ const char kTokenSeparator[] = ";=";
inline bool CharIsA(const char c, const char* chars) {
return strchr(chars, c) != nullptr;
}
+
+// Seek the iterator to the first occurrence of |character|.
+// Returns true if it hits the end, false otherwise.
+inline bool SeekToCharacter(std::string::const_iterator* it,
+ const std::string::const_iterator& end,
+ const char character) {
+ for (; *it != end && **it != character; ++(*it)) {
+ }
+ return *it == end;
+}
+
// Seek the iterator to the first occurrence of a character in |chars|.
// Returns true if it hit the end, false otherwise.
inline bool SeekTo(std::string::const_iterator* it,
@@ -122,19 +135,51 @@ bool IsValidCookieValue(const std::string& value) {
return true;
}
+// Returns the string piece within |value| that is a valid cookie value.
+base::StringPiece ValidStringPieceForValue(const std::string& value) {
+ std::string::const_iterator it = value.begin();
+ std::string::const_iterator end =
+ net::ParsedCookie::FindFirstTerminator(value);
+ std::string::const_iterator value_start;
+ std::string::const_iterator value_end;
+
+ net::ParsedCookie::ParseValue(&it, end, &value_start, &value_end);
+
+ return base::MakeStringPiece(value_start, value_end);
+}
+
} // namespace
namespace net {
-ParsedCookie::ParsedCookie(const std::string& cookie_line) {
+ParsedCookie::ParsedCookie(const std::string& cookie_line,
+ CookieInclusionStatus* status_out) {
+ // Put a pointer on the stack so the rest of the function can assign to it if
+ // the default nullptr is passed in.
+ CookieInclusionStatus blank_status;
+ if (status_out == nullptr) {
+ status_out = &blank_status;
+ }
+
if (cookie_line.size() > kMaxCookieSize) {
DVLOG(1) << "Not parsing cookie, too large: " << cookie_line.size();
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ status_out->AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
return;
}
- ParseTokenValuePairs(cookie_line);
- if (!pairs_.empty())
+ ParseTokenValuePairs(cookie_line, *status_out);
+ if (IsValid()) {
SetupAttributes();
+ } else if (status_out->IsInclude()) {
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ status_out->AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
+ }
+
+ // Status should indicate exclusion if the resulting ParsedCookie is invalid.
+ DCHECK(IsValid() || !status_out->IsInclude());
if (IsValid())
RecordCookieAttributeValueLengthHistograms();
@@ -228,6 +273,10 @@ bool ParsedCookie::SetIsSameParty(bool is_same_party) {
return SetBool(&same_party_index_, kSamePartyTokenName, is_same_party);
}
+bool ParsedCookie::SetIsPartitioned(bool is_partitioned) {
+ return SetBool(&partitioned_index_, kPartitionedTokenName, is_partitioned);
+}
+
std::string ParsedCookie::ToCookieLine() const {
std::string out;
for (auto it = pairs_.begin(); it != pairs_.end(); ++it) {
@@ -239,7 +288,8 @@ std::string ParsedCookie::ToCookieLine() const {
// we need to consider whether the name component is a special token.
if (it == pairs_.begin() ||
(it->first != kSecureTokenName && it->first != kHttpOnlyTokenName &&
- it->first != kSamePartyTokenName)) {
+ it->first != kSamePartyTokenName &&
+ it->first != kPartitionedTokenName)) {
out.append("=");
out.append(it->second);
}
@@ -303,22 +353,24 @@ void ParsedCookie::ParseValue(std::string::const_iterator* it,
std::string::const_iterator* value_end) {
DCHECK(it && value_start && value_end);
- // Seek past any whitespace that might in-between the token and value.
+ // Seek past any whitespace that might be in-between the token and value.
SeekPast(it, end, kWhitespace);
// value_start should point at the first character of the value.
*value_start = *it;
// Just look for ';' to terminate ('=' allowed).
// We can hit the end, maybe they didn't terminate.
- SeekTo(it, end, kValueSeparator);
+ SeekToCharacter(it, end, kValueSeparator);
- // Will be pointed at the ; seperator or the end.
+ // Will point at the ; separator or the end.
*value_end = *it;
// Ignore any unwanted whitespace after the value.
if (*value_end != *value_start) { // Could have an empty value
--(*value_end);
+ // Skip over any whitespace to the first non-whitespace character.
SeekBackPast(value_end, *value_start, kWhitespace);
+ // Point after it.
++(*value_end);
}
}
@@ -336,12 +388,15 @@ std::string ParsedCookie::ParseTokenString(const std::string& token) {
// static
std::string ParsedCookie::ParseValueString(const std::string& value) {
- std::string::const_iterator it = value.begin();
- std::string::const_iterator end = FindFirstTerminator(value);
+ return std::string(ValidStringPieceForValue(value));
+}
- std::string::const_iterator value_start, value_end;
- ParseValue(&it, end, &value_start, &value_end);
- return std::string(value_start, value_end);
+// static
+bool ParsedCookie::ValueMatchesParsedValue(const std::string& value) {
+ // ValidStringPieceForValue() returns a valid substring of |value|.
+ // If |value| can be fully parsed the result will have the same length
+ // as |value|.
+ return ValidStringPieceForValue(value).length() == value.length();
}
// static
@@ -356,7 +411,8 @@ bool ParsedCookie::IsValidCookieAttributeValue(const std::string& value) {
}
// Parse all token/value pairs and populate pairs_.
-void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) {
+void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line,
+ CookieInclusionStatus& status_out) {
pairs_.clear();
// Ok, here we go. We should be expecting to be starting somewhere
@@ -369,8 +425,12 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) {
std::string::const_iterator end = FindFirstTerminator(cookie_line);
// Exit early for an empty cookie string.
- if (it == end)
+ if (it == end) {
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ status_out.AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
return;
+ }
for (int pair_num = 0; it != end; ++pair_num) {
TokenValuePair pair;
@@ -417,6 +477,9 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) {
// Ignore cookies with neither name nor value.
if (pair_num == 0 && (pair.first.empty() && pair.second.empty())) {
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ status_out.AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
pairs_.clear();
break;
}
@@ -429,6 +492,9 @@ void ParsedCookie::ParseTokenValuePairs(const std::string& cookie_line) {
// http://crbug.com/238041.
if (!IsValidCookieAttributeValue(pair.first) ||
!IsValidCookieAttributeValue(pair.second)) {
+ // TODO(crbug.com/1228815): Apply more specific exclusion reasons.
+ status_out.AddExclusionReason(
+ CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE);
pairs_.clear();
break;
}
@@ -480,6 +546,8 @@ void ParsedCookie::SetupAttributes() {
priority_index_ = i;
} else if (pairs_[i].first == kSamePartyTokenName) {
same_party_index_ = i;
+ } else if (pairs_[i].first == kPartitionedTokenName) {
+ partitioned_index_ = i;
} else {
/* some attribute we don't know or don't care about. */
}
@@ -545,9 +613,10 @@ void ParsedCookie::ClearAttributePair(size_t index) {
if (index == 0)
return;
- size_t* indexes[] = {&path_index_, &domain_index_, &expires_index_,
- &maxage_index_, &secure_index_, &httponly_index_,
- &same_site_index_, &priority_index_, &same_party_index_};
+ size_t* indexes[] = {&path_index_, &domain_index_, &expires_index_,
+ &maxage_index_, &secure_index_, &httponly_index_,
+ &same_site_index_, &priority_index_, &same_party_index_,
+ &partitioned_index_};
for (size_t* attribute_index : indexes) {
if (*attribute_index == index)
*attribute_index = 0;
diff --git a/chromium/net/cookies/parsed_cookie.h b/chromium/net/cookies/parsed_cookie.h
index cd9cfed0eac..cd2897bf628 100644
--- a/chromium/net/cookies/parsed_cookie.h
+++ b/chromium/net/cookies/parsed_cookie.h
@@ -16,6 +16,8 @@
namespace net {
+class CookieInclusionStatus;
+
class NET_EXPORT ParsedCookie {
public:
typedef std::pair<std::string, std::string> TokenValuePair;
@@ -27,7 +29,12 @@ class NET_EXPORT ParsedCookie {
// Construct from a cookie string like "BLAH=1; path=/; domain=.google.com"
// Format is according to RFC 6265. Cookies with both name and value empty
// will be considered invalid.
- ParsedCookie(const std::string& cookie_line);
+ // `status_out` is a nullable output param which will be populated with
+ // informative exclusion reasons if the resulting ParsedCookie is invalid.
+ // The CookieInclusionStatus will not be altered if the resulting ParsedCookie
+ // is valid.
+ explicit ParsedCookie(const std::string& cookie_line,
+ CookieInclusionStatus* status_out = nullptr);
~ParsedCookie();
// You should not call any other methods except for SetName/SetValue on the
@@ -54,6 +61,7 @@ class NET_EXPORT ParsedCookie {
CookieSameSiteString* samesite_string = nullptr) const;
CookiePriority Priority() const;
bool IsSameParty() const { return same_party_index_ != 0; }
+ bool IsPartitioned() const { return partitioned_index_ != 0; }
bool HasTruncatedNameOrValue() const { return truncated_name_or_value_; }
// Returns the number of attributes, for example, returning 2 for:
@@ -81,6 +89,7 @@ class NET_EXPORT ParsedCookie {
bool SetSameSite(const std::string& same_site);
bool SetPriority(const std::string& priority);
bool SetIsSameParty(bool is_same_party);
+ bool SetIsPartitioned(bool is_partitioned);
// Returns the cookie description as it appears in a HTML response header.
std::string ToCookieLine() const;
@@ -114,11 +123,15 @@ class NET_EXPORT ParsedCookie {
static std::string ParseTokenString(const std::string& token);
static std::string ParseValueString(const std::string& value);
+ // Returns |true| if the parsed version of |value| matches |value|.
+ static bool ValueMatchesParsedValue(const std::string& value);
+
// Is the string valid as the value of a cookie attribute?
static bool IsValidCookieAttributeValue(const std::string& value);
private:
- void ParseTokenValuePairs(const std::string& cookie_line);
+ void ParseTokenValuePairs(const std::string& cookie_line,
+ CookieInclusionStatus& status_out);
void SetupAttributes();
// Sets a key/value pair for a cookie. |index| has to point to one of the
@@ -160,6 +173,7 @@ class NET_EXPORT ParsedCookie {
size_t same_site_index_ = 0;
size_t priority_index_ = 0;
size_t same_party_index_ = 0;
+ size_t partitioned_index_ = 0;
// For metrics on cookie name/value truncation. See usage at the bottom of
// `ParseTokenValuePairs()` for more details.
bool truncated_name_or_value_ = false;
diff --git a/chromium/net/cookies/parsed_cookie_unittest.cc b/chromium/net/cookies/parsed_cookie_unittest.cc
index c12c1b8317d..c511afaab16 100644
--- a/chromium/net/cookies/parsed_cookie_unittest.cc
+++ b/chromium/net/cookies/parsed_cookie_unittest.cc
@@ -16,6 +16,7 @@ TEST(ParsedCookieTest, TestBasic) {
EXPECT_FALSE(pc1.IsSecure());
EXPECT_FALSE(pc1.IsHttpOnly());
EXPECT_FALSE(pc1.IsSameParty());
+ EXPECT_FALSE(pc1.IsPartitioned());
EXPECT_EQ("a", pc1.Name());
EXPECT_EQ("b", pc1.Value());
EXPECT_FALSE(pc1.HasPath());
@@ -27,11 +28,12 @@ TEST(ParsedCookieTest, TestBasic) {
ParsedCookie pc2(
"c=d; secure; httponly; sameparty; path=/foo; domain=bar.test; "
- "max-age=60; samesite=lax; priority=high");
+ "max-age=60; samesite=lax; priority=high; partitioned;");
EXPECT_TRUE(pc2.IsValid());
EXPECT_TRUE(pc2.IsSecure());
EXPECT_TRUE(pc2.IsHttpOnly());
EXPECT_TRUE(pc2.IsSameParty());
+ EXPECT_TRUE(pc2.IsPartitioned());
EXPECT_EQ("c", pc2.Name());
EXPECT_EQ("d", pc2.Value());
EXPECT_TRUE(pc2.HasPath());
@@ -78,6 +80,70 @@ TEST(ParsedCookieTest, TestSetEmptyNameValue) {
EXPECT_TRUE(empty_name.IsValid());
}
+TEST(ParsedCookieTest, ParseValueStrings) {
+ std::string valid_values[] = {
+ "httpONLY", "1%7C1624663551161", "<K0<r<C_<G_<S0",
+ "lastRequest=1624663552846&activeDays=%5B0%2C0", "si=8da88dce-5fee-4835"};
+ for (const auto& value : valid_values) {
+ EXPECT_EQ(ParsedCookie::ParseValueString(value), value);
+ EXPECT_TRUE(ParsedCookie::ValueMatchesParsedValue(value));
+ }
+
+ std::string invalid_values[] = {
+ "\nhttpONLYsecure", // Newline char at start
+ "httpONLY\nsecure", // Newline char in middle
+ "httpONLYsecure\n", // Newline char at end
+ "\r<K0<r<C_<G_<S0", // Carriage return at start
+ "<K0<r\r<C_<G_<S0", // Carriage return in middle
+ "<K0<r<C_<G_<S0\r", // Carriage return at end
+ ";lastRequest=1624663552846", // Token separator at start
+ "lastRequest=1624663552846; activeDays=%5B0%2C0", // Token separator in
+ // middle
+ std::string("\0abcdef", 7), // 0 byte at start
+ std::string("abc\0def", 7), // 0 byte in middle
+ std::string("abcdef\0", 7)}; // 0 byte at end
+ for (const auto& value : invalid_values) {
+ EXPECT_NE(ParsedCookie::ParseValueString(value), value);
+ EXPECT_FALSE(ParsedCookie::ValueMatchesParsedValue(value));
+ }
+
+ // Strings with leading whitespace should parse OK but
+ // ValueMatchesParsedValue() should fail.
+ std::string leading_whitespace_values[] = {
+ " 1%7C1624663551161", // Space at start
+ "\t1%7C1624663551161", // Tab at start
+ };
+ for (const auto& value : leading_whitespace_values) {
+ EXPECT_TRUE(ParsedCookie::ParseValueString(value).length() ==
+ value.length() - 1);
+ EXPECT_FALSE(ParsedCookie::ValueMatchesParsedValue(value));
+ }
+
+ // Strings with trailing whitespace or the separator character should parse OK
+ // but ValueMatchesParsedValue() should fail.
+ std::string valid_values_with_trailing_chars[] = {
+ "lastRequest=1624663552846 ", // Space at end
+ "lastRequest=1624663552846\t", // Tab at end
+ "lastRequest=1624663552846;", // Token separator at end
+ };
+ const size_t valid_value_length =
+ valid_values_with_trailing_chars[0].length() - 1;
+ for (const auto& value : valid_values_with_trailing_chars) {
+ EXPECT_TRUE(ParsedCookie::ParseValueString(value).length() ==
+ valid_value_length);
+ EXPECT_FALSE(ParsedCookie::ValueMatchesParsedValue(value));
+ }
+
+ // A valid value (truncated after the ';') but parses out to a substring.
+ std::string value_with_separator_in_middle(
+ "lastRequest=1624663552846; activeDays=%5B0%2C0");
+ EXPECT_TRUE(
+ ParsedCookie::ParseValueString(value_with_separator_in_middle).length() ==
+ value_with_separator_in_middle.find(';'));
+ EXPECT_FALSE(
+ ParsedCookie::ValueMatchesParsedValue(value_with_separator_in_middle));
+}
+
TEST(ParsedCookieTest, TestQuoted) {
// These are some quoting cases which the major browsers all
// handle differently. I've tested Internet Explorer 6, Opera 9.6,
@@ -138,18 +204,20 @@ TEST(ParsedCookieTest, TestNameless) {
TEST(ParsedCookieTest, TestAttributeCase) {
ParsedCookie pc(
- "BLAH; Path=/; sECuRe; httpONLY; sAmESitE=LaX; pRIoRitY=hIgH; samePaRtY");
+ "BLAH; Path=/; sECuRe; httpONLY; sAmESitE=LaX; pRIoRitY=hIgH; samePaRtY; "
+ "pARTitIoNeD;");
EXPECT_TRUE(pc.IsValid());
EXPECT_TRUE(pc.IsSecure());
EXPECT_TRUE(pc.IsHttpOnly());
EXPECT_TRUE(pc.IsSameParty());
+ EXPECT_TRUE(pc.IsPartitioned());
EXPECT_EQ(CookieSameSite::LAX_MODE, pc.SameSite());
EXPECT_TRUE(pc.HasPath());
EXPECT_EQ("/", pc.Path());
EXPECT_EQ("", pc.Name());
EXPECT_EQ("BLAH", pc.Value());
EXPECT_EQ(COOKIE_PRIORITY_HIGH, pc.Priority());
- EXPECT_EQ(6U, pc.NumberOfAttributes());
+ EXPECT_EQ(7U, pc.NumberOfAttributes());
}
TEST(ParsedCookieTest, TestDoubleQuotedNameless) {
@@ -396,10 +464,11 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_TRUE(pc.SetSameSite("LAX"));
EXPECT_TRUE(pc.SetPriority("HIGH"));
EXPECT_TRUE(pc.SetIsSameParty(true));
+ EXPECT_TRUE(pc.SetIsPartitioned(true));
EXPECT_EQ(
"name=value; domain=domain.com; path=/; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; samesite=LAX; priority=HIGH; sameparty",
+ "httponly; samesite=LAX; priority=HIGH; sameparty; partitioned",
pc.ToCookieLine());
EXPECT_TRUE(pc.HasDomain());
EXPECT_TRUE(pc.HasPath());
@@ -423,7 +492,7 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; samesite=LAX; priority=HIGH; sameparty",
+ "httponly; samesite=LAX; priority=HIGH; sameparty; partitioned",
pc.ToCookieLine());
// Set priority to medium.
@@ -432,16 +501,16 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; samesite=LAX; priority=medium; sameparty",
+ "httponly; samesite=LAX; priority=medium; sameparty; partitioned",
pc.ToCookieLine());
// Clear attribute from the end.
- EXPECT_TRUE(pc.SetIsSameParty(false));
- EXPECT_FALSE(pc.IsSameParty());
+ EXPECT_TRUE(pc.SetIsPartitioned(false));
+ EXPECT_FALSE(pc.IsPartitioned());
EXPECT_EQ(
"name=value; domain=domain.com; path=/foo; "
"expires=Sun, 18-Apr-2027 21:06:29 GMT; max-age=12345; secure; "
- "httponly; samesite=LAX; priority=medium",
+ "httponly; samesite=LAX; priority=medium; sameparty",
pc.ToCookieLine());
// Clear the rest and change the name and value.
@@ -462,8 +531,11 @@ TEST(ParsedCookieTest, SetAttributes) {
EXPECT_FALSE(pc.IsSecure());
EXPECT_FALSE(pc.IsHttpOnly());
EXPECT_EQ(CookieSameSite::UNSPECIFIED, pc.SameSite());
+ EXPECT_TRUE(pc.SetIsSameParty(false));
+ EXPECT_TRUE(pc.SetIsPartitioned(false));
EXPECT_EQ("name2=value2", pc.ToCookieLine());
EXPECT_FALSE(pc.IsSameParty());
+ EXPECT_FALSE(pc.IsPartitioned());
}
// Set the domain attribute twice in a cookie line. If the second attribute's
@@ -692,6 +764,31 @@ TEST(ParsedCookieTest, ToCookieLineSpecialTokens) {
EXPECT_TRUE(pc.IsSameParty());
EXPECT_TRUE(pc.IsHttpOnly());
}
+ {
+ ParsedCookie pc("partitioned=foo");
+ EXPECT_EQ("partitioned", pc.Name());
+ EXPECT_EQ("foo", pc.Value());
+ EXPECT_FALSE(pc.IsPartitioned());
+ }
+ {
+ ParsedCookie pc("partitioned=");
+ EXPECT_EQ("partitioned", pc.Name());
+ EXPECT_EQ("", pc.Value());
+ EXPECT_FALSE(pc.IsPartitioned());
+ }
+ {
+ ParsedCookie pc("=partitioned");
+ EXPECT_EQ("", pc.Name());
+ EXPECT_EQ("partitioned", pc.Value());
+ EXPECT_FALSE(pc.IsPartitioned());
+ }
+ {
+ ParsedCookie pc(
+ "partitioned; partitioned; secure; httponly; httponly; secure");
+ EXPECT_EQ("", pc.Name());
+ EXPECT_EQ("partitioned", pc.Value());
+ EXPECT_TRUE(pc.IsPartitioned());
+ }
}
TEST(ParsedCookieTest, SameSiteValues) {
diff --git a/chromium/net/cookies/same_party_context.cc b/chromium/net/cookies/same_party_context.cc
new file mode 100644
index 00000000000..70d0dd04a84
--- /dev/null
+++ b/chromium/net/cookies/same_party_context.cc
@@ -0,0 +1,33 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/cookies/same_party_context.h"
+
+#include "net/cookies/cookie_constants.h"
+
+namespace net {
+
+SamePartyContext::SamePartyContext(Type type)
+ : SamePartyContext(type, type, type) {}
+
+SamePartyContext::SamePartyContext(Type context_type,
+ Type ancestors_for_metrics,
+ Type top_resource_for_metrics)
+ : context_type_(context_type),
+ ancestors_for_metrics_only_(ancestors_for_metrics),
+ top_resource_for_metrics_only_(top_resource_for_metrics) {}
+
+bool SamePartyContext::operator==(const SamePartyContext& other) const {
+ return std::make_tuple(context_type(), ancestors_for_metrics_only(),
+ top_resource_for_metrics_only()) ==
+ std::make_tuple(other.context_type(),
+ other.ancestors_for_metrics_only(),
+ other.top_resource_for_metrics_only());
+}
+
+// static
+SamePartyContext SamePartyContext::MakeInclusive() {
+ return SamePartyContext(Type::kSameParty);
+}
+} // namespace net
diff --git a/chromium/net/cookies/same_party_context.h b/chromium/net/cookies/same_party_context.h
new file mode 100644
index 00000000000..819f6414ba8
--- /dev/null
+++ b/chromium/net/cookies/same_party_context.h
@@ -0,0 +1,63 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_COOKIES_SAME_PARTY_CONTEXT_H_
+#define NET_COOKIES_SAME_PARTY_CONTEXT_H_
+
+#include "net/base/net_export.h"
+
+namespace net {
+
+// This struct bundles together a few different notions of same-party-ness.
+// `context_type()` gives the notion of same-party-ness that Chromium should use
+// in all cases except metrics; other accessors are just for metrics purposes,
+// to explore the impact of different definitions of "same-party".
+class NET_EXPORT SamePartyContext {
+ public:
+ // Computed in URLRequestHttpJob for every cookie access attempt but is only
+ // relevant for SameParty cookies.
+ enum class Type {
+ // The opposite to kSameParty. Should be the default value.
+ kCrossParty = 0,
+ // If the request URL is in the same First-Party Sets as the top-frame site
+ // and each member of the isolation_info.party_context.
+ kSameParty = 1,
+ };
+
+ SamePartyContext() = default;
+ explicit SamePartyContext(Type type);
+ SamePartyContext(Type context_type,
+ Type ancestors_for_metrics,
+ Type top_resource_for_metrics);
+
+ bool operator==(const SamePartyContext& other) const;
+
+ // How trusted is the current browser environment when it comes to accessing
+ // SameParty cookies. Default is not trusted, e.g. kCrossParty.
+ Type context_type() const { return context_type_; }
+
+ // We store the type of the SameParty context if we inferred singleton sets,
+ // for the purpose of metrics.
+ Type ancestors_for_metrics_only() const {
+ return ancestors_for_metrics_only_;
+ }
+ // We also store the type of the SameParty context if it were computed using
+ // only the top frame and resource URL and inferred singleton sets, for the
+ // purpose of metrics.
+ Type top_resource_for_metrics_only() const {
+ return top_resource_for_metrics_only_;
+ }
+
+ // Creates a SamePartyContext that is as permissive as possible.
+ static SamePartyContext MakeInclusive();
+
+ private:
+ Type context_type_ = Type::kCrossParty;
+ Type ancestors_for_metrics_only_ = Type::kCrossParty;
+ Type top_resource_for_metrics_only_ = Type::kCrossParty;
+};
+
+} // namespace net
+
+#endif // NET_COOKIES_SAME_PARTY_CONTEXT_H_
diff --git a/chromium/net/cookies/test_cookie_access_delegate.cc b/chromium/net/cookies/test_cookie_access_delegate.cc
index eb8c5d66dba..cacdb8ccb41 100644
--- a/chromium/net/cookies/test_cookie_access_delegate.cc
+++ b/chromium/net/cookies/test_cookie_access_delegate.cc
@@ -7,6 +7,7 @@
#include "net/base/schemeful_site.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/same_party_context.h"
namespace net {
@@ -34,11 +35,11 @@ bool TestCookieAccessDelegate::ShouldIgnoreSameSiteRestrictions(
return true;
}
-bool TestCookieAccessDelegate::IsContextSamePartyWithSite(
+SamePartyContext TestCookieAccessDelegate::ComputeSamePartyContext(
const net::SchemefulSite& site,
- const absl::optional<net::SchemefulSite>& top_frame_site,
+ const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const {
- return false;
+ return SamePartyContext();
}
FirstPartySetsContextType
diff --git a/chromium/net/cookies/test_cookie_access_delegate.h b/chromium/net/cookies/test_cookie_access_delegate.h
index 674b389480a..8a0320ebd53 100644
--- a/chromium/net/cookies/test_cookie_access_delegate.h
+++ b/chromium/net/cookies/test_cookie_access_delegate.h
@@ -9,6 +9,7 @@
#include "net/cookies/cookie_access_delegate.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/same_party_context.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
@@ -29,9 +30,9 @@ class TestCookieAccessDelegate : public CookieAccessDelegate {
bool ShouldIgnoreSameSiteRestrictions(
const GURL& url,
const SiteForCookies& site_for_cookies) const override;
- bool IsContextSamePartyWithSite(
+ SamePartyContext ComputeSamePartyContext(
const net::SchemefulSite& site,
- const absl::optional<net::SchemefulSite>& top_frame_site,
+ const net::SchemefulSite* top_frame_site,
const std::set<net::SchemefulSite>& party_context) const override;
FirstPartySetsContextType ComputeFirstPartySetsContextType(
const net::SchemefulSite& site,
diff --git a/chromium/net/data/ssl/blocklist/06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem b/chromium/net/data/ssl/blocklist/06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem
new file mode 100644
index 00000000000..ffc0c306ba4
--- /dev/null
+++ b/chromium/net/data/ssl/blocklist/06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 58:77:d3:0c:6f:0f:3c:36:7f:8c:34:f2:86:fd:a5:28:43:bb:b9:f3
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Validity
+ Not Before: Feb 28 06:30:37 2020 GMT
+ Not After : Feb 28 06:30:37 2040 GMT
+ Subject: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:e4:7b:b0:35:11:f4:da:c7:02:ab:9f:ca:bb:51:
+ bf:c4:69:85:fb:de:c2:60:45:f3:c9:ba:cf:51:bc:
+ 8b:75:b3:7a:98:99:a8:28:4b:00:dd:2c:4a:80:04:
+ 61:22:37:06:28:2b:d0:9a:b9:1b:47:48:9a:47:fd:
+ 97:12:da:07:a4:d2:26:56:f9:8c:50:a1:d4:8d:86:
+ 43:26:88:be:6f:f3:bf:51:71:d2:0b:86:5c:a8:05:
+ cb:ad:31:52:a5:62:f0:2b:9b:7a:f4:27:59:9e:3c:
+ 98:7c:28:bf:ca:c1:89:77:41:e9:03:c4:3c:3d:b3:
+ 3c:23:0f:2c:e2:10:c3:ac:9d:a8:0e:e9:47:ee:48:
+ 08:a9:91:a6:0f:08:b9:22:47:6e:57:47:a8:c3:66:
+ 18:d9:7b:e7:f8:86:dc:61:85:59:5e:94:2a:7a:1c:
+ 37:39:84:a3:94:81:f5:2a:83:b7:be:81:b8:39:4e:
+ cb:ae:9f:63:66:d3:9a:89:94:36:c7:c5:b1:50:cc:
+ eb:7e:4e:31:2c:48:bd:f6:53:d3:f5:27:3f:4d:4f:
+ 17:c4:58:34:13:c0:f4:7b:a4:5c:c9:33:aa:ed:ec:
+ 0e:e0:60:e6:23:38:22:03:56:e6:c5:70:91:63:01:
+ 2a:2d:b6:5c:3d:38:41:e9:a8:e9:af:2c:f2:aa:ba:
+ 01:47:f8:85:ed:26:ae:35:db:8f:83:b2:cf:1d:29:
+ 34:61:10:6e:8e:ed:d2:da:8a:9e:72:68:c5:b1:79:
+ 9c:67:71:ef:30:fb:d7:b9:af:0d:3f:af:9d:be:a4:
+ ab:e9:66:38:ed:9a:c8:e5:cb:c3:8c:dd:a2:58:97:
+ b0:35:6d:e6:b7:b9:e4:b6:68:a5:85:2d:5d:52:a7:
+ 0b:00:b1:af:eb:38:53:88:8b:33:0a:d0:75:a6:06:
+ 84:fa:b7:3e:9d:dc:4c:0e:c9:0d:a0:45:41:ed:e3:
+ 78:fa:88:83:f3:7a:2c:a3:a4:17:d5:f8:3c:49:81:
+ 22:d3:9a:49:a6:0c:a6:de:f2:37:0a:df:dd:28:c5:
+ d9:c4:5a:ab:75:de:28:a6:a3:e5:57:26:c9:2a:0b:
+ d9:c5:79:85:12:14:f9:a5:1f:84:f1:e3:f6:8f:f3:
+ bd:df:e0:32:08:b6:9a:5e:42:8b:81:d1:ae:06:2e:
+ ea:39:aa:b4:cc:4a:57:0b:72:e9:aa:0c:b7:ec:e4:
+ c1:31:57:89:0f:59:e4:10:e7:cf:3b:0e:ba:81:8e:
+ 6b:91:41:96:97:ad:40:3a:57:d2:5b:44:49:9a:96:
+ 85:14:93:c9:e0:09:7a:47:5e:71:f8:39:ff:8d:6d:
+ a1:55:b6:c5:c2:bc:ec:03:70:51:ca:35:7a:c6:80:
+ 63:18:c1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ D8:77:D3:0C:6F:0F:3C:36:7F:8C:34:F2:86:FD:A5:28:43:BB:B9:F3
+ X509v3 Authority Key Identifier:
+ keyid:D8:77:D3:0C:6F:0F:3C:36:7F:8C:34:F2:86:FD:A5:28:43:BB:B9:F3
+ DirName:/CN=Information Security Certification Authority/O=ISCA/C=KZ
+ serial:58:77:D3:0C:6F:0F:3C:36:7F:8C:34:F2:86:FD:A5:28:43:BB:B9:F3
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 47:00:fe:22:9e:43:ec:8e:0b:9c:8c:63:ad:98:8f:1e:e5:bd:
+ fd:35:dd:d4:5b:5c:fe:25:cb:bd:73:14:3a:53:21:e2:0e:14:
+ ed:d2:4b:81:6a:ca:29:82:92:6b:a9:76:1e:32:bc:e5:57:7b:
+ f2:b4:7d:1d:d4:15:2b:5a:e8:77:a0:5c:1e:49:9a:62:f4:b6:
+ 15:19:dc:90:97:81:1e:1f:f5:0c:f9:05:9a:ab:24:a1:1a:53:
+ 17:88:43:39:54:e6:34:c6:61:70:fb:ee:eb:cb:fc:5d:55:37:
+ 54:14:3e:03:14:94:73:49:18:4f:29:3d:f4:ae:08:8c:37:7e:
+ ad:fb:d1:7c:0e:6d:81:cc:ed:61:cd:81:08:ea:58:1c:51:d2:
+ dd:f6:d0:81:76:a3:aa:ac:4e:16:4c:15:09:35:18:c5:02:78:
+ d6:43:55:b8:c3:4a:f1:60:eb:21:64:96:db:51:4a:58:82:ae:
+ 38:41:84:a2:ce:60:1c:82:a7:4b:2d:29:cb:7b:91:de:5f:7c:
+ ad:1a:30:81:81:0b:3f:85:eb:83:2b:bf:f8:f5:37:cd:87:f9:
+ 45:62:4c:79:ca:eb:39:a5:0d:23:7e:a3:95:0c:2f:de:68:f8:
+ bf:7d:93:e8:1a:62:f3:78:84:d9:e9:f4:28:fe:02:01:4f:f4:
+ eb:39:a4:1b:e3:c4:2b:29:de:e9:ef:03:01:23:f7:1e:6f:0d:
+ 6b:9b:82:72:9c:0a:02:c1:a8:ac:54:87:4d:6e:81:59:58:aa:
+ 01:66:c0:73:58:e4:5f:84:cb:48:8e:69:6f:51:eb:ef:b2:76:
+ 6f:65:d8:cb:cb:b6:77:8e:a5:5f:c0:2a:85:79:75:0e:47:83:
+ 4c:ba:05:e1:3c:19:16:fb:fe:e6:11:2f:06:88:ad:eb:10:a7:
+ f2:ab:5f:89:f1:5c:1b:4c:52:34:dc:fc:b1:58:80:6e:1d:03:
+ cc:34:29:c9:f8:20:00:41:49:69:c4:c7:b1:fe:7f:4b:d3:f4:
+ ea:b4:b4:39:e9:f6:a2:e2:ea:ef:eb:0e:02:d8:a7:53:7b:34:
+ bc:15:8f:8e:43:2b:62:5b:8c:45:c6:11:78:08:b1:d9:1d:7d:
+ cb:52:32:2c:fe:0e:7d:0b:3c:9f:09:5e:b3:40:54:d2:e5:8d:
+ 10:d1:33:75:1a:e5:d9:a9:e7:98:aa:5c:88:61:2c:d4:4f:f4:
+ 8f:3a:f8:1c:38:80:df:c9:01:c6:02:24:c4:54:5d:2e:3c:99:
+ e2:31:ec:c6:e5:fa:7e:c6:5a:5e:7f:7c:35:7b:32:1a:0e:be:
+ fb:aa:60:65:8b:7c:33:25:cc:bc:1d:44:de:f2:85:08:58:d5:
+ 49:81:82:4a:b3:88:82:03
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIUWHfTDG8PPDZ/jDTyhv2lKEO7ufMwDQYJKoZIhvcNAQEL
+BQAwUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24gU2VjdXJpdHkgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0ExCzAJBgNVBAYTAktaMB4XDTIwMDIy
+ODA2MzAzN1oXDTQwMDIyODA2MzAzN1owUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24g
+U2VjdXJpdHkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0Ex
+CzAJBgNVBAYTAktaMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5Huw
+NRH02scCq5/Ku1G/xGmF+97CYEXzybrPUbyLdbN6mJmoKEsA3SxKgARhIjcGKCvQ
+mrkbR0iaR/2XEtoHpNImVvmMUKHUjYZDJoi+b/O/UXHSC4ZcqAXLrTFSpWLwK5t6
+9CdZnjyYfCi/ysGJd0HpA8Q8PbM8Iw8s4hDDrJ2oDulH7kgIqZGmDwi5IkduV0eo
+w2YY2Xvn+IbcYYVZXpQqehw3OYSjlIH1KoO3voG4OU7Lrp9jZtOaiZQ2x8WxUMzr
+fk4xLEi99lPT9Sc/TU8XxFg0E8D0e6RcyTOq7ewO4GDmIzgiA1bmxXCRYwEqLbZc
+PThB6ajpryzyqroBR/iF7SauNduPg7LPHSk0YRBuju3S2oqecmjFsXmcZ3HvMPvX
+ua8NP6+dvqSr6WY47ZrI5cvDjN2iWJewNW3mt7nktmilhS1dUqcLALGv6zhTiIsz
+CtB1pgaE+rc+ndxMDskNoEVB7eN4+oiD83oso6QX1fg8SYEi05pJpgym3vI3Ct/d
+KMXZxFqrdd4opqPlVybJKgvZxXmFEhT5pR+E8eP2j/O93+AyCLaaXkKLgdGuBi7q
+Oaq0zEpXC3Lpqgy37OTBMVeJD1nkEOfPOw66gY5rkUGWl61AOlfSW0RJmpaFFJPJ
+4Al6R15x+Dn/jW2hVbbFwrzsA3BRyjV6xoBjGMECAwEAAaOB1jCB0zAPBgNVHRMB
+Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU2HfTDG8PPDZ/jDTy
+hv2lKEO7ufMwgZAGA1UdIwSBiDCBhYAU2HfTDG8PPDZ/jDTyhv2lKEO7ufOhV6RV
+MFMxNTAzBgNVBAMTLEluZm9ybWF0aW9uIFNlY3VyaXR5IENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5MQ0wCwYDVQQKEwRJU0NBMQswCQYDVQQGEwJLWoIUWHfTDG8PPDZ/
+jDTyhv2lKEO7ufMwDQYJKoZIhvcNAQELBQADggIBAEcA/iKeQ+yOC5yMY62Yjx7l
+vf013dRbXP4ly71zFDpTIeIOFO3SS4FqyimCkmupdh4yvOVXe/K0fR3UFSta6Heg
+XB5JmmL0thUZ3JCXgR4f9Qz5BZqrJKEaUxeIQzlU5jTGYXD77uvL/F1VN1QUPgMU
+lHNJGE8pPfSuCIw3fq370XwObYHM7WHNgQjqWBxR0t320IF2o6qsThZMFQk1GMUC
+eNZDVbjDSvFg6yFklttRSliCrjhBhKLOYByCp0stKct7kd5ffK0aMIGBCz+F64Mr
+v/j1N82H+UViTHnK6zmlDSN+o5UML95o+L99k+gaYvN4hNnp9Cj+AgFP9Os5pBvj
+xCsp3unvAwEj9x5vDWubgnKcCgLBqKxUh01ugVlYqgFmwHNY5F+Ey0iOaW9R6++y
+dm9l2MvLtneOpV/AKoV5dQ5Hg0y6BeE8GRb7/uYRLwaIresQp/KrX4nxXBtMUjTc
+/LFYgG4dA8w0Kcn4IABBSWnEx7H+f0vT9Oq0tDnp9qLi6u/rDgLYp1N7NLwVj45D
+K2JbjEXGEXgIsdkdfctSMiz+Dn0LPJ8JXrNAVNLljRDRM3Ua5dmp55iqXIhhLNRP
+9I86+Bw4gN/JAcYCJMRUXS48meIx7Mbl+n7GWl5/fDV7MhoOvvuqYGWLfDMlzLwd
+RN7yhQhY1UmBgkqziIID
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blocklist/0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem b/chromium/net/data/ssl/blocklist/0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem
new file mode 100644
index 00000000000..16e93f8655f
--- /dev/null
+++ b/chromium/net/data/ssl/blocklist/0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 25:44:98:fc:aa:dd:96:de:51:81:47:2e:d0:7b:16:3f:f7:9e:6a:d3
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Validity
+ Not Before: Feb 28 06:46:02 2020 GMT
+ Not After : Feb 28 06:46:02 2040 GMT
+ Subject: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b0:cc:d3:38:fa:7d:9d:ad:22:e9:6a:a3:13:b2:
+ fd:5d:fa:cd:86:8d:7e:db:ae:0f:3c:26:74:9d:b2:
+ 46:dd:b7:e5:ab:96:1e:af:72:52:80:36:c7:e9:22:
+ 16:d4:3c:a7:b6:9c:f9:26:b8:43:37:71:bd:65:59:
+ cf:76:89:e1:bf:8c:a0:87:15:a3:bd:03:f6:c9:f3:
+ e7:ca:d1:9e:ec:ae:9d:81:a5:34:c4:fc:e9:56:2a:
+ d3:01:a1:ea:38:be:ea:06:94:eb:24:c9:00:3e:e9:
+ 54:9c:5d:55:73:6b:2f:d1:f6:83:ed:76:81:6c:a8:
+ c2:93:76:c2:35:12:79:0b:1f:91:11:61:c7:fc:0d:
+ 66:a2:28:1d:81:d7:3d:7d:d8:ab:3a:92:62:42:bc:
+ e5:b4:02:c8:74:71:3d:93:a1:54:e2:6a:0a:32:30:
+ 05:a0:bf:52:d4:5b:85:d9:21:94:11:dc:ac:92:f9:
+ 7f:65:7f:fc:6e:09:ba:97:d9:ec:8e:bf:85:25:5c:
+ 3f:71:f0:d7:41:31:6e:f8:fb:8e:8f:41:c5:41:55:
+ 1d:de:f0:af:0a:0e:86:7a:eb:7f:97:5a:7d:60:64:
+ b7:15:f3:f9:57:5f:20:d0:4a:12:a8:87:6f:d1:eb:
+ e5:c9:50:e8:3f:7e:dd:eb:eb:24:7e:ea:f6:7e:af:
+ 8f:aa:91:1d:7c:af:20:1e:7b:e3:9a:72:09:bb:10:
+ 2c:b4:cb:a7:f2:c7:d2:3d:0b:d4:de:d0:d7:b0:6a:
+ d7:94:1c:f1:85:ea:2d:6e:4f:e0:bd:38:2b:1d:43:
+ 3b:b5:d2:e8:d5:9a:f2:ae:67:ac:d5:70:53:d3:df:
+ 4f:e8:80:64:f3:a9:02:d1:74:3c:8d:f4:1c:1b:88:
+ cc:dd:73:8c:2c:8d:33:6b:ce:3a:e3:4f:26:dd:3c:
+ 45:1a:e4:f0:ee:2c:04:c0:32:a0:5a:70:f5:24:17:
+ 92:08:87:e6:e2:ef:fd:2a:bc:c4:bd:b3:6b:81:23:
+ da:7e:82:84:9d:99:ee:35:87:3e:66:37:94:db:37:
+ 64:e2:63:c6:d6:f4:e4:d8:b2:11:e0:a1:81:77:94:
+ 60:38:8b:ba:92:40:b4:13:a0:79:a0:6a:65:e1:3b:
+ d2:09:a0:34:2d:42:e4:21:62:da:3b:25:90:60:99:
+ 81:85:f9:65:c7:67:ce:af:02:e7:10:d2:b9:46:a6:
+ bb:da:0f:88:ee:04:d7:4b:1d:6c:df:9c:f0:7c:de:
+ eb:a4:c1:e7:59:bd:04:de:3a:ab:7f:45:85:e5:80:
+ 98:fa:a2:95:04:20:f1:71:1c:d4:9d:c5:a5:fb:28:
+ 3f:b4:13:f6:d1:24:55:bf:89:fb:8d:88:97:cb:db:
+ 96:22:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 25:44:98:FC:AA:DD:96:DE:51:81:47:2E:D0:7B:16:3F:F7:9E:6A:D3
+ X509v3 Authority Key Identifier:
+ keyid:25:44:98:FC:AA:DD:96:DE:51:81:47:2E:D0:7B:16:3F:F7:9E:6A:D3
+ DirName:/CN=Information Security Certification Authority/O=ISCA/C=KZ
+ serial:25:44:98:FC:AA:DD:96:DE:51:81:47:2E:D0:7B:16:3F:F7:9E:6A:D3
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 95:30:a3:c5:1f:0c:b2:dd:73:d3:7e:9f:da:81:d9:8f:d2:a0:
+ bc:d2:15:66:dd:db:f1:62:fd:c8:15:52:8c:2f:3d:24:82:41:
+ 9b:e5:98:6b:89:12:63:f2:d2:2f:61:4a:42:f9:31:51:19:d2:
+ f5:10:ae:cf:bd:ba:a1:41:6e:b1:6f:92:16:5d:4b:8c:85:f5:
+ f2:c1:d7:13:10:04:a6:cb:26:b6:b6:f1:ae:2e:92:4b:a1:5f:
+ ef:43:8f:57:77:9f:47:25:b4:a6:c3:b2:d3:fe:f9:a8:a4:ea:
+ 9d:29:d4:37:68:2c:22:58:df:80:ef:7c:b4:d0:4f:58:94:45:
+ 6d:56:30:b6:65:7a:c1:77:3e:e6:f3:9e:d6:a3:d9:16:a3:4d:
+ 04:d3:4c:ff:11:66:ed:1d:e3:db:8f:7d:97:9c:71:dc:ce:e9:
+ 48:e0:a8:69:0c:31:e8:20:ee:2c:49:80:c1:9e:cd:88:7b:90:
+ 7b:b9:a8:f5:81:11:d2:59:10:42:64:2b:9c:02:7a:91:46:b5:
+ 2d:9a:1a:00:fb:62:d2:b2:fd:84:d9:30:d8:df:25:16:72:e6:
+ 98:a7:b5:b8:cb:9f:ae:90:e0:91:b6:76:86:87:5a:dc:f0:1f:
+ bb:4c:43:05:28:df:f3:03:ac:8e:ef:11:b3:ab:d7:1d:4a:ee:
+ ad:23:65:04:8f:63:df:5b:d4:87:97:94:85:22:1f:80:66:01:
+ ea:79:c8:27:7b:fd:20:36:da:e7:60:19:d0:27:09:3f:93:cd:
+ ee:d9:3f:52:c3:3e:ba:7c:02:54:c6:6e:57:82:6f:3b:0c:25:
+ c2:c4:da:fd:d2:29:07:c5:10:36:9d:22:ea:1b:d8:78:4a:49:
+ f9:d9:19:fb:ea:ad:6f:43:1a:0f:4f:30:cb:87:19:d7:ab:90:
+ fe:4c:b9:cc:f7:a5:2b:23:90:2a:a9:10:e2:91:db:f5:45:0c:
+ eb:7c:58:1d:3c:e0:9c:86:8f:c7:45:70:09:37:c8:f1:c1:80:
+ 5e:e4:91:a5:8f:bc:7e:11:98:b3:ea:60:65:4d:09:50:d0:8b:
+ 7c:52:e6:a7:a2:8c:c9:98:7e:91:d3:11:b3:85:1c:a6:bf:7a:
+ 3b:b1:b2:c1:55:08:87:2b:40:8d:51:21:7d:1e:3e:96:16:2d:
+ d2:c0:17:0e:b7:1c:8a:54:5c:82:49:cf:68:ac:7c:2c:64:bf:
+ 2a:10:5e:36:0d:f0:45:90:12:15:53:4a:b5:37:d3:a8:06:54:
+ 0e:f4:f0:dc:1d:b5:33:09:ed:f4:d8:09:67:11:36:1e:2d:0a:
+ c2:d6:0b:01:0e:06:af:c8:98:ed:11:68:2c:90:16:96:73:e8:
+ 87:be:4c:14:48:10:ba:5f
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIUJUSY/Krdlt5RgUcu0HsWP/eeatMwDQYJKoZIhvcNAQEL
+BQAwUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24gU2VjdXJpdHkgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0ExCzAJBgNVBAYTAktaMB4XDTIwMDIy
+ODA2NDYwMloXDTQwMDIyODA2NDYwMlowUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24g
+U2VjdXJpdHkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0Ex
+CzAJBgNVBAYTAktaMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAsMzT
+OPp9na0i6WqjE7L9XfrNho1+264PPCZ0nbJG3bflq5Yer3JSgDbH6SIW1Dyntpz5
+JrhDN3G9ZVnPdonhv4yghxWjvQP2yfPnytGe7K6dgaU0xPzpVirTAaHqOL7qBpTr
+JMkAPulUnF1Vc2sv0faD7XaBbKjCk3bCNRJ5Cx+REWHH/A1moigdgdc9fdirOpJi
+QrzltALIdHE9k6FU4moKMjAFoL9S1FuF2SGUEdyskvl/ZX/8bgm6l9nsjr+FJVw/
+cfDXQTFu+PuOj0HFQVUd3vCvCg6Geut/l1p9YGS3FfP5V18g0EoSqIdv0evlyVDo
+P37d6+skfur2fq+PqpEdfK8gHnvjmnIJuxAstMun8sfSPQvU3tDXsGrXlBzxheot
+bk/gvTgrHUM7tdLo1Zryrmes1XBT099P6IBk86kC0XQ8jfQcG4jM3XOMLI0za846
+408m3TxFGuTw7iwEwDKgWnD1JBeSCIfm4u/9KrzEvbNrgSPafoKEnZnuNYc+ZjeU
+2zdk4mPG1vTk2LIR4KGBd5RgOIu6kkC0E6B5oGpl4TvSCaA0LULkIWLaOyWQYJmB
+hfllx2fOrwLnENK5Rqa72g+I7gTXSx1s35zwfN7rpMHnWb0E3jqrf0WF5YCY+qKV
+BCDxcRzUncWl+yg/tBP20SRVv4n7jYiXy9uWIrUCAwEAAaOB1jCB0zAPBgNVHRMB
+Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUJUSY/Krdlt5RgUcu
+0HsWP/eeatMwgZAGA1UdIwSBiDCBhYAUJUSY/Krdlt5RgUcu0HsWP/eeatOhV6RV
+MFMxNTAzBgNVBAMTLEluZm9ybWF0aW9uIFNlY3VyaXR5IENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5MQ0wCwYDVQQKEwRJU0NBMQswCQYDVQQGEwJLWoIUJUSY/Krdlt5R
+gUcu0HsWP/eeatMwDQYJKoZIhvcNAQELBQADggIBAJUwo8UfDLLdc9N+n9qB2Y/S
+oLzSFWbd2/Fi/cgVUowvPSSCQZvlmGuJEmPy0i9hSkL5MVEZ0vUQrs+9uqFBbrFv
+khZdS4yF9fLB1xMQBKbLJra28a4ukkuhX+9Dj1d3n0cltKbDstP++aik6p0p1Ddo
+LCJY34DvfLTQT1iURW1WMLZlesF3Pubzntaj2RajTQTTTP8RZu0d49uPfZeccdzO
+6UjgqGkMMegg7ixJgMGezYh7kHu5qPWBEdJZEEJkK5wCepFGtS2aGgD7YtKy/YTZ
+MNjfJRZy5pintbjLn66Q4JG2doaHWtzwH7tMQwUo3/MDrI7vEbOr1x1K7q0jZQSP
+Y99b1IeXlIUiH4BmAep5yCd7/SA22udgGdAnCT+Tze7ZP1LDPrp8AlTGbleCbzsM
+JcLE2v3SKQfFEDadIuob2HhKSfnZGfvqrW9DGg9PMMuHGderkP5Mucz3pSsjkCqp
+EOKR2/VFDOt8WB084JyGj8dFcAk3yPHBgF7kkaWPvH4RmLPqYGVNCVDQi3xS5qei
+jMmYfpHTEbOFHKa/ejuxssFVCIcrQI1RIX0ePpYWLdLAFw63HIpUXIJJz2isfCxk
+vyoQXjYN8EWQEhVTSrU306gGVA708NwdtTMJ7fTYCWcRNh4tCsLWCwEOBq/ImO0R
+aCyQFpZz6Ie+TBRIELpf
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/blocklist/README.md b/chromium/net/data/ssl/blocklist/README.md
index 405688b1daf..612be983a54 100644
--- a/chromium/net/data/ssl/blocklist/README.md
+++ b/chromium/net/data/ssl/blocklist/README.md
@@ -307,6 +307,9 @@ For details, see <https://security.googleblog.com/2019/08/protecting-chrome-user
* [61c0fc2e38b5b6f9071b42cee54a9013d858b6697c68b460948551b3249576a1.pem](61c0fc2e38b5b6f9071b42cee54a9013d858b6697c68b460948551b3249576a1.pem)
* [1df696f021ab1c3ace9a376b07ed7256a40214cd3396d7934087614924e2d7ef.pem](1df696f021ab1c3ace9a376b07ed7256a40214cd3396d7934087614924e2d7ef.pem)
* [0230a604d99220e5612ee7862ab9f7a6e18e4f1ac4c9e27075788cc5220169ab.pem](0230a604d99220e5612ee7862ab9f7a6e18e4f1ac4c9e27075788cc5220169ab.pem)
+ * [06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem](06fd20629c143b9eab28d2799caefc5d23fde267d16c631e3f5b8b4bab3f68e6.pem)
+ * [0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem](0bd39de4793cdc117138f47708aa4d583acf67adb059a0d91f668d1803bf6489.pem)
+ * [c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem](c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem)
### revoked.badssl.com
diff --git a/chromium/net/data/ssl/blocklist/c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem b/chromium/net/data/ssl/blocklist/c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem
new file mode 100644
index 00000000000..e79e72ff9a8
--- /dev/null
+++ b/chromium/net/data/ssl/blocklist/c95c133b68319ee516b5f41e377f589878af1556567cc2834ef03b1d10830fd3.pem
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 10:89:fc:3f:19:c9:03:f3:83:9b:cf:70:b9:7d:c7:cf:aa:d3:d4:dd
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Validity
+ Not Before: Feb 28 06:48:23 2020 GMT
+ Not After : Feb 28 06:48:23 2040 GMT
+ Subject: CN = Information Security Certification Authority, O = ISCA, C = KZ
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:d2:91:1b:e3:25:24:6a:31:8b:64:d7:29:52:e7:
+ fd:07:42:8a:da:c1:51:5b:69:9e:40:34:96:0a:96:
+ 8d:80:77:7e:6a:ae:48:e7:51:03:8a:22:c3:13:a9:
+ 98:cf:47:de:45:d0:61:b7:41:90:b8:d2:45:27:09:
+ 4a:5f:71:9c:e8:ab:2a:b2:74:85:27:6a:e9:c3:eb:
+ 5c:a3:b3:3c:0a:0f:55:aa:de:30:a4:72:65:de:a7:
+ 44:1b:04:5a:19:41:a4:6c:8d:4b:8b:81:88:99:73:
+ 4e:48:a6:2b:c4:13:62:c6:07:74:b8:6a:9e:09:29:
+ a7:bf:87:f5:e6:97:7f:74:5b:40:f1:75:33:2f:39:
+ 7b:bf:81:c5:9d:2f:bb:99:f4:a0:4f:9f:87:c2:3e:
+ b4:73:8f:01:e8:05:5a:86:0f:fa:f1:40:17:c0:eb:
+ d5:32:8d:9f:05:52:52:8b:6c:d6:62:b1:9a:67:a5:
+ fc:a9:24:a0:08:ee:cb:c7:12:c8:57:09:72:8c:57:
+ 25:31:32:81:4c:35:d6:3d:0f:18:e6:d8:d9:6f:c7:
+ d6:42:41:78:54:16:f1:69:af:7f:d1:d2:8d:2c:62:
+ 36:7c:0d:08:d5:30:ce:20:43:86:cf:3d:c7:44:99:
+ 7f:0e:c8:81:71:d3:0c:03:b6:9a:f6:fc:2b:34:7c:
+ f4:7f:a5:88:97:1a:3e:32:a6:f2:de:20:6a:20:ff:
+ ef:e4:db:b7:0a:3e:2f:29:b9:b0:b1:cf:c5:6c:4c:
+ e1:59:5c:d7:6b:05:75:89:9a:37:d4:01:86:1b:5c:
+ 37:97:4f:34:48:a6:1f:78:d9:29:4f:0c:c5:d0:81:
+ d2:23:4a:5f:dd:f4:0a:2a:de:57:b6:14:89:f2:e8:
+ 45:db:4d:e5:5b:c3:8c:1c:5d:5b:ef:24:7f:5d:3b:
+ 05:90:1d:79:49:dc:8a:ac:c5:a1:cd:ce:ac:55:8a:
+ 15:1d:85:f4:bf:a7:15:d4:59:53:7a:35:85:35:df:
+ 0c:5b:67:17:54:d3:94:c6:df:f3:86:b3:91:22:09:
+ 2c:c0:e2:cd:dd:11:48:c2:5a:1b:5d:bb:5d:ba:c2:
+ 84:af:c8:3c:55:33:ab:a9:19:c2:ad:f1:9c:75:c4:
+ 2d:88:db:91:72:23:3a:1b:4e:af:01:76:a2:9b:93:
+ 56:cd:50:cd:5d:df:5f:67:54:7c:ae:9b:0c:b0:ef:
+ 14:71:17:35:a4:f1:3d:5a:84:22:7f:ce:89:72:80:
+ 84:51:eb:b3:49:b5:e9:15:08:b4:1c:36:50:6f:40:
+ 59:ee:ad:9f:25:bb:ee:59:f2:6d:9a:03:b2:11:4f:
+ f7:57:de:59:79:ac:37:e9:4c:93:38:de:86:b2:36:
+ e6:d8:e9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 90:89:FC:3F:19:C9:03:F3:83:9B:CF:70:B9:7D:C7:CF:AA:D3:D4:DD
+ X509v3 Authority Key Identifier:
+ keyid:90:89:FC:3F:19:C9:03:F3:83:9B:CF:70:B9:7D:C7:CF:AA:D3:D4:DD
+ DirName:/CN=Information Security Certification Authority/O=ISCA/C=KZ
+ serial:10:89:FC:3F:19:C9:03:F3:83:9B:CF:70:B9:7D:C7:CF:AA:D3:D4:DD
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 5e:88:9d:cc:e9:04:bc:4b:6c:03:6a:73:3b:48:a8:d4:bf:54:
+ 1e:68:43:dc:2e:cd:fe:07:51:9a:bb:bd:fb:ba:59:ce:c3:fd:
+ f9:dd:39:9f:52:59:e4:fa:2f:af:5b:4c:a1:4a:b8:c4:08:68:
+ f3:68:3c:44:eb:c4:18:90:05:5f:b5:37:5f:c3:8a:cd:6c:12:
+ 59:13:27:ca:3d:bf:ec:3c:18:92:2b:f6:32:34:6b:4f:7a:76:
+ c2:37:27:f4:4a:33:21:74:07:de:72:67:6e:52:e1:71:89:ab:
+ 74:15:94:b3:28:05:9d:8a:c2:0f:0f:c8:e6:3d:f5:68:e5:36:
+ 64:ca:c2:0d:e7:25:a9:b7:9e:cc:89:54:3b:7d:23:1c:d6:8e:
+ 79:b6:19:25:cb:65:a6:fc:fd:48:0d:dd:c0:f8:2e:ce:b8:c7:
+ 41:68:fe:4f:a5:31:4a:61:73:34:37:5d:71:46:8a:3d:be:15:
+ 18:cd:9b:29:10:80:30:35:a1:0a:df:35:ff:b4:ae:7f:5f:19:
+ 3f:93:f6:31:76:7b:e3:e7:5c:ee:7c:3f:ed:9b:37:d3:eb:94:
+ 59:ac:25:9b:2e:f3:e0:f5:45:5f:72:d9:67:bf:f8:a4:5b:b0:
+ a8:7c:17:dc:f2:b0:58:24:28:6d:47:cc:f9:8c:56:89:95:bc:
+ b7:5a:e3:15:e6:84:d6:28:9e:69:3f:e9:ee:6c:b2:9b:45:8f:
+ 3c:2a:33:8d:5e:9e:44:3a:c2:ea:6b:29:d2:b4:92:e3:0d:3c:
+ 68:c1:7c:1e:15:12:80:f5:85:fa:46:3d:e5:ed:43:4c:1e:85:
+ 39:78:01:a3:0f:ea:bd:de:7d:61:cb:7c:65:02:6e:72:d8:ba:
+ f6:b1:c9:49:4a:65:54:99:d3:76:01:bf:a9:bd:40:ac:7e:13:
+ b4:7d:97:a3:30:63:d3:7b:ab:7d:35:c3:52:a7:c2:9d:af:73:
+ f6:9c:4d:cf:ea:ee:66:28:45:a6:b5:59:c6:cf:fb:06:25:50:
+ d7:b2:fb:6d:1a:6c:5e:68:43:b4:ad:a8:38:05:00:c0:73:4d:
+ c5:9b:da:7b:a5:cf:17:f6:3c:81:13:83:ad:c3:7b:24:71:1a:
+ a9:88:fc:6c:5f:10:52:64:75:ed:c1:05:09:76:f8:b9:ac:32:
+ bc:61:37:df:2c:67:1b:8e:f3:d7:ae:af:19:7b:47:03:e1:c6:
+ 5e:c5:a7:e0:41:bf:e3:9f:5e:14:41:13:71:3f:1e:60:db:07:
+ bf:b7:a9:04:d7:57:32:a4:0e:ad:80:37:a9:e4:43:8d:89:5a:
+ bc:0d:ee:47:b0:38:72:c5:b5:fb:2f:b2:bc:f9:76:67:51:06:
+ f6:25:bb:03:7b:6d:74:02
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIUEIn8PxnJA/ODm89wuX3Hz6rT1N0wDQYJKoZIhvcNAQEL
+BQAwUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24gU2VjdXJpdHkgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0ExCzAJBgNVBAYTAktaMB4XDTIwMDIy
+ODA2NDgyM1oXDTQwMDIyODA2NDgyM1owUzE1MDMGA1UEAxMsSW5mb3JtYXRpb24g
+U2VjdXJpdHkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxDTALBgNVBAoTBElTQ0Ex
+CzAJBgNVBAYTAktaMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0pEb
+4yUkajGLZNcpUuf9B0KK2sFRW2meQDSWCpaNgHd+aq5I51EDiiLDE6mYz0feRdBh
+t0GQuNJFJwlKX3Gc6KsqsnSFJ2rpw+tco7M8Cg9Vqt4wpHJl3qdEGwRaGUGkbI1L
+i4GImXNOSKYrxBNixgd0uGqeCSmnv4f15pd/dFtA8XUzLzl7v4HFnS+7mfSgT5+H
+wj60c48B6AVahg/68UAXwOvVMo2fBVJSi2zWYrGaZ6X8qSSgCO7LxxLIVwlyjFcl
+MTKBTDXWPQ8Y5tjZb8fWQkF4VBbxaa9/0dKNLGI2fA0I1TDOIEOGzz3HRJl/DsiB
+cdMMA7aa9vwrNHz0f6WIlxo+Mqby3iBqIP/v5Nu3Cj4vKbmwsc/FbEzhWVzXawV1
+iZo31AGGG1w3l080SKYfeNkpTwzF0IHSI0pf3fQKKt5XthSJ8uhF203lW8OMHF1b
+7yR/XTsFkB15SdyKrMWhzc6sVYoVHYX0v6cV1FlTejWFNd8MW2cXVNOUxt/zhrOR
+IgkswOLN3RFIwlobXbtdusKEr8g8VTOrqRnCrfGcdcQtiNuRciM6G06vAXaim5NW
+zVDNXd9fZ1R8rpsMsO8UcRc1pPE9WoQif86JcoCEUeuzSbXpFQi0HDZQb0BZ7q2f
+JbvuWfJtmgOyEU/3V95Zeaw36UyTON6Gsjbm2OkCAwEAAaOB1jCB0zAPBgNVHRMB
+Af8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUkIn8PxnJA/ODm89w
+uX3Hz6rT1N0wgZAGA1UdIwSBiDCBhYAUkIn8PxnJA/ODm89wuX3Hz6rT1N2hV6RV
+MFMxNTAzBgNVBAMTLEluZm9ybWF0aW9uIFNlY3VyaXR5IENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5MQ0wCwYDVQQKEwRJU0NBMQswCQYDVQQGEwJLWoIUEIn8PxnJA/OD
+m89wuX3Hz6rT1N0wDQYJKoZIhvcNAQELBQADggIBAF6InczpBLxLbANqcztIqNS/
+VB5oQ9wuzf4HUZq7vfu6Wc7D/fndOZ9SWeT6L69bTKFKuMQIaPNoPETrxBiQBV+1
+N1/Dis1sElkTJ8o9v+w8GJIr9jI0a096dsI3J/RKMyF0B95yZ25S4XGJq3QVlLMo
+BZ2Kwg8PyOY99WjlNmTKwg3nJam3nsyJVDt9IxzWjnm2GSXLZab8/UgN3cD4Ls64
+x0Fo/k+lMUphczQ3XXFGij2+FRjNmykQgDA1oQrfNf+0rn9fGT+T9jF2e+PnXO58
+P+2bN9PrlFmsJZsu8+D1RV9y2We/+KRbsKh8F9zysFgkKG1HzPmMVomVvLda4xXm
+hNYonmk/6e5ssptFjzwqM41enkQ6wuprKdK0kuMNPGjBfB4VEoD1hfpGPeXtQ0we
+hTl4AaMP6r3efWHLfGUCbnLYuvaxyUlKZVSZ03YBv6m9QKx+E7R9l6MwY9N7q301
+w1Knwp2vc/acTc/q7mYoRaa1WcbP+wYlUNey+20abF5oQ7StqDgFAMBzTcWb2nul
+zxf2PIETg63DeyRxGqmI/GxfEFJkde3BBQl2+LmsMrxhN98sZxuO89eurxl7RwPh
+xl7Fp+BBv+OfXhRBE3E/HmDbB7+3qQTXVzKkDq2AN6nkQ42JWrwN7kewOHLFtfsv
+srz5dmdRBvYluwN7bXQC
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/BUILD.gn b/chromium/net/data/ssl/chrome_root_store/BUILD.gn
new file mode 100644
index 00000000000..185d53ec055
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/BUILD.gn
@@ -0,0 +1,161 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+import("//build/compiled_action.gni")
+
+# Generate C++ include file for the Chrome root store.
+compiled_action("gen_root_store_inc") {
+ tool = "//net/tools/root_store_tool:root_store_tool"
+
+ # It'd be really nice to list an input as "store/certs/*", but it doesn't seem
+ # to work. So we list them all out.
+ inputs = [
+ "store/root_store.textproto",
+ "store/certs/02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem",
+ "store/certs/0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem",
+ "store/certs/04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem",
+ "store/certs/0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem",
+ "store/certs/0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem",
+ "store/certs/0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem",
+ "store/certs/0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem",
+ "store/certs/125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem",
+ "store/certs/1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem",
+ "store/certs/15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem",
+ "store/certs/15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem",
+ "store/certs/16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem",
+ "store/certs/1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem",
+ "store/certs/179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem",
+ "store/certs/18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem",
+ "store/certs/18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem",
+ "store/certs/1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem",
+ "store/certs/22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem",
+ "store/certs/2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem",
+ "store/certs/2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem",
+ "store/certs/2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem",
+ "store/certs/2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem",
+ "store/certs/2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem",
+ "store/certs/30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem",
+ "store/certs/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem",
+ "store/certs/3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem",
+ "store/certs/358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem",
+ "store/certs/3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem",
+ "store/certs/3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem",
+ "store/certs/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem",
+ "store/certs/40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem",
+ "store/certs/4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem",
+ "store/certs/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem",
+ "store/certs/43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem",
+ "store/certs/44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem",
+ "store/certs/45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem",
+ "store/certs/46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem",
+ "store/certs/49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem",
+ "store/certs/4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem",
+ "store/certs/4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem",
+ "store/certs/513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem",
+ "store/certs/52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem",
+ "store/certs/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem",
+ "store/certs/55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem",
+ "store/certs/55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem",
+ "store/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem",
+ "store/certs/59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem",
+ "store/certs/5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem",
+ "store/certs/5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem",
+ "store/certs/5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem",
+ "store/certs/5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem",
+ "store/certs/5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem",
+ "store/certs/62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem",
+ "store/certs/657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem",
+ "store/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem",
+ "store/certs/6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem",
+ "store/certs/6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem",
+ "store/certs/70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem",
+ "store/certs/71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem",
+ "store/certs/73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem",
+ "store/certs/7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem",
+ "store/certs/7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem",
+ "store/certs/7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem",
+ "store/certs/7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem",
+ "store/certs/8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem",
+ "store/certs/85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem",
+ "store/certs/85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem",
+ "store/certs/86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem",
+ "store/certs/88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem",
+ "store/certs/8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem",
+ "store/certs/8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem",
+ "store/certs/8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem",
+ "store/certs/91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem",
+ "store/certs/945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem",
+ "store/certs/960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem",
+ "store/certs/96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem",
+ "store/certs/97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem",
+ "store/certs/9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem",
+ "store/certs/9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem",
+ "store/certs/9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem",
+ "store/certs/a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem",
+ "store/certs/a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem",
+ "store/certs/a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem",
+ "store/certs/b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem",
+ "store/certs/b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem",
+ "store/certs/bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem",
+ "store/certs/bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem",
+ "store/certs/bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem",
+ "store/certs/be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem",
+ "store/certs/beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem",
+ "store/certs/bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem",
+ "store/certs/bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem",
+ "store/certs/bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem",
+ "store/certs/bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem",
+ "store/certs/c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem",
+ "store/certs/c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem",
+ "store/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem",
+ "store/certs/c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem",
+ "store/certs/ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem",
+ "store/certs/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem",
+ "store/certs/cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem",
+ "store/certs/cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem",
+ "store/certs/d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem",
+ "store/certs/d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem",
+ "store/certs/d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem",
+ "store/certs/d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem",
+ "store/certs/db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem",
+ "store/certs/dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem",
+ "store/certs/e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem",
+ "store/certs/e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem",
+ "store/certs/e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem",
+ "store/certs/e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem",
+ "store/certs/e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem",
+ "store/certs/eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem",
+ "store/certs/ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem",
+ "store/certs/ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem",
+ "store/certs/edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem",
+ "store/certs/eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem",
+ "store/certs/f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem",
+ "store/certs/f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem",
+ "store/certs/f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem",
+ "store/certs/fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem",
+ ]
+ outputs = [ "${target_gen_dir}/chrome-root-store-inc.cc" ]
+ args = [ "--write-cpp=" +
+ rebase_path("${target_gen_dir}/chrome-root-store-inc.cc",
+ root_build_dir) ]
+}
+
+compiled_action("gen_root_store_test_inc") {
+ tool = "//net/tools/root_store_tool:root_store_tool"
+
+ # It'd be really nice to list an input as "testdata/certs/*", but it doesn't
+ # seem to work. So we list them all out.
+ inputs = [
+ "testdata/root_store.textproto",
+ "testdata/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem",
+ "testdata/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem",
+ "testdata/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem",
+ ]
+ outputs = [ "${target_gen_dir}/chrome-root-store-test-data-inc.cc" ]
+ args = [
+ "--root-store-dir=net/data/ssl/chrome_root_store/testdata",
+ "--write-cpp=" +
+ rebase_path("${target_gen_dir}/chrome-root-store-test-data-inc.cc",
+ root_build_dir),
+ ]
+}
diff --git a/chromium/net/data/ssl/chrome_root_store/README.md b/chromium/net/data/ssl/chrome_root_store/README.md
new file mode 100644
index 00000000000..040f80e6a6d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/README.md
@@ -0,0 +1,14 @@
+# Chrome Root Store
+
+This directory contains the in development definition of the
+[Chrome Root Store](https://www.chromium.org/Home/chromium-security/root-ca-policy).
+It is currently not used for trust decisions in Chrome.
+
+The root store is defined by `store/root_store.textproto` file, which is a
+`RootStore` [protobuf](https://developers.google.com/protocol-buffers) message,
+defined in
+[`//net/tools/root_store_tool/root_store.proto`](/net/tools/root_store_tool/root_store.proto).
+It references certificates in the `store/certs` directory. The
+[`root_store_tool`](/net/tools/root_store_tool/root_store_tool.cc) will
+files in this directory to eventually use this data for trust decisions in
+Chrome.
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem
new file mode 100644
index 00000000000..a14028f7b04
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem
@@ -0,0 +1,56 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ a6:8b:79:29:00:00:00:00:50:d0:91:f9
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2012 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - EC1
+ Validity
+ Not Before: Dec 18 15:25:36 2012 GMT
+ Not After : Dec 18 15:55:36 2037 GMT
+ Subject: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2012 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - EC1
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:84:13:c9:d0:ba:6d:41:7b:e2:6c:d0:eb:55:5f:
+ 66:02:1a:24:f4:5b:89:69:47:e3:b8:c2:7d:f1:f2:
+ 02:c5:9f:a0:f6:5b:d5:8b:06:19:86:4f:53:10:6d:
+ 07:24:27:a1:a0:f8:d5:47:19:61:4c:7d:ca:93:27:
+ ea:74:0c:ef:6f:96:09:fe:63:ec:70:5d:36:ad:67:
+ 77:ae:c9:9d:7c:55:44:3a:a2:63:51:1f:f5:e3:62:
+ d4:a9:47:07:3e:cc:20
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ B7:63:E7:1A:DD:8D:E9:08:A6:55:83:A4:E0:6A:50:41:65:11:42:49
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:61:79:d8:e5:42:47:df:1c:ae:53:99:17:b6:6f:
+ 1c:7d:e1:bf:11:94:d1:03:88:75:e4:8d:89:a4:8a:77:46:de:
+ 6d:61:ef:02:f5:fb:b5:df:cc:fe:4e:ff:fe:a9:e6:a7:02:30:
+ 5b:99:d7:85:37:06:b5:7b:08:fd:eb:27:8b:4a:94:f9:e1:fa:
+ a7:8e:26:08:e8:7c:92:68:6d:73:d8:6f:26:ac:21:02:b8:99:
+ b7:26:41:5b:25:60:ae:d0:48:1a:ee:06
+-----BEGIN CERTIFICATE-----
+MIIC+TCCAoCgAwIBAgINAKaLeSkAAAAAUNCR+TAKBggqhkjOPQQDAzCBvzELMAkG
+A1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3
+d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEyIEVu
+dHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UEAxMq
+RW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4XDTEy
+MTIxODE1MjUzNloXDTM3MTIxODE1NTUzNlowgb8xCzAJBgNVBAYTAlVTMRYwFAYD
+VQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3QubmV0
+L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxMiBFbnRydXN0LCBJbmMuIC0g
+Zm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMzAxBgNVBAMTKkVudHJ1c3QgUm9vdCBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEVDMTB2MBAGByqGSM49AgEGBSuBBAAi
+A2IABIQTydC6bUF74mzQ61VfZgIaJPRbiWlH47jCffHyAsWfoPZb1YsGGYZPUxBt
+ByQnoaD41UcZYUx9ypMn6nQM72+WCf5j7HBdNq1nd67JnXxVRDqiY1Ef9eNi1KlH
+Bz7MIKNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
+BBYEFLdj5xrdjekIplWDpOBqUEFlEUJJMAoGCCqGSM49BAMDA2cAMGQCMGF52OVC
+R98crlOZF7ZvHH3hvxGU0QOIdeSNiaSKd0bebWHvAvX7td/M/k7//qnmpwIwW5nX
+hTcGtXsI/esni0qU+eH6p44mCOh8kmhtc9hvJqwhAriZtyZBWyVgrtBIGu4G
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem
new file mode 100644
index 00000000000..5357ec3c120
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem
@@ -0,0 +1,76 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8608355977964138876 (0x7777062726a9b17c)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = AffirmTrust, CN = AffirmTrust Commercial
+ Validity
+ Not Before: Jan 29 14:06:06 2010 GMT
+ Not After : Dec 31 14:06:06 2030 GMT
+ Subject: C = US, O = AffirmTrust, CN = AffirmTrust Commercial
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:f6:1b:4f:67:07:2b:a1:15:f5:06:22:cb:1f:01:
+ b2:e3:73:45:06:44:49:2c:bb:49:25:14:d6:ce:c3:
+ b7:ab:2c:4f:c6:41:32:94:57:fa:12:a7:5b:0e:e2:
+ 8f:1f:1e:86:19:a7:aa:b5:2d:b9:5f:0d:8a:c2:af:
+ 85:35:79:32:2d:bb:1c:62:37:f2:b1:5b:4a:3d:ca:
+ cd:71:5f:e9:42:be:94:e8:c8:de:f9:22:48:64:c6:
+ e5:ab:c6:2b:6d:ad:05:f0:fa:d5:0b:cf:9a:e5:f0:
+ 50:a4:8b:3b:47:a5:23:5b:7a:7a:f8:33:3f:b8:ef:
+ 99:97:e3:20:c1:d6:28:89:cf:94:fb:b9:45:ed:e3:
+ 40:17:11:d4:74:f0:0b:31:e2:2b:26:6a:9b:4c:57:
+ ae:ac:20:3e:ba:45:7a:05:f3:bd:9b:69:15:ae:7d:
+ 4e:20:63:c4:35:76:3a:07:02:c9:37:fd:c7:47:ee:
+ e8:f1:76:1d:73:15:f2:97:a4:b5:c8:7a:79:d9:42:
+ aa:2b:7f:5c:fe:ce:26:4f:a3:66:81:35:af:44:ba:
+ 54:1e:1c:30:32:65:9d:e6:3c:93:5e:50:4e:7a:e3:
+ 3a:d4:6e:cc:1a:fb:f9:d2:37:ae:24:2a:ab:57:03:
+ 22:28:0d:49:75:7f:b7:28:da:75:bf:8e:e3:dc:0e:
+ 79:31
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 9D:93:C6:53:8B:5E:CA:AF:3F:9F:1E:0F:E5:99:95:BC:24:F6:94:8F
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 58:ac:f4:04:0e:cd:c0:0d:ff:0a:fd:d4:ba:16:5f:29:bd:7b:
+ 68:99:58:49:d2:b4:1d:37:4d:7f:27:7d:46:06:5d:43:c6:86:
+ 2e:3e:73:b2:26:7d:4f:93:a9:b6:c4:2a:9a:ab:21:97:14:b1:
+ de:8c:d3:ab:89:15:d8:6b:24:d4:f1:16:ae:d8:a4:5c:d4:7f:
+ 51:8e:ed:18:01:b1:93:63:bd:bc:f8:61:80:9a:9e:b1:ce:42:
+ 70:e2:a9:7d:06:25:7d:27:a1:fe:6f:ec:b3:1e:24:da:e3:4b:
+ 55:1a:00:3b:35:b4:3b:d9:d7:5d:30:fd:81:13:89:f2:c2:06:
+ 2b:ed:67:c4:8e:c9:43:b2:5c:6b:15:89:02:bc:62:fc:4e:f2:
+ b5:33:aa:b2:6f:d3:0a:a2:50:e3:f6:3b:e8:2e:44:c2:db:66:
+ 38:a9:33:56:48:f1:6d:1b:33:8d:0d:8c:3f:60:37:9d:d3:ca:
+ 6d:7e:34:7e:0d:9f:72:76:8b:1b:9f:72:fd:52:35:41:45:02:
+ 96:2f:1c:b2:9a:73:49:21:b1:49:47:45:47:b4:ef:6a:34:11:
+ c9:4d:9a:cc:59:b7:d6:02:9e:5a:4e:65:b5:94:ae:1b:df:29:
+ b0:16:f1:bf:00:9e:07:3a:17:64:b5:04:b5:23:21:99:0a:95:
+ 3b:97:7c:ef
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBDb21tZXJjaWFsMB4XDTEwMDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6EqdbDuKP
+Hx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yr
+ba0F8PrVC8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPAL
+MeIrJmqbTFeurCA+ukV6BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1
+yHp52UKqK39c/s4mT6NmgTWvRLpUHhwwMmWd5jyTXlBOeuM61G7MGvv50jeuJCqr
+VwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNVHQ4EFgQUnZPGU4teyq8/
+nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYG
+XUPGhi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNj
+vbz4YYCanrHOQnDiqX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivt
+Z8SOyUOyXGsViQK8YvxO8rUzqrJv0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9g
+N53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0khsUlHRUe072o0EclNmsxZt9YC
+nlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem
new file mode 100644
index 00000000000..ab15d954166
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6047274297262753887 (0x53ec3beefbb2485f)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = ES, CN = Autoridad de Certificacion Firmaprofesional CIF A62634068
+ Validity
+ Not Before: May 20 08:38:15 2009 GMT
+ Not After : Dec 31 08:38:15 2030 GMT
+ Subject: C = ES, CN = Autoridad de Certificacion Firmaprofesional CIF A62634068
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ca:96:6b:8e:ea:f8:fb:f1:a2:35:e0:7f:4c:da:
+ e0:c3:52:d7:7d:b6:10:c8:02:5e:b3:43:2a:c4:4f:
+ 6a:b2:ca:1c:5d:28:9a:78:11:1a:69:59:57:af:b5:
+ 20:42:e4:8b:0f:e6:df:5b:a6:03:92:2f:f5:11:e4:
+ 62:d7:32:71:38:d9:04:0c:71:ab:3d:51:7e:0f:07:
+ df:63:05:5c:e9:bf:94:6f:c1:29:82:c0:b4:da:51:
+ b0:c1:3c:bb:ad:37:4a:5c:ca:f1:4b:36:0e:24:ab:
+ bf:c3:84:77:fd:a8:50:f4:b1:e7:c6:2f:d2:2d:59:
+ 8d:7a:0a:4e:96:69:52:02:aa:36:98:ec:fc:fa:14:
+ 83:0c:37:1f:c9:92:37:7f:d7:81:2d:e5:c4:b9:e0:
+ 3e:34:fe:67:f4:3e:66:d1:d3:f4:40:cf:5e:62:34:
+ 0f:70:06:3e:20:18:5a:ce:f7:72:1b:25:6c:93:74:
+ 14:93:a3:73:b1:0e:aa:87:10:23:59:5f:20:05:19:
+ 47:ed:68:8e:92:12:ca:5d:fc:d6:2b:b2:92:3c:20:
+ cf:e1:5f:af:20:be:a0:76:7f:76:e5:ec:1a:86:61:
+ 33:3e:e7:7b:b4:3f:a0:0f:8e:a2:b9:6a:6f:b9:87:
+ 26:6f:41:6c:88:a6:50:fd:6a:63:0b:f5:93:16:1b:
+ 19:8f:b2:ed:9b:9b:c9:90:f5:01:0c:df:19:3d:0f:
+ 3e:38:23:c9:2f:8f:0c:d1:02:fe:1b:55:d6:4e:d0:
+ 8d:3c:af:4f:a4:f3:fe:af:2a:d3:05:9d:79:08:a1:
+ cb:57:31:b4:9c:c8:90:b2:67:f4:18:16:93:3a:fc:
+ 47:d8:d1:78:96:31:1f:ba:2b:0c:5f:5d:99:ad:63:
+ 89:5a:24:20:76:d8:df:fd:ab:4e:a6:22:aa:9d:5e:
+ e6:27:8a:7d:68:29:a3:e7:8a:b8:da:11:bb:17:2d:
+ 99:9d:13:24:46:f7:c5:e2:d8:9f:8e:7f:c7:8f:74:
+ 6d:5a:b2:e8:72:f5:ac:ee:24:10:ad:2f:14:da:ff:
+ 2d:9a:46:71:47:be:42:df:bb:01:db:f4:7f:d3:28:
+ 8f:31:59:5b:d3:c9:02:a6:b4:52:ca:6e:97:fb:43:
+ c5:08:26:6f:8a:f4:bb:fd:9f:28:aa:0d:d5:45:f3:
+ 13:3a:1d:d8:c0:78:8f:41:67:3c:1e:94:64:ae:7b:
+ 0b:c5:e8:d9:01:88:39:1a:97:86:64:41:d5:3b:87:
+ 0c:6e:fa:0f:c6:bd:48:14:bf:39:4d:d4:9e:41:b6:
+ 8f:96:1d:63:96:93:d9:95:06:78:31:68:9e:37:06:
+ 3b:80:89:45:61:39:23:c7:1b:44:a3:15:e5:1c:f8:
+ 92:30:bb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:1
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 65:CD:EB:AB:35:1E:00:3E:7E:D5:74:C0:1C:B4:73:47:0E:1A:64:2F
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: http://www.firmaprofesional.com/cps
+ User Notice:
+ Explicit Text:
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 17:7d:a0:f9:b4:dd:c5:c5:eb:ad:4b:24:b5:a1:02:ab:dd:a5:
+ 88:4a:b2:0f:55:4b:2b:57:8c:3b:e5:31:dd:fe:c4:32:f1:e7:
+ 5b:64:96:36:32:18:ec:a5:32:77:d7:e3:44:b6:c0:11:2a:80:
+ b9:3d:6a:6e:7c:9b:d3:ad:fc:c3:d6:a3:e6:64:29:7c:d1:e1:
+ 38:1e:82:2b:ff:27:65:af:fb:16:15:c4:2e:71:84:e5:b5:ff:
+ fa:a4:47:bd:64:32:bb:f6:25:84:a2:27:42:f5:20:b0:c2:13:
+ 10:11:cd:10:15:ba:42:90:2a:d2:44:e1:96:26:eb:31:48:12:
+ fd:2a:da:c9:06:cf:74:1e:a9:4b:d5:87:28:f9:79:34:92:3e:
+ 2e:44:e8:f6:8f:4f:8f:35:3f:25:b3:39:dc:63:2a:90:6b:20:
+ 5f:c4:52:12:4e:97:2c:2a:ac:9d:97:de:48:f2:a3:66:db:c2:
+ d2:83:95:a6:66:a7:9e:25:0f:e9:0b:33:91:65:0a:5a:c3:d9:
+ 54:12:dd:af:c3:4e:0e:1f:26:5e:0d:dc:b3:8d:ec:d5:81:70:
+ de:d2:4f:24:05:f3:6c:4e:f5:4c:49:66:8d:d1:ff:d2:0b:25:
+ 41:48:fe:51:84:c6:42:af:80:04:cf:d0:7e:64:49:e4:f2:df:
+ a2:ec:b1:4c:c0:2a:1d:e7:b4:b1:65:a2:c4:bc:f1:98:f4:aa:
+ 70:07:63:b4:b8:da:3b:4c:fa:40:22:30:5b:11:a6:f0:05:0e:
+ c6:02:03:48:ab:86:9b:85:dd:db:dd:ea:a2:76:80:73:7d:f5:
+ 9c:04:c4:45:8d:e7:b9:1c:8b:9e:ea:d7:75:d1:72:b1:de:75:
+ 44:e7:42:7d:e2:57:6b:7d:dc:99:bc:3d:83:28:ea:80:93:8d:
+ c5:4c:65:c1:70:81:b8:38:fc:43:31:b2:f6:03:34:47:b2:ac:
+ fb:22:06:cb:1e:dd:17:47:1c:5f:66:b9:d3:1a:a2:da:11:b1:
+ a4:bc:23:c9:e4:be:87:ff:b9:94:b6:f8:5d:20:4a:d4:5f:e7:
+ bd:68:7b:65:f2:15:1e:d2:3a:a9:2d:e9:d8:6b:24:ac:97:58:
+ 44:47:ad:59:18:f1:21:65:70:de:ce:34:60:a8:40:f1:f3:3c:
+ a4:c3:28:23:8c:fe:27:33:43:40:a0:17:3c:eb:ea:3b:b0:72:
+ a6:a3:b9:4a:4b:5e:16:48:f4:b2:bc:c8:8c:92:c5:9d:9f:ac:
+ 72:36:bc:34:80:34:6b:a9:8b:92:c0:b8:17:ed:ec:76:53:f5:
+ 24:01:8c:b3:22:e8:4b:7c:55:c6:9d:fa:a3:14:bb:65:85:6e:
+ 6e:4f:12:7e:0a:3c:9d:95
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
+BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
+cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
+MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
+Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
+thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
+cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
+L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
+NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
+X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
+m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
+Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
+EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
+KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
+6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
+OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
+VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
+ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
+AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
+661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
+am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
+ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
+PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
+3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
+SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
+3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
+ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
+StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
+Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
+jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem
new file mode 100644
index 00000000000..74c0043ad6f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 44:af:b0:80:d6:a3:27:ba:89:30:39:86:2e:f8:40:6b
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O = Digital Signature Trust Co., CN = DST Root CA X3
+ Validity
+ Not Before: Sep 30 21:12:19 2000 GMT
+ Not After : Sep 30 14:01:15 2021 GMT
+ Subject: O = Digital Signature Trust Co., CN = DST Root CA X3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:df:af:e9:97:50:08:83:57:b4:cc:62:65:f6:90:
+ 82:ec:c7:d3:2c:6b:30:ca:5b:ec:d9:c3:7d:c7:40:
+ c1:18:14:8b:e0:e8:33:76:49:2a:e3:3f:21:49:93:
+ ac:4e:0e:af:3e:48:cb:65:ee:fc:d3:21:0f:65:d2:
+ 2a:d9:32:8f:8c:e5:f7:77:b0:12:7b:b5:95:c0:89:
+ a3:a9:ba:ed:73:2e:7a:0c:06:32:83:a2:7e:8a:14:
+ 30:cd:11:a0:e1:2a:38:b9:79:0a:31:fd:50:bd:80:
+ 65:df:b7:51:63:83:c8:e2:88:61:ea:4b:61:81:ec:
+ 52:6b:b9:a2:e2:4b:1a:28:9f:48:a3:9e:0c:da:09:
+ 8e:3e:17:2e:1e:dd:20:df:5b:c6:2a:8a:ab:2e:bd:
+ 70:ad:c5:0b:1a:25:90:74:72:c5:7b:6a:ab:34:d6:
+ 30:89:ff:e5:68:13:7b:54:0b:c8:d6:ae:ec:5a:9c:
+ 92:1e:3d:64:b3:8c:c6:df:bf:c9:41:70:ec:16:72:
+ d5:26:ec:38:55:39:43:d0:fc:fd:18:5c:40:f1:97:
+ eb:d5:9a:9b:8d:1d:ba:da:25:b9:c6:d8:df:c1:15:
+ 02:3a:ab:da:6e:f1:3e:2e:f5:5c:08:9c:3c:d6:83:
+ 69:e4:10:9b:19:2a:b6:29:57:e3:e5:3d:9b:9f:f0:
+ 02:5d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ C4:A7:B1:A4:7B:2C:71:FA:DB:E1:4B:90:75:FF:C4:15:60:85:89:10
+ Signature Algorithm: sha1WithRSAEncryption
+ a3:1a:2c:9b:17:00:5c:a9:1e:ee:28:66:37:3a:bf:83:c7:3f:
+ 4b:c3:09:a0:95:20:5d:e3:d9:59:44:d2:3e:0d:3e:bd:8a:4b:
+ a0:74:1f:ce:10:82:9c:74:1a:1d:7e:98:1a:dd:cb:13:4b:b3:
+ 20:44:e4:91:e9:cc:fc:7d:a5:db:6a:e5:fe:e6:fd:e0:4e:dd:
+ b7:00:3a:b5:70:49:af:f2:e5:eb:02:f1:d1:02:8b:19:cb:94:
+ 3a:5e:48:c4:18:1e:58:19:5f:1e:02:5a:f0:0c:f1:b1:ad:a9:
+ dc:59:86:8b:6e:e9:91:f5:86:ca:fa:b9:66:33:aa:59:5b:ce:
+ e2:a7:16:73:47:cb:2b:cc:99:b0:37:48:cf:e3:56:4b:f5:cf:
+ 0f:0c:72:32:87:c6:f0:44:bb:53:72:6d:43:f5:26:48:9a:52:
+ 67:b7:58:ab:fe:67:76:71:78:db:0d:a2:56:14:13:39:24:31:
+ 85:a2:a8:02:5a:30:47:e1:dd:50:07:bc:02:09:90:00:eb:64:
+ 63:60:9b:16:bc:88:c9:12:e6:d2:7d:91:8b:f9:3d:32:8d:65:
+ b4:e9:7c:b1:57:76:ea:c5:b6:28:39:bf:15:65:1c:c8:f6:77:
+ 96:6a:0a:8d:77:0b:d8:91:0b:04:8e:07:db:29:b6:0a:ee:9d:
+ 82:35:35:10
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
+MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
+DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
+PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
+Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
+rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
+OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
+xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
+7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
+aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
+SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
+ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
+AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
+R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
+JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
+Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem
new file mode 100644
index 00000000000..cad4ecd5fdf
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem
@@ -0,0 +1,126 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2711694510199101698 (0x25a1dfca33cb5902)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor RootCert CA-2
+ Validity
+ Not Before: Feb 4 12:32:23 2016 GMT
+ Not After : Dec 31 17:26:39 2034 GMT
+ Subject: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor RootCert CA-2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a7:20:6e:c2:2a:a2:62:24:95:90:76:c8:38:7e:
+ 80:d2:ab:c1:9b:65:05:94:f4:c1:0a:10:d5:02:ac:
+ ed:9f:93:c7:87:c8:b0:27:2b:42:0c:3d:0a:3e:41:
+ 5a:9e:75:dd:8d:ca:e0:9b:ec:68:32:a4:69:92:68:
+ 8c:0b:81:0e:56:a0:3e:1a:dd:2c:25:14:82:2f:97:
+ d3:64:46:f4:54:a9:dc:3a:54:2d:31:2b:99:82:f2:
+ d9:2a:d7:ef:71:00:b8:31:a4:be:7a:24:07:c3:42:
+ 20:f2:8a:d4:92:04:1b:65:56:4c:6c:d4:fb:b6:61:
+ 5a:47:23:b4:d8:69:b4:b7:3a:d0:74:3c:0c:75:a1:
+ 8c:4e:76:a1:e9:db:2a:a5:3b:fa:ce:b0:ff:7e:6a:
+ 28:fd:27:1c:c8:b1:e9:29:f1:57:6e:64:b4:d0:c1:
+ 15:6d:0e:be:2e:0e:46:c8:5e:f4:51:fe:ef:0e:63:
+ 3a:3b:71:ba:cf:6f:59:ca:0c:e3:9b:5d:49:b8:4c:
+ e2:57:b1:98:8a:42:57:9c:76:ef:ef:bd:d1:68:a8:
+ d2:f4:09:bb:77:35:be:25:82:08:c4:16:2c:44:20:
+ 56:a9:44:11:77:ef:5d:b4:1d:aa:5e:6b:3e:8b:32:
+ f6:07:2f:57:04:92:ca:f5:fe:9d:c2:e9:e8:b3:8e:
+ 4c:4b:02:31:d9:e4:3c:48:82:27:f7:18:82:76:48:
+ 3a:71:b1:13:a1:39:d5:2e:c5:34:c2:1d:62:85:df:
+ 03:fe:4d:f4:af:3d:df:5c:5b:8d:fa:70:e1:a5:7e:
+ 27:c7:86:2e:6a:8f:12:c6:84:5e:43:51:50:9c:19:
+ 9b:78:e6:fc:f6:ed:47:7e:7b:3d:66:ef:13:13:88:
+ 5f:3c:a1:63:fb:f9:ac:87:35:9f:f3:82:9e:a4:3f:
+ 0a:9c:31:69:8b:99:a4:88:4a:8e:6e:66:4d:ef:16:
+ c4:0f:79:28:21:60:0d:85:16:7d:d7:54:38:f1:92:
+ 56:fd:b5:33:4c:83:dc:d7:10:9f:4b:fd:c6:f8:42:
+ bd:ba:7c:73:02:e0:ff:7d:cd:5b:e1:d4:ac:61:7b:
+ 57:d5:4a:7b:5b:d4:85:58:27:5d:bf:f8:2b:60:ac:
+ a0:26:ae:14:21:27:c6:77:9a:33:80:3c:5e:46:3f:
+ f7:c3:b1:a3:86:33:c6:e8:5e:0d:b9:35:2c:aa:46:
+ c1:85:02:75:80:a0:eb:24:fb:15:aa:e4:67:7f:6e:
+ 77:3f:f4:04:8a:2f:7c:7b:e3:17:61:f0:dd:09:a9:
+ 20:c8:be:09:a4:d0:7e:44:c3:b2:30:4a:38:aa:a9:
+ ec:18:9a:07:82:2b:db:b8:9c:18:ad:da:e0:46:17:
+ ac:cf:5d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ D9:FE:21:40:6E:94:9E:BC:9B:3D:9C:7D:98:20:19:E5:8C:30:62:B2
+ X509v3 Authority Key Identifier:
+ keyid:D9:FE:21:40:6E:94:9E:BC:9B:3D:9C:7D:98:20:19:E5:8C:30:62:B2
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 9e:45:9e:0c:3b:b6:ef:e1:3a:c8:7c:d1:00:3d:cf:e2:ea:06:
+ b5:b2:3a:bb:06:4b:68:7a:d0:23:97:74:a7:2c:f0:08:d8:79:
+ 5a:d7:5a:84:8a:d8:12:9a:1b:d9:7d:5c:4d:70:c5:a5:f9:ab:
+ e5:a3:89:89:dd:01:fa:ec:dd:f9:e9:92:97:db:b0:46:42:f3:
+ d3:62:aa:95:fe:31:67:14:69:58:90:0a:aa:0b:ee:37:23:c7:
+ 50:51:b4:f5:7e:9e:e3:7b:f7:e4:cc:42:32:2d:49:0c:cb:ff:
+ 49:0c:9b:1e:34:fd:6e:6e:96:8a:79:03:b6:6f:db:09:cb:fd:
+ 5f:65:14:37:e1:38:f5:f3:61:16:58:e4:b5:6d:0d:0b:04:1b:
+ 3f:50:2d:7f:b3:c7:7a:1a:16:80:60:f8:8a:1f:e9:1b:2a:c6:
+ f9:ba:01:1a:69:bf:d2:58:c7:54:57:08:8f:e1:39:60:77:4b:
+ ac:59:84:1a:88:f1:dd:cb:4f:78:d7:e7:e1:33:2d:fc:ee:41:
+ fa:20:b0:be:cb:f7:38:94:c0:e1:d0:85:0f:bb:ed:2c:73:ab:
+ ed:fe:92:76:1a:64:7f:5b:0d:33:09:07:33:7b:06:3f:11:a4:
+ 5c:70:3c:85:c0:cf:e3:90:a8:83:77:fa:db:e6:c5:8c:68:67:
+ 10:67:a5:52:2d:f0:c4:99:8f:7f:bf:d1:6b:e2:b5:47:d6:d9:
+ d0:85:99:4d:94:9b:0f:4b:8d:ee:00:5a:47:1d:11:03:ac:41:
+ 18:af:87:b7:6f:0c:3a:8f:ca:cf:dc:03:c1:a2:09:c8:e5:fd:
+ 80:5e:c8:60:42:01:1b:1a:53:5a:bb:37:a6:b7:bc:ba:84:e9:
+ 1e:6c:1a:d4:64:da:d4:43:fe:93:8b:4b:f2:2c:79:16:10:d4:
+ 93:0b:88:8f:a1:d8:86:14:46:91:47:9b:28:24:ef:57:52:4e:
+ 5c:42:9c:aa:f7:49:ec:27:e8:40:1e:b3:a6:89:22:72:9c:f5:
+ 0d:33:b4:58:a3:30:3b:dd:d4:6a:54:93:be:1a:4d:f3:93:94:
+ f7:fc:84:0b:3f:84:20:5c:34:03:44:c5:da:ad:bc:0a:c1:02:
+ cf:1e:e5:94:d9:f3:8e:5b:d8:4c:f0:9d:ec:61:17:bb:14:32:
+ 54:0c:02:29:93:1e:92:86:f6:7f:ef:e7:92:05:0e:59:dd:99:
+ 08:2e:2e:fa:9c:00:52:d3:c5:66:29:e4:a7:97:44:a4:0e:28:
+ 81:13:35:c5:f6:6f:64:e6:41:c4:d5:2f:cc:34:45:25:cf:41:
+ 00:96:3d:4a:2e:c2:96:98:4f:4e:4a:9c:97:b7:db:1f:92:32:
+ c8:ff:0f:51:6e:d6:ec:09
+-----BEGIN CERTIFICATE-----
+MIIGLzCCBBegAwIBAgIIJaHfyjPLWQIwDQYJKoZIhvcNAQELBQAwgaQxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEfMB0GA1UEAwwWVHJ1c3RDb3Ig
+Um9vdENlcnQgQ0EtMjAeFw0xNjAyMDQxMjMyMjNaFw0zNDEyMzExNzI2MzlaMIGk
+MQswCQYDVQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEg
+Q2l0eTEkMCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYD
+VQQLDB5UcnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRy
+dXN0Q29yIFJvb3RDZXJ0IENBLTIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCnIG7CKqJiJJWQdsg4foDSq8GbZQWU9MEKENUCrO2fk8eHyLAnK0IMPQo+
+QVqedd2NyuCb7GgypGmSaIwLgQ5WoD4a3SwlFIIvl9NkRvRUqdw6VC0xK5mC8tkq
+1+9xALgxpL56JAfDQiDyitSSBBtlVkxs1Pu2YVpHI7TYabS3OtB0PAx1oYxOdqHp
+2yqlO/rOsP9+aij9JxzIsekp8VduZLTQwRVtDr4uDkbIXvRR/u8OYzo7cbrPb1nK
+DOObXUm4TOJXsZiKQlecdu/vvdFoqNL0Cbt3Nb4lggjEFixEIFapRBF37120Hape
+az6LMvYHL1cEksr1/p3C6eizjkxLAjHZ5DxIgif3GIJ2SDpxsROhOdUuxTTCHWKF
+3wP+TfSvPd9cW436cOGlfifHhi5qjxLGhF5DUVCcGZt45vz27Ud+ez1m7xMTiF88
+oWP7+ayHNZ/zgp6kPwqcMWmLmaSISo5uZk3vFsQPeSghYA2FFn3XVDjxklb9tTNM
+g9zXEJ9L/cb4Qr26fHMC4P99zVvh1Kxhe1fVSntb1IVYJ12/+CtgrKAmrhQhJ8Z3
+mjOAPF5GP/fDsaOGM8boXg25NSyqRsGFAnWAoOsk+xWq5Gd/bnc/9ASKL3x74xdh
+8N0JqSDIvgmk0H5Ew7IwSjiqqewYmgeCK9u4nBit2uBGF6zPXQIDAQABo2MwYTAd
+BgNVHQ4EFgQU2f4hQG6UnrybPZx9mCAZ5YwwYrIwHwYDVR0jBBgwFoAU2f4hQG6U
+nrybPZx9mCAZ5YwwYrIwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYw
+DQYJKoZIhvcNAQELBQADggIBAJ5Fngw7tu/hOsh80QA9z+LqBrWyOrsGS2h60COX
+dKcs8AjYeVrXWoSK2BKaG9l9XE1wxaX5q+WjiYndAfrs3fnpkpfbsEZC89NiqpX+
+MWcUaViQCqoL7jcjx1BRtPV+nuN79+TMQjItSQzL/0kMmx40/W5ulop5A7Zv2wnL
+/V9lFDfhOPXzYRZY5LVtDQsEGz9QLX+zx3oaFoBg+Iof6Rsqxvm6ARppv9JYx1RX
+CI/hOWB3S6xZhBqI8d3LT3jX5+EzLfzuQfogsL7L9ziUwOHQhQ+77Sxzq+3+knYa
+ZH9bDTMJBzN7Bj8RpFxwPIXAz+OQqIN3+tvmxYxoZxBnpVIt8MSZj3+/0WvitUfW
+2dCFmU2Umw9Lje4AWkcdEQOsQRivh7dvDDqPys/cA8GiCcjl/YBeyGBCARsaU1q7
+N6a3vLqE6R5sGtRk2tRD/pOLS/IseRYQ1JMLiI+h2IYURpFHmygk71dSTlxCnKr3
+Sewn6EAes6aJInKc9Q0ztFijMDvd1GpUk74aTfOTlPf8hAs/hCBcNANExdqtvArB
+As8e5ZTZ845b2EzwnexhF7sUMlQMAimTHpKG9n/v55IFDlndmQguLvqcAFLTxWYp
+5KeXRKQOKIETNcX2b2TmQcTVL8w0RSXPQQCWPUouwpaYT05KnJe32x+SMsj/D1Fu
+1uwJ
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem
new file mode 100644
index 00000000000..cf4187e5359
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem
@@ -0,0 +1,76 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8957382827206547757 (0x7c4f04391cd4992d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = AffirmTrust, CN = AffirmTrust Networking
+ Validity
+ Not Before: Jan 29 14:08:24 2010 GMT
+ Not After : Dec 31 14:08:24 2030 GMT
+ Subject: C = US, O = AffirmTrust, CN = AffirmTrust Networking
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b4:84:cc:33:17:2e:6b:94:6c:6b:61:52:a0:eb:
+ a3:cf:79:94:4c:e5:94:80:99:cb:55:64:44:65:8f:
+ 67:64:e2:06:e3:5c:37:49:f6:2f:9b:84:84:1e:2d:
+ f2:60:9d:30:4e:cc:84:85:e2:2c:cf:1e:9e:fe:36:
+ ab:33:77:35:44:d8:35:96:1a:3d:36:e8:7a:0e:d8:
+ d5:47:a1:6a:69:8b:d9:fc:bb:3a:ae:79:5a:d5:f4:
+ d6:71:bb:9a:90:23:6b:9a:b7:88:74:87:0c:1e:5f:
+ b9:9e:2d:fa:ab:53:2b:dc:bb:76:3e:93:4c:08:08:
+ 8c:1e:a2:23:1c:d4:6a:ad:22:ba:99:01:2e:6d:65:
+ cb:be:24:66:55:24:4b:40:44:b1:1b:d7:e1:c2:85:
+ c0:de:10:3f:3d:ed:b8:fc:f1:f1:23:53:dc:bf:65:
+ 97:6f:d9:f9:40:71:8d:7d:bd:95:d4:ce:be:a0:5e:
+ 27:23:de:fd:a6:d0:26:0e:00:29:eb:3c:46:f0:3d:
+ 60:bf:3f:50:d2:dc:26:41:51:9e:14:37:42:04:a3:
+ 70:57:a8:1b:87:ed:2d:fa:7b:ee:8c:0a:e3:a9:66:
+ 89:19:cb:41:f9:dd:44:36:61:cf:e2:77:46:c8:7d:
+ f6:f4:92:81:36:fd:db:34:f1:72:7e:f3:0c:16:bd:
+ b4:15
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 07:1F:D2:E7:9C:DA:C2:6E:A2:40:B4:B0:7A:50:10:50:74:C4:C8:BD
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ 89:57:b2:16:7a:a8:c2:fd:d6:d9:9b:9b:34:c2:9c:b4:32:14:
+ 4d:a7:a4:df:ec:be:a7:be:f8:43:db:91:37:ce:b4:32:2e:50:
+ 55:1a:35:4e:76:43:71:20:ef:93:77:4e:15:70:2e:87:c3:c1:
+ 1d:6d:dc:cb:b5:27:d4:2c:56:d1:52:53:3a:44:d2:73:c8:c4:
+ 1b:05:65:5a:62:92:9c:ee:41:8d:31:db:e7:34:ea:59:21:d5:
+ 01:7a:d7:64:b8:64:39:cd:c9:ed:af:ed:4b:03:48:a7:a0:99:
+ 01:80:dc:65:a3:36:ae:65:59:48:4f:82:4b:c8:65:f1:57:1d:
+ e5:59:2e:0a:3f:6c:d8:d1:f5:e5:09:b4:6c:54:00:0a:e0:15:
+ 4d:87:75:6d:b7:58:96:5a:dd:6d:d2:00:a0:f4:9b:48:be:c3:
+ 37:a4:ba:36:e0:7c:87:85:97:1a:15:a2:de:2e:a2:5b:bd:af:
+ 18:f9:90:50:cd:70:59:f8:27:67:47:cb:c7:a0:07:3a:7d:d1:
+ 2c:5d:6c:19:3a:66:b5:7d:fd:91:6f:82:b1:be:08:93:db:14:
+ 47:f1:a2:37:c7:45:9e:3c:c7:77:af:64:a8:93:df:f6:69:83:
+ 82:60:f2:49:42:34:ed:5a:00:54:85:1c:16:36:92:0c:5c:fa:
+ a6:ad:bf:db
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVz
+dCBOZXR3b3JraW5nMB4XDTEwMDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDEL
+MAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZp
+cm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SEHi3y
+YJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbua
+kCNrmreIdIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRL
+QESxG9fhwoXA3hA/Pe24/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp
+6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gbh+0t+nvujArjqWaJGctB+d1ENmHP4ndG
+yH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNVHQ4EFgQUBx/S55zawm6i
+QLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwDQYJ
+KoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfO
+tDIuUFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzu
+QY0x2+c06lkh1QF612S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZ
+Lgo/bNjR9eUJtGxUAArgFU2HdW23WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4u
+olu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9/ZFvgrG+CJPbFEfxojfHRZ48
+x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem
new file mode 100644
index 00000000000..afb26460aaf
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem
@@ -0,0 +1,87 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 4e:81:2d:8a:82:65:e0:0b:02:ee:3e:35:02:46:e5:3d
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO Certification Authority
+ Validity
+ Not Before: Dec 1 00:00:00 2006 GMT
+ Not After : Dec 31 23:59:59 2029 GMT
+ Subject: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d0:40:8b:8b:72:e3:91:1b:f7:51:c1:1b:54:04:
+ 98:d3:a9:bf:c1:e6:8a:5d:3b:87:fb:bb:88:ce:0d:
+ e3:2f:3f:06:96:f0:a2:29:50:99:ae:db:3b:a1:57:
+ b0:74:51:71:cd:ed:42:91:4d:41:fe:a9:c8:d8:6a:
+ 86:77:44:bb:59:66:97:50:5e:b4:d4:2c:70:44:cf:
+ da:37:95:42:69:3c:30:c4:71:b3:52:f0:21:4d:a1:
+ d8:ba:39:7c:1c:9e:a3:24:9d:f2:83:16:98:aa:16:
+ 7c:43:9b:15:5b:b7:ae:34:91:fe:d4:62:26:18:46:
+ 9a:3f:eb:c1:f9:f1:90:57:eb:ac:7a:0d:8b:db:72:
+ 30:6a:66:d5:e0:46:a3:70:dc:68:d9:ff:04:48:89:
+ 77:de:b5:e9:fb:67:6d:41:e9:bc:39:bd:32:d9:62:
+ 02:f1:b1:a8:3d:6e:37:9c:e2:2f:e2:d3:a2:26:8b:
+ c6:b8:55:43:88:e1:23:3e:a5:d2:24:39:6a:47:ab:
+ 00:d4:a1:b3:a9:25:fe:0d:3f:a7:1d:ba:d3:51:c1:
+ 0b:a4:da:ac:38:ef:55:50:24:05:65:46:93:34:4f:
+ 2d:8d:ad:c6:d4:21:19:d2:8e:ca:05:61:71:07:73:
+ 47:e5:8a:19:12:bd:04:4d:ce:4e:9c:a5:48:ac:bb:
+ 26:f7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 0B:58:E5:8B:C6:4C:15:37:A4:40:A9:30:A9:21:BE:47:36:5A:56:FF
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/COMODOCertificationAuthority.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 3e:98:9e:9b:f6:1b:e9:d7:39:b7:78:ae:1d:72:18:49:d3:87:
+ e4:43:82:eb:3f:c9:aa:f5:a8:b5:ef:55:7c:21:52:65:f9:d5:
+ 0d:e1:6c:f4:3e:8c:93:73:91:2e:02:c4:4e:07:71:6f:c0:8f:
+ 38:61:08:a8:1e:81:0a:c0:2f:20:2f:41:8b:91:dc:48:45:bc:
+ f1:c6:de:ba:76:6b:33:c8:00:2d:31:46:4c:ed:e7:9d:cf:88:
+ 94:ff:33:c0:56:e8:24:86:26:b8:d8:38:38:df:2a:6b:dd:12:
+ cc:c7:3f:47:17:4c:a2:c2:06:96:09:d6:db:fe:3f:3c:46:41:
+ df:58:e2:56:0f:3c:3b:c1:1c:93:35:d9:38:52:ac:ee:c8:ec:
+ 2e:30:4e:94:35:b4:24:1f:4b:78:69:da:f2:02:38:cc:95:52:
+ 93:f0:70:25:59:9c:20:67:c4:ee:f9:8b:57:61:f4:92:76:7d:
+ 3f:84:8d:55:b7:e8:e5:ac:d5:f1:f5:19:56:a6:5a:fb:90:1c:
+ af:93:eb:e5:1c:d4:67:97:5d:04:0e:be:0b:83:a6:17:83:b9:
+ 30:12:a0:c5:33:15:05:b9:0d:fb:c7:05:76:e3:d8:4a:8d:fc:
+ 34:17:a3:c6:21:28:be:30:45:31:1e:c7:78:be:58:61:38:ac:
+ 3b:e2:01:65
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
+gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
+BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
+MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
+YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
+RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
+UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
+2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
+Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
++2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
+nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
+/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
+PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
+QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
+SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
+IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
+zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
+BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
+ZQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem
new file mode 100644
index 00000000000..87295f0fa92
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ae:cf:00:ba:c4:cf:32:f8:43:b2
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, OU = emSign PKI, O = eMudhra Inc, CN = emSign Root CA - C1
+ Validity
+ Not Before: Feb 18 18:30:00 2018 GMT
+ Not After : Feb 18 18:30:00 2043 GMT
+ Subject: C = US, OU = emSign PKI, O = eMudhra Inc, CN = emSign Root CA - C1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:cf:eb:a9:b9:f1:99:05:cc:d8:28:21:4a:f3:73:
+ 34:51:84:56:10:f5:a0:4f:2c:12:e3:fa:13:9a:27:
+ d0:cf:f9:79:1a:74:5f:1d:79:39:fc:5b:f8:70:8e:
+ e0:92:52:f7:e4:25:f9:54:83:d9:1d:d3:c8:5a:85:
+ 3f:5e:c7:b6:07:ee:3e:c0:ce:9a:af:ac:56:42:2a:
+ 39:25:70:d6:bf:b5:7b:36:ad:ac:f6:73:dc:cd:d7:
+ 1d:8a:83:a5:fb:2b:90:15:37:6b:1c:26:47:dc:3b:
+ 29:56:93:6a:b3:c1:6a:3a:9d:3d:f5:c1:97:38:58:
+ 05:8b:1c:11:e3:e4:b4:b8:5d:85:1d:83:fe:78:5f:
+ 0b:45:68:18:48:a5:46:73:34:3b:fe:0f:c8:76:bb:
+ c7:18:f3:05:d1:86:f3:85:ed:e7:b9:d9:32:ad:55:
+ 88:ce:a6:b6:91:b0:4f:ac:7e:15:23:96:f6:3f:f0:
+ 20:34:16:de:0a:c6:c4:04:45:79:7f:a7:fd:be:d2:
+ a9:a5:af:9c:c5:23:2a:f7:3c:21:6c:bd:af:8f:4e:
+ c5:3a:b2:f3:34:12:fc:df:80:1a:49:a4:d4:a9:95:
+ f7:9e:89:5e:a2:89:ac:94:cb:a8:68:9b:af:8a:65:
+ 27:cd:89:ee:dd:8c:b5:6b:29:70:43:a0:69:0b:e4:
+ b9:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ FE:A1:E0:70:1E:2A:03:39:52:5A:42:BE:5C:91:85:7A:18:AA:4D:B5
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ c2:4a:56:fa:15:21:7b:28:a2:e9:e5:1d:fb:f8:2d:c4:39:96:
+ 41:4c:3b:27:2c:c4:6c:18:15:80:c6:ac:af:47:59:2f:26:0b:
+ e3:36:b0:ef:3b:fe:43:97:49:32:99:12:15:5b:df:11:29:ff:
+ ab:53:f8:bb:c1:78:0f:ac:9c:53:af:57:bd:68:8c:3d:69:33:
+ f0:a3:a0:23:63:3b:64:67:22:44:ad:d5:71:cb:56:2a:78:92:
+ a3:4f:12:31:36:36:e2:de:fe:00:c4:a3:60:0f:27:ad:a0:b0:
+ 8a:b5:36:7a:52:a1:bd:27:f4:20:27:62:e8:4d:94:24:13:e4:
+ 0a:04:e9:3c:ab:2e:c8:43:09:4a:c6:61:04:e5:49:34:7e:d3:
+ c4:c8:f5:0f:c0:aa:e9:ba:54:5e:f3:63:2b:4f:4f:50:d4:fe:
+ b9:7b:99:8c:3d:c0:2e:bc:02:2b:d3:c4:40:e4:8a:07:31:1e:
+ 9b:ce:26:99:13:fb:11:ea:9a:22:0c:11:19:c7:5e:1b:81:50:
+ 30:c8:96:12:6e:e7:cb:41:7f:91:3b:a2:47:b7:54:80:1b:dc:
+ 00:cc:9a:90:ea:c3:c3:50:06:62:0c:30:c0:15:48:a7:a8:59:
+ 7c:e1:ae:22:a2:e2:0a:7a:0f:fa:62:ab:52:4c:e1:f1:df:ca:
+ be:83:0d:42
+-----BEGIN CERTIFICATE-----
+MIIDczCCAlugAwIBAgILAK7PALrEzzL4Q7IwDQYJKoZIhvcNAQELBQAwVjELMAkG
+A1UEBhMCVVMxEzARBgNVBAsTCmVtU2lnbiBQS0kxFDASBgNVBAoTC2VNdWRocmEg
+SW5jMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEMxMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowVjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMRwwGgYDVQQDExNlbVNpZ24gUm9v
+dCBDQSAtIEMxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAz+upufGZ
+BczYKCFK83M0UYRWEPWgTywS4/oTmifQz/l5GnRfHXk5/Fv4cI7gklL35CX5VIPZ
+HdPIWoU/Xse2B+4+wM6ar6xWQio5JXDWv7V7Nq2s9nPczdcdioOl+yuQFTdrHCZH
+3DspVpNqs8FqOp099cGXOFgFixwR4+S0uF2FHYP+eF8LRWgYSKVGczQ7/g/IdrvH
+GPMF0Ybzhe3nudkyrVWIzqa2kbBPrH4VI5b2P/AgNBbeCsbEBEV5f6f9vtKppa+c
+xSMq9zwhbL2vj07FOrLzNBL834AaSaTUqZX3noleoomslMuoaJuvimUnzYnu3Yy1
+aylwQ6BpC+S5DwIDAQABo0IwQDAdBgNVHQ4EFgQU/qHgcB4qAzlSWkK+XJGFehiq
+TbUwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBAMJKVvoVIXsoounlHfv4LcQ5lkFMOycsxGwYFYDGrK9HWS8mC+M2sO87
+/kOXSTKZEhVb3xEp/6tT+LvBeA+snFOvV71ojD1pM/CjoCNjO2RnIkSt1XHLVip4
+kqNPEjE2NuLe/gDEo2APJ62gsIq1NnpSob0n9CAnYuhNlCQT5AoE6TyrLshDCUrG
+YQTlSTR+08TI9Q/Aqum6VF7zYytPT1DU/rl7mYw9wC68AivTxEDkigcxHpvOJpkT
++xHqmiIMERnHXhuBUDDIlhJu58tBf5E7oke3VIAb3ADMmpDqw8NQBmIMMMAVSKeo
+WXzhriKi4gp6D/piq1JM4fHfyr6DDUI=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem
new file mode 100644
index 00000000000..d8b5d60ddcd
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
+ Validity
+ Not Before: Jun 29 17:39:16 2004 GMT
+ Not After : Jun 29 17:39:16 2034 GMT
+ Subject: C = US, O = "Starfield Technologies, Inc.", OU = Starfield Class 2 Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b7:32:c8:fe:e9:71:a6:04:85:ad:0c:11:64:df:
+ ce:4d:ef:c8:03:18:87:3f:a1:ab:fb:3c:a6:9f:f0:
+ c3:a1:da:d4:d8:6e:2b:53:90:fb:24:a4:3e:84:f0:
+ 9e:e8:5f:ec:e5:27:44:f5:28:a6:3f:7b:de:e0:2a:
+ f0:c8:af:53:2f:9e:ca:05:01:93:1e:8f:66:1c:39:
+ a7:4d:fa:5a:b6:73:04:25:66:eb:77:7f:e7:59:c6:
+ 4a:99:25:14:54:eb:26:c7:f3:7f:19:d5:30:70:8f:
+ af:b0:46:2a:ff:ad:eb:29:ed:d7:9f:aa:04:87:a3:
+ d4:f9:89:a5:34:5f:db:43:91:82:36:d9:66:3c:b1:
+ b8:b9:82:fd:9c:3a:3e:10:c8:3b:ef:06:65:66:7a:
+ 9b:19:18:3d:ff:71:51:3c:30:2e:5f:be:3d:77:73:
+ b2:5d:06:6c:c3:23:56:9a:2b:85:26:92:1c:a7:02:
+ b3:e4:3f:0d:af:08:79:82:b8:36:3d:ea:9c:d3:35:
+ b3:bc:69:ca:f5:cc:9d:e8:fd:64:8d:17:80:33:6e:
+ 5e:4a:5d:99:c9:1e:87:b4:9d:1a:c0:d5:6e:13:35:
+ 23:5e:df:9b:5f:3d:ef:d6:f7:76:c2:ea:3e:bb:78:
+ 0d:1c:42:67:6b:04:d8:f8:d6:da:6f:8b:f2:44:a0:
+ 01:ab
+ Exponent: 3 (0x3)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
+ X509v3 Authority Key Identifier:
+ keyid:BF:5F:B7:D1:CE:DD:1F:86:F4:5B:55:AC:DC:D7:10:C2:0E:A9:88:E7
+ DirName:/C=US/O=Starfield Technologies, Inc./OU=Starfield Class 2 Certification Authority
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 05:9d:3f:88:9d:d1:c9:1a:55:a1:ac:69:f3:f3:59:da:9b:01:
+ 87:1a:4f:57:a9:a1:79:09:2a:db:f7:2f:b2:1e:cc:c7:5e:6a:
+ d8:83:87:a1:97:ef:49:35:3e:77:06:41:58:62:bf:8e:58:b8:
+ 0a:67:3f:ec:b3:dd:21:66:1f:c9:54:fa:72:cc:3d:4c:40:d8:
+ 81:af:77:9e:83:7a:bb:a2:c7:f5:34:17:8e:d9:11:40:f4:fc:
+ 2c:2a:4d:15:7f:a7:62:5d:2e:25:d3:00:0b:20:1a:1d:68:f9:
+ 17:b8:f4:bd:8b:ed:28:59:dd:4d:16:8b:17:83:c8:b2:65:c7:
+ 2d:7a:a5:aa:bc:53:86:6d:dd:57:a4:ca:f8:20:41:0b:68:f0:
+ f4:fb:74:be:56:5d:7a:79:f5:f9:1d:85:e3:2d:95:be:f5:71:
+ 90:43:cc:8d:1f:9a:00:0a:87:29:e9:55:22:58:00:23:ea:e3:
+ 12:43:29:5b:47:08:dd:8c:41:6a:65:06:a8:e5:21:aa:41:b4:
+ 95:21:95:b9:7d:d1:34:ab:13:d6:ad:bc:dc:e2:3d:39:cd:bd:
+ 3e:75:70:a1:18:59:03:c9:22:b4:8f:9c:d5:5e:2a:d7:a5:b6:
+ d4:0a:6d:f8:b7:40:11:46:9a:1f:79:0e:62:bf:0f:97:ec:e0:
+ 2f:1f:17:94
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
+MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
+U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
+NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
+ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
+ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
+DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
+8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
++lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
+X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
+K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
+1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
+A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
+zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
+YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
+bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
+DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
+L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
+eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
+VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
+WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem
new file mode 100644
index 00000000000..2b30dfec69b
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem
@@ -0,0 +1,51 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 6e:47:a9:c7:6c:a9:73:24:40:89:0f:03:55:dd:8d:1d
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R3
+ Validity
+ Not Before: Jun 22 00:00:00 2016 GMT
+ Not After : Jun 22 00:00:00 2036 GMT
+ Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:1f:4f:33:87:33:29:8a:a1:84:de:cb:c7:21:58:
+ 41:89:ea:56:9d:2b:4b:85:c6:1d:4c:27:bc:7f:26:
+ 51:72:6f:e2:9f:d6:a3:ca:cc:45:14:46:8b:ad:ef:
+ 7e:86:8c:ec:b1:7e:2f:ff:a9:71:9d:18:84:45:04:
+ 41:55:6e:2b:ea:26:7f:bb:90:01:e3:4b:19:ba:e4:
+ 54:96:45:09:b1:d5:6c:91:44:ad:84:13:8e:9a:8c:
+ 0d:80:0c:32:f6:e0:27
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ C1:F1:26:BA:A0:2D:AE:85:81:CF:D3:F1:2A:12:BD:B8:0A:67:FD:BC
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:66:02:31:00:80:5b:a4:7c:23:c0:95:a5:2c:dc:be:89:6f:
+ 23:b9:a3:dd:65:00:52:5e:91:ac:c8:9d:72:74:82:53:0b:7d:
+ a9:40:bd:68:60:c5:e1:b8:54:3b:c1:36:17:25:d8:c1:bd:02:
+ 31:00:9e:35:92:74:85:25:51:f5:24:ec:64:52:24:50:a5:1f:
+ db:e8:cb:c9:76:ec:ec:82:6e:f5:85:18:53:e8:b8:e3:9a:29:
+ aa:96:d3:83:23:c9:a4:7b:61:b3:cc:02:e8:5d
+-----BEGIN CERTIFICATE-----
+MIICDDCCAZGgAwIBAgIQbkepx2ypcyRAiQ8DVd2NHTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjMwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjMwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQfTzOHMymKoYTey8chWEGJ6ladK0uFxh1MJ7x/JlFyb+Kf1qPKzEUURout
+736GjOyxfi//qXGdGIRFBEFVbivqJn+7kAHjSxm65FSWRQmx1WyRRK2EE46ajA2A
+DDL24CejQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBTB8Sa6oC2uhYHP0/EqEr24Cmf9vDAKBggqhkjOPQQDAwNpADBmAjEAgFuk
+fCPAlaUs3L6JbyO5o91lAFJekazInXJ0glMLfalAvWhgxeG4VDvBNhcl2MG9AjEA
+njWSdIUlUfUk7GRSJFClH9voy8l27OyCbvWFGFPouOOaKaqW04MjyaR7YbPMAuhd
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem
new file mode 100644
index 00000000000..02a7a1eca12
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem
@@ -0,0 +1,85 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 57:cb:33:6f:c2:5c:16:e6:47:16:17:e3:90:31:68:e0
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = Network Solutions L.L.C., CN = Network Solutions Certificate Authority
+ Validity
+ Not Before: Dec 1 00:00:00 2006 GMT
+ Not After : Dec 31 23:59:59 2029 GMT
+ Subject: C = US, O = Network Solutions L.L.C., CN = Network Solutions Certificate Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:e4:bc:7e:92:30:6d:c6:d8:8e:2b:0b:bc:46:ce:
+ e0:27:96:de:de:f9:fa:12:d3:3c:33:73:b3:04:2f:
+ bc:71:8c:e5:9f:b6:22:60:3e:5f:5d:ce:09:ff:82:
+ 0c:1b:9a:51:50:1a:26:89:dd:d5:61:5d:19:dc:12:
+ 0f:2d:0a:a2:43:5d:17:d0:34:92:20:ea:73:cf:38:
+ 2c:06:26:09:7a:72:f7:fa:50:32:f8:c2:93:d3:69:
+ a2:23:ce:41:b1:cc:e4:d5:1f:36:d1:8a:3a:f8:8c:
+ 63:e2:14:59:69:ed:0d:d3:7f:6b:e8:b8:03:e5:4f:
+ 6a:e5:98:63:69:48:05:be:2e:ff:33:b6:e9:97:59:
+ 69:f8:67:19:ae:93:61:96:44:15:d3:72:b0:3f:bc:
+ 6a:7d:ec:48:7f:8d:c3:ab:aa:71:2b:53:69:41:53:
+ 34:b5:b0:b9:c5:06:0a:c4:b0:45:f5:41:5d:6e:89:
+ 45:7b:3d:3b:26:8c:74:c2:e5:d2:d1:7d:b2:11:d4:
+ fb:58:32:22:9a:80:c9:dc:fd:0c:e9:7f:5e:03:97:
+ ce:3b:00:14:87:27:70:38:a9:8e:6e:b3:27:76:98:
+ 51:e0:05:e3:21:ab:1a:d5:85:22:3c:29:b5:9a:16:
+ c5:80:a8:f4:bb:6b:30:8f:2f:46:02:a2:b1:0c:22:
+ e0:d3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 21:30:C9:FB:00:D7:4E:98:DA:87:AA:2A:D0:A7:2E:B1:40:31:A7:4C
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.netsolssl.com/NetworkSolutionsCertificateAuthority.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ bb:ae:4b:e7:b7:57:eb:7f:aa:2d:b7:73:47:85:6a:c1:e4:a5:
+ 1d:e4:e7:3c:e9:f4:59:65:77:b5:7a:5b:5a:8d:25:36:e0:7a:
+ 97:2e:38:c0:57:60:83:98:06:83:9f:b9:76:7a:6e:50:e0:ba:
+ 88:2c:fc:45:cc:18:b0:99:95:51:0e:ec:1d:b8:88:ff:87:50:
+ 1c:82:c2:e3:e0:32:80:bf:a0:0b:47:c8:c3:31:ef:99:67:32:
+ 80:4f:17:21:79:0c:69:5c:de:5e:34:ae:02:b5:26:ea:50:df:
+ 7f:18:65:2c:c9:f2:63:e1:a9:07:fe:7c:71:1f:6b:33:24:6a:
+ 1e:05:f7:05:68:c0:6a:12:cb:2e:5e:61:cb:ae:28:d3:7e:c2:
+ b4:66:91:26:5f:3c:2e:24:5f:cb:58:0f:eb:28:ec:af:11:96:
+ f3:dc:7b:6f:c0:a7:88:f2:53:77:b3:60:5e:ae:ae:28:da:35:
+ 2c:6f:34:45:d3:26:e1:de:ec:5b:4f:27:6b:16:7c:bd:44:04:
+ 18:82:b3:89:79:17:10:71:3d:7a:a2:16:4e:f5:01:cd:a4:6c:
+ 65:68:a1:49:76:5c:43:c9:d8:bc:36:67:6c:a5:94:b5:d4:cc:
+ b9:bd:6a:35:56:21:de:d8:c3:eb:fb:cb:a4:60:4c:b0:55:a0:
+ a0:7b:57:b2
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
+MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
+dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
+UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
+ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
+c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
+OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
+mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
+BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
+qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
+gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
+bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
+dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
+6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
+h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
+/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
+pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem
new file mode 100644
index 00000000000..a94af03428d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 33554617 (0x20000b9)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
+ Validity
+ Not Before: May 12 18:46:00 2000 GMT
+ Not After : May 12 23:59:00 2025 GMT
+ Subject: C = IE, O = Baltimore, OU = CyberTrust, CN = Baltimore CyberTrust Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:a3:04:bb:22:ab:98:3d:57:e8:26:72:9a:b5:79:
+ d4:29:e2:e1:e8:95:80:b1:b0:e3:5b:8e:2b:29:9a:
+ 64:df:a1:5d:ed:b0:09:05:6d:db:28:2e:ce:62:a2:
+ 62:fe:b4:88:da:12:eb:38:eb:21:9d:c0:41:2b:01:
+ 52:7b:88:77:d3:1c:8f:c7:ba:b9:88:b5:6a:09:e7:
+ 73:e8:11:40:a7:d1:cc:ca:62:8d:2d:e5:8f:0b:a6:
+ 50:d2:a8:50:c3:28:ea:f5:ab:25:87:8a:9a:96:1c:
+ a9:67:b8:3f:0c:d5:f7:f9:52:13:2f:c2:1b:d5:70:
+ 70:f0:8f:c0:12:ca:06:cb:9a:e1:d9:ca:33:7a:77:
+ d6:f8:ec:b9:f1:68:44:42:48:13:d2:c0:c2:a4:ae:
+ 5e:60:fe:b6:a6:05:fc:b4:dd:07:59:02:d4:59:18:
+ 98:63:f5:a5:63:e0:90:0c:7d:5d:b2:06:7a:f3:85:
+ ea:eb:d4:03:ae:5e:84:3e:5f:ff:15:ed:69:bc:f9:
+ 39:36:72:75:cf:77:52:4d:f3:c9:90:2c:b9:3d:e5:
+ c9:23:53:3f:1f:24:98:21:5c:07:99:29:bd:c6:3a:
+ ec:e7:6e:86:3a:6b:97:74:63:33:bd:68:18:31:f0:
+ 78:8d:76:bf:fc:9e:8e:5d:2a:86:a7:4d:90:dc:27:
+ 1a:39
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ E5:9D:59:30:82:47:58:CC:AC:FA:08:54:36:86:7B:3A:B5:04:4D:F0
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:3
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ 85:0c:5d:8e:e4:6f:51:68:42:05:a0:dd:bb:4f:27:25:84:03:
+ bd:f7:64:fd:2d:d7:30:e3:a4:10:17:eb:da:29:29:b6:79:3f:
+ 76:f6:19:13:23:b8:10:0a:f9:58:a4:d4:61:70:bd:04:61:6a:
+ 12:8a:17:d5:0a:bd:c5:bc:30:7c:d6:e9:0c:25:8d:86:40:4f:
+ ec:cc:a3:7e:38:c6:37:11:4f:ed:dd:68:31:8e:4c:d2:b3:01:
+ 74:ee:be:75:5e:07:48:1a:7f:70:ff:16:5c:84:c0:79:85:b8:
+ 05:fd:7f:be:65:11:a3:0f:c0:02:b4:f8:52:37:39:04:d5:a9:
+ 31:7a:18:bf:a0:2a:f4:12:99:f7:a3:45:82:e3:3c:5e:f5:9d:
+ 9e:b5:c8:9e:7c:2e:c8:a4:9e:4e:08:14:4b:6d:fd:70:6d:6b:
+ 1a:63:bd:64:e6:1f:b7:ce:f0:f2:9f:2e:bb:1b:b7:f2:50:88:
+ 73:92:c2:e2:e3:16:8d:9a:32:02:ab:8e:18:dd:e9:10:11:ee:
+ 7e:35:ab:90:af:3e:30:94:7a:d0:33:3d:a7:65:0f:f5:fc:8e:
+ 9e:62:cf:47:44:2c:01:5d:bb:1d:b5:32:d2:47:d2:38:2e:d0:
+ fe:81:dc:32:6a:1e:b5:ee:3c:d5:fc:e7:81:1d:19:c3:24:42:
+ ea:63:39:a9
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
+RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
+VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
+DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
+ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
+VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
+mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
+IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
+mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
+XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
+dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
+jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
+BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
+DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
+9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
+jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
+Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
+ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
+R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem
new file mode 100644
index 00000000000..3000f05e051
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem
@@ -0,0 +1,54 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 1f:47:af:aa:62:00:70:50:54:4c:01:9e:9b:63:99:2a
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO ECC Certification Authority
+ Validity
+ Not Before: Mar 6 00:00:00 2008 GMT
+ Not After : Jan 18 23:59:59 2038 GMT
+ Subject: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO ECC Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:03:47:7b:2f:75:c9:82:15:85:fb:75:e4:91:16:
+ d4:ab:62:99:f5:3e:52:0b:06:ce:41:00:7f:97:e1:
+ 0a:24:3c:1d:01:04:ee:3d:d2:8d:09:97:0c:e0:75:
+ e4:fa:fb:77:8a:2a:f5:03:60:4b:36:8b:16:23:16:
+ ad:09:71:f4:4a:f4:28:50:b4:fe:88:1c:6e:3f:6c:
+ 2f:2f:09:59:5b:a5:5b:0b:33:99:e2:c3:3d:89:f9:
+ 6a:2c:ef:b2:d3:06:e9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 75:71:A7:19:48:19:BC:9D:9D:EA:41:47:DF:94:C4:48:77:99:D3:79
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:31:00:ef:03:5b:7a:ac:b7:78:0a:72:b7:88:df:ff:
+ b5:46:14:09:0a:fa:a0:e6:7d:08:c6:1a:87:bd:18:a8:73:bd:
+ 26:ca:60:0c:9d:ce:99:9f:cf:5c:0f:30:e1:be:14:31:ea:02:
+ 30:14:f4:93:3c:49:a7:33:7a:90:46:47:b3:63:7d:13:9b:4e:
+ b7:6f:18:37:80:53:fe:dd:20:e0:35:9a:36:d1:c7:01:b9:e6:
+ dc:dd:f3:ff:1d:2c:3a:16:57:d9:92:39:d6
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
+IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
+MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
+ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
+T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
+FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
+cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
+BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
+fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
+GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem
new file mode 100644
index 00000000000..a13da95e91f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem
@@ -0,0 +1,52 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 60:59:49:e0:26:2e:bb:55:f9:0a:77:8a:71:f9:4a:d8:6c
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: OU = GlobalSign ECC Root CA - R5, O = GlobalSign, CN = GlobalSign
+ Validity
+ Not Before: Nov 13 00:00:00 2012 GMT
+ Not After : Jan 19 03:14:07 2038 GMT
+ Subject: OU = GlobalSign ECC Root CA - R5, O = GlobalSign, CN = GlobalSign
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:47:45:0e:96:fb:7d:5d:bf:e9:39:d1:21:f8:9f:
+ 0b:b6:d5:7b:1e:92:3a:48:59:1c:f0:62:31:2d:c0:
+ 7a:28:fe:1a:a7:5c:b3:b6:cc:97:e7:45:d4:58:fa:
+ d1:77:6d:43:a2:c0:87:65:34:0a:1f:7a:dd:eb:3c:
+ 33:a1:c5:9d:4d:a4:6f:41:95:38:7f:c9:1e:84:eb:
+ d1:9e:49:92:87:94:87:0c:3a:85:4a:66:9f:9d:59:
+ 93:4d:97:61:06:86:4a
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 3D:E6:29:48:9B:EA:07:CA:21:44:4A:26:DE:6E:DE:D2:83:D0:9F:59
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:31:00:e5:69:12:c9:6e:db:c6:31:ba:09:41:e1:97:
+ f8:fb:fd:9a:e2:7d:12:c9:ed:7c:64:d3:cb:05:25:8b:56:d9:
+ a0:e7:5e:5d:4e:0b:83:9c:5b:76:29:a0:09:26:21:6a:62:02:
+ 30:71:d2:b5:8f:5c:ea:3b:e1:78:09:85:a8:75:92:3b:c8:5c:
+ fd:48:ef:0d:74:22:a8:08:e2:6e:c5:49:ce:c7:0c:bc:a7:61:
+ 69:f1:f7:3b:e1:2a:cb:f9:2b:f3:66:90:37
+-----BEGIN CERTIFICATE-----
+MIICHjCCAaSgAwIBAgIRYFlJ4CYuu1X5CneKcflK2GwwCgYIKoZIzj0EAwMwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI1MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI1MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAER0UOlvt9Xb/pOdEh+J8LttV7HpI6SFkc
+8GIxLcB6KP4ap1yztsyX50XUWPrRd21DosCHZTQKH3rd6zwzocWdTaRvQZU4f8ke
+hOvRnkmSh5SHDDqFSmafnVmTTZdhBoZKo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUPeYpSJvqB8ohREom3m7e0oPQn1kwCgYI
+KoZIzj0EAwMDaAAwZQIxAOVpEslu28YxuglB4Zf4+/2a4n0Sye18ZNPLBSWLVtmg
+515dTguDnFt2KaAJJiFqYgIwcdK1j1zqO+F4CYWodZI7yFz9SO8NdCKoCOJuxUnO
+xwy8p2Fp8fc74SrL+SvzZpA3
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem
new file mode 100644
index 00000000000..94058894ece
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem
@@ -0,0 +1,46 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 06:6c:9f:d5:74:97:36:66:3f:3b:0b:9a:d9:e8:9e:76:03:f2:4a
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, O = Amazon, CN = Amazon Root CA 3
+ Validity
+ Not Before: May 26 00:00:00 2015 GMT
+ Not After : May 26 00:00:00 2040 GMT
+ Subject: C = US, O = Amazon, CN = Amazon Root CA 3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:29:97:a7:c6:41:7f:c0:0d:9b:e8:01:1b:56:c6:
+ f2:52:a5:ba:2d:b2:12:e8:d2:2e:d7:fa:c9:c5:d8:
+ aa:6d:1f:73:81:3b:3b:98:6b:39:7c:33:a5:c5:4e:
+ 86:8e:80:17:68:62:45:57:7d:44:58:1d:b3:37:e5:
+ 67:08:eb:66:de
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ AB:B6:DB:D7:06:9E:37:AC:30:86:07:91:70:C7:9C:C4:19:B1:78:C0
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:46:02:21:00:e0:85:92:a3:17:b7:8d:f9:2b:06:a5:93:ac:
+ 1a:98:68:61:72:fa:e1:a1:d0:fb:1c:78:60:a6:43:99:c5:b8:
+ c4:02:21:00:9c:02:ef:f1:94:9c:b3:96:f9:eb:c6:2a:f8:b6:
+ 2c:fe:3a:90:14:16:d7:8c:63:24:48:1c:df:30:7d:d5:68:3b
+-----BEGIN CERTIFICATE-----
+MIIBtjCCAVugAwIBAgITBmyf1XSXNmY/Owua2eiedgPySjAKBggqhkjOPQQDAjA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSAzMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgMzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABCmXp8ZBf8ANm+gBG1bG8lKl
+ui2yEujSLtf6ycXYqm0fc4E7O5hrOXwzpcVOho6AF2hiRVd9RFgdszflZwjrZt6j
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSr
+ttvXBp43rDCGB5Fwx5zEGbF4wDAKBggqhkjOPQQDAgNJADBGAiEA4IWSoxe3jfkr
+BqWTrBqYaGFy+uGh0PsceGCmQ5nFuMQCIQCcAu/xlJyzlvnrxir4tiz+OpAUFteM
+YyRIHN8wfdVoOw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem
new file mode 100644
index 00000000000..dd471d1edef
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem
@@ -0,0 +1,136 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1478 (0x5c6)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 3
+ Validity
+ Not Before: Nov 24 19:11:23 2006 GMT
+ Not After : Nov 24 19:06:44 2031 GMT
+ Subject: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:cc:57:42:16:54:9c:e6:98:d3:d3:4d:ee:fe:ed:
+ c7:9f:43:39:4a:65:b3:e8:16:88:34:db:0d:59:91:
+ 74:cf:92:b8:04:40:ad:02:4b:31:ab:bc:8d:91:68:
+ d8:20:0e:1a:01:e2:1a:7b:4e:17:5d:e2:8a:b7:3f:
+ 99:1a:cd:eb:61:ab:c2:65:a6:1f:b7:b7:bd:b7:8f:
+ fc:fd:70:8f:0b:a0:67:be:01:a2:59:cf:71:e6:0f:
+ 29:76:ff:b1:56:79:45:2b:1f:9e:7a:54:e8:a3:29:
+ 35:68:a4:01:4f:0f:a4:2e:37:ef:1b:bf:e3:8f:10:
+ a8:72:ab:58:57:e7:54:86:c8:c9:f3:5b:da:2c:da:
+ 5d:8e:6e:3c:a3:3e:da:fb:82:e5:dd:f2:5c:b2:05:
+ 33:6f:8a:36:ce:d0:13:4e:ff:bf:4a:0c:34:4c:a6:
+ c3:21:bd:50:04:55:eb:b1:bb:9d:fb:45:1e:64:15:
+ de:55:01:8c:02:76:b5:cb:a1:3f:42:69:bc:2f:bd:
+ 68:43:16:56:89:2a:37:61:91:fd:a6:ae:4e:c0:cb:
+ 14:65:94:37:4b:92:06:ef:04:d0:c8:9c:88:db:0b:
+ 7b:81:af:b1:3d:2a:c4:65:3a:78:b6:ee:dc:80:b1:
+ d2:d3:99:9c:3a:ee:6b:5a:6b:b3:8d:b7:d5:ce:9c:
+ c2:be:a5:4b:2f:16:b1:9e:68:3b:06:6f:ae:7d:9f:
+ f8:de:ec:cc:29:a7:98:a3:25:43:2f:ef:f1:5f:26:
+ e1:88:4d:f8:5e:6e:d7:d9:14:6e:19:33:69:a7:3b:
+ 84:89:93:c4:53:55:13:a1:51:78:40:f8:b8:c9:a2:
+ ee:7b:ba:52:42:83:9e:14:ed:05:52:5a:59:56:a7:
+ 97:fc:9d:3f:0a:29:d8:dc:4f:91:0e:13:bc:de:95:
+ a4:df:8b:99:be:ac:9b:33:88:ef:b5:81:af:1b:c6:
+ 22:53:c8:f6:c7:ee:97:14:b0:c5:7c:78:52:c8:f0:
+ ce:6e:77:60:84:a6:e9:2a:76:20:ed:58:01:17:30:
+ 93:e9:1a:8b:e0:73:63:d9:6a:92:94:49:4e:b4:ad:
+ 4a:85:c4:a3:22:30:fc:09:ed:68:22:73:a6:88:0c:
+ 55:21:58:c5:e1:3a:9f:2a:dd:ca:e1:90:e0:d9:73:
+ ab:6c:80:b8:e8:0b:64:93:a0:9c:8c:19:ff:b3:d2:
+ 0c:ec:91:26:87:8a:b3:a2:e1:70:8f:2c:0a:e5:cd:
+ 6d:68:51:eb:da:3f:05:7f:8b:32:e6:13:5c:6b:fe:
+ 5f:40:e2:22:c8:b4:b4:64:4f:d6:ba:7d:48:3e:a8:
+ 69:0c:d7:bb:86:71:c9:73:b8:3f:3b:9d:25:4b:da:
+ ff:40:eb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.8024.0.3
+ User Notice:
+ Explicit Text: Any use of this Certificate constitutes acceptance of the QuoVadis Root CA 3 Certificate Policy / Certification Practice Statement.
+ CPS: http://www.quovadisglobal.com/cps
+
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0
+ X509v3 Authority Key Identifier:
+ keyid:F2:C0:13:E0:82:43:3E:FB:EE:2F:67:32:96:35:5C:DB:B8:CB:02:D0
+ DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 3
+ serial:05:C6
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 4f:ad:a0:2c:4c:fa:c0:f2:6f:f7:66:55:ab:23:34:ee:e7:29:
+ da:c3:5b:b6:b0:83:d9:d0:d0:e2:21:fb:f3:60:a7:3b:5d:60:
+ 53:27:a2:9b:f6:08:22:2a:e7:bf:a0:72:e5:9c:24:6a:31:b1:
+ 90:7a:27:db:84:11:89:27:a6:77:5a:38:d7:bf:ac:86:fc:ee:
+ 5d:83:bc:06:c6:d1:77:6b:0f:6d:24:2f:4b:7a:6c:a7:07:96:
+ ca:e3:84:9f:ad:88:8b:1d:ab:16:8d:5b:66:17:d9:16:f4:8b:
+ 80:d2:dd:f8:b2:76:c3:fc:38:13:aa:0c:de:42:69:2b:6e:f3:
+ 3c:eb:80:27:db:f5:a6:44:0d:9f:5a:55:59:0b:d5:0d:52:48:
+ c5:ae:9f:f2:2f:80:c5:ea:32:50:35:12:97:2e:c1:e1:ff:f1:
+ 23:88:51:38:9f:f2:66:56:76:e7:0f:51:97:a5:52:0c:4d:49:
+ 51:95:36:3d:bf:a2:4b:0c:10:1d:86:99:4c:aa:f3:72:11:93:
+ e4:ea:f6:9b:da:a8:5d:a7:4d:b7:9e:02:ae:73:00:c8:da:23:
+ 03:e8:f9:ea:19:74:62:00:94:cb:22:20:be:94:a7:59:b5:82:
+ 6a:be:99:79:7a:a9:f2:4a:24:52:f7:74:fd:ba:4e:e6:a8:1d:
+ 02:6e:b1:0d:80:44:c1:ae:d3:23:37:5f:bb:85:7c:2b:92:2e:
+ e8:7e:a5:8b:dd:99:e1:bf:27:6f:2d:5d:aa:7b:87:fe:0a:dd:
+ 4b:fc:8e:f5:26:e4:6e:70:42:6e:33:ec:31:9e:7b:93:c1:e4:
+ c9:69:1a:3d:c0:6b:4e:22:6d:ee:ab:58:4d:c6:d0:41:c1:2b:
+ ea:4f:12:87:5e:eb:45:d8:6c:f5:98:02:d3:a0:d8:55:8a:06:
+ 99:19:a2:a0:77:d1:30:9e:ac:cc:75:ee:83:f5:b0:62:39:cf:
+ 6c:57:e2:4c:d2:91:0b:0e:75:28:1b:9a:bf:fd:1a:43:f1:ca:
+ 77:fb:3b:8f:61:b8:69:28:16:42:04:5e:70:2a:1c:21:d8:8f:
+ e1:bd:23:5b:2d:74:40:92:d9:63:19:0d:73:dd:69:bc:62:47:
+ bc:e0:74:2b:b2:eb:7d:be:41:1b:b5:c0:46:c5:a1:22:cb:5f:
+ 4e:c1:28:92:de:18:ba:d5:2a:28:bb:11:8b:17:93:98:99:60:
+ 94:5c:23:cf:5a:27:97:5e:0b:05:06:93:37:1e:3b:69:36:eb:
+ a9:9e:61:1d:8f:32:da:8e:0c:d6:74:3e:7b:09:24:da:01:77:
+ 47:c4:3b:cd:34:8c:99:f5:ca:e1:25:61:33:b2:59:1b:e2:6e:
+ d7:37:57:b6:0d:a9:12:da
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
+V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
+4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
+H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
+8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
+vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
+mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
+btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
+T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
+WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
+c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
+4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
+VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
+CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
+aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
+dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
+czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
+A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
+Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
+7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
+d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
++LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
+4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
+t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
+DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
+k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
+zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
+Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
+mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
+4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem
new file mode 100644
index 00000000000..0e8723d6d2d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 06:6c:9f:d2:96:35:86:9f:0a:0f:e5:86:78:f8:5b:26:bb:8a:37
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = Amazon, CN = Amazon Root CA 2
+ Validity
+ Not Before: May 26 00:00:00 2015 GMT
+ Not After : May 26 00:00:00 2040 GMT
+ Subject: C = US, O = Amazon, CN = Amazon Root CA 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ad:96:9f:2d:9c:4a:4c:4a:81:79:51:99:ec:8a:
+ cb:6b:60:51:13:bc:4d:6d:06:fc:b0:08:8d:dd:19:
+ 10:6a:c7:26:0c:35:d8:c0:6f:20:84:e9:94:b1:9b:
+ 85:03:c3:5b:db:4a:e8:c8:f8:90:76:d9:5b:4f:e3:
+ 4c:e8:06:36:4d:cc:9a:ac:3d:0c:90:2b:92:d4:06:
+ 19:60:ac:37:44:79:85:81:82:ad:5a:37:e0:0d:cc:
+ 9d:a6:4c:52:76:ea:43:9d:b7:04:d1:50:f6:55:e0:
+ d5:d2:a6:49:85:e9:37:e9:ca:7e:ae:5c:95:4d:48:
+ 9a:3f:ae:20:5a:6d:88:95:d9:34:b8:52:1a:43:90:
+ b0:bf:6c:05:b9:b6:78:b7:ea:d0:e4:3a:3c:12:53:
+ 62:ff:4a:f2:7b:be:35:05:a9:12:34:e3:f3:64:74:
+ 62:2c:3d:00:49:5a:28:fe:32:44:bb:87:dd:65:27:
+ 02:71:3b:da:4a:f7:1f:da:cd:f7:21:55:90:4f:0f:
+ ec:ae:82:e1:9f:6b:d9:45:d3:bb:f0:5f:87:ed:3c:
+ 2c:39:86:da:3f:de:ec:72:55:eb:79:a3:ad:db:dd:
+ 7c:b0:ba:1c:ce:fc:de:4f:35:76:cf:0f:f8:78:1f:
+ 6a:36:51:46:27:61:5b:e9:9e:cf:f0:a2:55:7d:7c:
+ 25:8a:6f:2f:b4:c5:cf:84:2e:2b:fd:0d:51:10:6c:
+ fb:5f:1b:bc:1b:7e:c5:ae:3b:98:01:31:92:ff:0b:
+ 57:f4:9a:b2:b9:57:e9:ab:ef:0d:76:d1:f0:ee:f4:
+ ce:86:a7:e0:6e:e9:b4:69:a1:df:69:f6:33:c6:69:
+ 2e:97:13:9e:a5:87:b0:57:10:81:37:c9:53:b3:bb:
+ 7f:f6:92:d1:9c:d0:18:f4:92:6e:da:83:4f:a6:63:
+ 99:4c:a5:fb:5e:ef:21:64:7a:20:5f:6c:64:85:15:
+ cb:37:e9:62:0c:0b:2a:16:dc:01:2e:32:da:3e:4b:
+ f5:9e:3a:f6:17:40:94:ef:9e:91:08:86:fa:be:63:
+ a8:5a:33:ec:cb:74:43:95:f9:6c:69:52:36:c7:29:
+ 6f:fc:55:03:5c:1f:fb:9f:bd:47:eb:e7:49:47:95:
+ 0b:4e:89:22:09:49:e0:f5:61:1e:f1:bf:2e:8a:72:
+ 6e:80:59:ff:57:3a:f9:75:32:a3:4e:5f:ec:ed:28:
+ 62:d9:4d:73:f2:cc:81:17:60:ed:cd:eb:dc:db:a7:
+ ca:c5:7e:02:bd:f2:54:08:54:fd:b4:2d:09:2c:17:
+ 54:4a:98:d1:54:e1:51:67:08:d2:ed:6e:7e:6f:3f:
+ d2:2d:81:59:29:66:cb:90:39:95:11:1e:74:27:fe:
+ dd:eb:af
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B0:0C:F0:4C:30:F4:05:58:02:48:FD:33:E5:52:AF:4B:84:E3:66:52
+ Signature Algorithm: sha384WithRSAEncryption
+ aa:a8:80:8f:0e:78:a3:e0:a2:d4:cd:e6:f5:98:7a:3b:ea:00:
+ 03:b0:97:0e:93:bc:5a:a8:f6:2c:8c:72:87:a9:b1:fc:7f:73:
+ fd:63:71:78:a5:87:59:cf:30:e1:0d:10:b2:13:5a:6d:82:f5:
+ 6a:e6:80:9f:a0:05:0b:68:e4:47:6b:c7:6a:df:b6:fd:77:32:
+ 72:e5:18:fa:09:f4:a0:93:2c:5d:d2:8c:75:85:76:65:90:0c:
+ 03:79:b7:31:23:63:ad:78:83:09:86:68:84:ca:ff:f9:cf:26:
+ 9a:92:79:e7:cd:4b:c5:e7:61:a7:17:cb:f3:a9:12:93:93:6b:
+ a7:e8:2f:53:92:c4:60:58:b0:cc:02:51:18:5b:85:8d:62:59:
+ 63:b6:ad:b4:de:9a:fb:26:f7:00:27:c0:5d:55:37:74:99:c9:
+ 50:7f:e3:59:2e:44:e3:2c:25:ee:ec:4c:32:77:b4:9f:1a:e9:
+ 4b:5d:20:c5:da:fd:1c:87:16:c6:43:e8:d4:bb:26:9a:45:70:
+ 5e:a9:0b:37:53:e2:46:7b:27:fd:e0:46:f2:89:b7:cc:42:b6:
+ cb:28:26:6e:d9:a5:c9:3a:c8:41:13:60:f7:50:8c:15:ae:b2:
+ 6d:1a:15:1a:57:78:e6:92:2a:d9:65:90:82:3f:6c:02:af:ae:
+ 12:3a:27:96:36:04:d7:1d:a2:80:63:a9:9b:f1:e5:ba:b4:7c:
+ 14:b0:4e:c9:b1:1f:74:5f:38:f6:51:ea:9b:fa:2c:a2:11:d4:
+ a9:2d:27:1a:45:b1:af:b2:4e:71:0d:c0:58:46:d6:69:06:cb:
+ 53:cb:b3:fe:6b:41:cd:41:7e:7d:4c:0f:7c:72:79:7a:59:cd:
+ 5e:4a:0e:ac:9b:a9:98:73:79:7c:b4:f4:cc:b9:b8:07:0c:b2:
+ 74:5c:b8:c7:6f:88:a1:90:a7:f4:aa:f9:bf:67:3a:f4:1a:15:
+ 62:1e:b7:9f:be:3d:b1:29:af:67:a1:12:f2:58:10:19:53:03:
+ 30:1b:b8:1a:89:f6:9c:bd:97:03:8e:a3:09:f3:1d:8b:21:f1:
+ b4:df:e4:1c:d1:9f:65:02:06:ea:5c:d6:13:b3:84:ef:a2:a5:
+ 5c:8c:77:29:a7:68:c0:6b:ae:40:d2:a8:b4:ea:cd:f0:8d:4b:
+ 38:9c:19:9a:1b:28:54:b8:89:90:ef:ca:75:81:3e:1e:f2:64:
+ 24:c7:18:af:4e:ff:47:9e:07:f6:35:65:a4:d3:0a:56:ff:f5:
+ 17:64:6c:ef:a8:22:25:49:93:b6:df:00:17:da:58:7e:5d:ee:
+ c5:1b:b0:d1:d1:5f:21:10:c7:f9:f3:ba:02:0a:27:07:c5:f1:
+ d6:c7:d3:e0:fb:09:60:6c
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgITBmyf0pY1hp8KD+WGePhbJruKNzANBgkqhkiG9w0BAQwF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAyMB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK2Wny2cSkxK
+gXlRmeyKy2tgURO8TW0G/LAIjd0ZEGrHJgw12MBvIITplLGbhQPDW9tK6Mj4kHbZ
+W0/jTOgGNk3Mmqw9DJArktQGGWCsN0R5hYGCrVo34A3MnaZMUnbqQ523BNFQ9lXg
+1dKmSYXpN+nKfq5clU1Imj+uIFptiJXZNLhSGkOQsL9sBbm2eLfq0OQ6PBJTYv9K
+8nu+NQWpEjTj82R0Yiw9AElaKP4yRLuH3WUnAnE72kr3H9rN9yFVkE8P7K6C4Z9r
+2UXTu/Bfh+08LDmG2j/e7HJV63mjrdvdfLC6HM783k81ds8P+HgfajZRRidhW+me
+z/CiVX18JYpvL7TFz4QuK/0NURBs+18bvBt+xa47mAExkv8LV/SasrlX6avvDXbR
+8O70zoan4G7ptGmh32n2M8ZpLpcTnqWHsFcQgTfJU7O7f/aS0ZzQGPSSbtqDT6Zj
+mUyl+17vIWR6IF9sZIUVyzfpYgwLKhbcAS4y2j5L9Z469hdAlO+ekQiG+r5jqFoz
+7Mt0Q5X5bGlSNscpb/xVA1wf+5+9R+vnSUeVC06JIglJ4PVhHvG/LopyboBZ/1c6
++XUyo05f7O0oYtlNc/LMgRdg7c3r3NunysV+Ar3yVAhU/bQtCSwXVEqY0VThUWcI
+0u1ufm8/0i2BWSlmy5A5lREedCf+3euvAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMB
+Af8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQWBBSwDPBMMPQFWAJI/TPlUq9LhONm
+UjANBgkqhkiG9w0BAQwFAAOCAgEAqqiAjw54o+Ci1M3m9Zh6O+oAA7CXDpO8Wqj2
+LIxyh6mx/H9z/WNxeKWHWc8w4Q0QshNabYL1auaAn6AFC2jkR2vHat+2/XcycuUY
++gn0oJMsXdKMdYV2ZZAMA3m3MSNjrXiDCYZohMr/+c8mmpJ5581LxedhpxfL86kS
+k5Nrp+gvU5LEYFiwzAJRGFuFjWJZY7attN6a+yb3ACfAXVU3dJnJUH/jWS5E4ywl
+7uxMMne0nxrpS10gxdr9HIcWxkPo1LsmmkVwXqkLN1PiRnsn/eBG8om3zEK2yygm
+btmlyTrIQRNg91CMFa6ybRoVGld45pIq2WWQgj9sAq+uEjonljYE1x2igGOpm/Hl
+urR8FLBOybEfdF849lHqm/osohHUqS0nGkWxr7JOcQ3AWEbWaQbLU8uz/mtBzUF+
+fUwPfHJ5elnNXkoOrJupmHN5fLT0zLm4BwyydFy4x2+IoZCn9Kr5v2c69BoVYh63
+n749sSmvZ6ES8lgQGVMDMBu4Gon2nL2XA46jCfMdiyHxtN/kHNGfZQIG6lzWE7OE
+76KlXIx3KadowGuuQNKotOrN8I1LOJwZmhsoVLiJkO/KdYE+HvJkJMcYr07/R54H
+9jVlpNMKVv/1F2Rs76giJUmTtt8AF9pYfl3uxRuw0dFfIRDH+fO6AgonB8Xx1sfT
+4PsJYGw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem
new file mode 100644
index 00000000000..17ec3a9d91f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem
@@ -0,0 +1,56 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3182246526754555285 (0x2c299c5b16ed0595)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com EV Root Certification Authority ECC
+ Validity
+ Not Before: Feb 12 18:15:23 2016 GMT
+ Not After : Feb 12 18:15:23 2041 GMT
+ Subject: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com EV Root Certification Authority ECC
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:aa:12:47:90:98:1b:fb:ef:c3:40:07:83:20:4e:
+ f1:30:82:a2:06:d1:f2:92:86:61:f2:f6:21:68:ca:
+ 00:c4:c7:ea:43:00:54:86:dc:fd:1f:df:00:b8:41:
+ 62:5c:dc:70:16:32:de:1f:99:d4:cc:c5:07:c8:08:
+ 1f:61:16:07:51:3d:7d:5c:07:53:e3:35:38:8c:df:
+ cd:9f:d9:2e:0d:4a:b6:19:2e:5a:70:5a:06:ed:be:
+ f0:a1:b0:ca:d0:09:29
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:5B:CA:5E:E5:DE:D2:81:AA:CD:A8:2D:64:51:B6:D9:72:9B:97:E6:4F
+
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:65:02:31:00:8a:e6:40:89:37:eb:e9:d5:13:d9:ca:d4:6b:
+ 24:f3:b0:3d:87:46:58:1a:ec:b1:df:6f:fb:56:ba:70:6b:c7:
+ 38:cc:e8:b1:8c:4f:0f:f7:f1:67:76:0e:83:d0:1e:51:8f:02:
+ 30:3d:f6:23:28:26:4c:c6:60:87:93:26:9b:b2:35:1e:ba:d6:
+ f7:3c:d1:1c:ce:fa:25:3c:a6:1a:81:15:5b:f3:12:0f:6c:ee:
+ 65:8a:c9:87:a8:f9:07:e0:62:9a:8c:5c:4a
+-----BEGIN CERTIFICATE-----
+MIIClDCCAhqgAwIBAgIILCmcWxbtBZUwCgYIKoZIzj0EAwIwfzELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xNDAyBgNVBAMMK1NTTC5jb20gRVYgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNTIzWhcNNDEwMjEyMTgx
+NTIzWjB/MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjE0MDIGA1UEAwwrU1NMLmNv
+bSBFViBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49
+AgEGBSuBBAAiA2IABKoSR5CYG/vvw0AHgyBO8TCCogbR8pKGYfL2IWjKAMTH6kMA
+VIbc/R/fALhBYlzccBYy3h+Z1MzFB8gIH2EWB1E9fVwHU+M1OIzfzZ/ZLg1Kthku
+WnBaBu2+8KGwytAJKaNjMGEwHQYDVR0OBBYEFFvKXuXe0oGqzagtZFG22XKbl+ZP
+MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUW8pe5d7SgarNqC1kUbbZcpuX
+5k8wDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2gAMGUCMQCK5kCJN+vp1RPZ
+ytRrJPOwPYdGWBrssd9v+1a6cGvHOMzosYxPD/fxZ3YOg9AeUY8CMD32IygmTMZg
+h5Mmm7I1HrrW9zzRHM76JTymGoEVW/MSD2zuZYrJh6j5B+BimoxcSg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem
new file mode 100644
index 00000000000..314a93406a8
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem
@@ -0,0 +1,124 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ b0:b7:5a:16:48:5f:bf:e1:cb:f5:8b:d7:19:e6:7d
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = ES, O = IZENPE S.A., CN = Izenpe.com
+ Validity
+ Not Before: Dec 13 13:08:28 2007 GMT
+ Not After : Dec 13 08:27:25 2037 GMT
+ Subject: C = ES, O = IZENPE S.A., CN = Izenpe.com
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c9:d3:7a:ca:0f:1e:ac:a7:86:e8:16:65:6a:b1:
+ c2:1b:45:32:71:95:d9:fe:10:5b:cc:af:e7:a5:79:
+ 01:8f:89:c3:ca:f2:55:71:f7:77:be:77:94:f3:72:
+ a4:2c:44:d8:9e:92:9b:14:3a:a1:e7:24:90:0a:0a:
+ 56:8e:c5:d8:26:94:e1:d9:48:e1:2d:3e:da:0a:72:
+ dd:a3:99:15:da:81:a2:87:f4:7b:6e:26:77:89:58:
+ ad:d6:eb:0c:b2:41:7a:73:6e:6d:db:7a:78:41:e9:
+ 08:88:12:7e:87:2e:66:11:63:6c:54:fb:3c:9d:72:
+ c0:bc:2e:ff:c2:b7:dd:0d:76:e3:3a:d7:f7:b4:68:
+ be:a2:f5:e3:81:6e:c1:46:6f:5d:8d:e0:4d:c6:54:
+ 55:89:1a:33:31:0a:b1:57:b9:a3:8a:98:c3:ec:3b:
+ 34:c5:95:41:69:7e:75:c2:3c:20:c5:61:ba:51:47:
+ a0:20:90:93:a1:90:4b:f3:4e:7c:85:45:54:9a:d1:
+ 05:26:41:b0:b5:4d:1d:33:be:c4:03:c8:25:7c:c1:
+ 70:db:3b:f4:09:2d:54:27:48:ac:2f:e1:c4:ac:3e:
+ c8:cb:92:4c:53:39:37:23:ec:d3:01:f9:e0:09:44:
+ 4d:4d:64:c0:e1:0d:5a:87:22:bc:ad:1b:a3:fe:26:
+ b5:15:f3:a7:fc:84:19:e9:ec:a1:88:b4:44:69:84:
+ 83:f3:89:d1:74:06:a9:cc:0b:d6:c2:de:27:85:50:
+ 26:ca:17:b8:c9:7a:87:56:2c:1a:01:1e:6c:be:13:
+ ad:10:ac:b5:24:f5:38:91:a1:d6:4b:da:f1:bb:d2:
+ de:47:b5:f1:bc:81:f6:59:6b:cf:19:53:e9:8d:15:
+ cb:4a:cb:a9:6f:44:e5:1b:41:cf:e1:86:a7:ca:d0:
+ 6a:9f:bc:4c:8d:06:33:5a:a2:85:e5:90:35:a0:62:
+ 5c:16:4e:f0:e3:a2:fa:03:1a:b4:2c:71:b3:58:2c:
+ de:7b:0b:db:1a:0f:eb:de:21:1f:06:77:06:03:b0:
+ c9:ef:99:fc:c0:b9:4f:0b:86:28:fe:d2:b9:ea:e3:
+ da:a5:c3:47:69:12:e0:db:f0:f6:19:8b:ed:7b:70:
+ d7:02:d6:ed:87:18:28:2c:04:24:4c:77:e4:48:8a:
+ 1a:c6:3b:9a:d4:0f:ca:fa:75:d2:01:40:5a:8d:79:
+ bf:8b:cf:4b:cf:aa:16:c1:95:e4:ad:4c:8a:3e:17:
+ 91:d4:b1:62:e5:82:e5:80:04:a4:03:7e:8d:bf:da:
+ 7f:a2:0f:97:4f:0c:d3:0d:fb:d7:d1:e5:72:7e:1c:
+ c8:77:ff:5b:9a:0f:b7:ae:05:46:e5:f1:a8:16:ec:
+ 47:a4:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Alternative Name:
+ email:info@izenpe.com, DirName:/O=IZENPE S.A. - CIF A01337260-RMerc.Vitoria-Gasteiz T1055 F62 S8/street=Avda del Mediterraneo Etorbidea 14 - 01010 Vitoria-Gasteiz
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 1D:1C:65:0E:A8:F2:25:7B:B4:91:CF:E4:B1:B1:E6:BD:55:74:6C:05
+ Signature Algorithm: sha256WithRSAEncryption
+ 78:a6:0c:16:4a:9f:4c:88:3a:c0:cb:0e:a5:16:7d:9f:b9:48:
+ 5f:18:8f:0d:62:36:f6:cd:19:6b:ac:ab:d5:f6:91:7d:ae:71:
+ f3:3f:b3:0e:78:85:9b:95:a4:27:21:47:42:4a:7c:48:3a:f5:
+ 45:7c:b3:0c:8e:51:78:ac:95:13:de:c6:fd:7d:b8:1a:90:4c:
+ ab:92:03:c7:ed:42:01:ce:0f:d8:b1:fa:a2:92:e1:60:6d:ae:
+ 7a:6b:09:aa:c6:29:ee:68:49:67:30:80:24:7a:31:16:39:5b:
+ 7e:f1:1c:2e:dd:6c:09:ad:f2:31:c1:82:4e:b9:bb:f9:be:bf:
+ 2a:85:3f:c0:40:a3:3a:59:fc:59:4b:3c:28:24:db:b4:15:75:
+ ae:0d:88:ba:2e:73:c0:bd:58:87:e5:42:f2:eb:5e:ee:1e:30:
+ 22:99:cb:37:d1:c4:21:6c:81:ec:be:6d:26:e6:1c:e4:42:20:
+ 9e:47:b0:ac:83:59:70:2c:35:d6:af:36:34:b4:cd:3b:f8:32:
+ a8:ef:e3:78:89:fb:8d:45:2c:da:9c:b8:7e:40:1c:61:e7:3e:
+ a2:92:2c:4b:f2:cd:fa:98:b6:29:ff:f3:f2:7b:a9:1f:2e:a0:
+ 93:57:2b:de:85:03:f9:69:37:cb:9e:78:6a:05:b4:c5:31:78:
+ 89:ec:7a:a7:85:e1:b9:7b:3c:de:be:1e:79:84:ce:9f:70:0e:
+ 59:c2:35:2e:90:2a:31:d9:e4:45:7a:41:a4:2e:13:9b:34:0e:
+ 66:7b:49:ab:64:97:d0:46:c3:79:9d:72:50:63:a6:98:5b:06:
+ bd:48:6d:d8:39:83:70:e8:35:f0:05:d1:aa:bc:e3:db:c8:02:
+ ea:7c:fd:82:da:c2:5b:52:35:ae:98:3a:ad:ba:35:93:23:a7:
+ 1f:48:dd:35:46:98:b2:10:68:e4:a5:31:c2:0a:58:2e:19:81:
+ 10:c9:50:75:fc:ea:5a:16:ce:11:d7:ee:ef:50:88:2d:61:ff:
+ 3f:42:73:05:94:43:d5:8e:3c:4e:01:3a:19:a5:1f:46:4e:77:
+ d0:5d:e5:81:22:21:87:fe:94:7d:84:d8:93:ad:d6:68:43:48:
+ b2:db:eb:73:24:e7:91:7f:54:a4:b6:80:3e:9d:a3:3c:4c:72:
+ c2:57:c4:a0:d4:cc:38:27:ce:d5:06:9e:a2:48:d9:e9:9f:ce:
+ 82:70:36:93:9a:3b:df:96:21:e3:59:b7:0c:da:91:37:f0:fd:
+ 59:5a:b3:99:c8:69:6c:43:26:01:35:63:60:55:89:03:3a:75:
+ d8:ba:4a:d9:54:ff:ee:de:80:d8:2d:d1:38:d5:5e:2d:0b:98:
+ 7d:3e:6c:db:fc:26:88:c7
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
+MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
+ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
+VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
+b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
+scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
+xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
+LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
+uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
+yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
+rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
+BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
+hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
+QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
+HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
+Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
+QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
+BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
+A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
+laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
+awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
+JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
+LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
+VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
+LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
+UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
+QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
+QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem
new file mode 100644
index 00000000000..363c0719073
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 6e:47:a9:c5:4b:47:0c:0d:ec:33:d0:89:b9:1c:f4:e1
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R1
+ Validity
+ Not Before: Jun 22 00:00:00 2016 GMT
+ Not After : Jun 22 00:00:00 2036 GMT
+ Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b6:11:02:8b:1e:e3:a1:77:9b:3b:dc:bf:94:3e:
+ b7:95:a7:40:3c:a1:fd:82:f9:7d:32:06:82:71:f6:
+ f6:8c:7f:fb:e8:db:bc:6a:2e:97:97:a3:8c:4b:f9:
+ 2b:f6:b1:f9:ce:84:1d:b1:f9:c5:97:de:ef:b9:f2:
+ a3:e9:bc:12:89:5e:a7:aa:52:ab:f8:23:27:cb:a4:
+ b1:9c:63:db:d7:99:7e:f0:0a:5e:eb:68:a6:f4:c6:
+ 5a:47:0d:4d:10:33:e3:4e:b1:13:a3:c8:18:6c:4b:
+ ec:fc:09:90:df:9d:64:29:25:23:07:a1:b4:d2:3d:
+ 2e:60:e0:cf:d2:09:87:bb:cd:48:f0:4d:c2:c2:7a:
+ 88:8a:bb:ba:cf:59:19:d6:af:8f:b0:07:b0:9e:31:
+ f1:82:c1:c0:df:2e:a6:6d:6c:19:0e:b5:d8:7e:26:
+ 1a:45:03:3d:b0:79:a4:94:28:ad:0f:7f:26:e5:a8:
+ 08:fe:96:e8:3c:68:94:53:ee:83:3a:88:2b:15:96:
+ 09:b2:e0:7a:8c:2e:75:d6:9c:eb:a7:56:64:8f:96:
+ 4f:68:ae:3d:97:c2:84:8f:c0:bc:40:c0:0b:5c:bd:
+ f6:87:b3:35:6c:ac:18:50:7f:84:e0:4c:cd:92:d3:
+ 20:e9:33:bc:52:99:af:32:b5:29:b3:25:2a:b4:48:
+ f9:72:e1:ca:64:f7:e6:82:10:8d:e8:9d:c2:8a:88:
+ fa:38:66:8a:fc:63:f9:01:f9:78:fd:7b:5c:77:fa:
+ 76:87:fa:ec:df:b1:0e:79:95:57:b4:bd:26:ef:d6:
+ 01:d1:eb:16:0a:bb:8e:0b:b5:c5:c5:8a:55:ab:d3:
+ ac:ea:91:4b:29:cc:19:a4:32:25:4e:2a:f1:65:44:
+ d0:02:ce:aa:ce:49:b4:ea:9f:7c:83:b0:40:7b:e7:
+ 43:ab:a7:6c:a3:8f:7d:89:81:fa:4c:a5:ff:d5:8e:
+ c3:ce:4b:e0:b5:d8:b3:8e:45:cf:76:c0:ed:40:2b:
+ fd:53:0f:b0:a7:d5:3b:0d:b1:8a:a2:03:de:31:ad:
+ cc:77:ea:6f:7b:3e:d6:df:91:22:12:e6:be:fa:d8:
+ 32:fc:10:63:14:51:72:de:5d:d6:16:93:bd:29:68:
+ 33:ef:3a:66:ec:07:8a:26:df:13:d7:57:65:78:27:
+ de:5e:49:14:00:a2:00:7f:9a:a8:21:b6:a9:b1:95:
+ b0:a5:b9:0d:16:11:da:c7:6c:48:3c:40:e0:7e:0d:
+ 5a:cd:56:3c:d1:97:05:b9:cb:4b:ed:39:4b:9c:c4:
+ 3f:d2:55:13:6e:24:b0:d6:71:fa:f4:c1:ba:cc:ed:
+ 1b:f5:fe:81:41:d8:00:98:3d:3a:c8:ae:7a:98:37:
+ 18:05:95
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ E4:AF:2B:26:71:1A:2B:48:27:85:2F:52:66:2C:EF:F0:89:13:71:3E
+ Signature Algorithm: sha384WithRSAEncryption
+ 38:96:0a:ee:3d:b4:96:1e:5f:ef:9d:9c:0b:33:9f:2b:e0:ca:
+ fd:d2:8e:0a:1f:41:74:a5:7c:aa:84:d4:e5:f2:1e:e6:37:52:
+ 32:9c:0b:d1:61:1d:bf:28:c1:b6:44:29:35:75:77:98:b2:7c:
+ d9:bd:74:ac:8a:68:e3:a9:31:09:29:01:60:73:e3:47:7c:53:
+ a8:90:4a:27:ef:4b:d7:9f:93:e7:82:36:ce:9a:68:0c:82:e7:
+ cf:d4:10:16:6f:5f:0e:99:5c:f6:1f:71:7d:ef:ef:7b:2f:7e:
+ ea:36:d6:97:70:0b:15:ee:d7:5c:56:6a:33:a5:e3:49:38:0c:
+ b8:7d:fb:8d:85:a4:b1:59:5e:f4:6a:e1:dd:a1:f6:64:44:ae:
+ e6:51:83:21:66:c6:11:3e:f3:ce:47:ee:9c:28:1f:25:da:ff:
+ ac:66:95:dd:35:0f:5c:ef:20:2c:62:fd:91:ba:a9:cc:fc:5a:
+ 9c:93:81:83:29:97:4a:7c:5a:72:b4:39:d0:b7:77:cb:79:fd:
+ 69:3a:92:37:ed:6e:38:65:46:7e:e9:60:bd:79:88:97:5f:38:
+ 12:f4:ee:af:5b:82:c8:86:d5:e1:99:6d:8c:04:f2:76:ba:49:
+ f6:6e:e9:6d:1e:5f:a0:ef:27:82:76:40:f8:a6:d3:58:5c:0f:
+ 2c:42:da:42:c6:7b:88:34:c7:c1:d8:45:9b:c1:3e:c5:61:1d:
+ d9:63:50:49:f6:34:85:6a:e0:18:c5:6e:47:ab:41:42:29:9b:
+ f6:60:0d:d2:31:d3:63:98:23:93:5a:00:81:48:b4:ef:cd:8a:
+ cd:c9:cf:99:ee:d9:9e:aa:36:e1:68:4b:71:49:14:36:28:3a:
+ 3d:1d:ce:9a:8f:25:e6:80:71:61:2b:b5:7b:cc:f9:25:16:81:
+ e1:31:5f:a1:a3:7e:16:a4:9c:16:6a:97:18:bd:76:72:a5:0b:
+ 9e:1d:36:e6:2f:a1:2f:be:70:91:0f:a8:e6:da:f8:c4:92:40:
+ 6c:25:7e:7b:b3:09:dc:b2:17:ad:80:44:f0:68:a5:8f:94:75:
+ ff:74:5a:e8:a8:02:7c:0c:09:e2:a9:4b:0b:a0:85:0b:62:b9:
+ ef:a1:31:92:fb:ef:f6:51:04:89:6c:e8:a9:74:a1:bb:17:b3:
+ b5:fd:49:0f:7c:3c:ec:83:18:20:43:4e:d5:93:ba:b4:34:b1:
+ 1f:16:36:1f:0c:e6:64:39:16:4c:dc:e0:fe:1d:c8:a9:62:3d:
+ 40:ea:ca:c5:34:02:b4:ae:89:88:33:35:dc:2c:13:73:d8:27:
+ f1:d0:72:ee:75:3b:22:de:98:68:66:5b:f1:c6:63:47:55:1c:
+ ba:a5:08:51:75:a6:48:25
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxUtHDA3sM9CJuRz04TANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjEwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQC2EQKLHuOhd5s73L+UPreVp0A8of2C+X0yBoJx9vaM
+f/vo27xqLpeXo4xL+Sv2sfnOhB2x+cWX3u+58qPpvBKJXqeqUqv4IyfLpLGcY9vX
+mX7wCl7raKb0xlpHDU0QM+NOsROjyBhsS+z8CZDfnWQpJSMHobTSPS5g4M/SCYe7
+zUjwTcLCeoiKu7rPWRnWr4+wB7CeMfGCwcDfLqZtbBkOtdh+JhpFAz2weaSUKK0P
+fyblqAj+lug8aJRT7oM6iCsVlgmy4HqMLnXWnOunVmSPlk9orj2XwoSPwLxAwAtc
+vfaHszVsrBhQf4TgTM2S0yDpM7xSma8ytSmzJSq0SPly4cpk9+aCEI3oncKKiPo4
+Zor8Y/kB+Xj9e1x3+naH+uzfsQ55lVe0vSbv1gHR6xYKu44LtcXFilWr06zqkUsp
+zBmkMiVOKvFlRNACzqrOSbTqn3yDsEB750Orp2yjj32JgfpMpf/VjsPOS+C12LOO
+Rc92wO1AK/1TD7Cn1TsNsYqiA94xrcx36m97PtbfkSIS5r762DL8EGMUUXLeXdYW
+k70paDPvOmbsB4om3xPXV2V4J95eSRQAogB/mqghtqmxlbCluQ0WEdrHbEg8QOB+
+DVrNVjzRlwW5y0vtOUucxD/SVRNuJLDWcfr0wbrM7Rv1/oFB2ACYPTrIrnqYNxgF
+lQIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQU5K8rJnEaK0gnhS9SZizv8IkTcT4wDQYJKoZIhvcNAQEMBQADggIBADiW
+Cu49tJYeX++dnAsznyvgyv3SjgofQXSlfKqE1OXyHuY3UjKcC9FhHb8owbZEKTV1
+d5iyfNm9dKyKaOOpMQkpAWBz40d8U6iQSifvS9efk+eCNs6aaAyC58/UEBZvXw6Z
+XPYfcX3v73svfuo21pdwCxXu11xWajOl40k4DLh9+42FpLFZXvRq4d2h9mREruZR
+gyFmxhE+885H7pwoHyXa/6xmld01D1zvICxi/ZG6qcz8WpyTgYMpl0p8WnK0OdC3
+d8t5/Wk6kjftbjhlRn7pYL15iJdfOBL07q9bgsiG1eGZbYwE8na6SfZu6W0eX6Dv
+J4J2QPim01hcDyxC2kLGe4g0x8HYRZvBPsVhHdljUEn2NIVq4BjFbkerQUIpm/Zg
+DdIx02OYI5NaAIFItO/Nis3Jz5nu2Z6qNuFoS3FJFDYoOj0dzpqPJeaAcWErtXvM
++SUWgeExX6GjfhaknBZqlxi9dnKlC54dNuYvoS++cJEPqOba+MSSQGwlfnuzCdyy
+F62ARPBopY+Udf90WuioAnwMCeKpSwughQtiue+hMZL77/ZRBIls6Kl0obsXs7X9
+SQ98POyDGCBDTtWTurQ0sR8WNh8M5mQ5Fkzc4P4dyKliPUDqysU0ArSuiYgzNdws
+E3PYJ/HQcu51OyLemGhmW/HGY0dVHLqlCFF1pkgl
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem
new file mode 100644
index 00000000000..f6e4c478f5b
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem
@@ -0,0 +1,123 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 45:e6:bb:03:83:33:c3:85:65:48:e6:ff:45:51
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: OU = GlobalSign Root CA - R6, O = GlobalSign, CN = GlobalSign
+ Validity
+ Not Before: Dec 10 00:00:00 2014 GMT
+ Not After : Dec 10 00:00:00 2034 GMT
+ Subject: OU = GlobalSign Root CA - R6, O = GlobalSign, CN = GlobalSign
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:95:07:e8:73:ca:66:f9:ec:14:ca:7b:3c:f7:0d:
+ 08:f1:b4:45:0b:2c:82:b4:48:c6:eb:5b:3c:ae:83:
+ b8:41:92:33:14:a4:6f:7f:e9:2a:cc:c6:b0:88:6b:
+ c5:b6:89:d1:c6:b2:ff:14:ce:51:14:21:ec:4a:dd:
+ 1b:5a:c6:d6:87:ee:4d:3a:15:06:ed:64:66:0b:92:
+ 80:ca:44:de:73:94:4e:f3:a7:89:7f:4f:78:63:08:
+ c8:12:50:6d:42:66:2f:4d:b9:79:28:4d:52:1a:8a:
+ 1a:80:b7:19:81:0e:7e:c4:8a:bc:64:4c:21:1c:43:
+ 68:d7:3d:3c:8a:c5:b2:66:d5:90:9a:b7:31:06:c5:
+ be:e2:6d:32:06:a6:1e:f9:b9:eb:aa:a3:b8:bf:be:
+ 82:63:50:d0:f0:18:89:df:e4:0f:79:f5:ea:a2:1f:
+ 2a:d2:70:2e:7b:e7:bc:93:bb:6d:53:e2:48:7c:8c:
+ 10:07:38:ff:66:b2:77:61:7e:e0:ea:8c:3c:aa:b4:
+ a4:f6:f3:95:4a:12:07:6d:fd:8c:b2:89:cf:d0:a0:
+ 61:77:c8:58:74:b0:d4:23:3a:f7:5d:3a:ca:a2:db:
+ 9d:09:de:5d:44:2d:90:f1:81:cd:57:92:fa:7e:bc:
+ 50:04:63:34:df:6b:93:18:be:6b:36:b2:39:e4:ac:
+ 24:36:b7:f0:ef:b6:1c:13:57:93:b6:de:b2:f8:e2:
+ 85:b7:73:a2:b8:35:aa:45:f2:e0:9d:36:a1:6f:54:
+ 8a:f1:72:56:6e:2e:88:c5:51:42:44:15:94:ee:a3:
+ c5:38:96:9b:4e:4e:5a:0b:47:f3:06:36:49:77:30:
+ bc:71:37:e5:a6:ec:21:08:75:fc:e6:61:16:3f:77:
+ d5:d9:91:97:84:0a:6c:d4:02:4d:74:c0:14:ed:fd:
+ 39:fb:83:f2:5e:14:a1:04:b0:0b:e9:fe:ee:8f:e1:
+ 6e:0b:b2:08:b3:61:66:09:6a:b1:06:3a:65:96:59:
+ c0:f0:35:fd:c9:da:28:8d:1a:11:87:70:81:0a:a8:
+ 9a:75:1d:9e:3a:86:05:00:9e:db:80:d6:25:f9:dc:
+ 05:9e:27:59:4c:76:39:5b:ea:f9:a5:a1:d8:83:0f:
+ d1:ff:df:30:11:f9:85:cf:33:48:f5:ca:6d:64:14:
+ 2c:7a:58:4f:d3:4b:08:49:c5:95:64:1a:63:0e:79:
+ 3d:f5:b3:8c:ca:58:ad:9c:42:45:79:6e:0e:87:19:
+ 5c:54:b1:65:b6:bf:8c:9b:dc:13:e9:0d:6f:b8:2e:
+ dc:67:6e:c9:8b:11:b5:84:14:8a:00:19:70:83:79:
+ 91:97:91:d4:1a:27:bf:37:1e:32:07:d8:14:63:3c:
+ 28:4c:af
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ AE:6C:05:A3:93:13:E2:A2:E7:E2:D7:1C:D6:C7:F0:7F:C8:67:53:A0
+ X509v3 Authority Key Identifier:
+ keyid:AE:6C:05:A3:93:13:E2:A2:E7:E2:D7:1C:D6:C7:F0:7F:C8:67:53:A0
+
+ Signature Algorithm: sha384WithRSAEncryption
+ 83:25:ed:e8:d1:fd:95:52:cd:9e:c0:04:a0:91:69:e6:5c:d0:
+ 84:de:dc:ad:a2:4f:e8:47:78:d6:65:98:a9:5b:a8:3c:87:7c:
+ 02:8a:d1:6e:b7:16:73:e6:5f:c0:54:98:d5:74:be:c1:cd:e2:
+ 11:91:ad:23:18:3d:dd:e1:72:44:96:b4:95:5e:c0:7b:8e:99:
+ 78:16:43:13:56:57:b3:a2:b3:3b:b5:77:dc:40:72:ac:a3:eb:
+ 9b:35:3e:b1:08:21:a1:e7:c4:43:37:79:32:be:b5:e7:9c:2c:
+ 4c:bc:43:29:99:8e:30:d3:ac:21:e0:e3:1d:fa:d8:07:33:76:
+ 54:00:22:2a:b9:4d:20:2e:70:68:da:e5:53:fc:83:5c:d3:9d:
+ f2:ff:44:0c:44:66:f2:d2:e3:bd:46:00:1a:6d:02:ba:25:5d:
+ 8d:a1:31:51:dd:54:46:1c:4d:db:99:96:ef:1a:1c:04:5c:a6:
+ 15:ef:78:e0:79:fe:5d:db:3e:aa:4c:55:fd:9a:15:a9:6f:e1:
+ a6:fb:df:70:30:e9:c3:ee:42:46:ed:c2:93:05:89:fa:7d:63:
+ 7b:3f:d0:71:81:7c:00:e8:98:ae:0e:78:34:c3:25:fb:af:0a:
+ 9f:20:6b:dd:3b:13:8f:12:8c:e2:41:1a:48:7a:73:a0:77:69:
+ c7:b6:5c:7f:82:c8:1e:fe:58:1b:28:2b:a8:6c:ad:5e:6d:c0:
+ 05:d2:7b:b7:eb:80:fe:25:37:fe:02:9b:68:ac:42:5d:c3:ee:
+ f5:cc:dc:f0:50:75:d2:36:69:9c:e6:7b:04:df:6e:06:69:b6:
+ de:0a:09:48:59:87:eb:7b:14:60:7a:64:aa:69:43:ef:91:c7:
+ 4c:ec:18:dd:6c:ef:53:2d:8c:99:e1:5e:f2:72:3e:cf:54:c8:
+ bd:67:ec:a4:0f:4c:45:ff:d3:b9:30:23:07:4c:8f:10:bf:86:
+ 96:d9:99:5a:b4:99:57:1c:a4:cc:bb:15:89:53:ba:2c:05:0f:
+ e4:c4:9e:19:b1:18:34:d5:4c:9d:ba:ed:f7:1f:af:24:95:04:
+ 78:a8:03:bb:ee:81:e5:da:5f:7c:8b:4a:a1:90:74:25:a7:b3:
+ 3e:4b:c8:2c:56:bd:c7:c8:ef:38:e2:5c:92:f0:79:f7:9c:84:
+ ba:74:2d:61:01:20:7e:7e:d1:f2:4f:07:59:5f:8b:2d:43:52:
+ eb:46:0c:94:e1:f5:66:47:79:77:d5:54:5b:1f:ad:24:37:cb:
+ 45:5a:4e:a0:44:48:c8:d8:b0:99:c5:15:84:09:f6:d6:49:49:
+ c0:65:b8:e6:1a:71:6e:a0:a8:f1:82:e8:45:3e:6c:d6:02:d7:
+ 0a:67:83:05:5a:c9:a4:10
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIORea7A4Mzw4VlSOb/RVEwDQYJKoZIhvcNAQEMBQAwTDEg
+MB4GA1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjYxEzARBgNVBAoTCkdsb2Jh
+bFNpZ24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMTQxMjEwMDAwMDAwWhcNMzQx
+MjEwMDAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSNjET
+MBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAJUH6HPKZvnsFMp7PPcNCPG0RQssgrRI
+xutbPK6DuEGSMxSkb3/pKszGsIhrxbaJ0cay/xTOURQh7ErdG1rG1ofuTToVBu1k
+ZguSgMpE3nOUTvOniX9PeGMIyBJQbUJmL025eShNUhqKGoC3GYEOfsSKvGRMIRxD
+aNc9PIrFsmbVkJq3MQbFvuJtMgamHvm566qjuL++gmNQ0PAYid/kD3n16qIfKtJw
+LnvnvJO7bVPiSHyMEAc4/2ayd2F+4OqMPKq0pPbzlUoSB239jLKJz9CgYXfIWHSw
+1CM69106yqLbnQneXUQtkPGBzVeS+n68UARjNN9rkxi+azayOeSsJDa38O+2HBNX
+k7besvjihbdzorg1qkXy4J02oW9UivFyVm4uiMVRQkQVlO6jxTiWm05OWgtH8wY2
+SXcwvHE35absIQh1/OZhFj931dmRl4QKbNQCTXTAFO39OfuD8l4UoQSwC+n+7o/h
+bguyCLNhZglqsQY6ZZZZwPA1/cnaKI0aEYdwgQqomnUdnjqGBQCe24DWJfncBZ4n
+WUx2OVvq+aWh2IMP0f/fMBH5hc8zSPXKbWQULHpYT9NLCEnFlWQaYw55PfWzjMpY
+rZxCRXluDocZXFSxZba/jJvcE+kNb7gu3GduyYsRtYQUigAZcIN5kZeR1Bonvzce
+MgfYFGM8KEyvAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBSubAWjkxPioufi1xzWx/B/yGdToDAfBgNVHSMEGDAWgBSu
+bAWjkxPioufi1xzWx/B/yGdToDANBgkqhkiG9w0BAQwFAAOCAgEAgyXt6NH9lVLN
+nsAEoJFp5lzQhN7craJP6Ed41mWYqVuoPId8AorRbrcWc+ZfwFSY1XS+wc3iEZGt
+Ixg93eFyRJa0lV7Ae46ZeBZDE1ZXs6KzO7V33EByrKPrmzU+sQghoefEQzd5Mr61
+55wsTLxDKZmOMNOsIeDjHfrYBzN2VAAiKrlNIC5waNrlU/yDXNOd8v9EDERm8tLj
+vUYAGm0CuiVdjaExUd1URhxN25mW7xocBFymFe944Hn+Xds+qkxV/ZoVqW/hpvvf
+cDDpw+5CRu3CkwWJ+n1jez/QcYF8AOiYrg54NMMl+68KnyBr3TsTjxKM4kEaSHpz
+oHdpx7Zcf4LIHv5YGygrqGytXm3ABdJ7t+uA/iU3/gKbaKxCXcPu9czc8FB10jZp
+nOZ7BN9uBmm23goJSFmH63sUYHpkqmlD75HHTOwY3WzvUy2MmeFe8nI+z1TIvWfs
+pA9MRf/TuTAjB0yPEL+GltmZWrSZVxykzLsViVO6LAUP5MSeGbEYNNVMnbrt9x+v
+JJUEeKgDu+6B5dpffItKoZB0JaezPkvILFa9x8jvOOJckvB595yEunQtYQEgfn7R
+8k8HWV+LLUNS60YMlOH1Zkd5d9VUWx+tJDfLRVpOoERIyNiwmcUVhAn21klJwGW4
+5hpxbqCo8YLoRT5s1gLXCmeDBVrJpBA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem
new file mode 100644
index 00000000000..3461891d54b
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Root Certificate Authority - G2
+ Validity
+ Not Before: Sep 1 00:00:00 2009 GMT
+ Not After : Dec 31 23:59:59 2037 GMT
+ Subject: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Root Certificate Authority - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bd:ed:c1:03:fc:f6:8f:fc:02:b1:6f:5b:9f:48:
+ d9:9d:79:e2:a2:b7:03:61:56:18:c3:47:b6:d7:ca:
+ 3d:35:2e:89:43:f7:a1:69:9b:de:8a:1a:fd:13:20:
+ 9c:b4:49:77:32:29:56:fd:b9:ec:8c:dd:22:fa:72:
+ dc:27:61:97:ee:f6:5a:84:ec:6e:19:b9:89:2c:dc:
+ 84:5b:d5:74:fb:6b:5f:c5:89:a5:10:52:89:46:55:
+ f4:b8:75:1c:e6:7f:e4:54:ae:4b:f8:55:72:57:02:
+ 19:f8:17:71:59:eb:1e:28:07:74:c5:9d:48:be:6c:
+ b4:f4:a4:b0:f3:64:37:79:92:c0:ec:46:5e:7f:e1:
+ 6d:53:4c:62:af:cd:1f:0b:63:bb:3a:9d:fb:fc:79:
+ 00:98:61:74:cf:26:82:40:63:f3:b2:72:6a:19:0d:
+ 99:ca:d4:0e:75:cc:37:fb:8b:89:c1:59:f1:62:7f:
+ 5f:b3:5f:65:30:f8:a7:b7:4d:76:5a:1e:76:5e:34:
+ c0:e8:96:56:99:8a:b3:f0:7f:a4:cd:bd:dc:32:31:
+ 7c:91:cf:e0:5f:11:f8:6b:aa:49:5c:d1:99:94:d1:
+ a2:e3:63:5b:09:76:b5:56:62:e1:4b:74:1d:96:d4:
+ 26:d4:08:04:59:d0:98:0e:0e:e6:de:fc:c3:ec:1f:
+ 90:f1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 7C:0C:32:1F:A7:D9:30:7F:C4:7D:68:A3:62:A8:A1:CE:AB:07:5B:27
+ Signature Algorithm: sha256WithRSAEncryption
+ 11:59:fa:25:4f:03:6f:94:99:3b:9a:1f:82:85:39:d4:76:05:
+ 94:5e:e1:28:93:6d:62:5d:09:c2:a0:a8:d4:b0:75:38:f1:34:
+ 6a:9d:e4:9f:8a:86:26:51:e6:2c:d1:c6:2d:6e:95:20:4a:92:
+ 01:ec:b8:8a:67:7b:31:e2:67:2e:8c:95:03:26:2e:43:9d:4a:
+ 31:f6:0e:b5:0c:bb:b7:e2:37:7f:22:ba:00:a3:0e:7b:52:fb:
+ 6b:bb:3b:c4:d3:79:51:4e:cd:90:f4:67:07:19:c8:3c:46:7a:
+ 0d:01:7d:c5:58:e7:6d:e6:85:30:17:9a:24:c4:10:e0:04:f7:
+ e0:f2:7f:d4:aa:0a:ff:42:1d:37:ed:94:e5:64:59:12:20:77:
+ 38:d3:32:3e:38:81:75:96:73:fa:68:8f:b1:cb:ce:1f:c5:ec:
+ fa:9c:7e:cf:7e:b1:f1:07:2d:b6:fc:bf:ca:a4:bf:d0:97:05:
+ 4a:bc:ea:18:28:02:90:bd:54:78:09:21:71:d3:d1:7d:1d:d9:
+ 16:b0:a9:61:3d:d0:0a:00:22:fc:c7:7b:cb:09:64:45:0b:3b:
+ 40:81:f7:7d:7c:32:f5:98:ca:58:8e:7d:2a:ee:90:59:73:64:
+ f9:36:74:5e:25:a1:f5:66:05:2e:7f:39:15:a9:2a:fb:50:8b:
+ 8e:85:69:f4
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVs
+ZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAw
+MFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQgVGVj
+aG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZp
+Y2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL3twQP89o/8ArFvW59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMg
+nLRJdzIpVv257IzdIvpy3Cdhl+72WoTsbhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1
+HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNkN3mSwOxGXn/hbVNMYq/N
+Hwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7NfZTD4p7dN
+dloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0
+HZbUJtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
+BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0G
+CSqGSIb3DQEBCwUAA4IBAQARWfolTwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjU
+sHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx4mcujJUDJi5DnUox9g61DLu3
+4jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUwF5okxBDgBPfg
+8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1
+mMpYjn0q7pBZc2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem
new file mode 100644
index 00000000000..fb4614a611d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem
@@ -0,0 +1,124 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6248227494352943350 (0x56b629cd34bc78f6)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com EV Root Certification Authority RSA R2
+ Validity
+ Not Before: May 31 18:14:37 2017 GMT
+ Not After : May 30 18:14:37 2042 GMT
+ Subject: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com EV Root Certification Authority RSA R2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:8f:36:65:40:e1:d6:4d:c0:d7:b4:e9:46:da:6b:
+ ea:33:47:cd:4c:f9:7d:7d:be:bd:2d:3d:f0:db:78:
+ e1:86:a5:d9:ba:09:57:68:ed:57:3e:a0:d0:08:41:
+ 83:e7:28:41:24:1f:e3:72:15:d0:01:1a:fb:5e:70:
+ 23:b2:cb:9f:39:e3:cf:c5:4e:c6:92:6d:26:c6:7b:
+ bb:b3:da:27:9d:0a:86:e9:81:37:05:fe:f0:71:71:
+ ec:c3:1c:e9:63:a2:17:14:9d:ef:1b:67:d3:85:55:
+ 02:02:d6:49:c9:cc:5a:e1:b1:f7:6f:32:9f:c9:d4:
+ 3b:88:41:a8:9c:bd:cb:ab:db:6d:7b:09:1f:a2:4c:
+ 72:90:da:2b:08:fc:cf:3c:54:ce:67:0f:a8:cf:5d:
+ 96:19:0b:c4:e3:72:eb:ad:d1:7d:1d:27:ef:92:eb:
+ 10:bf:5b:eb:3b:af:cf:80:dd:c1:d2:96:04:5b:7a:
+ 7e:a4:a9:3c:38:76:a4:62:8e:a0:39:5e:ea:77:cf:
+ 5d:00:59:8f:66:2c:3e:07:a2:a3:05:26:11:69:97:
+ ea:85:b7:0f:96:0b:4b:c8:40:e1:50:ba:2e:8a:cb:
+ f7:0f:9a:22:e7:7f:9a:37:13:cd:f2:4d:13:6b:21:
+ d1:c0:cc:22:f2:a1:46:f6:44:69:9c:ca:61:35:07:
+ 00:6f:d6:61:08:11:ea:ba:b8:f6:e9:b3:60:e5:4d:
+ b9:ec:9f:14:66:c9:57:58:db:cd:87:69:f8:8a:86:
+ 12:03:47:bf:66:13:76:ac:77:7d:34:24:85:83:cd:
+ d7:aa:9c:90:1a:9f:21:2c:7f:78:b7:64:b8:d8:e8:
+ a6:f4:78:b3:55:cb:84:d2:32:c4:78:ae:a3:8f:61:
+ dd:ce:08:53:ad:ec:88:fc:15:e4:9a:0d:e6:9f:1a:
+ 77:ce:4c:8f:b8:14:15:3d:62:9c:86:38:06:00:66:
+ 12:e4:59:76:5a:53:c0:02:98:a2:10:2b:68:44:7b:
+ 8e:79:ce:33:4a:76:aa:5b:81:16:1b:b5:8a:d8:d0:
+ 00:7b:5e:62:b4:09:d6:86:63:0e:a6:05:95:49:ba:
+ 28:8b:88:93:b2:34:1c:d8:a4:55:6e:b7:1c:d0:de:
+ 99:55:3b:23:f4:22:e0:f9:29:66:26:ec:20:50:77:
+ db:4a:0b:8f:be:e5:02:60:70:41:5e:d4:ae:50:39:
+ 22:14:26:cb:b2:3b:73:74:55:47:07:79:81:39:a8:
+ 30:13:44:e5:04:8a:ae:96:13:25:42:0f:b9:53:c4:
+ 9b:fc:cd:e4:1c:de:3c:fa:ab:d6:06:4a:1f:67:a6:
+ 98:30:1c:dd:2c:db:dc:18:95:57:66:c6:ff:5c:8b:
+ 56:f5:77
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E
+
+ X509v3 Subject Key Identifier:
+ F9:60:BB:D4:E3:D5:34:F6:B8:F5:06:80:25:A7:73:DB:46:69:A8:9E
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 56:b3:8e:cb:0a:9d:49:8e:bf:a4:c4:91:bb:66:17:05:51:98:
+ 75:fb:e5:50:2c:7a:9e:f1:14:fa:ab:d3:8a:3e:ff:91:29:8f:
+ 63:8b:d8:b4:a9:54:01:0d:be:93:86:2f:f9:4a:6d:c7:5e:f5:
+ 57:f9:ca:55:1c:12:be:47:0f:36:c5:df:6a:b7:db:75:c2:47:
+ 25:7f:b9:f1:63:f8:68:2d:55:04:d1:f2:8d:b0:a4:cf:bc:3c:
+ 5e:1f:78:e7:a5:a0:20:70:b0:04:c5:b7:f7:72:a7:de:22:0d:
+ bd:33:25:46:8c:64:92:26:e3:3e:2e:63:96:da:9b:8c:3d:f8:
+ 18:09:d7:03:cc:7d:86:82:e0:ca:04:07:51:50:d7:ff:92:d5:
+ 0c:ef:da:86:9f:99:d7:eb:b7:af:68:e2:39:26:94:ba:68:b7:
+ bf:83:d3:ea:7a:67:3d:62:67:ae:25:e5:72:e8:e2:e4:ec:ae:
+ 12:f6:4b:2b:3c:9f:e9:b0:40:f3:38:54:b3:fd:b7:68:c8:da:
+ c6:8f:51:3c:b2:fb:91:dc:1c:e7:9b:9d:e1:b7:0d:72:8f:e2:
+ a4:c4:a9:78:f9:eb:14:ac:c6:43:05:c2:65:39:28:18:02:c3:
+ 82:b2:9d:05:be:65:ed:96:5f:65:74:3c:fb:09:35:2e:7b:9c:
+ 13:fd:1b:0f:5d:c7:6d:81:3a:56:0f:cc:3b:e1:af:02:2f:22:
+ ac:46:ca:46:3c:a0:1c:4c:d6:44:b4:5e:2e:5c:15:66:09:e1:
+ 26:29:fe:c6:52:61:ba:b1:73:ff:c3:0c:9c:e5:6c:6a:94:3f:
+ 14:ca:40:16:95:84:f3:59:a9:ac:5f:4c:61:93:6d:d1:3b:cc:
+ a2:95:0c:22:a6:67:67:44:2e:b9:d9:d2:8a:41:b3:66:0b:5a:
+ fb:7d:23:a5:f2:1a:b0:ff:de:9b:83:94:2e:d1:3f:df:92:b7:
+ 91:af:05:3b:65:c7:a0:6c:b1:cd:62:12:c3:90:1b:e3:25:ce:
+ 34:bc:6f:77:76:b1:10:c3:f7:05:1a:c0:d6:af:74:62:48:17:
+ 77:92:69:90:61:1c:de:95:80:74:54:8f:18:1c:c3:f3:03:d0:
+ bf:a4:43:75:86:53:18:7a:0a:2e:09:1c:36:9f:91:fd:82:8a:
+ 22:4b:d1:0e:50:25:dd:cb:03:0c:17:c9:83:00:08:4e:35:4d:
+ 8a:8b:ed:f0:02:94:66:2c:44:7f:cb:95:27:96:17:ad:09:30:
+ ac:b6:71:17:6e:8b:17:f6:1c:09:d4:2d:3b:98:a5:71:d3:54:
+ 13:d9:60:f3:f5:4b:66:4f:fa:f1:ee:20:12:8d:b4:ac:57:b1:
+ 45:63:a1:ac:76:a9:c2:fb
+-----BEGIN CERTIFICATE-----
+MIIF6zCCA9OgAwIBAgIIVrYpzTS8ePYwDQYJKoZIhvcNAQELBQAwgYIxCzAJBgNV
+BAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4GA1UEBwwHSG91c3RvbjEYMBYGA1UE
+CgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQDDC5TU0wuY29tIEVWIFJvb3QgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIyMB4XDTE3MDUzMTE4MTQzN1oXDTQy
+MDUzMDE4MTQzN1owgYIxCzAJBgNVBAYTAlVTMQ4wDAYDVQQIDAVUZXhhczEQMA4G
+A1UEBwwHSG91c3RvbjEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMTcwNQYDVQQD
+DC5TU0wuY29tIEVWIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgUlNBIFIy
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAjzZlQOHWTcDXtOlG2mvq
+M0fNTPl9fb69LT3w23jhhqXZuglXaO1XPqDQCEGD5yhBJB/jchXQARr7XnAjssuf
+OePPxU7Gkm0mxnu7s9onnQqG6YE3Bf7wcXHswxzpY6IXFJ3vG2fThVUCAtZJycxa
+4bH3bzKfydQ7iEGonL3Lq9ttewkfokxykNorCPzPPFTOZw+oz12WGQvE43LrrdF9
+HSfvkusQv1vrO6/PgN3B0pYEW3p+pKk8OHakYo6gOV7qd89dAFmPZiw+B6KjBSYR
+aZfqhbcPlgtLyEDhULouisv3D5oi53+aNxPN8k0TayHRwMwi8qFG9kRpnMphNQcA
+b9ZhCBHqurj26bNg5U257J8UZslXWNvNh2n4ioYSA0e/ZhN2rHd9NCSFg83XqpyQ
+Gp8hLH94t2S42Oim9HizVcuE0jLEeK6jj2HdzghTreyI/BXkmg3mnxp3zkyPuBQV
+PWKchjgGAGYS5Fl2WlPAApiiECtoRHuOec4zSnaqW4EWG7WK2NAAe15itAnWhmMO
+pgWVSbooi4iTsjQc2KRVbrcc0N6ZVTsj9CLg+SlmJuwgUHfbSguPvuUCYHBBXtSu
+UDkiFCbLsjtzdFVHB3mBOagwE0TlBIqulhMlQg+5U8Sb/M3kHN48+qvWBkofZ6aY
+MBzdLNvcGJVXZsb/XItW9XcCAwEAAaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNV
+HSMEGDAWgBT5YLvU49U09rj1BoAlp3PbRmmonjAdBgNVHQ4EFgQU+WC71OPVNPa4
+9QaAJadz20ZpqJ4wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQBW
+s47LCp1Jjr+kxJG7ZhcFUZh1++VQLHqe8RT6q9OKPv+RKY9ji9i0qVQBDb6Thi/5
+Sm3HXvVX+cpVHBK+Rw82xd9qt9t1wkclf7nxY/hoLVUE0fKNsKTPvDxeH3jnpaAg
+cLAExbf3cqfeIg29MyVGjGSSJuM+LmOW2puMPfgYCdcDzH2GguDKBAdRUNf/ktUM
+79qGn5nX67evaOI5JpS6aLe/g9Pqemc9YmeuJeVy6OLk7K4S9ksrPJ/psEDzOFSz
+/bdoyNrGj1E8svuR3Bznm53htw1yj+KkxKl4+esUrMZDBcJlOSgYAsOCsp0FvmXt
+ll9ldDz7CTUue5wT/RsPXcdtgTpWD8w74a8CLyKsRspGPKAcTNZEtF4uXBVmCeEm
+Kf7GUmG6sXP/wwyc5WxqlD8UykAWlYTzWamsX0xhk23RO8yilQwipmdnRC652dKK
+QbNmC1r7fSOl8hqw/96bg5Qu0T/fkreRrwU7ZcegbLHNYhLDkBvjJc40vG93drEQ
+w/cFGsDWr3RiSBd3kmmQYRzelYB0VI8YHMPzA9C/pEN1hlMYegouCRw2n5H9gooi
+S9EOUCXdywMMF8mDAAhONU2Ki+3wApRmLER/y5UnlhetCTCstnEXbosX9hwJ1C07
+mKVx01QT2WDz9UtmT/rx7iASjbSsV7FFY6GsdqnC+w==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem
new file mode 100644
index 00000000000..b0acbfb921b
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0a:01:42:80:00:00:01:45:23:cf:46:7c:00:00:00:02
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = IdenTrust, CN = IdenTrust Public Sector Root CA 1
+ Validity
+ Not Before: Jan 16 17:53:32 2014 GMT
+ Not After : Jan 16 17:53:32 2034 GMT
+ Subject: C = US, O = IdenTrust, CN = IdenTrust Public Sector Root CA 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b6:22:94:fc:a4:48:af:e8:47:6b:0a:fb:27:76:
+ e4:f2:3f:8a:3b:7a:4a:2c:31:2a:8c:8d:b0:a9:c3:
+ 31:6b:a8:77:76:84:26:b6:ac:81:42:0d:08:eb:55:
+ 58:bb:7a:f8:bc:65:7d:f2:a0:6d:8b:a8:47:e9:62:
+ 76:1e:11:ee:08:14:d1:b2:44:16:f4:ea:d0:fa:1e:
+ 2f:5e:db:cb:73:41:ae:bc:00:b0:4a:2b:40:b2:ac:
+ e1:3b:4b:c2:2d:9d:e4:a1:9b:ec:1a:3a:1e:f0:08:
+ b3:d0:e4:24:35:07:9f:9c:b4:c9:52:6d:db:07:ca:
+ 8f:b5:5b:f0:83:f3:4f:c7:2d:a5:c8:ad:cb:95:20:
+ a4:31:28:57:58:5a:e4:8d:1b:9a:ab:9e:0d:0c:f2:
+ 0a:33:39:22:39:0a:97:2e:f3:53:77:b9:44:45:fd:
+ 84:cb:36:20:81:59:2d:9a:6f:6d:48:48:61:ca:4c:
+ df:53:d1:af:52:bc:44:9f:ab:2f:6b:83:72:ef:75:
+ 80:da:06:33:1b:5d:c8:da:63:c6:4d:cd:ac:66:31:
+ cd:d1:de:3e:87:10:36:e1:b9:a4:7a:ef:60:50:b2:
+ cb:ca:a6:56:e0:37:af:ab:34:13:39:25:e8:39:66:
+ e4:98:7a:aa:12:98:9c:59:66:86:3e:ad:f1:b0:ca:
+ 3e:06:0f:7b:f0:11:4b:37:a0:44:6d:7b:cb:a8:8c:
+ 71:f4:d5:b5:91:36:cc:f0:15:c6:2b:de:51:17:b1:
+ 97:4c:50:3d:b1:95:59:7c:05:7d:2d:21:d5:00:bf:
+ 01:67:a2:5e:7b:a6:5c:f2:f7:22:f1:90:0d:93:db:
+ aa:44:51:66:cc:7d:76:03:eb:6a:a8:2a:38:19:97:
+ 76:0d:6b:8a:61:f9:bc:f6:ee:76:fd:70:2b:dd:29:
+ 3c:f8:0a:1e:5b:42:1c:8b:56:2f:55:1b:1c:a1:2e:
+ b5:c7:16:e6:f8:aa:3c:92:8e:69:b6:01:c1:b5:86:
+ 9d:89:0f:0b:38:94:54:e8:ea:dc:9e:3d:25:bc:53:
+ 26:ed:d5:ab:39:aa:c5:40:4c:54:ab:b2:b4:d9:d9:
+ f8:d7:72:db:1c:bc:6d:bd:65:5f:ef:88:35:2a:66:
+ 2f:ee:f6:b3:65:f0:33:8d:7c:98:41:69:46:0f:43:
+ 1c:69:fa:9b:b5:d0:61:6a:cd:ca:4b:d9:4c:90:46:
+ ab:15:59:a1:47:54:29:2e:83:28:5f:1c:c2:a2:ab:
+ 72:17:00:06:8e:45:ec:8b:e2:33:3d:7f:da:19:44:
+ e4:62:72:c3:df:22:c6:f2:56:d4:dd:5f:95:72:ed:
+ 6d:5f:f7:48:03:5b:fd:c5:2a:a0:f6:73:23:84:10:
+ 1b:01:e7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ E3:71:E0:9E:D8:A7:42:D9:DB:71:91:6B:94:93:EB:C3:A3:D1:14:A3
+ Signature Algorithm: sha256WithRSAEncryption
+ 47:fa:dd:0a:b0:11:91:38:ad:4d:5d:f7:e5:0e:97:54:19:82:
+ 48:87:54:8c:aa:64:99:d8:5a:fe:88:01:c5:58:a5:99:b1:23:
+ 54:23:b7:6a:1d:20:57:e5:01:62:41:17:d3:09:db:75:cb:6e:
+ 54:90:75:fe:1a:9f:81:0a:c2:dd:d7:f7:09:d0:5b:72:15:e4:
+ 1e:09:6a:3d:33:f3:21:9a:e6:15:7e:ad:51:d5:0d:10:ed:7d:
+ 42:c0:8f:ee:c0:9a:08:d5:41:d6:5c:0e:21:69:6e:80:61:0e:
+ 15:c0:b8:cf:c5:49:12:52:cc:be:3a:cc:d4:2e:38:05:de:35:
+ fd:1f:6f:b8:80:68:98:3d:4d:a0:ca:40:65:d2:73:7c:f5:8b:
+ d9:0a:95:3f:d8:3f:23:6d:1a:d1:2a:24:19:d9:85:b3:17:ef:
+ 78:6e:a9:58:d1:23:d3:c7:13:ed:72:25:7f:5d:b1:73:70:d0:
+ 7f:06:97:09:84:29:80:61:1d:fa:5e:ff:73:ac:a0:e3:89:b8:
+ 1c:71:15:c6:de:31:7f:12:dc:e1:6d:9b:af:e7:e8:9f:75:78:
+ 4c:ab:46:3b:9a:ce:bf:05:18:5d:4d:15:3c:16:9a:19:50:04:
+ 9a:b2:9a:6f:65:8b:52:5f:3c:58:04:28:25:c0:66:61:31:7e:
+ b9:e0:75:b9:1a:a8:81:d6:72:17:b3:c5:03:31:35:11:78:78:
+ a2:e0:e9:30:8c:7f:80:df:58:df:3c:ba:27:96:e2:80:34:6d:
+ e3:98:d3:64:27:ac:48:7e:28:77:5c:c6:25:61:25:f8:85:0c:
+ 65:fa:c4:32:2f:a5:98:05:e4:f8:0b:67:16:16:c6:82:b8:32:
+ 19:f9:f9:b9:79:dc:1f:cd:eb:af:ab:0e:dd:1b:db:45:e4:7a:
+ e7:02:e2:95:5d:fc:69:f0:53:69:61:95:75:79:0b:5e:55:e6:
+ 38:1c:94:a9:59:33:9e:c8:71:74:79:7f:51:89:b6:c8:6a:b8:
+ 30:c8:6a:38:c3:6e:9e:e1:37:16:ea:05:62:4c:5b:12:47:ed:
+ a7:b4:b3:58:56:c7:49:f3:7f:12:68:09:31:71:f0:6d:f8:4e:
+ 47:fb:d6:85:ee:c5:58:40:19:a4:1d:a7:f9:4b:43:37:dc:68:
+ 5a:4f:cf:eb:c2:64:74:de:b4:15:d9:f4:54:54:1a:2f:1c:d7:
+ 97:71:54:90:8e:d9:20:9d:53:2b:7f:ab:8f:e2:ea:30:bc:50:
+ 37:ef:f1:47:b5:7d:7c:2c:04:ec:68:9d:b4:49:44:10:f4:72:
+ 4b:1c:64:e7:fc:e6:6b:90:dd:69:7d:69:fd:00:56:a5:b7:ac:
+ b6:ad:b7:ca:3e:01:ef:9c
+-----BEGIN CERTIFICATE-----
+MIIFZjCCA06gAwIBAgIQCgFCgAAAAUUjz0Z8AAAAAjANBgkqhkiG9w0BAQsFADBN
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MSowKAYDVQQDEyFJZGVu
+VHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwHhcNMTQwMTE2MTc1MzMyWhcN
+MzQwMTE2MTc1MzMyWjBNMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0
+MSowKAYDVQQDEyFJZGVuVHJ1c3QgUHVibGljIFNlY3RvciBSb290IENBIDEwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2IpT8pEiv6EdrCvsnduTyP4o7
+ekosMSqMjbCpwzFrqHd2hCa2rIFCDQjrVVi7evi8ZX3yoG2LqEfpYnYeEe4IFNGy
+RBb06tD6Hi9e28tzQa68ALBKK0CyrOE7S8ItneShm+waOh7wCLPQ5CQ1B5+ctMlS
+bdsHyo+1W/CD80/HLaXIrcuVIKQxKFdYWuSNG5qrng0M8gozOSI5Cpcu81N3uURF
+/YTLNiCBWS2ab21ISGHKTN9T0a9SvESfqy9rg3LvdYDaBjMbXcjaY8ZNzaxmMc3R
+3j6HEDbhuaR672BQssvKplbgN6+rNBM5Jeg5ZuSYeqoSmJxZZoY+rfGwyj4GD3vw
+EUs3oERte8uojHH01bWRNszwFcYr3lEXsZdMUD2xlVl8BX0tIdUAvwFnol57plzy
+9yLxkA2T26pEUWbMfXYD62qoKjgZl3YNa4ph+bz27nb9cCvdKTz4Ch5bQhyLVi9V
+GxyhLrXHFub4qjySjmm2AcG1hp2JDws4lFTo6tyePSW8Uybt1as5qsVATFSrsrTZ
+2fjXctscvG29ZV/viDUqZi/u9rNl8DONfJhBaUYPQxxp+pu10GFqzcpL2UyQRqsV
+WaFHVCkugyhfHMKiq3IXAAaOReyL4jM9f9oZRORicsPfIsbyVtTdX5Vy7W1f90gD
+W/3FKqD2cyOEEBsB5wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQU43HgntinQtnbcZFrlJPrw6PRFKMwDQYJKoZIhvcN
+AQELBQADggIBAEf63QqwEZE4rU1d9+UOl1QZgkiHVIyqZJnYWv6IAcVYpZmxI1Qj
+t2odIFflAWJBF9MJ23XLblSQdf4an4EKwt3X9wnQW3IV5B4Jaj0z8yGa5hV+rVHV
+DRDtfULAj+7AmgjVQdZcDiFpboBhDhXAuM/FSRJSzL46zNQuOAXeNf0fb7iAaJg9
+TaDKQGXSc3z1i9kKlT/YPyNtGtEqJBnZhbMX73huqVjRI9PHE+1yJX9dsXNw0H8G
+lwmEKYBhHfpe/3OsoOOJuBxxFcbeMX8S3OFtm6/n6J91eEyrRjuazr8FGF1NFTwW
+mhlQBJqymm9li1JfPFgEKCXAZmExfrngdbkaqIHWchezxQMxNRF4eKLg6TCMf4Df
+WN88uieW4oA0beOY02QnrEh+KHdcxiVhJfiFDGX6xDIvpZgF5PgLZxYWxoK4Mhn5
++bl53B/N66+rDt0b20XkeucC4pVd/GnwU2lhlXV5C15V5jgclKlZM57IcXR5f1GJ
+tshquDDIajjDbp7hNxbqBWJMWxJH7ae0s1hWx0nzfxJoCTFx8G34Tkf71oXuxVhA
+GaQdp/lLQzfcaFpPz+vCZHTetBXZ9FRUGi8c15dxVJCO2SCdUyt/q4/i6jC8UDfv
+8Ue1fXwsBOxonbRJRBD0ckscZOf85muQ3Wl9af0AVqW3rLatt8o+Ae+c
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem
new file mode 100644
index 00000000000..653f9b9dcdd
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 05:55:56:bc:f2:5e:a4:35:35:c3:a4:0f:d5:ab:45:72
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G3
+ Validity
+ Not Before: Aug 1 12:00:00 2013 GMT
+ Not After : Jan 15 12:00:00 2038 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:dd:a7:d9:bb:8a:b8:0b:fb:0b:7f:21:d2:f0:be:
+ be:73:f3:33:5d:1a:bc:34:ea:de:c6:9b:bc:d0:95:
+ f6:f0:cc:d0:0b:ba:61:5b:51:46:7e:9e:2d:9f:ee:
+ 8e:63:0c:17:ec:07:70:f5:cf:84:2e:40:83:9c:e8:
+ 3f:41:6d:3b:ad:d3:a4:14:59:36:78:9d:03:43:ee:
+ 10:13:6c:72:de:ae:88:a7:a1:6b:b5:43:ce:67:dc:
+ 23:ff:03:1c:a3:e2:3e
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B3:DB:48:A4:F9:A1:C5:D8:AE:36:41:CC:11:63:69:62:29:BC:4B:C6
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:31:00:ad:bc:f2:6c:3f:12:4a:d1:2d:39:c3:0a:09:
+ 97:73:f4:88:36:8c:88:27:bb:e6:88:8d:50:85:a7:63:f9:9e:
+ 32:de:66:93:0f:f1:cc:b1:09:8f:dd:6c:ab:fa:6b:7f:a0:02:
+ 30:39:66:5b:c2:64:8d:b8:9e:50:dc:a8:d5:49:a2:ed:c7:dc:
+ d1:49:7f:17:01:b8:c8:86:8f:4e:8c:88:2b:a8:9a:a9:8a:c5:
+ d1:00:bd:f8:54:e2:9a:e5:5b:7c:b3:27:17
+-----BEGIN CERTIFICATE-----
+MIICPzCCAcWgAwIBAgIQBVVWvPJepDU1w6QP1atFcjAKBggqhkjOPQQDAzBhMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBHMzAe
+Fw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVTMRUw
+EwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20x
+IDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEczMHYwEAYHKoZIzj0CAQYF
+K4EEACIDYgAE3afZu4q4C/sLfyHS8L6+c/MzXRq8NOrexpu80JX28MzQC7phW1FG
+fp4tn+6OYwwX7Adw9c+ELkCDnOg/QW07rdOkFFk2eJ0DQ+4QE2xy3q6Ip6FrtUPO
+Z9wj/wMco+I+o0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAd
+BgNVHQ4EFgQUs9tIpPmhxdiuNkHMEWNpYim8S8YwCgYIKoZIzj0EAwMDaAAwZQIx
+AK288mw/EkrRLTnDCgmXc/SINoyIJ7vmiI1Qhadj+Z4y3maTD/HMsQmP3Wyr+mt/
+oAIwOWZbwmSNuJ5Q3KjVSaLtx9zRSX8XAbjIho9OjIgrqJqpisXRAL34VOKa5Vt8
+sycX
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem
new file mode 100644
index 00000000000..7f08771d124
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem
@@ -0,0 +1,56 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8495723813297216424 (0x75e6dfcbc1685ba8)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com Root Certification Authority ECC
+ Validity
+ Not Before: Feb 12 18:14:03 2016 GMT
+ Not After : Feb 12 18:14:03 2041 GMT
+ Subject: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com Root Certification Authority ECC
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:45:6e:a9:50:c4:a6:23:36:9e:5f:28:8d:17:cb:
+ 96:22:64:3f:dc:7a:8e:1d:cc:08:b3:a2:71:24:ba:
+ 8e:49:b9:04:1b:47:96:58:ab:2d:95:c8:ed:9e:08:
+ 35:c8:27:eb:89:8c:53:58:eb:62:8a:fe:f0:5b:0f:
+ 6b:31:52:63:41:3b:89:cd:ec:ec:b6:8d:19:d3:34:
+ 07:dc:bb:c6:06:7f:c2:45:95:ec:cb:7f:a8:23:e0:
+ 09:e9:81:fa:f3:47:d3
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:82:D1:85:73:30:E7:35:04:D3:8E:02:92:FB:E5:A4:D1:C4:21:E8:CD
+
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:64:02:30:6f:e7:eb:59:11:a4:60:cf:61:b0:96:7b:ed:05:
+ f9:2f:13:91:dc:ed:e5:fc:50:6b:11:46:46:b3:1c:21:00:62:
+ bb:be:c3:e7:e8:cd:07:99:f9:0d:0b:5d:72:3e:c4:aa:02:30:
+ 1f:bc:ba:0b:e2:30:24:fb:7c:6d:80:55:0a:99:3e:80:0d:33:
+ e5:66:a3:b3:a3:bb:a5:d5:8b:8f:09:2c:a6:5d:7e:e2:f0:07:
+ 08:68:6d:d2:7c:69:6e:5f:df:e5:6a:65
+-----BEGIN CERTIFICATE-----
+MIICjTCCAhSgAwIBAgIIdebfy8FoW6gwCgYIKoZIzj0EAwIwfDELMAkGA1UEBhMC
+VVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQKDA9T
+U0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBFQ0MwHhcNMTYwMjEyMTgxNDAzWhcNNDEwMjEyMTgxNDAz
+WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hvdXN0
+b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNvbSBS
+b290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IEVDQzB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABEVuqVDEpiM2nl8ojRfLliJkP9x6jh3MCLOicSS6jkm5BBtHllirLZXI
+7Z4INcgn64mMU1jrYor+8FsPazFSY0E7ic3s7LaNGdM0B9y7xgZ/wkWV7Mt/qCPg
+CemB+vNH06NjMGEwHQYDVR0OBBYEFILRhXMw5zUE044CkvvlpNHEIejNMA8GA1Ud
+EwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUgtGFczDnNQTTjgKS++Wk0cQh6M0wDgYD
+VR0PAQH/BAQDAgGGMAoGCCqGSM49BAMCA2cAMGQCMG/n61kRpGDPYbCWe+0F+S8T
+kdzt5fxQaxFGRrMcIQBiu77D5+jNB5n5DQtdcj7EqgIwH7y6C+IwJPt8bYBVCpk+
+gA0z5Wajs6O7pdWLjwkspl1+4vAHCGht0nxpbl/f5Wpl
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem
new file mode 100644
index 00000000000..c971f311762
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem
@@ -0,0 +1,55 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 66:f2:3d:af:87:de:8b:b1:4a:ea:0c:57:31:01:c2:ec
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = Microsoft Corporation, CN = Microsoft ECC Root Certificate Authority 2017
+ Validity
+ Not Before: Dec 18 23:06:45 2019 GMT
+ Not After : Jul 18 23:16:04 2042 GMT
+ Subject: C = US, O = Microsoft Corporation, CN = Microsoft ECC Root Certificate Authority 2017
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:d4:bc:3d:02:42:75:41:13:23:cd:80:04:86:02:
+ 51:2f:6a:a8:81:62:0b:65:cc:f6:ca:9d:1e:6f:4a:
+ 66:51:a2:03:d9:9d:91:fa:b6:16:b1:8c:6e:de:7c:
+ cd:db:79:a6:2f:ce:bb:ce:71:2f:e5:a5:ab:28:ec:
+ 63:04:66:99:f8:fa:f2:93:10:05:e1:81:28:42:e3:
+ c6:68:f4:e6:1b:84:60:4a:89:af:ed:79:0f:3b:ce:
+ f1:f6:44:f5:01:78:c0
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ C8:CB:99:72:70:52:0C:F8:E6:BE:B2:04:57:29:2A:CF:42:10:ED:35
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:30:58:f2:4d:ea:0c:f9:5f:5e:ee:60:29:cb:3a:f2:
+ db:d6:32:84:19:3f:7c:d5:2f:c2:b1:cc:93:ae:50:bb:09:32:
+ c6:c6:ed:7e:c9:36:94:12:e4:68:85:06:a2:1b:d0:2f:02:31:
+ 00:99:e9:16:b4:0e:fa:56:48:d4:a4:30:16:91:78:db:54:8c:
+ 65:01:8a:e7:50:66:c2:31:b7:39:ba:b8:1a:22:07:4e:fc:6b:
+ 54:16:20:ff:2b:b5:e7:4c:0c:4d:a6:4f:73
+-----BEGIN CERTIFICATE-----
+MIICWTCCAd+gAwIBAgIQZvI9r4fei7FK6gxXMQHC7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYD
+VQQDEy1NaWNyb3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIw
+MTcwHhcNMTkxMjE4MjMwNjQ1WhcNNDIwNzE4MjMxNjA0WjBlMQswCQYDVQQGEwJV
+UzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1NaWNy
+b3NvZnQgRUNDIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAATUvD0CQnVBEyPNgASGAlEvaqiBYgtlzPbKnR5vSmZR
+ogPZnZH6thaxjG7efM3beaYvzrvOcS/lpaso7GMEZpn4+vKTEAXhgShC48Zo9OYb
+hGBKia/teQ87zvH2RPUBeMCjVDBSMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBTIy5lycFIM+Oa+sgRXKSrPQhDtNTAQBgkrBgEEAYI3
+FQEEAwIBADAKBggqhkjOPQQDAwNoADBlAjBY8k3qDPlfXu5gKcs68tvWMoQZP3zV
+L8KxzJOuULsJMsbG7X7JNpQS5GiFBqIb0C8CMQCZ6Ra0DvpWSNSkMBaReNtUjGUB
+iudQZsIxtzm6uBoiB078a1QWIP8rtedMDE2mT3M=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem
new file mode 100644
index 00000000000..87c272b888a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10003001 (0x98a239)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden Root CA - G3
+ Validity
+ Not Before: Nov 14 11:28:42 2013 GMT
+ Not After : Nov 13 23:00:00 2028 GMT
+ Subject: C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden Root CA - G3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:be:32:a2:54:0f:70:fb:2c:5c:59:eb:6c:c4:a4:
+ 51:e8:85:2a:b3:cc:4a:34:f2:b0:5f:f3:0e:c7:1c:
+ 3d:53:1e:88:08:68:d8:6f:3d:ad:c2:9e:cc:82:67:
+ 07:27:87:68:71:3a:9f:75:96:22:46:05:b0:ed:ad:
+ c7:5b:9e:2a:de:9c:fc:3a:c6:95:a7:f5:17:67:18:
+ e7:2f:49:08:0c:5c:cf:e6:cc:34:ed:78:fb:50:b1:
+ dc:6b:32:f0:a2:fe:b6:3c:e4:ec:5a:97:c7:3f:1e:
+ 70:08:30:a0:dc:c5:b3:6d:6f:d0:82:72:11:ab:d2:
+ 81:68:59:82:17:b7:78:92:60:fa:cc:de:3f:84:eb:
+ 8d:38:33:90:0a:72:23:fa:35:cc:26:71:31:d1:72:
+ 28:92:d9:5b:23:6d:66:b5:6d:07:42:eb:a6:33:ce:
+ 92:db:c0:f6:6c:63:78:cd:ca:4e:3d:b5:e5:52:9b:
+ f1:be:3b:e6:54:60:b0:66:1e:09:ab:07:fe:54:89:
+ 11:42:d1:f7:24:ba:60:78:1a:98:f7:c9:11:fd:16:
+ c1:35:1a:54:75:ef:43:d3:e5:ae:4e:ce:e7:7b:c3:
+ c6:4e:61:51:4b:ab:9a:45:4b:a1:1f:41:bd:48:53:
+ 15:71:64:0b:86:b3:e5:2e:be:ce:a4:1b:c1:29:84:
+ a2:b5:cb:08:23:76:43:22:24:1f:17:04:d4:6e:9c:
+ c6:fc:7f:2b:66:1a:ec:8a:e5:d6:cf:4d:f5:63:09:
+ b7:15:39:d6:7b:ac:eb:e3:7c:e9:4e:fc:75:42:c8:
+ ed:58:95:0c:06:42:a2:9c:f7:e4:70:b3:df:72:6f:
+ 5a:37:40:89:d8:85:a4:d7:f1:0b:de:43:19:d4:4a:
+ 58:2c:8c:8a:39:9e:bf:84:87:f1:16:3b:36:0c:e9:
+ d3:b4:ca:6c:19:41:52:09:a1:1d:b0:6a:bf:82:ef:
+ 70:51:21:32:dc:05:76:8c:cb:f7:64:e4:03:50:af:
+ 8c:91:67:ab:c5:f2:ee:58:d8:de:be:f7:e7:31:cf:
+ 6c:c9:3b:71:c1:d5:88:b5:65:bc:c0:e8:17:17:07:
+ 12:b5:5c:d2:ab:20:93:b4:e6:82:83:70:36:c5:cd:
+ a3:8d:ad:8b:ec:a3:c1:43:87:e6:43:e2:34:be:95:
+ 8b:35:ed:07:39:da:a8:1d:7a:9f:36:9e:12:b0:0c:
+ 65:12:90:15:60:d9:26:40:44:e3:56:60:a5:10:d4:
+ 6a:3c:fd:41:dc:0e:5a:47:b6:ef:97:61:75:4f:d9:
+ fe:c7:b2:1d:d4:ed:5d:49:b3:a9:6a:cb:66:84:13:
+ d5:5c:a0:dc:df:6e:77:06:d1:71:75:c8:57:6f:af:
+ 0f:77:5b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 54:AD:FA:C7:92:57:AE:CA:35:9C:2E:12:FB:E4:BA:5D:20:DC:94:57
+ Signature Algorithm: sha256WithRSAEncryption
+ 30:99:9d:05:32:c8:5e:0e:3b:98:01:3a:8a:a4:e7:07:f7:7a:
+ f8:e7:9a:df:50:43:53:97:2a:3d:ca:3c:47:98:2e:e1:15:7b:
+ f1:92:f3:61:da:90:25:16:65:c0:9f:54:5d:0e:03:3b:5b:77:
+ 02:9c:84:b6:0d:98:5f:34:dd:3b:63:c2:c3:28:81:c2:9c:29:
+ 2e:29:e2:c8:c3:01:f2:33:ea:2a:aa:cc:09:08:f7:65:67:c6:
+ cd:df:d3:b6:2b:a7:bd:cc:d1:0e:70:5f:b8:23:d1:cb:91:4e:
+ 0a:f4:c8:7a:e5:d9:63:36:c1:d4:df:fc:22:97:f7:60:5d:ea:
+ 29:2f:58:b2:bd:58:bd:8d:96:4f:10:75:bf:48:7b:3d:51:87:
+ a1:3c:74:22:c2:fc:07:7f:80:dc:c4:ac:fe:6a:c1:70:30:b0:
+ e9:8e:69:e2:2c:69:81:94:09:ba:dd:fe:4d:c0:83:8c:94:58:
+ c0:46:20:af:9c:1f:02:f8:35:55:49:2f:46:d4:c0:f0:a0:96:
+ 02:0f:33:c5:71:f3:9e:23:7d:94:b7:fd:3a:d3:09:83:06:21:
+ fd:60:3d:ae:32:c0:d2:ee:8d:a6:f0:e7:b4:82:7c:0a:cc:70:
+ c9:79:80:f8:fe:4c:f7:35:84:19:8a:31:fb:0a:d9:d7:7f:9b:
+ f0:a2:9a:6b:c3:05:4a:ed:41:60:14:30:d1:aa:11:42:6e:d3:
+ 23:02:04:0b:c6:65:dd:dd:52:77:da:81:6b:b2:a8:fa:01:38:
+ b9:96:ea:2a:6c:67:97:89:94:9e:bc:e1:54:d5:e4:6a:78:ef:
+ 4a:bd:2b:9a:3d:40:7e:c6:c0:75:d2:6e:fb:68:30:ec:ec:8b:
+ 9d:f9:49:35:9a:1a:2c:d9:b3:95:39:d5:1e:92:f7:a6:b9:65:
+ 2f:e5:3d:6d:3a:48:4c:08:dc:e4:28:12:28:be:7d:35:5c:ea:
+ e0:16:7e:13:1b:6a:d7:3e:d7:9e:fc:2d:75:b2:c1:14:d5:23:
+ 03:db:5b:6f:0b:3e:78:2f:0d:de:33:8d:16:b7:48:e7:83:9a:
+ 81:0f:7b:c1:43:4d:55:04:17:38:4a:51:d5:59:a2:89:74:d3:
+ 9f:be:1e:4b:d7:c6:6d:b7:88:24:6f:60:91:a4:82:85:5b:56:
+ 41:bc:d0:44:ab:6a:13:be:d1:2c:58:b7:12:33:58:b2:37:63:
+ dc:13:f5:94:1d:3f:40:51:f5:4f:f5:3a:ed:c8:c5:eb:c2:1e:
+ 1d:16:95:7a:c7:7e:42:71:93:6e:4b:15:b7:30:df:aa:ed:57:
+ 85:48:ac:1d:6a:dd:39:69:e4:e1:79:78:be:ce:05:bf:a1:0c:
+ f7:80:7b:21:67:27:30:59
+-----BEGIN CERTIFICATE-----
+MIIFdDCCA1ygAwIBAgIEAJiiOTANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEczMB4XDTEzMTExNDExMjg0MloX
+DTI4MTExMzIzMDAwMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
+ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
+b3QgQ0EgLSBHMzCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAL4yolQP
+cPssXFnrbMSkUeiFKrPMSjTysF/zDsccPVMeiAho2G89rcKezIJnByeHaHE6n3WW
+IkYFsO2tx1ueKt6c/DrGlaf1F2cY5y9JCAxcz+bMNO14+1Cx3Gsy8KL+tjzk7FqX
+xz8ecAgwoNzFs21v0IJyEavSgWhZghe3eJJg+szeP4TrjTgzkApyI/o1zCZxMdFy
+KJLZWyNtZrVtB0LrpjPOktvA9mxjeM3KTj215VKb8b475lRgsGYeCasH/lSJEULR
+9yS6YHgamPfJEf0WwTUaVHXvQ9Plrk7O53vDxk5hUUurmkVLoR9BvUhTFXFkC4az
+5S6+zqQbwSmEorXLCCN2QyIkHxcE1G6cxvx/K2Ya7Irl1s9N9WMJtxU51nus6+N8
+6U78dULI7ViVDAZCopz35HCz33JvWjdAidiFpNfxC95DGdRKWCyMijmev4SH8RY7
+Ngzp07TKbBlBUgmhHbBqv4LvcFEhMtwFdozL92TkA1CvjJFnq8Xy7ljY3r735zHP
+bMk7ccHViLVlvMDoFxcHErVc0qsgk7TmgoNwNsXNo42ti+yjwUOH5kPiNL6VizXt
+BznaqB16nzaeErAMZRKQFWDZJkBE41ZgpRDUajz9QdwOWke275dhdU/Z/seyHdTt
+XUmzqWrLZoQT1Vyg3N9udwbRcXXIV2+vD3dbAgMBAAGjQjBAMA8GA1UdEwEB/wQF
+MAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRUrfrHkleuyjWcLhL75Lpd
+INyUVzANBgkqhkiG9w0BAQsFAAOCAgEAMJmdBTLIXg47mAE6iqTnB/d6+Oea31BD
+U5cqPco8R5gu4RV78ZLzYdqQJRZlwJ9UXQ4DO1t3ApyEtg2YXzTdO2PCwyiBwpwp
+LiniyMMB8jPqKqrMCQj3ZWfGzd/TtiunvczRDnBfuCPRy5FOCvTIeuXZYzbB1N/8
+Ipf3YF3qKS9Ysr1YvY2WTxB1v0h7PVGHoTx0IsL8B3+A3MSs/mrBcDCw6Y5p4ixp
+gZQJut3+TcCDjJRYwEYgr5wfAvg1VUkvRtTA8KCWAg8zxXHzniN9lLf9OtMJgwYh
+/WA9rjLA0u6NpvDntIJ8CsxwyXmA+P5M9zWEGYox+wrZ13+b8KKaa8MFSu1BYBQw
+0aoRQm7TIwIEC8Zl3d1Sd9qBa7Ko+gE4uZbqKmxnl4mUnrzhVNXkanjvSr0rmj1A
+fsbAddJu+2gw7OyLnflJNZoaLNmzlTnVHpL3prllL+U9bTpITAjc5CgSKL59NVzq
+4BZ+Extq1z7XnvwtdbLBFNUjA9tbbws+eC8N3jONFrdI54OagQ97wUNNVQQXOEpR
+1VmiiXTTn74eS9fGbbeIJG9gkaSChVtWQbzQRKtqE77RLFi3EjNYsjdj3BP1lB0/
+QFH1T/U67cjF68IeHRaVesd+QnGTbksVtzDfqu1XhUisHWrdOWnk4Xl4vs4Fv6EM
+94B7IWcnMFk=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem
new file mode 100644
index 00000000000..83169eb5491
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem
@@ -0,0 +1,86 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ c2:7e:43:04:4e:47:3f:19
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = HU, L = Budapest, O = Microsec Ltd., CN = Microsec e-Szigno Root CA 2009, emailAddress = info@e-szigno.hu
+ Validity
+ Not Before: Jun 16 11:30:18 2009 GMT
+ Not After : Dec 30 11:30:18 2029 GMT
+ Subject: C = HU, L = Budapest, O = Microsec Ltd., CN = Microsec e-Szigno Root CA 2009, emailAddress = info@e-szigno.hu
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:e9:f8:8f:f3:63:ad:da:86:d8:a7:e0:42:fb:cf:
+ 91:de:a6:26:f8:99:a5:63:70:ad:9b:ae:ca:33:40:
+ 7d:6d:96:6e:a1:0e:44:ee:e1:13:9d:94:42:52:9a:
+ bd:75:85:74:2c:a8:0e:1d:93:b6:18:b7:8c:2c:a8:
+ cf:fb:5c:71:b9:da:ec:fe:e8:7e:8f:e4:2f:1d:b2:
+ a8:75:87:d8:b7:a1:e5:3b:cf:99:4a:46:d0:83:19:
+ 7d:c0:a1:12:1c:95:6d:4a:f4:d8:c7:a5:4d:33:2e:
+ 85:39:40:75:7e:14:7c:80:12:98:50:c7:41:67:b8:
+ a0:80:61:54:a6:6c:4e:1f:e0:9d:0e:07:e9:c9:ba:
+ 33:e7:fe:c0:55:28:2c:02:80:a7:19:f5:9e:dc:55:
+ 53:03:97:7b:07:48:ff:99:fb:37:8a:24:c4:59:cc:
+ 50:10:63:8e:aa:a9:1a:b0:84:1a:86:f9:5f:bb:b1:
+ 50:6e:a4:d1:0a:cc:d5:71:7e:1f:a7:1b:7c:f5:53:
+ 6e:22:5f:cb:2b:e6:d4:7c:5d:ae:d6:c2:c6:4c:e5:
+ 05:01:d9:ed:57:fc:c1:23:79:fc:fa:c8:24:83:95:
+ f3:b5:6a:51:01:d0:77:d6:e9:12:a1:f9:1a:83:fb:
+ 82:1b:b9:b0:97:f4:76:06:33:43:49:a0:ff:0b:b5:
+ fa:b5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68
+ X509v3 Authority Key Identifier:
+ keyid:CB:0F:C6:DF:42:43:CC:3D:CB:B5:48:23:A1:1A:7A:A6:2A:BB:34:68
+
+ X509v3 Subject Alternative Name:
+ email:info@e-szigno.hu
+ Signature Algorithm: sha256WithRSAEncryption
+ c9:d1:0e:5e:2e:d5:cc:b3:7c:3e:cb:fc:3d:ff:0d:28:95:93:
+ 04:c8:bf:da:cd:79:b8:43:90:f0:a4:be:ef:f2:ef:21:98:bc:
+ d4:d4:5d:06:f6:ee:42:ec:30:6c:a0:aa:a9:ca:f1:af:8a:fa:
+ 3f:0b:73:6a:3e:ea:2e:40:7e:1f:ae:54:61:79:eb:2e:08:37:
+ d7:23:f3:8c:9f:be:1d:b1:e1:a4:75:db:a0:e2:54:14:b1:ba:
+ 1c:29:a4:18:f6:12:ba:a2:14:14:e3:31:35:c8:40:ff:b7:e0:
+ 05:76:57:c1:1c:59:f2:f8:bf:e4:ed:25:62:5c:84:f0:7e:7e:
+ 1f:b3:be:f9:b7:21:11:cc:03:01:56:70:a7:10:92:1e:1b:34:
+ 81:1e:ad:9c:1a:c3:04:3c:ed:02:61:d6:1e:06:f3:5f:3a:87:
+ f2:2b:f1:45:87:e5:3d:ac:d1:c7:57:84:bd:6b:ae:dc:d8:f9:
+ b6:1b:62:70:0b:3d:36:c9:42:f2:32:d7:7a:61:e6:d2:db:3d:
+ cf:c8:a9:c9:9b:dc:db:58:44:d7:6f:38:af:7f:78:d3:a3:ad:
+ 1a:75:ba:1c:c1:36:7c:8f:1e:6d:1c:c3:75:46:ae:35:05:a6:
+ f6:5c:3d:21:ee:56:f0:c9:82:22:2d:7a:54:ab:70:c3:7d:22:
+ 65:82:70:96
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
+VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
+ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
+CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
+OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
+FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
+Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
+kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
+cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
+fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
+N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
+xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
++rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
+Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
+SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
+mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
+ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
+2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
+HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem
new file mode 100644
index 00000000000..c06ab6cc12e
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0c:e7:e0:e5:17:d8:46:fe:8f:e5:60:fc:1b:f0:30:39
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root CA
+ Validity
+ Not Before: Nov 10 00:00:00 2006 GMT
+ Not After : Nov 10 00:00:00 2031 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ad:0e:15:ce:e4:43:80:5c:b1:87:f3:b7:60:f9:
+ 71:12:a5:ae:dc:26:94:88:aa:f4:ce:f5:20:39:28:
+ 58:60:0c:f8:80:da:a9:15:95:32:61:3c:b5:b1:28:
+ 84:8a:8a:dc:9f:0a:0c:83:17:7a:8f:90:ac:8a:e7:
+ 79:53:5c:31:84:2a:f6:0f:98:32:36:76:cc:de:dd:
+ 3c:a8:a2:ef:6a:fb:21:f2:52:61:df:9f:20:d7:1f:
+ e2:b1:d9:fe:18:64:d2:12:5b:5f:f9:58:18:35:bc:
+ 47:cd:a1:36:f9:6b:7f:d4:b0:38:3e:c1:1b:c3:8c:
+ 33:d9:d8:2f:18:fe:28:0f:b3:a7:83:d6:c3:6e:44:
+ c0:61:35:96:16:fe:59:9c:8b:76:6d:d7:f1:a2:4b:
+ 0d:2b:ff:0b:72:da:9e:60:d0:8e:90:35:c6:78:55:
+ 87:20:a1:cf:e5:6d:0a:c8:49:7c:31:98:33:6c:22:
+ e9:87:d0:32:5a:a2:ba:13:82:11:ed:39:17:9d:99:
+ 3a:72:a1:e6:fa:a4:d9:d5:17:31:75:ae:85:7d:22:
+ ae:3f:01:46:86:f6:28:79:c8:b1:da:e4:57:17:c4:
+ 7e:1c:0e:b0:b4:92:a6:56:b3:bd:b2:97:ed:aa:a7:
+ f0:b7:c5:a8:3f:95:16:d0:ff:a1:96:eb:08:5f:18:
+ 77:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F
+ X509v3 Authority Key Identifier:
+ keyid:45:EB:A2:AF:F4:92:CB:82:31:2D:51:8B:A7:A7:21:9D:F3:6D:C8:0F
+
+ Signature Algorithm: sha1WithRSAEncryption
+ a2:0e:bc:df:e2:ed:f0:e3:72:73:7a:64:94:bf:f7:72:66:d8:
+ 32:e4:42:75:62:ae:87:eb:f2:d5:d9:de:56:b3:9f:cc:ce:14:
+ 28:b9:0d:97:60:5c:12:4c:58:e4:d3:3d:83:49:45:58:97:35:
+ 69:1a:a8:47:ea:56:c6:79:ab:12:d8:67:81:84:df:7f:09:3c:
+ 94:e6:b8:26:2c:20:bd:3d:b3:28:89:f7:5f:ff:22:e2:97:84:
+ 1f:e9:65:ef:87:e0:df:c1:67:49:b3:5d:eb:b2:09:2a:eb:26:
+ ed:78:be:7d:3f:2b:f3:b7:26:35:6d:5f:89:01:b6:49:5b:9f:
+ 01:05:9b:ab:3d:25:c1:cc:b6:7f:c2:f1:6f:86:c6:fa:64:68:
+ eb:81:2d:94:eb:42:b7:fa:8c:1e:dd:62:f1:be:50:67:b7:6c:
+ bd:f3:f1:1f:6b:0c:36:07:16:7f:37:7c:a9:5b:6d:7a:f1:12:
+ 46:60:83:d7:27:04:be:4b:ce:97:be:c3:67:2a:68:11:df:80:
+ e7:0c:33:66:bf:13:0d:14:6e:f3:7f:1f:63:10:1e:fa:8d:1b:
+ 25:6d:6c:8f:a5:b7:61:01:b1:d2:a3:26:a1:10:71:9d:ad:e2:
+ c3:f9:c3:99:51:b7:2b:07:08:ce:2e:e6:50:b2:a7:fa:0a:45:
+ 2f:a2:f0:f2
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
+JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
+mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
+VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
+AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
+AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
+BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
+pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
+dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
+fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
+NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
+H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem
new file mode 100644
index 00000000000..cf78be92339
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 31:f5:e4:62:0c:6c:58:ed:d6:d8
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = IN, OU = emSign PKI, O = eMudhra Technologies Limited, CN = emSign Root CA - G1
+ Validity
+ Not Before: Feb 18 18:30:00 2018 GMT
+ Not After : Feb 18 18:30:00 2043 GMT
+ Subject: C = IN, OU = emSign PKI, O = eMudhra Technologies Limited, CN = emSign Root CA - G1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:93:4b:bb:e9:66:8a:ee:9d:5b:d5:34:93:d0:1b:
+ 1e:c3:e7:9e:b8:64:33:7f:63:78:68:b4:cd:2e:71:
+ 75:d7:9b:20:c6:4d:29:bc:b6:68:60:8a:f7:21:9a:
+ 56:35:5a:f3:76:bd:d8:cd:9a:ff:93:56:4b:a5:59:
+ 06:a1:93:34:29:dd:16:34:75:4e:f2:81:b4:c7:96:
+ 4e:ad:19:15:52:4a:fe:3c:70:75:70:cd:af:2b:ab:
+ 15:9a:33:3c:aa:b3:8b:aa:cd:43:fd:f5:ea:70:ff:
+ ed:cf:11:3b:94:ce:4e:32:16:d3:23:40:2a:77:b3:
+ af:3c:01:2c:6c:ed:99:2c:8b:d9:4e:69:98:b2:f7:
+ 8f:41:b0:32:78:61:d6:0d:5f:c3:fa:a2:40:92:1d:
+ 5c:17:e6:70:3e:35:e7:a2:b7:c2:62:e2:ab:a4:38:
+ 4c:b5:39:35:6f:ea:03:69:fa:3a:54:68:85:6d:d6:
+ f2:2f:43:55:1e:91:0d:0e:d8:d5:6a:a4:96:d1:13:
+ 3c:2c:78:50:e8:3a:92:d2:17:56:e5:35:1a:40:1c:
+ 3e:8d:2c:ed:39:df:42:e0:83:41:74:df:a3:cd:c2:
+ 86:60:48:68:e3:69:0b:54:00:8b:e4:76:69:21:0d:
+ 79:4e:34:08:5e:14:c2:cc:b1:b7:ad:d7:7c:70:8a:
+ c7:85
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ FB:EF:0D:86:9E:B0:E3:DD:A9:B9:F1:21:17:7F:3E:FC:F0:77:2B:1A
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 59:ff:f2:8c:f5:87:7d:71:3d:a3:9f:1b:5b:d1:da:f8:d3:9c:
+ 6b:36:bd:9b:a9:61:eb:de:16:2c:74:3d:9e:e6:75:da:d7:ba:
+ a7:bc:42:17:e7:3d:91:eb:e5:7d:dd:3e:9c:f1:cf:92:ac:6c:
+ 48:cc:c2:22:3f:69:3b:c5:b6:15:2f:a3:35:c6:68:2a:1c:57:
+ af:39:ef:8d:d0:35:c3:18:0c:7b:00:56:1c:cd:8b:19:74:de:
+ be:0f:12:e0:d0:aa:a1:3f:02:34:b1:70:ce:9d:18:d6:08:03:
+ 09:46:ee:60:e0:7e:b6:c4:49:04:51:7d:70:60:bc:aa:b2:ff:
+ 79:72:7a:a6:1d:3d:5f:2a:f8:ca:e2:fd:39:b7:47:b9:eb:7e:
+ df:04:23:af:fa:9c:06:07:e9:fb:63:93:80:40:b5:c6:6c:0a:
+ 31:28:ce:0c:9f:cf:b3:23:35:80:41:8d:6c:c4:37:7b:81:2f:
+ 80:a1:40:42:85:e9:d9:38:8d:e8:a1:53:cd:01:bf:69:e8:5a:
+ 06:f2:45:0b:90:fa:ae:e1:bf:9d:f2:ae:57:3c:a5:ae:b2:56:
+ f4:8b:65:40:e9:fd:31:81:2c:f4:39:09:d8:ee:6b:a7:b4:a6:
+ 1d:15:a5:98:f7:01:81:d8:85:7d:f3:51:5c:71:88:de:ba:cc:
+ 1f:80:7e:4a
+-----BEGIN CERTIFICATE-----
+MIIDlDCCAnygAwIBAgIKMfXkYgxsWO3W2DANBgkqhkiG9w0BAQsFADBnMQswCQYD
+VQQGEwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBU
+ZWNobm9sb2dpZXMgTGltaXRlZDEcMBoGA1UEAxMTZW1TaWduIFJvb3QgQ0EgLSBH
+MTAeFw0xODAyMTgxODMwMDBaFw00MzAyMTgxODMwMDBaMGcxCzAJBgNVBAYTAklO
+MRMwEQYDVQQLEwplbVNpZ24gUEtJMSUwIwYDVQQKExxlTXVkaHJhIFRlY2hub2xv
+Z2llcyBMaW1pdGVkMRwwGgYDVQQDExNlbVNpZ24gUm9vdCBDQSAtIEcxMIIBIjAN
+BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAk0u76WaK7p1b1TST0Bsew+eeuGQz
+f2N4aLTNLnF115sgxk0pvLZoYIr3IZpWNVrzdr3YzZr/k1ZLpVkGoZM0Kd0WNHVO
+8oG0x5ZOrRkVUkr+PHB1cM2vK6sVmjM8qrOLqs1D/fXqcP/tzxE7lM5OMhbTI0Aq
+d7OvPAEsbO2ZLIvZTmmYsvePQbAyeGHWDV/D+qJAkh1cF+ZwPjXnorfCYuKrpDhM
+tTk1b+oDafo6VGiFbdbyL0NVHpENDtjVaqSW0RM8LHhQ6DqS0hdW5TUaQBw+jSzt
+Od9C4INBdN+jzcKGYEho42kLVACL5HZpIQ15TjQIXhTCzLG3rdd8cIrHhQIDAQAB
+o0IwQDAdBgNVHQ4EFgQU++8Nhp6w492pufEhF38+/PB3KxowDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAFn/8oz1h31x
+PaOfG1vR2vjTnGs2vZupYeveFix0PZ7mddrXuqe8QhfnPZHr5X3dPpzxz5KsbEjM
+wiI/aTvFthUvozXGaCocV685743QNcMYDHsAVhzNixl03r4PEuDQqqE/AjSxcM6d
+GNYIAwlG7mDgfrbESQRRfXBgvKqy/3lyeqYdPV8q+Mri/Tm3R7nrft8EI6/6nAYH
+6ftjk4BAtcZsCjEozgyfz7MjNYBBjWzEN3uBL4ChQEKF6dk4jeihU80Bv2noWgby
+RQuQ+q7hv53yrlc8pa6yVvSLZUDp/TGBLPQ5Cdjua6e0ph0VpZj3AYHYhX3zUVxx
+iN66zB+Afko=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem
new file mode 100644
index 00000000000..3b09b60e239
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem
@@ -0,0 +1,88 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 07:56:22:a4:e8:d4:8a:89:4d:f4:13:c8:f0:f8:ea:a5
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = SecureTrust Corporation, CN = Secure Global CA
+ Validity
+ Not Before: Nov 7 19:42:28 2006 GMT
+ Not After : Dec 31 19:52:06 2029 GMT
+ Subject: C = US, O = SecureTrust Corporation, CN = Secure Global CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:af:35:2e:d8:ac:6c:55:69:06:71:e5:13:68:24:
+ b3:4f:d8:cc:21:47:f8:f1:60:38:89:89:03:e9:bd:
+ ea:5e:46:53:09:dc:5c:f5:5a:e8:f7:45:2a:02:eb:
+ 31:61:d7:29:33:4c:ce:c7:7c:0a:37:7e:0f:ba:32:
+ 98:e1:1d:97:af:8f:c7:dc:c9:38:96:f3:db:1a:fc:
+ 51:ed:68:c6:d0:6e:a4:7c:24:d1:ae:42:c8:96:50:
+ 63:2e:e0:fe:75:fe:98:a7:5f:49:2e:95:e3:39:33:
+ 64:8e:1e:a4:5f:90:d2:67:3c:b2:d9:fe:41:b9:55:
+ a7:09:8e:72:05:1e:8b:dd:44:85:82:42:d0:49:c0:
+ 1d:60:f0:d1:17:2c:95:eb:f6:a5:c1:92:a3:c5:c2:
+ a7:08:60:0d:60:04:10:96:79:9e:16:34:e6:a9:b6:
+ fa:25:45:39:c8:1e:65:f9:93:f5:aa:f1:52:dc:99:
+ 98:3d:a5:86:1a:0c:35:33:fa:4b:a5:04:06:15:1c:
+ 31:80:ef:aa:18:6b:c2:7b:d7:da:ce:f9:33:20:d5:
+ f5:bd:6a:33:2d:81:04:fb:b0:5c:d4:9c:a3:e2:5c:
+ 1d:e3:a9:42:75:5e:7b:d4:77:ef:39:54:ba:c9:0a:
+ 18:1b:12:99:49:2f:88:4b:fd:50:62:d1:73:e7:8f:
+ 7a:43
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ 1.3.6.1.4.1.311.20.2:
+ ...C.A
+ X509v3 Key Usage:
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ AF:44:04:C2:41:7E:48:83:DB:4E:39:02:EC:EC:84:7A:E6:CE:C9:A4
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.securetrust.com/SGCA.crl
+
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: sha1WithRSAEncryption
+ 63:1a:08:40:7d:a4:5e:53:0d:77:d8:7a:ae:1f:0d:0b:51:16:
+ 03:ef:18:7c:c8:e3:af:6a:58:93:14:60:91:b2:84:dc:88:4e:
+ be:39:8a:3a:f3:e6:82:89:5d:01:37:b3:ab:24:a4:15:0e:92:
+ 35:5a:4a:44:5e:4e:57:fa:75:ce:1f:48:ce:66:f4:3c:40:26:
+ 92:98:6c:1b:ee:24:46:0c:17:b3:52:a5:db:a5:91:91:cf:37:
+ d3:6f:e7:27:08:3a:4e:19:1f:3a:a7:58:5c:17:cf:79:3f:8b:
+ e4:a7:d3:26:23:9d:26:0f:58:69:fc:47:7e:b2:d0:8d:8b:93:
+ bf:29:4f:43:69:74:76:67:4b:cf:07:8c:e6:02:f7:b5:e1:b4:
+ 43:b5:4b:2d:14:9f:f9:dc:26:0d:bf:a6:47:74:06:d8:88:d1:
+ 3a:29:30:84:ce:d2:39:80:62:1b:a8:c7:57:49:bc:6a:55:51:
+ 67:15:4a:be:35:07:e4:d5:75:98:37:79:30:14:db:29:9d:6c:
+ c5:69:cc:47:55:a2:30:f7:cc:5c:7f:c2:c3:98:1c:6b:4e:16:
+ 80:eb:7a:78:65:45:a2:00:1a:af:0c:0d:55:64:34:48:b8:92:
+ b9:f1:b4:50:29:f2:4f:23:1f:da:6c:ac:1f:44:e1:dd:23:78:
+ 51:5b:c7:16
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
+MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
+Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
+iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
+/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
+jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
+HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
+sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
+gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
+KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
+AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
+URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
+H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
+I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
+iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem
new file mode 100644
index 00000000000..c76d6c60525
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 08:3b:e0:56:90:42:46:b1:a1:75:6a:c9:59:91:c7:4a
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
+ Validity
+ Not Before: Nov 10 00:00:00 2006 GMT
+ Not After : Nov 10 00:00:00 2031 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:e2:3b:e1:11:72:de:a8:a4:d3:a3:57:aa:50:a2:
+ 8f:0b:77:90:c9:a2:a5:ee:12:ce:96:5b:01:09:20:
+ cc:01:93:a7:4e:30:b7:53:f7:43:c4:69:00:57:9d:
+ e2:8d:22:dd:87:06:40:00:81:09:ce:ce:1b:83:bf:
+ df:cd:3b:71:46:e2:d6:66:c7:05:b3:76:27:16:8f:
+ 7b:9e:1e:95:7d:ee:b7:48:a3:08:da:d6:af:7a:0c:
+ 39:06:65:7f:4a:5d:1f:bc:17:f8:ab:be:ee:28:d7:
+ 74:7f:7a:78:99:59:85:68:6e:5c:23:32:4b:bf:4e:
+ c0:e8:5a:6d:e3:70:bf:77:10:bf:fc:01:f6:85:d9:
+ a8:44:10:58:32:a9:75:18:d5:d1:a2:be:47:e2:27:
+ 6a:f4:9a:33:f8:49:08:60:8b:d4:5f:b4:3a:84:bf:
+ a1:aa:4a:4c:7d:3e:cf:4f:5f:6c:76:5e:a0:4b:37:
+ 91:9e:dc:22:e6:6d:ce:14:1a:8e:6a:cb:fe:cd:b3:
+ 14:64:17:c7:5b:29:9e:32:bf:f2:ee:fa:d3:0b:42:
+ d4:ab:b7:41:32:da:0c:d4:ef:f8:81:d5:bb:8d:58:
+ 3f:b5:1b:e8:49:28:a2:70:da:31:04:dd:f7:b2:16:
+ f2:4c:0a:4e:07:a8:ed:4a:3d:5e:b5:7f:a3:90:c3:
+ af:27
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+ X509v3 Authority Key Identifier:
+ keyid:03:DE:50:35:56:D1:4C:BB:66:F0:A3:E2:1B:1B:C3:97:B2:3D:D1:55
+
+ Signature Algorithm: sha1WithRSAEncryption
+ cb:9c:37:aa:48:13:12:0a:fa:dd:44:9c:4f:52:b0:f4:df:ae:
+ 04:f5:79:79:08:a3:24:18:fc:4b:2b:84:c0:2d:b9:d5:c7:fe:
+ f4:c1:1f:58:cb:b8:6d:9c:7a:74:e7:98:29:ab:11:b5:e3:70:
+ a0:a1:cd:4c:88:99:93:8c:91:70:e2:ab:0f:1c:be:93:a9:ff:
+ 63:d5:e4:07:60:d3:a3:bf:9d:5b:09:f1:d5:8e:e3:53:f4:8e:
+ 63:fa:3f:a7:db:b4:66:df:62:66:d6:d1:6e:41:8d:f2:2d:b5:
+ ea:77:4a:9f:9d:58:e2:2b:59:c0:40:23:ed:2d:28:82:45:3e:
+ 79:54:92:26:98:e0:80:48:a8:37:ef:f0:d6:79:60:16:de:ac:
+ e8:0e:cd:6e:ac:44:17:38:2f:49:da:e1:45:3e:2a:b9:36:53:
+ cf:3a:50:06:f7:2e:e8:c4:57:49:6c:61:21:18:d5:04:ad:78:
+ 3c:2c:3a:80:6b:a7:eb:af:15:14:e9:d8:89:c1:b9:38:6c:e2:
+ 91:6c:8a:ff:64:b9:77:25:57:30:c0:1b:24:a3:e1:dc:e9:df:
+ 47:7c:b5:b4:24:08:05:30:ec:2d:bd:0b:bf:45:bf:50:b9:a9:
+ f3:eb:98:01:12:ad:c8:88:c6:98:34:5f:8d:0a:3c:c6:e9:d5:
+ 95:95:6d:de
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
+QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
+CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
+nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
+43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
+T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
+gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
+BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
+TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
+DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
+hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
+06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
+PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
+YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem
new file mode 100644
index 00000000000..6ac2a1b1b17
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1246989352 (0x4a538c28)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2009 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - G2
+ Validity
+ Not Before: Jul 7 17:25:54 2009 GMT
+ Not After : Dec 7 17:55:54 2030 GMT
+ Subject: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2009 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ba:84:b6:72:db:9e:0c:6b:e2:99:e9:30:01:a7:
+ 76:ea:32:b8:95:41:1a:c9:da:61:4e:58:72:cf:fe:
+ f6:82:79:bf:73:61:06:0a:a5:27:d8:b3:5f:d3:45:
+ 4e:1c:72:d6:4e:32:f2:72:8a:0f:f7:83:19:d0:6a:
+ 80:80:00:45:1e:b0:c7:e7:9a:bf:12:57:27:1c:a3:
+ 68:2f:0a:87:bd:6a:6b:0e:5e:65:f3:1c:77:d5:d4:
+ 85:8d:70:21:b4:b3:32:e7:8b:a2:d5:86:39:02:b1:
+ b8:d2:47:ce:e4:c9:49:c4:3b:a7:de:fb:54:7d:57:
+ be:f0:e8:6e:c2:79:b2:3a:0b:55:e2:50:98:16:32:
+ 13:5c:2f:78:56:c1:c2:94:b3:f2:5a:e4:27:9a:9f:
+ 24:d7:c6:ec:d0:9b:25:82:e3:cc:c2:c4:45:c5:8c:
+ 97:7a:06:6b:2a:11:9f:a9:0a:6e:48:3b:6f:db:d4:
+ 11:19:42:f7:8f:07:bf:f5:53:5f:9c:3e:f4:17:2c:
+ e6:69:ac:4e:32:4c:62:77:ea:b7:e8:e5:bb:34:bc:
+ 19:8b:ae:9c:51:e7:b7:7e:b5:53:b1:33:22:e5:6d:
+ cf:70:3c:1a:fa:e2:9b:67:b6:83:f4:8d:a5:af:62:
+ 4c:4d:e0:58:ac:64:34:12:03:f8:b6:8d:94:63:24:
+ a4:71
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 6A:72:26:7A:D0:1E:EF:7D:E7:3B:69:51:D4:6C:8D:9F:90:12:66:AB
+ Signature Algorithm: sha256WithRSAEncryption
+ 79:9f:1d:96:c6:b6:79:3f:22:8d:87:d3:87:03:04:60:6a:6b:
+ 9a:2e:59:89:73:11:ac:43:d1:f5:13:ff:8d:39:2b:c0:f2:bd:
+ 4f:70:8c:a9:2f:ea:17:c4:0b:54:9e:d4:1b:96:98:33:3c:a8:
+ ad:62:a2:00:76:ab:59:69:6e:06:1d:7e:c4:b9:44:8d:98:af:
+ 12:d4:61:db:0a:19:46:47:f3:eb:f7:63:c1:40:05:40:a5:d2:
+ b7:f4:b5:9a:36:bf:a9:88:76:88:04:55:04:2b:9c:87:7f:1a:
+ 37:3c:7e:2d:a5:1a:d8:d4:89:5e:ca:bd:ac:3d:6c:d8:6d:af:
+ d5:f3:76:0f:cd:3b:88:38:22:9d:6c:93:9a:c4:3d:bf:82:1b:
+ 65:3f:a6:0f:5d:aa:fc:e5:b2:15:ca:b5:ad:c6:bc:3d:d0:84:
+ e8:ea:06:72:b0:4d:39:32:78:bf:3e:11:9c:0b:a4:9d:9a:21:
+ f3:f0:9b:0b:30:78:db:c1:dc:87:43:fe:bc:63:9a:ca:c5:c2:
+ 1c:c9:c7:8d:ff:3b:12:58:08:e6:b6:3d:ec:7a:2c:4e:fb:83:
+ 96:ce:0c:3c:69:87:54:73:a4:73:c2:93:ff:51:10:ac:15:54:
+ 01:d8:fc:05:b1:89:a1:7f:74:83:9a:49:d7:dc:4e:7b:8a:48:
+ 6f:8b:45:f6
+-----BEGIN CERTIFICATE-----
+MIIEPjCCAyagAwIBAgIESlOMKDANBgkqhkiG9w0BAQsFADCBvjELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50
+cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3Qs
+IEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVz
+dCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzIwHhcNMDkwNzA3MTcy
+NTU0WhcNMzAxMjA3MTc1NTU0WjCBvjELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVu
+dHJ1c3QsIEluYy4xKDAmBgNVBAsTH1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwt
+dGVybXMxOTA3BgNVBAsTMChjKSAyMDA5IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0
+aG9yaXplZCB1c2Ugb25seTEyMDAGA1UEAxMpRW50cnVzdCBSb290IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQC6hLZy254Ma+KZ6TABp3bqMriVQRrJ2mFOWHLP/vaCeb9zYQYKpSfYs1/T
+RU4cctZOMvJyig/3gxnQaoCAAEUesMfnmr8SVycco2gvCoe9amsOXmXzHHfV1IWN
+cCG0szLni6LVhjkCsbjSR87kyUnEO6fe+1R9V77w6G7CebI6C1XiUJgWMhNcL3hW
+wcKUs/Ja5CeanyTXxuzQmyWC48zCxEXFjJd6BmsqEZ+pCm5IO2/b1BEZQvePB7/1
+U1+cPvQXLOZprE4yTGJ36rfo5bs0vBmLrpxR57d+tVOxMyLlbc9wPBr64ptntoP0
+jaWvYkxN4FisZDQSA/i2jZRjJKRxAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqciZ60B7vfec7aVHUbI2fkBJmqzAN
+BgkqhkiG9w0BAQsFAAOCAQEAeZ8dlsa2eT8ijYfThwMEYGprmi5ZiXMRrEPR9RP/
+jTkrwPK9T3CMqS/qF8QLVJ7UG5aYMzyorWKiAHarWWluBh1+xLlEjZivEtRh2woZ
+Rkfz6/djwUAFQKXSt/S1mja/qYh2iARVBCuch38aNzx+LaUa2NSJXsq9rD1s2G2v
+1fN2D807iDginWyTmsQ9v4IbZT+mD12q/OWyFcq1rca8PdCE6OoGcrBNOTJ4vz4R
+nAuknZoh8/CbCzB428Hch0P+vGOaysXCHMnHjf87ElgI5rY97HosTvuDls4MPGmH
+VHOkc8KT/1EQrBVUAdj8BbGJoX90g5pJ19xOe4pIb4tF9g==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem
new file mode 100644
index 00000000000..56ab5842f07
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem
@@ -0,0 +1,54 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = GR, L = Athens, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions ECC RootCA 2015
+ Validity
+ Not Before: Jul 7 10:37:12 2015 GMT
+ Not After : Jun 30 10:37:12 2040 GMT
+ Subject: C = GR, L = Athens, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions ECC RootCA 2015
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:92:a0:41:e8:4b:82:84:5c:e2:f8:31:11:99:86:
+ 64:4e:09:25:2f:9d:41:2f:0a:ae:35:4f:74:95:b2:
+ 51:64:6b:8d:6b:e6:3f:70:95:f0:05:44:47:a6:72:
+ 38:50:76:95:02:5a:8e:ae:28:9e:f9:2d:4e:99:ef:
+ 2c:48:6f:4c:25:29:e8:d1:71:5b:df:1d:c1:75:37:
+ b4:d7:fa:7b:7a:42:9c:6a:0a:56:5a:7c:69:0b:aa:
+ 80:09:24:6c:7e:c1:46
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B4:22:0B:82:99:24:01:0E:9C:BB:E4:0E:FD:BF:FB:97:20:93:99:2A
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:64:02:30:67:ce:16:62:38:a2:ac:62:45:a7:a9:95:24:c0:
+ 1a:27:9c:32:3b:c0:c0:d5:ba:a9:e7:f8:04:43:53:85:ee:52:
+ 21:de:9d:f5:25:83:3e:9e:58:4b:2f:d7:67:13:0e:21:02:30:
+ 05:e1:75:01:de:68:ed:2a:1f:4d:4c:09:08:0d:ec:4b:ad:64:
+ 17:28:e7:75:ce:45:65:72:21:17:cb:22:41:0e:8c:13:98:38:
+ 9a:54:6d:9b:ca:e2:7c:ea:02:58:22:91
+-----BEGIN CERTIFICATE-----
+MIICwzCCAkqgAwIBAgIBADAKBggqhkjOPQQDAjCBqjELMAkGA1UEBhMCR1IxDzAN
+BgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxRDBCBgNVBAMTO0hl
+bGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgRUNDIFJv
+b3RDQSAyMDE1MB4XDTE1MDcwNzEwMzcxMloXDTQwMDYzMDEwMzcxMlowgaoxCzAJ
+BgNVBAYTAkdSMQ8wDQYDVQQHEwZBdGhlbnMxRDBCBgNVBAoTO0hlbGxlbmljIEFj
+YWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9yaXR5
+MUQwQgYDVQQDEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0
+dXRpb25zIEVDQyBSb290Q0EgMjAxNTB2MBAGByqGSM49AgEGBSuBBAAiA2IABJKg
+QehLgoRc4vgxEZmGZE4JJS+dQS8KrjVPdJWyUWRrjWvmP3CV8AVER6ZyOFB2lQJa
+jq4onvktTpnvLEhvTCUp6NFxW98dwXU3tNf6e3pCnGoKVlp8aQuqgAkkbH7BRqNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFLQi
+C4KZJAEOnLvkDv2/+5cgk5kqMAoGCCqGSM49BAMCA2cAMGQCMGfOFmI4oqxiRaep
+lSTAGiecMjvAwNW6qef4BENThe5SId6d9SWDPp5YSy/XZxMOIQIwBeF1Ad5o7Sof
+TUwJCA3sS61kFyjndc5FZXIhF8siQQ6ME5g4mlRtm8rifOoCWCKR
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem
new file mode 100644
index 00000000000..7b4cb313b68
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
+ Validity
+ Not Before: Sep 1 00:00:00 2009 GMT
+ Not After : Dec 31 23:59:59 2037 GMT
+ Subject: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:71:62:08:f1:fa:59:34:f7:1b:c9:18:a3:f7:
+ 80:49:58:e9:22:83:13:a6:c5:20:43:01:3b:84:f1:
+ e6:85:49:9f:27:ea:f6:84:1b:4e:a0:b4:db:70:98:
+ c7:32:01:b1:05:3e:07:4e:ee:f4:fa:4f:2f:59:30:
+ 22:e7:ab:19:56:6b:e2:80:07:fc:f3:16:75:80:39:
+ 51:7b:e5:f9:35:b6:74:4e:a9:8d:82:13:e4:b6:3f:
+ a9:03:83:fa:a2:be:8a:15:6a:7f:de:0b:c3:b6:19:
+ 14:05:ca:ea:c3:a8:04:94:3b:46:7c:32:0d:f3:00:
+ 66:22:c8:8d:69:6d:36:8c:11:18:b7:d3:b2:1c:60:
+ b4:38:fa:02:8c:ce:d3:dd:46:07:de:0a:3e:eb:5d:
+ 7c:c8:7c:fb:b0:2b:53:a4:92:62:69:51:25:05:61:
+ 1a:44:81:8c:2c:a9:43:96:23:df:ac:3a:81:9a:0e:
+ 29:c5:1c:a9:e9:5d:1e:b6:9e:9e:30:0a:39:ce:f1:
+ 88:80:fb:4b:5d:cc:32:ec:85:62:43:25:34:02:56:
+ 27:01:91:b4:3b:70:2a:3f:6e:b1:e8:9c:88:01:7d:
+ 9f:d4:f9:db:53:6d:60:9d:bf:2c:e7:58:ab:b8:5f:
+ 46:fc:ce:c4:1b:03:3c:09:eb:49:31:5c:69:46:b3:
+ e0:47
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 3A:9A:85:07:10:67:28:B6:EF:F6:BD:05:41:6E:20:C1:94:DA:0F:DE
+ Signature Algorithm: sha256WithRSAEncryption
+ 99:db:5d:79:d5:f9:97:59:67:03:61:f1:7e:3b:06:31:75:2d:
+ a1:20:8e:4f:65:87:b4:f7:a6:9c:bc:d8:e9:2f:d0:db:5a:ee:
+ cf:74:8c:73:b4:38:42:da:05:7b:f8:02:75:b8:fd:a5:b1:d7:
+ ae:f6:d7:de:13:cb:53:10:7e:8a:46:d1:97:fa:b7:2e:2b:11:
+ ab:90:b0:27:80:f9:e8:9f:5a:e9:37:9f:ab:e4:df:6c:b3:85:
+ 17:9d:3d:d9:24:4f:79:91:35:d6:5f:04:eb:80:83:ab:9a:02:
+ 2d:b5:10:f4:d8:90:c7:04:73:40:ed:72:25:a0:a9:9f:ec:9e:
+ ab:68:12:99:57:c6:8f:12:3a:09:a4:bd:44:fd:06:15:37:c1:
+ 9b:e4:32:a3:ed:38:e8:d8:64:f3:2c:7e:14:fc:02:ea:9f:cd:
+ ff:07:68:17:db:22:90:38:2d:7a:8d:d1:54:f1:69:e3:5f:33:
+ ca:7a:3d:7b:0a:e3:ca:7f:5f:39:e5:e2:75:ba:c5:76:18:33:
+ ce:2c:f0:2f:4c:ad:f7:b1:e7:ce:4f:a8:c4:9b:4a:54:06:c5:
+ 7f:7d:d5:08:0f:e2:1c:fe:7e:17:b8:ac:5e:f6:d4:16:b2:43:
+ 09:0c:4d:f6:a7:6b:b4:99:84:65:ca:7a:88:e2:e2:44:be:5c:
+ f7:ea:1c:f5
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoT
+EUdvRGFkZHkuY29tLCBJbmMuMTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRp
+ZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIz
+NTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQH
+EwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8GA1UE
+AxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKD
+E6bFIEMBO4Tx5oVJnyfq9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH
+/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD+qK+ihVqf94Lw7YZFAXK6sOoBJQ7Rnwy
+DfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutdfMh8+7ArU6SSYmlRJQVh
+GkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMlNAJWJwGR
+tDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEA
+AaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FDqahQcQZyi27/a9BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmX
+WWcDYfF+OwYxdS2hII5PZYe096acvNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu
+9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r5N9ss4UXnT3ZJE95kTXWXwTr
+gIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYVN8Gb5DKj7Tjo
+2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI
+4uJEvlz36hz1
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem
new file mode 100644
index 00000000000..757615c7a9c
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem
@@ -0,0 +1,82 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = TR, L = Gebze - Kocaeli, O = Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK, OU = Kamu Sertifikasyon Merkezi - Kamu SM, CN = TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+ Validity
+ Not Before: Nov 25 08:25:55 2013 GMT
+ Not After : Oct 25 08:25:55 2043 GMT
+ Subject: C = TR, L = Gebze - Kocaeli, O = Turkiye Bilimsel ve Teknolojik Arastirma Kurumu - TUBITAK, OU = Kamu Sertifikasyon Merkezi - Kamu SM, CN = TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:af:75:30:33:aa:bb:6b:d3:99:2c:12:37:84:d9:
+ 8d:7b:97:80:d3:6e:e7:ff:9b:50:95:3e:90:95:56:
+ 42:d7:19:7c:26:84:8d:92:fa:01:1d:3a:0f:e2:64:
+ 38:b7:8c:bc:e8:88:f9:8b:24:ab:2e:a3:f5:37:e4:
+ 40:8e:18:25:79:83:75:1f:3b:ff:6c:a8:c5:c6:56:
+ f8:b4:ed:8a:44:a3:ab:6c:4c:fc:1d:d0:dc:ef:68:
+ bd:cf:e4:aa:ce:f0:55:f7:a2:34:d4:83:6b:37:7c:
+ 1c:c2:fe:b5:03:ec:57:ce:bc:b4:b5:c5:ed:00:0f:
+ 53:37:2a:4d:f4:4f:0c:83:fb:86:cf:cb:fe:8c:4e:
+ bd:87:f9:a7:8b:21:57:9c:7a:df:03:67:89:2c:9d:
+ 97:61:a7:10:b8:55:90:7f:0e:2d:27:38:74:df:e7:
+ fd:da:4e:12:e3:4d:15:22:02:c8:e0:e0:fc:0f:ad:
+ 8a:d7:c9:54:50:cc:3b:0f:ca:16:80:84:d0:51:56:
+ c3:8e:56:7f:89:22:33:2f:e6:85:0a:bd:a5:a8:1b:
+ 36:de:d3:dc:2c:6d:3b:c7:13:bd:59:23:2c:e6:e5:
+ a4:f7:d8:0b:ed:ea:90:40:44:a8:95:bb:93:d5:d0:
+ 80:34:b6:46:78:0e:1f:00:93:46:e1:ee:e9:f9:ec:
+ 4f:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 65:3F:C7:8A:86:C6:3C:DD:3C:54:5C:35:F8:3A:ED:52:0C:47:57:C8
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 2a:3f:e1:f1:32:8e:ae:e1:98:5c:4b:5e:cf:6b:1e:6a:09:d2:
+ 22:a9:12:c7:5e:57:7d:73:56:64:80:84:7a:93:e4:09:b9:10:
+ cd:9f:2a:27:e1:00:77:be:48:c8:35:a8:81:9f:e4:b8:2c:c9:
+ 7f:0e:b0:d2:4b:37:5d:ea:b9:d5:0b:5e:34:bd:f4:73:29:c3:
+ ed:26:15:9c:7e:08:53:8a:58:8d:d0:4b:28:df:c1:b3:df:20:
+ f3:f9:e3:e3:3a:df:cc:9c:94:d8:4e:4f:c3:6b:17:b7:f7:72:
+ e8:ad:66:33:b5:25:53:ab:e0:f8:4c:a9:9d:fd:f2:0d:ba:ae:
+ b9:d9:aa:c6:6b:f9:93:bb:ae:ab:b8:97:3c:03:1a:ba:43:c6:
+ 96:b9:45:72:38:b3:a7:a1:96:3d:91:7b:7e:c0:21:53:4c:87:
+ ed:f2:0b:54:95:51:93:d5:22:a5:0d:8a:f1:93:0e:3e:54:0e:
+ b0:d8:c9:4e:dc:f2:31:32:56:ea:64:f9:ea:b5:9d:16:66:42:
+ 72:f3:7f:d3:b1:31:43:fc:a4:8e:17:f1:6d:23:ab:94:66:f8:
+ ad:fb:0f:08:6e:26:2d:7f:17:07:09:b2:8c:fb:50:c0:9f:96:
+ 8d:cf:b6:fd:00:9d:5a:14:9a:bf:02:44:f5:c1:c2:9f:22:5e:
+ a2:0f:a1:e3
+-----BEGIN CERTIFICATE-----
+MIIEYzCCA0ugAwIBAgIBATANBgkqhkiG9w0BAQsFADCB0jELMAkGA1UEBhMCVFIx
+GDAWBgNVBAcTD0dlYnplIC0gS29jYWVsaTFCMEAGA1UEChM5VHVya2l5ZSBCaWxp
+bXNlbCB2ZSBUZWtub2xvamlrIEFyYXN0aXJtYSBLdXJ1bXUgLSBUVUJJVEFLMS0w
+KwYDVQQLEyRLYW11IFNlcnRpZmlrYXN5b24gTWVya2V6aSAtIEthbXUgU00xNjA0
+BgNVBAMTLVRVQklUQUsgS2FtdSBTTSBTU0wgS29rIFNlcnRpZmlrYXNpIC0gU3Vy
+dW0gMTAeFw0xMzExMjUwODI1NTVaFw00MzEwMjUwODI1NTVaMIHSMQswCQYDVQQG
+EwJUUjEYMBYGA1UEBxMPR2ViemUgLSBLb2NhZWxpMUIwQAYDVQQKEzlUdXJraXll
+IEJpbGltc2VsIHZlIFRla25vbG9qaWsgQXJhc3Rpcm1hIEt1cnVtdSAtIFRVQklU
+QUsxLTArBgNVBAsTJEthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppIC0gS2FtdSBT
+TTE2MDQGA1UEAxMtVFVCSVRBSyBLYW11IFNNIFNTTCBLb2sgU2VydGlmaWthc2kg
+LSBTdXJ1bSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAr3UwM6q7
+a9OZLBI3hNmNe5eA027n/5tQlT6QlVZC1xl8JoSNkvoBHToP4mQ4t4y86Ij5iySr
+LqP1N+RAjhgleYN1Hzv/bKjFxlb4tO2KRKOrbEz8HdDc72i9z+SqzvBV96I01INr
+N3wcwv61A+xXzry0tcXtAA9TNypN9E8Mg/uGz8v+jE69h/mniyFXnHrfA2eJLJ2X
+YacQuFWQfw4tJzh03+f92k4S400VIgLI4OD8D62K18lUUMw7D8oWgITQUVbDjlZ/
+iSIzL+aFCr2lqBs23tPcLG07xxO9WSMs5uWk99gL7eqQQESolbuT1dCANLZGeA4f
+AJNG4e7p+exPFwIDAQABo0IwQDAdBgNVHQ4EFgQUZT/HiobGPN08VFw1+DrtUgxH
+V8gwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEL
+BQADggEBACo/4fEyjq7hmFxLXs9rHmoJ0iKpEsdeV31zVmSAhHqT5Am5EM2fKifh
+AHe+SMg1qIGf5LgsyX8OsNJLN13qudULXjS99HMpw+0mFZx+CFOKWI3QSyjfwbPf
+IPP54+M638yclNhOT8NrF7f3cuitZjO1JVOr4PhMqZ398g26rrnZqsZr+ZO7rqu4
+lzwDGrpDxpa5RXI4s6ehlj2Re37AIVNMh+3yC1SVUZPVIqUNivGTDj5UDrDYyU7c
+8jEyVupk+eq1nRZmQnLzf9OxMUP8pI4X8W0jq5Rm+K37DwhuJi1/FwcJsoz7UMCf
+lo3Ptv0AnVoUmr8CRPXBwp8iXqIPoeM=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem
new file mode 100644
index 00000000000..95f06cb8f43
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem
@@ -0,0 +1,89 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 623603 (0x983f3)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 2009
+ Validity
+ Not Before: Nov 5 08:35:58 2009 GMT
+ Not After : Nov 5 08:35:58 2029 GMT
+ Subject: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 2009
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d3:b2:4a:cf:7a:47:ef:75:9b:23:fa:3a:2f:d6:
+ 50:45:89:35:3a:c6:6b:db:fe:db:00:68:a8:e0:03:
+ 11:1d:37:50:08:9f:4d:4a:68:94:35:b3:53:d1:94:
+ 63:a7:20:56:af:de:51:78:ec:2a:3d:f3:48:48:50:
+ 3e:0a:df:46:55:8b:27:6d:c3:10:4d:0d:91:52:43:
+ d8:87:e0:5d:4e:36:b5:21:ca:5f:39:40:04:5f:5b:
+ 7e:cc:a3:c6:2b:a9:40:1e:d9:36:84:d6:48:f3:92:
+ 1e:34:46:20:24:c1:a4:51:8e:4a:1a:ef:50:3f:69:
+ 5d:19:7f:45:c3:c7:01:8f:51:c9:23:e8:72:ae:b4:
+ bc:56:09:7f:12:cb:1c:b1:af:29:90:0a:c9:55:cc:
+ 0f:d3:b4:1a:ed:47:35:5a:4a:ed:9c:73:04:21:d0:
+ aa:bd:0c:13:b5:00:ca:26:6c:c4:6b:0c:94:5a:95:
+ 94:da:50:9a:f1:ff:a5:2b:66:31:a4:c9:38:a0:df:
+ 1d:1f:b8:09:2e:f3:a7:e8:67:52:ab:95:1f:e0:46:
+ 3e:d8:a4:c3:ca:5a:c5:31:80:e8:48:9a:9f:94:69:
+ fe:19:dd:d8:73:7c:81:ca:96:de:8e:ed:b3:32:05:
+ 65:84:34:e6:e6:fd:57:10:b5:5f:76:bf:2f:b0:10:
+ 0d:c5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ FD:DA:14:C4:9F:30:DE:21:BD:1E:42:39:FC:AB:63:23:49:E0:F1:84
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+ Full Name:
+ URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_2009.crl
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 7f:97:db:30:c8:df:a4:9c:7d:21:7a:80:70:ce:14:12:69:88:
+ 14:95:60:44:01:ac:b2:e9:30:4f:9b:50:c2:66:d8:7e:8d:30:
+ b5:70:31:e9:e2:69:c7:f3:70:db:20:15:86:d0:0d:f0:be:ac:
+ 01:75:84:ce:7e:9f:4d:bf:b7:60:3b:9c:f3:ca:1d:e2:5e:68:
+ d8:a3:9d:97:e5:40:60:d2:36:21:fe:d0:b4:b8:17:da:74:a3:
+ 7f:d4:df:b0:98:02:ac:6f:6b:6b:2c:25:24:72:a1:65:ee:25:
+ 5a:e5:e6:32:e7:f2:df:ab:49:fa:f3:90:69:23:db:04:d9:e7:
+ 5c:58:fc:65:d4:97:be:cc:fc:2e:0a:cc:25:2a:35:04:f8:60:
+ 91:15:75:3d:41:ff:23:1f:19:c8:6c:eb:82:53:04:a6:e4:4c:
+ 22:4d:8d:8c:ba:ce:5b:73:ec:64:54:50:6d:d1:9c:55:fb:69:
+ c3:36:c3:8c:bc:3c:85:a6:6b:0a:26:0d:e0:93:98:60:ae:7e:
+ c6:24:97:8a:61:5f:91:8e:66:92:09:87:36:cd:8b:9b:2d:3e:
+ f6:51:d4:50:d4:59:28:bd:83:f2:cc:28:7b:53:86:6d:d8:26:
+ 88:70:d7:ea:91:cd:3e:b9:ca:c0:90:6e:5a:c6:5e:74:65:d7:
+ 5c:fe:a3:e2
+-----BEGIN CERTIFICATE-----
+MIIEMzCCAxugAwIBAgIDCYPzMA0GCSqGSIb3DQEBCwUAME0xCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMMHkQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgMjAwOTAeFw0wOTExMDUwODM1NThaFw0yOTExMDUwODM1NTha
+ME0xCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxJzAlBgNVBAMM
+HkQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgMjAwOTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBANOySs96R+91myP6Oi/WUEWJNTrGa9v+2wBoqOADER03
+UAifTUpolDWzU9GUY6cgVq/eUXjsKj3zSEhQPgrfRlWLJ23DEE0NkVJD2IfgXU42
+tSHKXzlABF9bfsyjxiupQB7ZNoTWSPOSHjRGICTBpFGOShrvUD9pXRl/RcPHAY9R
+ySPocq60vFYJfxLLHLGvKZAKyVXMD9O0Gu1HNVpK7ZxzBCHQqr0ME7UAyiZsxGsM
+lFqVlNpQmvH/pStmMaTJOKDfHR+4CS7zp+hnUquVH+BGPtikw8paxTGA6Eian5Rp
+/hnd2HN8gcqW3o7tszIFZYQ05ub9VxC1X3a/L7AQDcUCAwEAAaOCARowggEWMA8G
+A1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFP3aFMSfMN4hvR5COfyrYyNJ4PGEMA4G
+A1UdDwEB/wQEAwIBBjCB0wYDVR0fBIHLMIHIMIGAoH6gfIZ6bGRhcDovL2RpcmVj
+dG9yeS5kLXRydXN0Lm5ldC9DTj1ELVRSVVNUJTIwUm9vdCUyMENsYXNzJTIwMyUy
+MENBJTIwMiUyMDIwMDksTz1ELVRydXN0JTIwR21iSCxDPURFP2NlcnRpZmljYXRl
+cmV2b2NhdGlvbmxpc3QwQ6BBoD+GPWh0dHA6Ly93d3cuZC10cnVzdC5uZXQvY3Js
+L2QtdHJ1c3Rfcm9vdF9jbGFzc18zX2NhXzJfMjAwOS5jcmwwDQYJKoZIhvcNAQEL
+BQADggEBAH+X2zDI36ScfSF6gHDOFBJpiBSVYEQBrLLpME+bUMJm2H6NMLVwMeni
+acfzcNsgFYbQDfC+rAF1hM5+n02/t2A7nPPKHeJeaNijnZflQGDSNiH+0LS4F9p0
+o3/U37CYAqxva2ssJSRyoWXuJVrl5jLn8t+rSfrzkGkj2wTZ51xY/GXUl77M/C4K
+zCUqNQT4YJEVdT1B/yMfGchs64JTBKbkTCJNjYy6zltz7GRUUG3RnFX7acM2w4y8
+PIWmawomDeCTmGCufsYkl4phX5GOZpIJhzbNi5stPvZR1FDUWSi9g/LMKHtThm3Y
+Johw1+qRzT65ysCQblrGXnRl11z+o+I=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem
new file mode 100644
index 00000000000..2b2a80ad786
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 10000013 (0x98968d)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
+ Validity
+ Not Before: Dec 8 11:19:29 2010 GMT
+ Not After : Dec 8 11:10:28 2022 GMT
+ Subject: C = NL, O = Staat der Nederlanden, CN = Staat der Nederlanden EV Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:e3:c7:7e:89:f9:24:4b:3a:d2:33:83:35:2c:69:
+ ec:dc:09:a4:e3:51:a8:25:2b:79:b8:08:3d:e0:91:
+ ba:84:85:c6:85:a4:ca:e6:c9:2e:53:a4:c9:24:1e:
+ fd:55:66:71:5d:2c:c5:60:68:04:b7:d9:c2:52:26:
+ 38:88:a4:d6:3b:40:a6:c2:cd:3f:cd:98:93:b3:54:
+ 14:58:96:55:d5:50:fe:86:ad:a4:63:7f:5c:87:f6:
+ 8e:e6:27:92:67:17:92:02:03:2c:dc:d6:66:74:ed:
+ dd:67:ff:c1:61:8d:63:4f:0f:9b:6d:17:30:26:ef:
+ ab:d2:1f:10:a0:f9:c5:7f:16:69:81:03:47:ed:1e:
+ 68:8d:72:a1:4d:b2:26:c6:ba:6c:5f:6d:d6:af:d1:
+ b1:13:8e:a9:ad:f3:5e:69:75:26:18:3e:41:2b:21:
+ 7f:ee:8b:5d:07:06:9d:43:c4:29:0a:2b:fc:2a:3e:
+ 86:cb:3c:83:3a:f9:c9:0d:da:c5:99:e2:bc:78:41:
+ 33:76:e1:bf:2f:5d:e5:a4:98:50:0c:15:dd:e0:fa:
+ 9c:7f:38:68:d0:b2:a6:7a:a7:d1:31:bd:7e:8a:58:
+ 27:43:b3:ba:33:91:d3:a7:98:15:5c:9a:e6:d3:0f:
+ 75:d9:fc:41:98:97:3e:aa:25:db:8f:92:2e:b0:7b:
+ 0c:5f:f1:63:a9:37:f9:9b:75:69:4c:28:26:25:da:
+ d5:f2:12:70:45:55:e3:df:73:5e:37:f5:21:6c:90:
+ 8e:35:5a:c9:d3:23:eb:d3:c0:be:78:ac:42:28:58:
+ 66:a5:46:6d:70:02:d7:10:f9:4b:54:fc:5d:86:4a:
+ 87:cf:7f:ca:45:ac:11:5a:b5:20:51:8d:2f:88:47:
+ 97:39:c0:cf:ba:c0:42:01:40:99:48:21:0b:6b:a7:
+ d2:fd:96:d5:d1:be:46:9d:49:e0:0b:a6:a0:22:4e:
+ 38:d0:c1:3c:30:bc:70:8f:2c:75:cc:d0:c5:8c:51:
+ 3b:3d:94:08:64:26:61:7d:b9:c3:65:8f:14:9c:21:
+ d0:aa:fd:17:72:03:8f:bd:9b:8c:e6:5e:53:9e:b9:
+ 9d:ef:82:bb:e1:bc:e2:72:41:5b:21:94:d3:45:37:
+ 94:d1:df:09:39:5d:e7:23:aa:9a:1d:ca:6d:a8:0a:
+ 86:85:8a:82:be:42:07:d6:f2:38:82:73:da:87:5b:
+ e5:3c:d3:9e:3e:a7:3b:9e:f4:03:b3:f9:f1:7d:13:
+ 74:02:ff:bb:a1:e5:fa:00:79:1c:a6:66:41:88:5c:
+ 60:57:a6:2e:09:c4:ba:fd:9a:cf:a7:1f:40:c3:bb:
+ cc:5a:0a:55:4b:3b:38:76:51:b8:63:8b:84:94:16:
+ e6:56:f3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ FE:AB:00:90:98:9E:24:FC:A9:CC:1A:8A:FB:27:B8:BF:30:6E:A8:3B
+ Signature Algorithm: sha256WithRSAEncryption
+ cf:77:2c:6e:56:be:4e:b3:b6:84:00:94:ab:47:c9:0d:d2:76:
+ c7:86:9f:1d:07:d3:b6:b4:bb:08:78:af:69:d2:0b:49:de:33:
+ c5:ac:ad:c2:88:02:7d:06:b7:35:02:c1:60:c9:bf:c4:e8:94:
+ de:d4:d3:a9:13:25:5a:fe:6e:a2:ae:7d:05:dc:7d:f3:6c:f0:
+ 7e:a6:8d:ee:d9:d7:ce:58:17:e8:a9:29:ae:73:48:87:e7:9b:
+ ca:6e:29:a1:64:5f:19:13:f7:ae:06:10:ff:51:c6:9b:4d:55:
+ 25:4f:93:99:10:01:53:75:f1:13:ce:c7:a6:41:41:d2:bf:88:
+ a5:7f:45:fc:ac:b8:a5:b5:33:0c:82:c4:fb:07:f6:6a:e5:25:
+ 84:5f:06:ca:c1:86:39:11:db:58:cd:77:3b:2c:c2:4c:0f:5e:
+ 9a:e3:f0:ab:3e:61:1b:50:24:c2:c0:f4:f1:19:f0:11:29:b6:
+ a5:18:02:9b:d7:63:4c:70:8c:47:a3:03:43:5c:b9:5d:46:a0:
+ 0d:6f:ff:59:8e:be:dd:9f:72:c3:5b:2b:df:8c:5b:ce:e5:0c:
+ 46:6c:92:b2:0a:a3:4c:54:42:18:15:12:18:bd:da:fc:ba:74:
+ 6e:ff:c1:b6:a0:64:d8:a9:5f:55:ae:9f:5c:6a:76:96:d8:73:
+ 67:87:fb:4d:7f:5c:ee:69:ca:73:10:fb:8a:a9:fd:9e:bd:36:
+ 38:49:49:87:f4:0e:14:f0:e9:87:b8:3f:a7:4f:7a:5a:8e:79:
+ d4:93:e4:bb:68:52:84:ac:6c:e9:f3:98:70:55:72:32:f9:34:
+ ab:2b:49:b5:cd:20:62:e4:3a:7a:67:63:ab:96:dc:6d:ae:97:
+ ec:fc:9f:76:56:88:2e:66:cf:5b:b6:c9:a4:b0:d7:05:ba:e1:
+ 27:2f:93:bb:26:2a:a2:93:b0:1b:f3:8e:be:1d:40:a3:b9:36:
+ 8f:3e:82:1a:1a:5e:88:ea:50:f8:59:e2:83:46:29:0b:e3:44:
+ 5c:e1:95:b6:69:90:9a:14:6f:97:ae:81:cf:68:ef:99:9a:be:
+ b5:e7:e1:7f:f8:fa:13:47:16:4c:cc:6d:08:40:e7:8b:78:6f:
+ 50:82:44:50:3f:66:06:8a:ab:43:84:56:4a:0f:20:2d:86:0e:
+ f5:d2:db:d2:7a:8a:4b:cd:a5:e8:4e:f1:5e:26:25:01:59:23:
+ a0:7e:d2:f6:7e:21:57:d7:27:bc:15:57:4c:a4:46:c1:e0:83:
+ 1e:0c:4c:4d:1f:4f:06:19:e2:f9:a8:f4:3a:82:a1:b2:79:43:
+ 79:d6:ad:6f:7a:27:90:03:a4:ea:24:87:3f:d9:bd:d9:e9:f2:
+ 5f:50:49:1c:ee:ec:d7:2e
+-----BEGIN CERTIFICATE-----
+MIIFcDCCA1igAwIBAgIEAJiWjTANBgkqhkiG9w0BAQsFADBYMQswCQYDVQQGEwJO
+TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSkwJwYDVQQDDCBTdGFh
+dCBkZXIgTmVkZXJsYW5kZW4gRVYgUm9vdCBDQTAeFw0xMDEyMDgxMTE5MjlaFw0y
+MjEyMDgxMTEwMjhaMFgxCzAJBgNVBAYTAk5MMR4wHAYDVQQKDBVTdGFhdCBkZXIg
+TmVkZXJsYW5kZW4xKTAnBgNVBAMMIFN0YWF0IGRlciBOZWRlcmxhbmRlbiBFViBS
+b290IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA48d+ifkkSzrS
+M4M1LGns3Amk41GoJSt5uAg94JG6hIXGhaTK5skuU6TJJB79VWZxXSzFYGgEt9nC
+UiY4iKTWO0Cmws0/zZiTs1QUWJZV1VD+hq2kY39ch/aO5ieSZxeSAgMs3NZmdO3d
+Z//BYY1jTw+bbRcwJu+r0h8QoPnFfxZpgQNH7R5ojXKhTbImxrpsX23Wr9GxE46p
+rfNeaXUmGD5BKyF/7otdBwadQ8QpCiv8Kj6GyzyDOvnJDdrFmeK8eEEzduG/L13l
+pJhQDBXd4Pqcfzho0LKmeqfRMb1+ilgnQ7O6M5HTp5gVXJrm0w912fxBmJc+qiXb
+j5IusHsMX/FjqTf5m3VpTCgmJdrV8hJwRVXj33NeN/UhbJCONVrJ0yPr08C+eKxC
+KFhmpUZtcALXEPlLVPxdhkqHz3/KRawRWrUgUY0viEeXOcDPusBCAUCZSCELa6fS
+/ZbV0b5GnUngC6agIk440ME8MLxwjyx1zNDFjFE7PZQIZCZhfbnDZY8UnCHQqv0X
+cgOPvZuM5l5Tnrmd74K74bzickFbIZTTRTeU0d8JOV3nI6qaHcptqAqGhYqCvkIH
+1vI4gnPah1vlPNOePqc7nvQDs/nxfRN0Av+7oeX6AHkcpmZBiFxgV6YuCcS6/ZrP
+px9Aw7vMWgpVSzs4dlG4Y4uElBbmVvMCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFP6rAJCYniT8qcwaivsnuL8wbqg7
+MA0GCSqGSIb3DQEBCwUAA4ICAQDPdyxuVr5Os7aEAJSrR8kN0nbHhp8dB9O2tLsI
+eK9p0gtJ3jPFrK3CiAJ9Brc1AsFgyb/E6JTe1NOpEyVa/m6irn0F3H3zbPB+po3u
+2dfOWBfoqSmuc0iH55vKbimhZF8ZE/euBhD/UcabTVUlT5OZEAFTdfETzsemQUHS
+v4ilf0X8rLiltTMMgsT7B/Zq5SWEXwbKwYY5EdtYzXc7LMJMD16a4/CrPmEbUCTC
+wPTxGfARKbalGAKb12NMcIxHowNDXLldRqANb/9Zjr7dn3LDWyvfjFvO5QxGbJKy
+CqNMVEIYFRIYvdr8unRu/8G2oGTYqV9Vrp9canaW2HNnh/tNf1zuacpzEPuKqf2e
+vTY4SUmH9A4U8OmHuD+nT3pajnnUk+S7aFKErGzp85hwVXIy+TSrK0m1zSBi5Dp6
+Z2Orltxtrpfs/J92VoguZs9btsmksNcFuuEnL5O7Jiqik7Ab846+HUCjuTaPPoIa
+Gl6I6lD4WeKDRikL40Rc4ZW2aZCaFG+XroHPaO+Zmr615+F/+PoTRxZMzG0IQOeL
+eG9QgkRQP2YGiqtDhFZKDyAthg710tvSeopLzaXoTvFeJiUBWSOgftL2fiFX1ye8
+FVdMpEbB4IMeDExNH08GGeL5qPQ6gqGyeUN51q1veieQA6TqJIc/2b3Z6fJfUEkc
+7uzXLg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem
new file mode 100644
index 00000000000..786d3374bda
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem
@@ -0,0 +1,54 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 5c:8b:99:c5:5a:94:c5:d2:71:56:de:cd:89:80:cc:26
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust ECC Certification Authority
+ Validity
+ Not Before: Feb 1 00:00:00 2010 GMT
+ Not After : Jan 18 23:59:59 2038 GMT
+ Subject: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust ECC Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:1a:ac:54:5a:a9:f9:68:23:e7:7a:d5:24:6f:53:
+ c6:5a:d8:4b:ab:c6:d5:b6:d1:e6:73:71:ae:dd:9c:
+ d6:0c:61:fd:db:a0:89:03:b8:05:14:ec:57:ce:ee:
+ 5d:3f:e2:21:b3:ce:f7:d4:8a:79:e0:a3:83:7e:2d:
+ 97:d0:61:c4:f1:99:dc:25:91:63:ab:7f:30:a3:b4:
+ 70:e2:c7:a1:33:9c:f3:bf:2e:5c:53:b1:5f:b3:7d:
+ 32:7f:8a:34:e3:79:79
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 3A:E1:09:86:D4:CF:19:C2:96:76:74:49:76:DC:E0:35:C6:63:63:9A
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:30:36:67:a1:16:08:dc:e4:97:00:41:1d:4e:be:e1:
+ 63:01:cf:3b:aa:42:11:64:a0:9d:94:39:02:11:79:5c:7b:1d:
+ fa:64:b9:ee:16:42:b3:bf:8a:c2:09:c4:ec:e4:b1:4d:02:31:
+ 00:e9:2a:61:47:8c:52:4a:4b:4e:18:70:f6:d6:44:d6:6e:f5:
+ 83:ba:6d:58:bd:24:d9:56:48:ea:ef:c4:a2:46:81:88:6a:3a:
+ 46:d1:a9:9b:4d:c9:61:da:d1:5d:57:6a:18
+-----BEGIN CERTIFICATE-----
+MIICjzCCAhWgAwIBAgIQXIuZxVqUxdJxVt7NiYDMJjAKBggqhkjOPQQDAzCBiDEL
+MAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNl
+eSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMT
+JVVTRVJUcnVzdCBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMjAx
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNVBAgT
+Ck5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVUaGUg
+VVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBFQ0MgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQarFRaqflo
+I+d61SRvU8Za2EurxtW20eZzca7dnNYMYf3boIkDuAUU7FfO7l0/4iGzzvfUinng
+o4N+LZfQYcTxmdwlkWOrfzCjtHDix6EznPO/LlxTsV+zfTJ/ijTjeXmjQjBAMB0G
+A1UdDgQWBBQ64QmG1M8ZwpZ2dEl23OA1xmNjmjAOBgNVHQ8BAf8EBAMCAQYwDwYD
+VR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjA2Z6EWCNzklwBBHU6+4WMB
+zzuqQhFkoJ2UOQIReVx7Hfpkue4WQrO/isIJxOzksU0CMQDpKmFHjFJKS04YcPbW
+RNZu9YO6bVi9JNlWSOrvxKJGgYhqOkbRqZtNyWHa0V1Xahg=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem
new file mode 100644
index 00000000000..5a56b71f3d3
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = JP, O = "SECOM Trust Systems CO.,LTD.", OU = Security Communication RootCA2
+ Validity
+ Not Before: May 29 05:00:39 2009 GMT
+ Not After : May 29 05:00:39 2029 GMT
+ Subject: C = JP, O = "SECOM Trust Systems CO.,LTD.", OU = Security Communication RootCA2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d0:15:39:52:b1:52:b3:ba:c5:59:82:c4:5d:52:
+ ae:3a:43:65:80:4b:c7:f2:96:bc:db:36:97:d6:a6:
+ 64:8c:a8:5e:f0:e3:0a:1c:f7:df:97:3d:4b:ae:f6:
+ 5d:ec:21:b5:41:ab:cd:b9:7e:76:9f:be:f9:3e:36:
+ 34:a0:3b:c1:f6:31:11:45:74:93:3d:57:80:c5:f9:
+ 89:99:ca:e5:ab:6a:d4:b5:da:41:90:10:c1:d6:d6:
+ 42:89:c2:bf:f4:38:12:95:4c:54:05:f7:36:e4:45:
+ 83:7b:14:65:d6:dc:0c:4d:d1:de:7e:0c:ab:3b:c4:
+ 15:be:3a:56:a6:5a:6f:76:69:52:a9:7a:b9:c8:eb:
+ 6a:9a:5d:52:d0:2d:0a:6b:35:16:09:10:84:d0:6a:
+ ca:3a:06:00:37:47:e4:7e:57:4f:3f:8b:eb:67:b8:
+ 88:aa:c5:be:53:55:b2:91:c4:7d:b9:b0:85:19:06:
+ 78:2e:db:61:1a:fa:85:f5:4a:91:a1:e7:16:d5:8e:
+ a2:39:df:94:b8:70:1f:28:3f:8b:fc:40:5e:63:83:
+ 3c:83:2a:1a:99:6b:cf:de:59:6a:3b:fc:6f:16:d7:
+ 1f:fd:4a:10:eb:4e:82:16:3a:ac:27:0c:53:f1:ad:
+ d5:24:b0:6b:03:50:c1:2d:3c:16:dd:44:34:27:1a:
+ 75:fb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 0A:85:A9:77:65:05:98:7C:40:81:F8:0F:97:2C:38:F1:0A:EC:3C:CF
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 4c:3a:a3:44:ac:b9:45:b1:c7:93:7e:c8:0b:0a:42:df:64:ea:
+ 1c:ee:59:6c:08:ba:89:5f:6a:ca:4a:95:9e:7a:8f:07:c5:da:
+ 45:72:82:71:0e:3a:d2:cc:6f:a7:b4:a1:23:bb:f6:24:9f:cb:
+ 17:fe:8c:a6:ce:c2:d2:db:cc:8d:fc:71:fc:03:29:c1:6c:5d:
+ 33:5f:64:b6:65:3b:89:6f:18:76:78:f5:dc:a2:48:1f:19:3f:
+ 8e:93:eb:f1:fa:17:ee:cd:4e:e3:04:12:55:d6:e5:e4:dd:fb:
+ 3e:05:7c:e2:1d:5e:c6:a7:bc:97:4f:68:3a:f5:e9:2e:0a:43:
+ b6:af:57:5c:62:68:7c:b7:fd:a3:8a:84:a0:ac:62:be:2b:09:
+ 87:34:f0:6a:01:bb:9b:29:56:3c:fe:00:37:cf:23:6c:f1:4e:
+ aa:b6:74:46:12:6c:91:ee:34:d5:ec:9a:91:e7:44:be:90:31:
+ 72:d5:49:02:f6:02:e5:f4:1f:eb:7c:d9:96:55:a9:ff:ec:8a:
+ f9:99:47:ff:35:5a:02:aa:04:cb:8a:5b:87:71:29:91:bd:a4:
+ b4:7a:0d:bd:9a:f5:57:23:00:07:21:17:3f:4a:39:d1:05:49:
+ 0b:a7:b6:37:81:a5:5d:8c:aa:33:5e:81:28:7c:a7:7d:27:eb:
+ 00:ae:8d:37
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDEl
+MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMe
+U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoX
+DTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRy
+dXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3VyaXR5IENvbW11bmlj
+YXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANAV
+OVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGr
+zbl+dp+++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVM
+VAX3NuRFg3sUZdbcDE3R3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQ
+hNBqyjoGADdH5H5XTz+L62e4iKrFvlNVspHEfbmwhRkGeC7bYRr6hfVKkaHnFtWO
+ojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1KEOtOghY6rCcMU/Gt1SSw
+awNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8QIH4D5cs
+OPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3
+DQEBCwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpF
+coJxDjrSzG+ntKEju/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXc
+okgfGT+Ok+vx+hfuzU7jBBJV1uXk3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8
+t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6qtnRGEmyR7jTV7JqR50S+kDFy
+1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29mvVXIwAHIRc/
+SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem
new file mode 100644
index 00000000000..c40849bba84
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 4c:aa:f9:ca:db:63:6f:e0:1f:f7:4e:d8:5b:03:86:9d
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
+ Validity
+ Not Before: Jan 19 00:00:00 2010 GMT
+ Not After : Jan 18 23:59:59 2038 GMT
+ Subject: C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO RSA Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:91:e8:54:92:d2:0a:56:b1:ac:0d:24:dd:c5:cf:
+ 44:67:74:99:2b:37:a3:7d:23:70:00:71:bc:53:df:
+ c4:fa:2a:12:8f:4b:7f:10:56:bd:9f:70:72:b7:61:
+ 7f:c9:4b:0f:17:a7:3d:e3:b0:04:61:ee:ff:11:97:
+ c7:f4:86:3e:0a:fa:3e:5c:f9:93:e6:34:7a:d9:14:
+ 6b:e7:9c:b3:85:a0:82:7a:76:af:71:90:d7:ec:fd:
+ 0d:fa:9c:6c:fa:df:b0:82:f4:14:7e:f9:be:c4:a6:
+ 2f:4f:7f:99:7f:b5:fc:67:43:72:bd:0c:00:d6:89:
+ eb:6b:2c:d3:ed:8f:98:1c:14:ab:7e:e5:e3:6e:fc:
+ d8:a8:e4:92:24:da:43:6b:62:b8:55:fd:ea:c1:bc:
+ 6c:b6:8b:f3:0e:8d:9a:e4:9b:6c:69:99:f8:78:48:
+ 30:45:d5:ad:e1:0d:3c:45:60:fc:32:96:51:27:bc:
+ 67:c3:ca:2e:b6:6b:ea:46:c7:c7:20:a0:b1:1f:65:
+ de:48:08:ba:a4:4e:a9:f2:83:46:37:84:eb:e8:cc:
+ 81:48:43:67:4e:72:2a:9b:5c:bd:4c:1b:28:8a:5c:
+ 22:7b:b4:ab:98:d9:ee:e0:51:83:c3:09:46:4e:6d:
+ 3e:99:fa:95:17:da:7c:33:57:41:3c:8d:51:ed:0b:
+ b6:5c:af:2c:63:1a:df:57:c8:3f:bc:e9:5d:c4:9b:
+ af:45:99:e2:a3:5a:24:b4:ba:a9:56:3d:cf:6f:aa:
+ ff:49:58:be:f0:a8:ff:f4:b8:ad:e9:37:fb:ba:b8:
+ f4:0b:3a:f9:e8:43:42:1e:89:d8:84:cb:13:f1:d9:
+ bb:e1:89:60:b8:8c:28:56:ac:14:1d:9c:0a:e7:71:
+ eb:cf:0e:dd:3d:a9:96:a1:48:bd:3c:f7:af:b5:0d:
+ 22:4c:c0:11:81:ec:56:3b:f6:d3:a2:e2:5b:b7:b2:
+ 04:22:52:95:80:93:69:e8:8e:4c:65:f1:91:03:2d:
+ 70:74:02:ea:8b:67:15:29:69:52:02:bb:d7:df:50:
+ 6a:55:46:bf:a0:a3:28:61:7f:70:d0:c3:a2:aa:2c:
+ 21:aa:47:ce:28:9c:06:45:76:bf:82:18:27:b4:d5:
+ ae:b4:cb:50:e6:6b:f4:4c:86:71:30:e9:a6:df:16:
+ 86:e0:d8:ff:40:dd:fb:d0:42:88:7f:a3:33:3a:2e:
+ 5c:1e:41:11:81:63:ce:18:71:6b:2b:ec:a6:8a:b7:
+ 31:5c:3a:6a:47:e0:c3:79:59:d6:20:1a:af:f2:6a:
+ 98:aa:72:bc:57:4a:d2:4b:9d:bb:10:fc:b0:4c:41:
+ e5:ed:1d:3d:5e:28:9d:9c:cc:bf:b3:51:da:a7:47:
+ e5:84:53
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ BB:AF:7E:02:3D:FA:A6:F1:3C:84:8E:AD:EE:38:98:EC:D9:32:32:D4
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha384WithRSAEncryption
+ 0a:f1:d5:46:84:b7:ae:51:bb:6c:b2:4d:41:14:00:93:4c:9c:
+ cb:e5:c0:54:cf:a0:25:8e:02:f9:fd:b0:a2:0d:f5:20:98:3c:
+ 13:2d:ac:56:a2:b0:d6:7e:11:92:e9:2e:ba:9e:2e:9a:72:b1:
+ bd:19:44:6c:61:35:a2:9a:b4:16:12:69:5a:8c:e1:d7:3e:a4:
+ 1a:e8:2f:03:f4:ae:61:1d:10:1b:2a:a4:8b:7a:c5:fe:05:a6:
+ e1:c0:d6:c8:fe:9e:ae:8f:2b:ba:3d:99:f8:d8:73:09:58:46:
+ 6e:a6:9c:f4:d7:27:d3:95:da:37:83:72:1c:d3:73:e0:a2:47:
+ 99:03:38:5d:d5:49:79:00:29:1c:c7:ec:9b:20:1c:07:24:69:
+ 57:78:b2:39:fc:3a:84:a0:b5:9c:7c:8d:bf:2e:93:62:27:b7:
+ 39:da:17:18:ae:bd:3c:09:68:ff:84:9b:3c:d5:d6:0b:03:e3:
+ 57:9e:14:f7:d1:eb:4f:c8:bd:87:23:b7:b6:49:43:79:85:5c:
+ ba:eb:92:0b:a1:c6:e8:68:a8:4c:16:b1:1a:99:0a:e8:53:2c:
+ 92:bb:a1:09:18:75:0c:65:a8:7b:cb:23:b7:1a:c2:28:85:c3:
+ 1b:ff:d0:2b:62:ef:a4:7b:09:91:98:67:8c:14:01:cd:68:06:
+ 6a:63:21:75:03:80:88:8a:6e:81:c6:85:f2:a9:a4:2d:e7:f4:
+ a5:24:10:47:83:ca:cd:f4:8d:79:58:b1:06:9b:e7:1a:2a:d9:
+ 9d:01:d7:94:7d:ed:03:4a:ca:f0:db:e8:a9:01:3e:f5:56:99:
+ c9:1e:8e:49:3d:bb:e5:09:b9:e0:4f:49:92:3d:16:82:40:cc:
+ cc:59:c6:e6:3a:ed:12:2e:69:3c:6c:95:b1:fd:aa:1d:7b:7f:
+ 86:be:1e:0e:32:46:fb:fb:13:8f:75:7f:4c:8b:4b:46:63:fe:
+ 00:34:40:70:c1:c3:b9:a1:dd:a6:70:e2:04:b3:41:bc:e9:80:
+ 91:ea:64:9c:7a:e1:22:03:a9:9c:6e:6f:0e:65:4f:6c:87:87:
+ 5e:f3:6e:a0:f9:75:a5:9b:40:e8:53:b2:27:9d:4a:b9:c0:77:
+ 21:8d:ff:87:f2:de:bc:8c:ef:17:df:b7:49:0b:d1:f2:6e:30:
+ 0b:1a:0e:4e:76:ed:11:fc:f5:e9:56:b2:7d:bf:c7:6d:0a:93:
+ 8c:a5:d0:c0:b6:1d:be:3a:4e:94:a2:d7:6e:6c:0b:c2:8a:7c:
+ fa:20:f3:c4:e4:e5:cd:0d:a8:cb:91:92:b1:7c:85:ec:b5:14:
+ 69:66:0e:82:e7:cd:ce:c8:2d:a6:51:7f:21:c1:35:53:85:06:
+ 4a:5d:9f:ad:bb:1b:5f:74
+-----BEGIN CERTIFICATE-----
+MIIF2DCCA8CgAwIBAgIQTKr5yttjb+Af907YWwOGnTANBgkqhkiG9w0BAQwFADCB
+hTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
+A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNV
+BAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAwMTE5
+MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgT
+EkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBSU0EgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCR
+6FSS0gpWsawNJN3Fz0RndJkrN6N9I3AAcbxT38T6KhKPS38QVr2fcHK3YX/JSw8X
+pz3jsARh7v8Rl8f0hj4K+j5c+ZPmNHrZFGvnnLOFoIJ6dq9xkNfs/Q36nGz637CC
+9BR++b7Epi9Pf5l/tfxnQ3K9DADWietrLNPtj5gcFKt+5eNu/Nio5JIk2kNrYrhV
+/erBvGy2i/MOjZrkm2xpmfh4SDBF1a3hDTxFYPwyllEnvGfDyi62a+pGx8cgoLEf
+Zd5ICLqkTqnyg0Y3hOvozIFIQ2dOciqbXL1MGyiKXCJ7tKuY2e7gUYPDCUZObT6Z
++pUX2nwzV0E8jVHtC7ZcryxjGt9XyD+86V3Em69FmeKjWiS0uqlWPc9vqv9JWL7w
+qP/0uK3pN/u6uPQLOvnoQ0IeidiEyxPx2bvhiWC4jChWrBQdnArncevPDt09qZah
+SL0896+1DSJMwBGB7FY79tOi4lu3sgQiUpWAk2nojkxl8ZEDLXB0AuqLZxUpaVIC
+u9ffUGpVRr+goyhhf3DQw6KqLCGqR84onAZFdr+CGCe01a60y1Dma/RMhnEw6abf
+Fobg2P9A3fvQQoh/ozM6LlweQRGBY84YcWsr7KaKtzFcOmpH4MN5WdYgGq/yapiq
+crxXStJLnbsQ/LBMQeXtHT1eKJ2czL+zUdqnR+WEUwIDAQABo0IwQDAdBgNVHQ4E
+FgQUu69+Aj36pvE8hI6t7jiY7NkyMtQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB
+/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAArx1UaEt65Ru2yyTUEUAJNMnMvl
+wFTPoCWOAvn9sKIN9SCYPBMtrFaisNZ+EZLpLrqeLppysb0ZRGxhNaKatBYSaVqM
+4dc+pBroLwP0rmEdEBsqpIt6xf4FpuHA1sj+nq6PK7o9mfjYcwlYRm6mnPTXJ9OV
+2jeDchzTc+CiR5kDOF3VSXkAKRzH7JsgHAckaVd4sjn8OoSgtZx8jb8uk2Intzna
+FxiuvTwJaP+EmzzV1gsD41eeFPfR60/IvYcjt7ZJQ3mFXLrrkguhxuhoqEwWsRqZ
+CuhTLJK7oQkYdQxlqHvLI7cawiiFwxv/0Cti76R7CZGYZ4wUAc1oBmpjIXUDgIiK
+boHGhfKppC3n9KUkEEeDys30jXlYsQab5xoq2Z0B15R97QNKyvDb6KkBPvVWmcke
+jkk9u+UJueBPSZI9FoJAzMxZxuY67RIuaTxslbH9qh17f4a+Hg4yRvv7E491f0yL
+S0Zj/gA0QHDBw7mh3aZw4gSzQbzpgJHqZJx64SIDqZxubw5lT2yHh17zbqD5daWb
+QOhTsiedSrnAdyGN/4fy3ryM7xfft0kL0fJuMAsaDk527RH89elWsn2/x20Kk4yl
+0MC2Hb46TpSi125sC8KKfPog88Tk5c0NqMuRkrF8hey1FGlmDoLnzc7ILaZRfyHB
+NVOFBkpdn627G190
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem
new file mode 100644
index 00000000000..20cd57a9424
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem
@@ -0,0 +1,120 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 05:9b:1b:57:9e:8e:21:32:e2:39:07:bd:a7:77:75:5c
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Trusted Root G4
+ Validity
+ Not Before: Aug 1 12:00:00 2013 GMT
+ Not After : Jan 15 12:00:00 2038 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Trusted Root G4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:bf:e6:90:73:68:de:bb:e4:5d:4a:3c:30:22:30:
+ 69:33:ec:c2:a7:25:2e:c9:21:3d:f2:8a:d8:59:c2:
+ e1:29:a7:3d:58:ab:76:9a:cd:ae:7b:1b:84:0d:c4:
+ 30:1f:f3:1b:a4:38:16:eb:56:c6:97:6d:1d:ab:b2:
+ 79:f2:ca:11:d2:e4:5f:d6:05:3c:52:0f:52:1f:c6:
+ 9e:15:a5:7e:be:9f:a9:57:16:59:55:72:af:68:93:
+ 70:c2:b2:ba:75:99:6a:73:32:94:d1:10:44:10:2e:
+ df:82:f3:07:84:e6:74:3b:6d:71:e2:2d:0c:1b:ee:
+ 20:d5:c9:20:1d:63:29:2d:ce:ec:5e:4e:c8:93:f8:
+ 21:61:9b:34:eb:05:c6:5e:ec:5b:1a:bc:eb:c9:cf:
+ cd:ac:34:40:5f:b1:7a:66:ee:77:c8:48:a8:66:57:
+ 57:9f:54:58:8e:0c:2b:b7:4f:a7:30:d9:56:ee:ca:
+ 7b:5d:e3:ad:c9:4f:5e:e5:35:e7:31:cb:da:93:5e:
+ dc:8e:8f:80:da:b6:91:98:40:90:79:c3:78:c7:b6:
+ b1:c4:b5:6a:18:38:03:10:8d:d8:d4:37:a4:2e:05:
+ 7d:88:f5:82:3e:10:91:70:ab:55:82:41:32:d7:db:
+ 04:73:2a:6e:91:01:7c:21:4c:d4:bc:ae:1b:03:75:
+ 5d:78:66:d9:3a:31:44:9a:33:40:bf:08:d7:5a:49:
+ a4:c2:e6:a9:a0:67:dd:a4:27:bc:a1:4f:39:b5:11:
+ 58:17:f7:24:5c:46:8f:64:f7:c1:69:88:76:98:76:
+ 3d:59:5d:42:76:87:89:97:69:7a:48:f0:e0:a2:12:
+ 1b:66:9a:74:ca:de:4b:1e:e7:0e:63:ae:e6:d4:ef:
+ 92:92:3a:9e:3d:dc:00:e4:45:25:89:b6:9a:44:19:
+ 2b:7e:c0:94:b4:d2:61:6d:eb:33:d9:c5:df:4b:04:
+ 00:cc:7d:1c:95:c3:8f:f7:21:b2:b2:11:b7:bb:7f:
+ f2:d5:8c:70:2c:41:60:aa:b1:63:18:44:95:1a:76:
+ 62:7e:f6:80:b0:fb:e8:64:a6:33:d1:89:07:e1:bd:
+ b7:e6:43:a4:18:b8:a6:77:01:e1:0f:94:0c:21:1d:
+ b2:54:29:25:89:6c:e5:0e:52:51:47:74:be:26:ac:
+ b6:41:75:de:7a:ac:5f:8d:3f:c9:bc:d3:41:11:12:
+ 5b:e5:10:50:eb:31:c5:ca:72:16:22:09:df:7c:4c:
+ 75:3f:63:ec:21:5f:c4:20:51:6b:6f:b1:ab:86:8b:
+ 4f:c2:d6:45:5f:9d:20:fc:a1:1e:c5:c0:8f:a2:b1:
+ 7e:0a:26:99:f5:e4:69:2f:98:1d:2d:f5:d9:a9:b2:
+ 1d:e5:1b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ EC:D7:E3:82:D2:71:5D:64:4C:DF:2E:67:3F:E7:BA:98:AE:1C:0F:4F
+ Signature Algorithm: sha384WithRSAEncryption
+ bb:61:d9:7d:a9:6c:be:17:c4:91:1b:c3:a1:a2:00:8d:e3:64:
+ 68:0f:56:cf:77:ae:70:f9:fd:9a:4a:99:b9:c9:78:5c:0c:0c:
+ 5f:e4:e6:14:29:56:0b:36:49:5d:44:63:e0:ad:9c:96:18:66:
+ 1b:23:0d:3d:79:e9:6d:6b:d6:54:f8:d2:3c:c1:43:40:ae:1d:
+ 50:f5:52:fc:90:3b:bb:98:99:69:6b:c7:c1:a7:a8:68:a4:27:
+ dc:9d:f9:27:ae:30:85:b9:f6:67:4d:3a:3e:8f:59:39:22:53:
+ 44:eb:c8:5d:03:ca:ed:50:7a:7d:62:21:0a:80:c8:73:66:d1:
+ a0:05:60:5f:e8:a5:b4:a7:af:a8:f7:6d:35:9c:7c:5a:8a:d6:
+ a2:38:99:f3:78:8b:f4:4d:d2:20:0b:de:04:ee:8c:9b:47:81:
+ 72:0d:c0:14:32:ef:30:59:2e:ae:e0:71:f2:56:e4:6a:97:6f:
+ 92:50:6d:96:8d:68:7a:9a:b2:36:14:7a:06:f2:24:b9:09:11:
+ 50:d7:08:b1:b8:89:7a:84:23:61:42:29:e5:a3:cd:a2:20:41:
+ d7:d1:9c:64:d9:ea:26:a1:8b:14:d7:4c:19:b2:50:41:71:3d:
+ 3f:4d:70:23:86:0c:4a:dc:81:d2:cc:32:94:84:0d:08:09:97:
+ 1c:4f:c0:ee:6b:20:74:30:d2:e0:39:34:10:85:21:15:01:08:
+ e8:55:32:de:71:49:d9:28:17:50:4d:e6:be:4d:d1:75:ac:d0:
+ ca:fb:41:b8:43:a5:aa:d3:c3:05:44:4f:2c:36:9b:e2:fa:e2:
+ 45:b8:23:53:6c:06:6f:67:55:7f:46:b5:4c:3f:6e:28:5a:79:
+ 26:d2:a4:a8:62:97:d2:1e:e2:ed:4a:8b:bc:1b:fd:47:4a:0d:
+ df:67:66:7e:b2:5b:41:d0:3b:e4:f4:3b:f4:04:63:e9:ef:c2:
+ 54:00:51:a0:8a:2a:c9:ce:78:cc:d5:ea:87:04:18:b3:ce:af:
+ 49:88:af:f3:92:99:b6:b3:e6:61:0f:d2:85:00:e7:50:1a:e4:
+ 1b:95:9d:19:a1:b9:9c:b1:9b:b1:00:1e:ef:d0:0f:4f:42:6c:
+ c9:0a:bc:ee:43:fa:3a:71:a5:c8:4d:26:a5:35:fd:89:5d:bc:
+ 85:62:1d:32:d2:a0:2b:54:ed:9a:57:c1:db:fa:10:cf:19:b7:
+ 8b:4a:1b:8f:01:b6:27:95:53:e8:b6:89:6d:5b:bc:68:d4:23:
+ e8:8b:51:a2:56:f9:f0:a6:80:a0:d6:1e:b3:bc:0f:0f:53:75:
+ 29:aa:ea:13:77:e4:de:8c:81:21:ad:07:10:47:11:ad:87:3d:
+ 07:d1:75:bc:cf:f3:66:7e
+-----BEGIN CERTIFICATE-----
+MIIFkDCCA3igAwIBAgIQBZsbV56OITLiOQe9p3d1XDANBgkqhkiG9w0BAQwFADBi
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3Qg
+RzQwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBiMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSEwHwYDVQQDExhEaWdpQ2VydCBUcnVzdGVkIFJvb3QgRzQwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQC/5pBzaN675F1KPDAiMGkz7MKnJS7JIT3y
+ithZwuEppz1Yq3aaza57G4QNxDAf8xukOBbrVsaXbR2rsnnyyhHS5F/WBTxSD1If
+xp4VpX6+n6lXFllVcq9ok3DCsrp1mWpzMpTREEQQLt+C8weE5nQ7bXHiLQwb7iDV
+ySAdYyktzuxeTsiT+CFhmzTrBcZe7FsavOvJz82sNEBfsXpm7nfISKhmV1efVFiO
+DCu3T6cw2Vbuyntd463JT17lNecxy9qTXtyOj4DatpGYQJB5w3jHtrHEtWoYOAMQ
+jdjUN6QuBX2I9YI+EJFwq1WCQTLX2wRzKm6RAXwhTNS8rhsDdV14Ztk6MUSaM0C/
+CNdaSaTC5qmgZ92kJ7yhTzm1EVgX9yRcRo9k98FpiHaYdj1ZXUJ2h4mXaXpI8OCi
+EhtmmnTK3kse5w5jrubU75KSOp493ADkRSWJtppEGSt+wJS00mFt6zPZxd9LBADM
+fRyVw4/3IbKyEbe7f/LVjHAsQWCqsWMYRJUadmJ+9oCw++hkpjPRiQfhvbfmQ6QY
+uKZ3AeEPlAwhHbJUKSWJbOUOUlFHdL4mrLZBdd56rF+NP8m800ERElvlEFDrMcXK
+chYiCd98THU/Y+whX8QgUWtvsauGi0/C1kVfnSD8oR7FwI+isX4KJpn15GkvmB0t
+9dmpsh3lGwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+hjAdBgNVHQ4EFgQU7NfjgtJxXWRM3y5nP+e6mK4cD08wDQYJKoZIhvcNAQEMBQAD
+ggIBALth2X2pbL4XxJEbw6GiAI3jZGgPVs93rnD5/ZpKmbnJeFwMDF/k5hQpVgs2
+SV1EY+CtnJYYZhsjDT156W1r1lT40jzBQ0CuHVD1UvyQO7uYmWlrx8GnqGikJ9yd
++SeuMIW59mdNOj6PWTkiU0TryF0Dyu1Qen1iIQqAyHNm0aAFYF/opbSnr6j3bTWc
+fFqK1qI4mfN4i/RN0iAL3gTujJtHgXINwBQy7zBZLq7gcfJW5GqXb5JQbZaNaHqa
+sjYUegbyJLkJEVDXCLG4iXqEI2FCKeWjzaIgQdfRnGTZ6iahixTXTBmyUEFxPT9N
+cCOGDErcgdLMMpSEDQgJlxxPwO5rIHQw0uA5NBCFIRUBCOhVMt5xSdkoF1BN5r5N
+0XWs0Mr7QbhDparTwwVETyw2m+L64kW4I1NsBm9nVX9GtUw/bihaeSbSpKhil9Ie
+4u1Ki7wb/UdKDd9nZn6yW0HQO+T0O/QEY+nvwlQAUaCKKsnOeMzV6ocEGLPOr0mI
+r/OSmbaz5mEP0oUA51Aa5BuVnRmhuZyxm7EAHu/QD09CbMkKvO5D+jpxpchNJqU1
+/YldvIViHTLSoCtU7ZpXwdv6EM8Zt4tKG48BtieVU+i2iW1bvGjUI+iLUaJW+fCm
+gKDWHrO8Dw9TdSmq6hN35N6MgSGtBxBHEa2HPQfRdbzP82Z+
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem
new file mode 100644
index 00000000000..9a51a7a89d3
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem
@@ -0,0 +1,55 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 08:bd:85:97:6c:99:27:a4:80:68:47:3b
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global ECC P384 Certification Authority
+ Validity
+ Not Before: Aug 23 19:36:43 2017 GMT
+ Not After : Aug 23 19:36:43 2042 GMT
+ Subject: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global ECC P384 Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:6b:da:0d:75:35:08:31:47:05:ae:45:99:55:f1:
+ 11:13:2e:4a:f8:10:31:23:a3:7e:83:d3:7f:28:08:
+ 3a:26:1a:3a:cf:97:82:1f:80:b7:27:09:8f:d1:8e:
+ 30:c4:0a:9b:0e:ac:58:04:ab:f7:36:7d:94:23:a4:
+ 9b:0a:8a:8b:ab:eb:fd:39:25:66:f1:5e:fe:8c:ae:
+ 8d:41:79:9d:09:60:ce:28:a9:d3:8a:6d:f3:d6:45:
+ d4:f2:98:84:38:65:a0
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 55:A9:84:89:D2:C1:32:BD:18:CB:6C:A6:07:4E:C8:E7:9D:BE:82:90
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:37:01:92:97:45:12:7e:a0:f3:3e:ad:19:3a:72:
+ dd:f4:50:93:03:12:be:44:d2:4f:41:a4:8c:9c:9d:1f:a3:f6:
+ c2:92:e7:48:14:fe:4e:9b:a5:91:57:ae:c6:37:72:bb:02:30:
+ 67:25:0a:b1:0c:5e:ee:a9:63:92:6f:e5:90:0b:fe:66:22:ca:
+ 47:fd:8a:31:f7:83:fe:7a:bf:10:be:18:2b:1e:8f:f6:29:1e:
+ 94:59:ef:8e:21:37:cb:51:98:a5:6e:4b
+-----BEGIN CERTIFICATE-----
+MIICnTCCAiSgAwIBAgIMCL2Fl2yZJ6SAaEc7MAoGCCqGSM49BAMDMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM2NDNaFw00MjA4MjMxOTM2NDNaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDM4NCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTB2MBAGByqGSM49AgEGBSuB
+BAAiA2IABGvaDXU1CDFHBa5FmVXxERMuSvgQMSOjfoPTfygIOiYaOs+Xgh+AtycJ
+j9GOMMQKmw6sWASr9zZ9lCOkmwqKi6vr/TklZvFe/oyujUF5nQlgziip04pt89ZF
+1PKYhDhloKNDMEEwDwYDVR0TAQH/BAUwAwEB/zAPBgNVHQ8BAf8EBQMDBwYAMB0G
+A1UdDgQWBBRVqYSJ0sEyvRjLbKYHTsjnnb6CkDAKBggqhkjOPQQDAwNnADBkAjA3
+AZKXRRJ+oPM+rRk6ct30UJMDEr5E0k9BpIycnR+j9sKS50gU/k6bpZFXrsY3crsC
+MGclCrEMXu6pY5Jv5ZAL/mYiykf9ijH3g/56vxC+GCsej/YpHpRZ744hN8tRmKVu
+Sw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem
new file mode 100644
index 00000000000..20fed2b20b0
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem
@@ -0,0 +1,123 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6271844772424770508 (0x570a119742c4e3cc)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = IT, L = Milan, O = Actalis S.p.A./03358520967, CN = Actalis Authentication Root CA
+ Validity
+ Not Before: Sep 22 11:22:02 2011 GMT
+ Not After : Sep 22 11:22:02 2030 GMT
+ Subject: C = IT, L = Milan, O = Actalis S.p.A./03358520967, CN = Actalis Authentication Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a7:c6:c4:a5:29:a4:2c:ef:e5:18:c5:b0:50:a3:
+ 6f:51:3b:9f:0a:5a:c9:c2:48:38:0a:c2:1c:a0:18:
+ 7f:91:b5:87:b9:40:3f:dd:1d:68:1f:08:83:d5:2d:
+ 1e:88:a0:f8:8f:56:8f:6d:99:02:92:90:16:d5:5f:
+ 08:6c:89:d7:e1:ac:bc:20:c2:b1:e0:83:51:8a:69:
+ 4d:00:96:5a:6f:2f:c0:44:7e:a3:0e:e4:91:cd:58:
+ ee:dc:fb:c7:1e:45:47:dd:27:b9:08:01:9f:a6:21:
+ 1d:f5:41:2d:2f:4c:fd:28:ad:e0:8a:ad:22:b4:56:
+ 65:8e:86:54:8f:93:43:29:de:39:46:78:a3:30:23:
+ ba:cd:f0:7d:13:57:c0:5d:d2:83:6b:48:4c:c4:ab:
+ 9f:80:5a:5b:3a:bd:c9:a7:22:3f:80:27:33:5b:0e:
+ b7:8a:0c:5d:07:37:08:cb:6c:d2:7a:47:22:44:35:
+ c5:cc:cc:2e:8e:dd:2a:ed:b7:7d:66:0d:5f:61:51:
+ 22:55:1b:e3:46:e3:e3:3d:d0:35:62:9a:db:af:14:
+ c8:5b:a1:cc:89:1b:e1:30:26:fc:a0:9b:1f:81:a7:
+ 47:1f:04:eb:a3:39:92:06:9f:99:d3:bf:d3:ea:4f:
+ 50:9c:19:fe:96:87:1e:3c:65:f6:a3:18:24:83:86:
+ 10:e7:54:3e:a8:3a:76:24:4f:81:21:c5:e3:0f:02:
+ f8:93:94:47:20:bb:fe:d4:0e:d3:68:b9:dd:c4:7a:
+ 84:82:e3:53:54:79:dd:db:9c:d2:f2:07:9b:2e:b6:
+ bc:3e:ed:85:6d:ef:25:11:f2:97:1a:42:61:f7:4a:
+ 97:e8:8b:b1:10:07:fa:65:81:b2:a2:39:cf:f7:3c:
+ ff:18:fb:c6:f1:5a:8b:59:e2:02:ac:7b:92:d0:4e:
+ 14:4f:59:45:f6:0c:5e:28:5f:b0:e8:3f:45:cf:cf:
+ af:9b:6f:fb:84:d3:77:5a:95:6f:ac:94:84:9e:ee:
+ bc:c0:4a:8f:4a:93:f8:44:21:e2:31:45:61:50:4e:
+ 10:d8:e3:35:7c:4c:19:b4:de:05:bf:a3:06:9f:c8:
+ b5:cd:e4:1f:d7:17:06:0d:7a:95:74:55:0d:68:1a:
+ fc:10:1b:62:64:9d:6d:e0:95:a0:c3:94:07:57:0d:
+ 14:e6:bd:05:fb:b8:9f:e6:df:8b:e2:c6:e7:7e:96:
+ f6:53:c5:80:34:50:28:58:f0:12:50:71:17:30:ba:
+ e6:78:63:bc:f4:b2:ad:9b:2b:b2:fe:e1:39:8c:5e:
+ ba:0b:20:94:de:7b:83:b8:ff:e3:56:8d:b7:11:e9:
+ 3b:8c:f2:b1:c1:5d:9d:a4:0b:4c:2b:d9:b2:18:f5:
+ b5:9f:4b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:52:D8:88:3A:C8:9F:78:66:ED:89:F3:7B:38:70:94:C9:02:02:36:D0
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 0b:7b:72:87:c0:60:a6:49:4c:88:58:e6:1d:88:f7:14:64:48:
+ a6:d8:58:0a:0e:4f:13:35:df:35:1d:d4:ed:06:31:c8:81:3e:
+ 6a:d5:dd:3b:1a:32:ee:90:3d:11:d2:2e:f4:8e:c3:63:2e:23:
+ 66:b0:67:be:6f:b6:c0:13:39:60:aa:a2:34:25:93:75:52:de:
+ a7:9d:ad:0e:87:89:52:71:6a:16:3c:19:1d:83:f8:9a:29:65:
+ be:f4:3f:9a:d9:f0:f3:5a:87:21:71:80:4d:cb:e0:38:9b:3f:
+ bb:fa:e0:30:4d:cf:86:d3:65:10:19:18:d1:97:02:b1:2b:72:
+ 42:68:ac:a0:bd:4e:5a:da:18:bf:6b:98:81:d0:fd:9a:be:5e:
+ 15:48:cd:11:15:b9:c0:29:5c:b4:e8:88:f7:3e:36:ae:b7:62:
+ fd:1e:62:de:70:78:10:1c:48:5b:da:bc:a4:38:ba:67:ed:55:
+ 3e:5e:57:df:d4:03:40:4c:81:a4:d2:4f:63:a7:09:42:09:14:
+ fc:00:a9:c2:80:73:4f:2e:c0:40:d9:11:7b:48:ea:7a:02:c0:
+ d3:eb:28:01:26:58:74:c1:c0:73:22:6d:93:95:fd:39:7d:bb:
+ 2a:e3:f6:82:e3:2c:97:5f:4e:1f:91:94:fa:fe:2c:a3:d8:76:
+ 1a:b8:4d:b2:38:4f:9b:fa:1d:48:60:79:26:e2:f3:fd:a9:d0:
+ 9a:e8:70:8f:49:7a:d6:e5:bd:0a:0e:db:2d:f3:8d:bf:eb:e3:
+ a4:7d:cb:c7:95:71:e8:da:a3:7c:c5:c2:f8:74:92:04:1b:86:
+ ac:a4:22:53:40:b6:ac:fe:4c:76:cf:fb:94:32:c0:35:9f:76:
+ 3f:6e:e5:90:6e:a0:a6:26:a2:b8:2c:be:d1:2b:85:fd:a7:68:
+ c8:ba:01:2b:b1:6c:74:1d:b8:73:95:e7:ee:b7:c7:25:f0:00:
+ 4c:00:b2:7e:b6:0b:8b:1c:f3:c0:50:9e:25:b9:e0:08:de:36:
+ 66:ff:37:a5:d1:bb:54:64:2c:c9:27:b5:4b:92:7e:65:ff:d3:
+ 2d:e1:b9:4e:bc:7f:a4:41:21:90:41:77:a6:39:1f:ea:9e:e3:
+ 9f:d0:66:6f:05:ec:aa:76:7e:bf:6b:16:a0:eb:b5:c7:fc:92:
+ 54:2f:2b:11:27:25:37:78:4c:51:6a:b0:f3:cc:58:5d:14:f1:
+ 6a:48:15:ff:c2:07:b6:b1:8d:0f:8e:5c:50:46:b3:3d:bf:01:
+ 98:4f:b2:59:54:47:3e:34:7b:78:6d:56:93:2e:73:ea:66:28:
+ 78:cd:1d:14:bf:a0:8f:2f:2e:b8:2e:8e:f2:14:8a:cc:e9:b5:
+ 7c:fb:6c:9d:0c:a5:e1:96
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UE
+BhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8w
+MzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDkyMjExMjIwMlowazELMAkGA1UEBhMC
+SVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1
+ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENB
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNv
+UTufClrJwkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX
+4ay8IMKx4INRimlNAJZaby/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9
+KK3giq0itFZljoZUj5NDKd45RnijMCO6zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/
+gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1fYVEiVRvjRuPjPdA1Yprb
+rxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2oxgkg4YQ
+51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2F
+be8lEfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxe
+KF+w6D9Fz8+vm2/7hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4F
+v6MGn8i1zeQf1xcGDXqVdFUNaBr8EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbn
+fpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5jF66CyCU3nuDuP/jVo23Eek7
+jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLYiDrIn3hm7Ynz
+ezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAL
+e3KHwGCmSUyIWOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70
+jsNjLiNmsGe+b7bAEzlgqqI0JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDz
+WochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKxK3JCaKygvU5a2hi/a5iB0P2avl4V
+SM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+Xlff1ANATIGk0k9j
+pwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC4yyX
+X04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+Ok
+fcvHlXHo2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7R
+K4X9p2jIugErsWx0Hbhzlefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btU
+ZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXemOR/qnuOf0GZvBeyqdn6/axag67XH/JJU
+LysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9vwGYT7JZVEc+NHt4bVaT
+LnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem
new file mode 100644
index 00000000000..477930e295d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem
@@ -0,0 +1,80 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
+ Validity
+ Not Before: Sep 1 00:00:00 2009 GMT
+ Not After : Dec 31 23:59:59 2037 GMT
+ Subject: C = US, ST = Arizona, L = Scottsdale, O = "Starfield Technologies, Inc.", CN = Starfield Services Root Certificate Authority - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d5:0c:3a:c4:2a:f9:4e:e2:f5:be:19:97:5f:8e:
+ 88:53:b1:1f:3f:cb:cf:9f:20:13:6d:29:3a:c8:0f:
+ 7d:3c:f7:6b:76:38:63:d9:36:60:a8:9b:5e:5c:00:
+ 80:b2:2f:59:7f:f6:87:f9:25:43:86:e7:69:1b:52:
+ 9a:90:e1:71:e3:d8:2d:0d:4e:6f:f6:c8:49:d9:b6:
+ f3:1a:56:ae:2b:b6:74:14:eb:cf:fb:26:e3:1a:ba:
+ 1d:96:2e:6a:3b:58:94:89:47:56:ff:25:a0:93:70:
+ 53:83:da:84:74:14:c3:67:9e:04:68:3a:df:8e:40:
+ 5a:1d:4a:4e:cf:43:91:3b:e7:56:d6:00:70:cb:52:
+ ee:7b:7d:ae:3a:e7:bc:31:f9:45:f6:c2:60:cf:13:
+ 59:02:2b:80:cc:34:47:df:b9:de:90:65:6d:02:cf:
+ 2c:91:a6:a6:e7:de:85:18:49:7c:66:4e:a3:3a:6d:
+ a9:b5:ee:34:2e:ba:0d:03:b8:33:df:47:eb:b1:6b:
+ 8d:25:d9:9b:ce:81:d1:45:46:32:96:70:87:de:02:
+ 0e:49:43:85:b6:6c:73:bb:64:ea:61:41:ac:c9:d4:
+ 54:df:87:2f:c7:22:b2:26:cc:9f:59:54:68:9f:fc:
+ be:2a:2f:c4:55:1c:75:40:60:17:85:02:55:39:8b:
+ 7f:05
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 9C:5F:00:DF:AA:01:D7:30:2B:38:88:A2:B8:6D:4A:9C:F2:11:91:83
+ Signature Algorithm: sha256WithRSAEncryption
+ 4b:36:a6:84:77:69:dd:3b:19:9f:67:23:08:6f:0e:61:c9:fd:
+ 84:dc:5f:d8:36:81:cd:d8:1b:41:2d:9f:60:dd:c7:1a:68:d9:
+ d1:6e:86:e1:88:23:cf:13:de:43:cf:e2:34:b3:04:9d:1f:29:
+ d5:bf:f8:5e:c8:d5:c1:bd:ee:92:6f:32:74:f2:91:82:2f:bd:
+ 82:42:7a:ad:2a:b7:20:7d:4d:bc:7a:55:12:c2:15:ea:bd:f7:
+ 6a:95:2e:6c:74:9f:cf:1c:b4:f2:c5:01:a3:85:d0:72:3e:ad:
+ 73:ab:0b:9b:75:0c:6d:45:b7:8e:94:ac:96:37:b5:a0:d0:8f:
+ 15:47:0e:e3:e8:83:dd:8f:fd:ef:41:01:77:cc:27:a9:62:85:
+ 33:f2:37:08:ef:71:cf:77:06:de:c8:19:1d:88:40:cf:7d:46:
+ 1d:ff:1e:c7:e1:ce:ff:23:db:c6:fa:8d:55:4e:a9:02:e7:47:
+ 11:46:3e:f4:fd:bd:7b:29:26:bb:a9:61:62:37:28:b6:2d:2a:
+ f6:10:86:64:c9:70:a7:d2:ad:b7:29:70:79:ea:3c:da:63:25:
+ 9f:fd:68:b7:30:ec:70:fb:75:8a:b7:6d:60:67:b2:1e:c8:b9:
+ e9:d8:a8:6f:02:8b:67:0d:4d:26:57:71:da:20:fc:c1:4a:50:
+ 8d:b1:28:ba
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMx
+EDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoT
+HFN0YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVs
+ZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNVBAYTAlVTMRAwDgYD
+VQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFy
+ZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2Vy
+dmljZXMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20p
+OsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm2
+8xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4PahHQUw2eeBGg6345AWh1K
+Ts9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLPLJGmpufe
+hRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk
+6mFBrMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+q
+AdcwKziIorhtSpzyEZGDMA0GCSqGSIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMI
+bw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPPE95Dz+I0swSdHynVv/heyNXB
+ve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTyxQGjhdByPq1z
+qwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn
+0q23KXB56jzaYyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCN
+sSi6
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem
new file mode 100644
index 00000000000..0d484d9efaf
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem
@@ -0,0 +1,116 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 3262 (0xcbe)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = TW, O = TAIWAN-CA, OU = Root CA, CN = TWCA Global Root CA
+ Validity
+ Not Before: Jun 27 06:28:33 2012 GMT
+ Not After : Dec 31 15:59:59 2030 GMT
+ Subject: C = TW, O = TAIWAN-CA, OU = Root CA, CN = TWCA Global Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b0:05:db:c8:eb:8c:c4:6e:8a:21:ef:8e:4d:9c:
+ 71:0a:1f:52:70:ed:6d:82:9c:97:c5:d7:4c:4e:45:
+ 49:cb:40:42:b5:12:34:6c:19:c2:74:a4:31:5f:85:
+ 02:97:ec:43:33:0a:53:d2:9c:8c:8e:b7:b8:79:db:
+ 2b:d5:6a:f2:8e:66:c4:ee:2b:01:07:92:d4:b3:d0:
+ 02:df:50:f6:55:af:66:0e:cb:e0:47:60:2f:2b:32:
+ 39:35:52:3a:28:83:f8:7b:16:c6:18:b8:62:d6:47:
+ 25:91:ce:f0:19:12:4d:ad:63:f5:d3:3f:75:5f:29:
+ f0:a1:30:1c:2a:a0:98:a6:15:bd:ee:fd:19:36:f0:
+ e2:91:43:8f:fa:ca:d6:10:27:49:4c:ef:dd:c1:f1:
+ 85:70:9b:ca:ea:a8:5a:43:fc:6d:86:6f:73:e9:37:
+ 45:a9:f0:36:c7:cc:88:75:1e:bb:6c:06:ff:9b:6b:
+ 3e:17:ec:61:aa:71:7c:c6:1d:a2:f7:49:e9:15:b5:
+ 3c:d6:a1:61:f5:11:f7:05:6f:1d:fd:11:be:d0:30:
+ 07:c2:29:b0:09:4e:26:dc:e3:a2:a8:91:6a:1f:c2:
+ 91:45:88:5c:e5:98:b8:71:a5:15:19:c9:7c:75:11:
+ cc:70:74:4f:2d:9b:1d:91:44:fd:56:28:a0:fe:bb:
+ 86:6a:c8:fa:5c:0b:58:dc:c6:4b:76:c8:ab:22:d9:
+ 73:0f:a5:f4:5a:02:89:3f:4f:9e:22:82:ee:a2:74:
+ 53:2a:3d:53:27:69:1d:6c:8e:32:2c:64:00:26:63:
+ 61:36:4e:a3:46:b7:3f:7d:b3:2d:ac:6d:90:a2:95:
+ a2:ce:cf:da:82:e7:07:34:19:96:e9:b8:21:aa:29:
+ 7e:a6:38:be:8e:29:4a:21:66:79:1f:b3:c3:b5:09:
+ 67:de:d6:d4:07:46:f3:2a:da:e6:22:37:60:cb:81:
+ b6:0f:a0:0f:e9:c8:95:7f:bf:55:91:05:7a:cf:3d:
+ 15:c0:6f:de:09:94:01:83:d7:34:1b:cc:40:a5:f0:
+ b8:9b:67:d5:98:91:3b:a7:84:78:95:26:a4:5a:08:
+ f8:2b:74:b4:00:04:3c:df:b8:14:8e:e8:df:a9:8d:
+ 6c:67:92:33:1d:c0:b7:d2:ec:92:c8:be:09:bf:2c:
+ 29:05:6f:02:6b:9e:ef:bc:bf:2a:bc:5b:c0:50:8f:
+ 41:70:71:87:b2:4d:b7:04:a9:84:a3:32:af:ae:ee:
+ 6b:17:8b:b2:b1:fe:6c:e1:90:8c:88:a8:97:48:ce:
+ c8:4d:cb:f3:06:cf:5f:6a:0a:42:b1:1e:1e:77:2f:
+ 8e:a0:e6:92:0e:06:fc:05:22:d2:26:e1:31:51:7d:
+ 32:dc:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha256WithRSAEncryption
+ 5f:34:81:76:ef:96:1d:d5:e5:b5:d9:02:63:84:16:c1:ae:a0:
+ 70:51:a7:f7:4c:47:35:c8:0b:d7:28:3d:89:71:d9:aa:33:41:
+ ea:14:1b:6c:21:00:c0:6c:42:19:7e:9f:69:5b:20:42:df:a2:
+ d2:da:c4:7c:97:4b:8d:b0:e8:ac:c8:ee:a5:69:04:99:0a:92:
+ a6:ab:27:2e:1a:4d:81:bf:84:d4:70:1e:ad:47:fe:fd:4a:9d:
+ 33:e0:f2:b9:c4:45:08:21:0a:da:69:69:73:72:0d:be:34:fe:
+ 94:8b:ad:c3:1e:35:d7:a2:83:ef:e5:38:c7:a5:85:1f:ab:cf:
+ 34:ec:3f:28:fe:0c:f1:57:86:4e:c9:55:f7:1c:d4:d8:a5:7d:
+ 06:7a:6f:d5:df:10:df:81:4e:21:65:b1:b6:e1:17:79:95:45:
+ 06:ce:5f:cc:dc:46:89:63:68:44:8d:93:f4:64:70:a0:3d:9d:
+ 28:05:c3:39:70:b8:62:7b:20:fd:e4:db:e9:08:a1:b8:9e:3d:
+ 09:c7:4f:fb:2c:f8:93:76:41:de:52:e0:e1:57:d2:9d:03:bc:
+ 77:9e:fe:9e:29:5e:f7:c1:51:60:1f:de:da:0b:b2:2d:75:b7:
+ 43:48:93:e7:f6:79:c6:84:5d:80:59:60:94:fc:78:98:8f:3c:
+ 93:51:ed:40:90:07:df:64:63:24:cb:4e:71:05:a1:d7:94:1a:
+ 88:32:f1:22:74:22:ae:a5:a6:d8:12:69:4c:60:a3:02:ee:2b:
+ ec:d4:63:92:0b:5e:be:2f:76:6b:a3:b6:26:bc:8f:03:d8:0a:
+ f2:4c:64:46:bd:39:62:e5:96:eb:34:63:11:28:cc:95:f1:ad:
+ ef:ef:dc:80:58:48:e9:4b:b8:ea:65:ac:e9:fc:80:b5:b5:c8:
+ 45:f9:ac:c1:9f:d9:b9:ea:62:88:8e:c4:f1:4b:83:12:ad:e6:
+ 8b:84:d6:9e:c2:eb:83:18:9f:6a:bb:1b:24:60:33:70:cc:ec:
+ f7:32:f3:5c:d9:79:7d:ef:9e:a4:fe:c9:23:c3:24:ee:15:92:
+ b1:3d:91:4f:26:86:bd:66:73:24:13:ea:a4:ae:63:c1:ad:7d:
+ 84:03:3c:10:78:86:1b:79:e3:c4:f3:f2:04:95:20:ae:23:82:
+ c4:b3:3a:00:62:bf:e6:36:24:e1:57:ba:c7:1e:90:75:d5:5f:
+ 3f:95:61:2b:c1:3b:cd:e5:b3:68:61:d0:46:26:a9:21:52:69:
+ 2d:eb:2e:c7:eb:77:ce:a6:3a:b5:03:33:4f:76:d1:e7:5c:54:
+ 01:5d:cb:78:f4:c9:0c:bf:cf:12:8e:17:2d:23:68:94:e7:ab:
+ fe:a9:b2:2b:06:d0:04:cd
+-----BEGIN CERTIFICATE-----
+MIIFQTCCAymgAwIBAgICDL4wDQYJKoZIhvcNAQELBQAwUTELMAkGA1UEBhMCVFcx
+EjAQBgNVBAoTCVRBSVdBTi1DQTEQMA4GA1UECxMHUm9vdCBDQTEcMBoGA1UEAxMT
+VFdDQSBHbG9iYWwgUm9vdCBDQTAeFw0xMjA2MjcwNjI4MzNaFw0zMDEyMzExNTU5
+NTlaMFExCzAJBgNVBAYTAlRXMRIwEAYDVQQKEwlUQUlXQU4tQ0ExEDAOBgNVBAsT
+B1Jvb3QgQ0ExHDAaBgNVBAMTE1RXQ0EgR2xvYmFsIFJvb3QgQ0EwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCwBdvI64zEbooh745NnHEKH1Jw7W2CnJfF
+10xORUnLQEK1EjRsGcJ0pDFfhQKX7EMzClPSnIyOt7h52yvVavKOZsTuKwEHktSz
+0ALfUPZVr2YOy+BHYC8rMjk1Ujoog/h7FsYYuGLWRyWRzvAZEk2tY/XTP3VfKfCh
+MBwqoJimFb3u/Rk28OKRQ4/6ytYQJ0lM793B8YVwm8rqqFpD/G2Gb3PpN0Wp8DbH
+zIh1HrtsBv+baz4X7GGqcXzGHaL3SekVtTzWoWH1EfcFbx39Eb7QMAfCKbAJTibc
+46KokWofwpFFiFzlmLhxpRUZyXx1EcxwdE8tmx2RRP1WKKD+u4ZqyPpcC1jcxkt2
+yKsi2XMPpfRaAok/T54igu6idFMqPVMnaR1sjjIsZAAmY2E2TqNGtz99sy2sbZCi
+laLOz9qC5wc0GZbpuCGqKX6mOL6OKUohZnkfs8O1CWfe1tQHRvMq2uYiN2DLgbYP
+oA/pyJV/v1WRBXrPPRXAb94JlAGD1zQbzECl8LibZ9WYkTunhHiVJqRaCPgrdLQA
+BDzfuBSO6N+pjWxnkjMdwLfS7JLIvgm/LCkFbwJrnu+8vyq8W8BQj0FwcYeyTbcE
+qYSjMq+u7msXi7Kx/mzhkIyIqJdIzshNy/MGz19qCkKxHh53L46g5pIOBvwFItIm
+4TFRfTLcDwIDAQABoyMwITAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zANBgkqhkiG9w0BAQsFAAOCAgEAXzSBdu+WHdXltdkCY4QWwa6gcFGn90xHNcgL
+1yg9iXHZqjNB6hQbbCEAwGxCGX6faVsgQt+i0trEfJdLjbDorMjupWkEmQqSpqsn
+LhpNgb+E1HAerUf+/UqdM+DyucRFCCEK2mlpc3INvjT+lIutwx4116KD7+U4x6WF
+H6vPNOw/KP4M8VeGTslV9xzU2KV9Bnpv1d8Q34FOIWWxtuEXeZVFBs5fzNxGiWNo
+RI2T9GRwoD2dKAXDOXC4Ynsg/eTb6QihuJ49CcdP+yz4k3ZB3lLg4VfSnQO8d57+
+nile98FRYB/e2guyLXW3Q0iT5/Z5xoRdgFlglPx4mI88k1HtQJAH32RjJMtOcQWh
+15QaiDLxInQirqWm2BJpTGCjAu4r7NRjkgtevi92a6O2JryPA9gK8kxkRr05YuWW
+6zRjESjMlfGt7+/cgFhI6Uu46mWs6fyAtbXIRfmswZ/ZuepiiI7E8UuDEq3mi4TW
+nsLrgxifarsbJGAzcMzs9zLzXNl5fe+epP7JI8Mk7hWSsT2RTyaGvWZzJBPqpK5j
+wa19hAM8EHiGG3njxPPyBJUgriOCxLM6AGK/5jYk4Ve6xx6QddVfP5VhK8E7zeWz
+aGHQRiapIVJpLesux+t3zqY6tQMzT3bR51xUAV3LePTJDL/PEo4XLSNolOer/qmy
+KwbQBM0=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem
new file mode 100644
index 00000000000..43021ef5202
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem
@@ -0,0 +1,125 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 08:16:5f:8a:4c:a5:ec:00:c9:93:40:df:c4:c6:ae:23:b8:1c:5a:a4
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = HK, ST = Hong Kong, L = Hong Kong, O = Hongkong Post, CN = Hongkong Post Root CA 3
+ Validity
+ Not Before: Jun 3 02:29:46 2017 GMT
+ Not After : Jun 3 02:29:46 2042 GMT
+ Subject: C = HK, ST = Hong Kong, L = Hong Kong, O = Hongkong Post, CN = Hongkong Post Root CA 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b3:88:d7:ea:ce:0f:20:4e:be:e6:d6:03:6d:ee:
+ 59:fc:c2:57:df:29:68:a1:83:0e:3e:68:c7:68:58:
+ 9c:1c:60:4b:89:43:0c:b9:d4:15:b2:ee:c1:4e:75:
+ e9:b5:a7:ef:e5:e9:35:99:e4:cc:1c:e7:4b:5f:8d:
+ 33:30:20:33:53:d9:a6:bb:d5:3e:13:8e:e9:1f:87:
+ 49:ad:50:2d:50:ca:18:be:01:58:a2:13:70:96:bb:
+ 89:88:56:80:5c:f8:bd:2c:3c:e1:4c:57:88:bb:d3:
+ b9:95:ef:cb:c7:f6:da:31:74:28:a6:e6:54:89:f5:
+ 41:31:ca:e5:26:1a:cd:82:e0:70:da:3b:29:bb:d5:
+ 03:f5:99:ba:55:f5:64:d1:60:0e:b3:89:49:b8:8a:
+ 2f:05:d2:84:45:28:7c:8f:68:50:12:78:fc:0b:b5:
+ 53:cb:c2:98:1c:84:a3:9e:b0:be:23:a4:da:dc:c8:
+ 2b:1e:da:6e:45:1e:89:98:da:f9:00:2e:06:e9:0c:
+ 3b:70:d5:50:25:88:99:cb:cd:73:60:f7:d5:ff:35:
+ 67:c5:a1:bc:5e:ab:cd:4a:b8:45:eb:c8:68:1e:0d:
+ 0d:14:46:12:e3:d2:64:62:8a:42:98:bc:b4:c6:08:
+ 08:f8:fd:a8:4c:64:9c:76:01:bd:2f:a9:6c:33:0f:
+ d8:3f:28:b8:3c:69:01:42:86:7e:69:c1:c9:06:ca:
+ e5:7a:46:65:e9:c2:d6:50:41:2e:3f:b7:e4:ed:6c:
+ d7:bf:26:01:11:a2:16:29:4a:6b:34:06:90:ec:13:
+ d2:b6:fb:6a:76:d2:3c:ed:f0:d6:2d:dd:e1:15:ec:
+ a3:9b:2f:2c:c9:3e:2b:e4:69:3b:ff:72:25:b1:36:
+ 86:5b:c7:7f:6b:8b:55:1b:4a:c5:20:61:3d:ae:cb:
+ 50:e1:08:3a:be:b0:8f:63:41:53:30:08:59:3c:98:
+ 1d:77:ba:63:91:7a:ca:10:50:60:bf:f0:d7:bc:95:
+ 87:8f:97:c5:fe:97:6a:01:94:a3:7c:5b:85:1d:2a:
+ 39:3a:d0:54:a1:d1:39:71:9d:fd:21:f9:b5:7b:f0:
+ e2:e0:02:8f:6e:96:24:25:2c:a0:1e:2c:a8:c4:89:
+ a7:ef:ed:99:06:2f:b6:0a:4c:4f:db:a2:cc:37:1a:
+ af:47:85:2d:8a:5f:c4:34:34:4c:00:fd:18:93:67:
+ 13:d1:37:e6:48:b4:8b:06:c5:57:7b:19:86:0a:79:
+ cb:00:c9:52:af:42:ff:37:8f:e1:a3:1e:7a:3d:50:
+ ab:63:06:e7:15:b5:3f:b6:45:37:94:37:b1:7e:f2:
+ 48:c3:7f:c5:75:fe:97:8d:45:8f:1a:a7:1a:72:28:
+ 1a:40:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Authority Key Identifier:
+ keyid:17:9D:CD:1E:8B:D6:39:2B:70:D3:5C:D4:A0:B8:1F:B0:00:FC:C5:61
+
+ X509v3 Subject Key Identifier:
+ 17:9D:CD:1E:8B:D6:39:2B:70:D3:5C:D4:A0:B8:1F:B0:00:FC:C5:61
+ Signature Algorithm: sha256WithRSAEncryption
+ 56:d5:7b:6e:e6:22:01:d2:42:9b:18:d5:0e:d7:66:23:5c:e3:
+ fe:a0:c7:92:d2:e9:94:ad:4b:a2:c6:ec:12:7c:74:d5:48:d2:
+ 59:14:99:c0:eb:b9:d1:eb:f4:48:30:5b:ad:a7:57:73:99:a9:
+ d3:e5:b7:d1:2e:59:24:58:dc:68:2e:2e:62:d8:6a:e4:70:0b:
+ 2d:20:50:20:a4:32:95:d1:00:98:bb:d3:fd:f7:32:f2:49:ae:
+ c6:7a:e0:47:be:6e:ce:cb:a3:72:3a:2d:69:5d:cb:c8:e8:45:
+ 39:d4:fa:42:c1:11:4c:77:5d:92:fb:6a:ff:58:44:e5:eb:81:
+ 9e:af:a0:99:ad:be:a9:01:66:cb:38:1d:3c:df:43:1f:f4:4d:
+ 6e:b4:ba:17:46:fc:7d:fd:87:81:79:6a:0d:33:0f:fa:2f:f8:
+ 14:b9:80:b3:5d:4d:aa:97:e1:f9:e4:18:c5:f8:d5:38:8c:26:
+ 3c:fd:f2:28:e2:ee:5a:49:88:2c:df:79:3d:8e:9e:90:3c:bd:
+ 41:4a:3a:dd:5b:f6:9a:b4:ce:3f:25:30:7f:32:7d:a2:03:94:
+ d0:dc:7a:a1:52:de:6e:93:8d:18:26:fd:55:ac:bd:8f:9b:d2:
+ cf:af:e7:86:2c:cb:1f:09:6f:a3:6f:a9:84:d4:73:bf:4d:a1:
+ 74:1b:4e:23:60:f2:cc:0e:aa:7f:a4:9c:4c:25:a8:b2:66:3b:
+ 38:ff:d9:94:30:f6:72:84:be:68:55:10:0f:c6:73:2c:16:69:
+ 93:07:fe:b1:45:ed:bb:a2:55:6a:b0:da:b5:4a:02:25:27:85:
+ d7:b7:b7:86:44:16:89:6c:80:2b:3e:97:a9:9c:d5:7e:55:4c:
+ c6:de:45:10:1c:ea:e9:3b:9f:03:53:ee:ee:7a:01:02:16:78:
+ d4:e8:c2:be:46:76:88:13:3f:22:bb:48:12:1d:52:00:b4:02:
+ 7e:21:1a:1e:9c:25:f4:f3:3d:5e:1e:d2:1c:f9:b3:2d:b6:f7:
+ 37:5c:c6:cb:21:4e:b0:f7:99:47:18:85:c1:2b:ba:55:ae:06:
+ ea:d0:07:b2:dc:ab:d0:82:96:75:ce:d2:50:fe:99:e7:cf:2f:
+ 9f:e7:76:d1:61:2a:fb:21:bb:31:d0:aa:9f:47:a4:b2:22:ca:
+ 16:3a:50:57:c4:5b:43:67:c5:65:62:03:49:01:eb:43:d9:d8:
+ f8:9e:ad:cf:b1:63:0e:45:f4:a0:5a:2c:9b:2d:c5:a6:c0:ad:
+ a8:47:f4:27:4c:38:0d:2e:1b:49:3b:52:f4:e8:88:83:2b:54:
+ 28:d4:f2:35:52:b4:32:83:62:69:64:0c:91:9c:9f:97:ea:74:
+ 16:fd:1f:11:06:9a:9b:f4
+-----BEGIN CERTIFICATE-----
+MIIFzzCCA7egAwIBAgIUCBZfikyl7ADJk0DfxMauI7gcWqQwDQYJKoZIhvcNAQEL
+BQAwbzELMAkGA1UEBhMCSEsxEjAQBgNVBAgTCUhvbmcgS29uZzESMBAGA1UEBxMJ
+SG9uZyBLb25nMRYwFAYDVQQKEw1Ib25na29uZyBQb3N0MSAwHgYDVQQDExdIb25n
+a29uZyBQb3N0IFJvb3QgQ0EgMzAeFw0xNzA2MDMwMjI5NDZaFw00MjA2MDMwMjI5
+NDZaMG8xCzAJBgNVBAYTAkhLMRIwEAYDVQQIEwlIb25nIEtvbmcxEjAQBgNVBAcT
+CUhvbmcgS29uZzEWMBQGA1UEChMNSG9uZ2tvbmcgUG9zdDEgMB4GA1UEAxMXSG9u
+Z2tvbmcgUG9zdCBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCziNfqzg8gTr7m1gNt7ln8wlffKWihgw4+aMdoWJwcYEuJQwy51BWy7sFO
+dem1p+/l6TWZ5Mwc50tfjTMwIDNT2aa71T4Tjukfh0mtUC1Qyhi+AViiE3CWu4mI
+VoBc+L0sPOFMV4i707mV78vH9toxdCim5lSJ9UExyuUmGs2C4HDaOym71QP1mbpV
+9WTRYA6ziUm4ii8F0oRFKHyPaFASePwLtVPLwpgchKOesL4jpNrcyCse2m5FHomY
+2vkALgbpDDtw1VAliJnLzXNg99X/NWfFobxeq81KuEXryGgeDQ0URhLj0mRiikKY
+vLTGCAj4/ahMZJx2Ab0vqWwzD9g/KLg8aQFChn5pwckGyuV6RmXpwtZQQS4/t+Tt
+bNe/JgERohYpSms0BpDsE9K2+2p20jzt8NYt3eEV7KObLyzJPivkaTv/ciWxNoZb
+x39ri1UbSsUgYT2uy1DhCDq+sI9jQVMwCFk8mB13umOResoQUGC/8Ne8lYePl8X+
+l2oBlKN8W4UdKjk60FSh0Tlxnf0h+bV78OLgAo9uliQlLKAeLKjEiafv7ZkGL7YK
+TE/bosw3Gq9HhS2KX8Q0NEwA/RiTZxPRN+ZItIsGxVd7GYYKecsAyVKvQv83j+Gj
+Hno9UKtjBucVtT+2RTeUN7F+8kjDf8V1/peNRY8apxpyKBpADwIDAQABo2MwYTAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQXnc0e
+i9Y5K3DTXNSguB+wAPzFYTAdBgNVHQ4EFgQUF53NHovWOStw01zUoLgfsAD8xWEw
+DQYJKoZIhvcNAQELBQADggIBAFbVe27mIgHSQpsY1Q7XZiNc4/6gx5LS6ZStS6LG
+7BJ8dNVI0lkUmcDrudHr9EgwW62nV3OZqdPlt9EuWSRY3GguLmLYauRwCy0gUCCk
+MpXRAJi70/33MvJJrsZ64Ee+bs7Lo3I6LWldy8joRTnU+kLBEUx3XZL7av9YROXr
+gZ6voJmtvqkBZss4HTzfQx/0TW60uhdG/H39h4F5ag0zD/ov+BS5gLNdTaqX4fnk
+GMX41TiMJjz98iji7lpJiCzfeT2OnpA8vUFKOt1b9pq0zj8lMH8yfaIDlNDceqFS
+3m6TjRgm/VWsvY+b0s+v54Ysyx8Jb6NvqYTUc79NoXQbTiNg8swOqn+knEwlqLJm
+Ozj/2ZQw9nKEvmhVEA/GcywWaZMH/rFF7buiVWqw2rVKAiUnhde3t4ZEFolsgCs+
+l6mc1X5VTMbeRRAc6uk7nwNT7u56AQIWeNTowr5GdogTPyK7SBIdUgC0An4hGh6c
+JfTzPV4e0hz5sy229zdcxsshTrD3mUcYhcErulWuBurQB7Lcq9CClnXO0lD+mefP
+L5/ndtFhKvshuzHQqp9HpLIiyhY6UFfEW0NnxWViA0kB60PZ2Pierc+xYw5F9KBa
+LJstxabArahH9CdMOA0uG0k7UvToiIMrVCjU8jVStDKDYmlkDJGcn5fqdBb9HxEG
+mpv0
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem
new file mode 100644
index 00000000000..b50983dcdfc
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem
@@ -0,0 +1,85 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 84:82:2c:5f:1c:62:d0:40
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor ECA-1
+ Validity
+ Not Before: Feb 4 12:32:33 2016 GMT
+ Not After : Dec 31 17:28:07 2029 GMT
+ Subject: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor ECA-1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:cf:8f:e0:11:b5:9f:a8:76:76:db:df:0f:54:ef:
+ 73:63:29:82:ad:47:c6:a3:6b:ed:fe:5f:33:f8:43:
+ 51:e9:1a:33:91:31:17:a0:74:c4:d4:a7:01:e6:b2:
+ 92:3e:6a:9d:ed:0e:f9:74:98:40:d3:3f:03:80:06:
+ 82:40:e8:b1:e2:a7:51:a7:1d:83:26:6b:ab:de:fa:
+ 17:91:2b:d8:c6:ac:1e:b1:9e:19:01:d5:97:a6:ea:
+ 0d:b7:c4:55:1f:27:7c:d2:08:d5:76:1f:29:15:87:
+ 40:39:dd:38:45:11:75:d0:9a:a7:34:e0:bf:cd:c8:
+ 52:1d:b9:47:7e:0d:b8:bb:c6:0c:f6:73:57:16:5a:
+ 7e:43:91:1f:55:3a:c6:6d:44:04:aa:9c:a9:9c:a7:
+ 4c:89:17:83:ae:a3:04:5e:52:80:8b:1e:12:25:11:
+ 19:d7:0c:7d:7d:31:44:41:ea:db:af:b0:1c:ef:81:
+ d0:2c:c5:9a:21:9b:3d:ed:42:3b:50:26:f2:ec:ce:
+ 71:61:06:62:21:54:4e:7f:c1:9d:3e:7f:20:8c:80:
+ cb:2a:d8:97:62:c8:83:33:91:7d:b0:a2:5a:0f:57:
+ e8:3b:cc:f2:25:b2:d4:7c:2f:ec:4d:c6:a1:3a:15:
+ 7a:e7:b6:5d:35:f5:f6:48:4a:36:45:66:d4:ba:98:
+ 58:c1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 44:9E:48:F5:CC:6D:48:D4:A0:4B:7F:FE:59:24:2F:83:97:99:9A:86
+ X509v3 Authority Key Identifier:
+ keyid:44:9E:48:F5:CC:6D:48:D4:A0:4B:7F:FE:59:24:2F:83:97:99:9A:86
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 05:3e:35:5c:15:70:9b:c9:c7:73:61:6f:72:2b:d4:c2:8f:f2:
+ 43:5d:02:ce:c4:94:b9:94:11:83:67:5d:e2:67:6c:75:76:bf:
+ bb:0c:aa:36:c6:ad:47:93:63:dc:1e:7e:d6:de:2e:fe:e9:19:
+ 32:38:03:7f:14:f6:00:73:2c:59:b1:21:06:e1:fb:ac:18:95:
+ 0c:a3:ff:99:96:f7:2b:27:9b:d5:24:cc:1d:dd:c1:3a:e0:98:
+ 44:b0:c4:e4:3e:77:b1:73:a9:64:2c:f6:1c:01:7c:3f:5d:45:
+ 85:c0:85:e7:25:8f:95:dc:17:f3:3c:9f:1a:6e:b0:ca:e3:1d:
+ 2a:e9:4c:63:fa:24:61:62:d6:da:7e:b6:1c:6c:f5:02:1d:d4:
+ 2a:dd:55:90:eb:2a:11:47:3c:2e:5e:74:b2:82:22:a5:7d:53:
+ 1f:45:ec:27:91:7d:e7:22:16:e8:c0:68:36:d8:c6:f1:4f:80:
+ 44:32:f9:e1:d1:d1:1d:aa:de:a8:ab:9c:04:af:ad:20:0e:64:
+ 98:4d:a5:6b:c0:48:58:96:69:4d:dc:07:8c:51:93:a2:df:9f:
+ 0f:3d:8b:60:b4:82:8d:aa:08:4e:62:45:e0:f9:0b:d2:e0:e0:
+ 3c:5b:de:5c:71:27:25:c2:e6:03:81:8b:10:53:e3:c7:55:a2:
+ b4:9f:d7:e6
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIJAISCLF8cYtBAMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxFzAVBgNVBAMMDlRydXN0Q29y
+IEVDQS0xMB4XDTE2MDIwNDEyMzIzM1oXDTI5MTIzMTE3MjgwN1owgZwxCzAJBgNV
+BAYTAlBBMQ8wDQYDVQQIDAZQYW5hbWExFDASBgNVBAcMC1BhbmFtYSBDaXR5MSQw
+IgYDVQQKDBtUcnVzdENvciBTeXN0ZW1zIFMuIGRlIFIuTC4xJzAlBgNVBAsMHlRy
+dXN0Q29yIENlcnRpZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAwwOVHJ1c3RDb3Ig
+RUNBLTEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDPj+ARtZ+odnbb
+3w9U73NjKYKtR8aja+3+XzP4Q1HpGjORMRegdMTUpwHmspI+ap3tDvl0mEDTPwOA
+BoJA6LHip1GnHYMma6ve+heRK9jGrB6xnhkB1Zem6g23xFUfJ3zSCNV2HykVh0A5
+3ThFEXXQmqc04L/NyFIduUd+Dbi7xgz2c1cWWn5DkR9VOsZtRASqnKmcp0yJF4Ou
+owReUoCLHhIlERnXDH19MURB6tuvsBzvgdAsxZohmz3tQjtQJvLsznFhBmIhVE5/
+wZ0+fyCMgMsq2JdiyIMzkX2woloPV+g7zPIlstR8L+xNxqE6FXrntl019fZISjZF
+ZtS6mFjBAgMBAAGjYzBhMB0GA1UdDgQWBBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAf
+BgNVHSMEGDAWgBREnkj1zG1I1KBLf/5ZJC+Dl5mahjAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAQEABT41XBVwm8nHc2Fv
+civUwo/yQ10CzsSUuZQRg2dd4mdsdXa/uwyqNsatR5Nj3B5+1t4u/ukZMjgDfxT2
+AHMsWbEhBuH7rBiVDKP/mZb3Kyeb1STMHd3BOuCYRLDE5D53sXOpZCz2HAF8P11F
+hcCF5yWPldwX8zyfGm6wyuMdKulMY/okYWLW2n62HGz1Ah3UKt1VkOsqEUc8Ll50
+soIipX1TH0XsJ5F95yIW6MBoNtjG8U+ARDL54dHRHareqKucBK+tIA5kmE2la8BI
+WJZpTdwHjFGTot+fDz2LYLSCjaoITmJF4PkL0uDgPFveXHEnJcLmA4GLEFPjx1Wi
+tJ/X5g==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem
new file mode 100644
index 00000000000..3151ac5cf17
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 279744 (0x444c0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA
+ Validity
+ Not Before: Oct 22 12:07:37 2008 GMT
+ Not After : Dec 31 12:07:37 2029 GMT
+ Subject: C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:e3:fb:7d:a3:72:ba:c2:f0:c9:14:87:f5:6b:01:
+ 4e:e1:6e:40:07:ba:6d:27:5d:7f:f7:5b:2d:b3:5a:
+ c7:51:5f:ab:a4:32:a6:61:87:b6:6e:0f:86:d2:30:
+ 02:97:f8:d7:69:57:a1:18:39:5d:6a:64:79:c6:01:
+ 59:ac:3c:31:4a:38:7c:d2:04:d2:4b:28:e8:20:5f:
+ 3b:07:a2:cc:4d:73:db:f3:ae:4f:c7:56:d5:5a:a7:
+ 96:89:fa:f3:ab:68:d4:23:86:59:27:cf:09:27:bc:
+ ac:6e:72:83:1c:30:72:df:e0:a2:e9:d2:e1:74:75:
+ 19:bd:2a:9e:7b:15:54:04:1b:d7:43:39:ad:55:28:
+ c5:e2:1a:bb:f4:c0:e4:ae:38:49:33:cc:76:85:9f:
+ 39:45:d2:a4:9e:f2:12:8c:51:f8:7c:e4:2d:7f:f5:
+ ac:5f:eb:16:9f:b1:2d:d1:ba:cc:91:42:77:4c:25:
+ c9:90:38:6f:db:f0:cc:fb:8e:1e:97:59:3e:d5:60:
+ 4e:e6:05:28:ed:49:79:13:4b:ba:48:db:2f:f9:72:
+ d3:39:ca:fe:1f:d8:34:72:f5:b4:40:cf:31:01:c3:
+ ec:de:11:2d:17:5d:1f:b8:50:d1:5e:19:a7:69:de:
+ 07:33:28:ca:50:95:f9:a7:54:cb:54:86:50:45:a9:
+ f9:49
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 08:76:CD:CB:07:FF:24:F6:C5:CD:ED:BB:90:BC:E2:84:37:46:75:F7
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ a6:a8:ad:22:ce:01:3d:a6:a3:ff:62:d0:48:9d:8b:5e:72:b0:
+ 78:44:e3:dc:1c:af:09:fd:23:48:fa:bd:2a:c4:b9:55:04:b5:
+ 10:a3:8d:27:de:0b:82:63:d0:ee:de:0c:37:79:41:5b:22:b2:
+ b0:9a:41:5c:a6:70:e0:d4:d0:77:cb:23:d3:00:e0:6c:56:2f:
+ e1:69:0d:0d:d9:aa:bf:21:81:50:d9:06:a5:a8:ff:95:37:d0:
+ aa:fe:e2:b3:f5:99:2d:45:84:8a:e5:42:09:d7:74:02:2f:f7:
+ 89:d8:99:e9:bc:27:d4:47:8d:ba:0d:46:1c:77:cf:14:a4:1c:
+ b9:a4:31:c4:9c:28:74:03:34:ff:33:19:26:a5:e9:0d:74:b7:
+ 3e:97:c6:76:e8:27:96:a3:66:dd:e1:ae:f2:41:5b:ca:98:56:
+ 83:73:70:e4:86:1a:d2:31:41:ba:2f:be:2d:13:5a:76:6f:4e:
+ e8:4e:81:0e:3f:5b:03:22:a0:12:be:66:58:11:4a:cb:03:c4:
+ b4:2a:2a:2d:96:17:e0:39:54:bc:48:d3:76:27:9d:9a:2d:06:
+ a6:c9:ec:39:d2:ab:db:9f:9a:0b:27:02:35:29:b1:40:95:e7:
+ f9:e8:9c:55:88:19:46:d6:b7:34:f5:7e:ce:39:9a:d9:38:f1:
+ 51:f7:4f:2c
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBM
+MSIwIAYDVQQKExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5D
+ZXJ0dW0gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBU
+cnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIyMTIwNzM3WhcNMjkxMjMxMTIwNzM3
+WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBUZWNobm9sb2dpZXMg
+Uy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MSIw
+IAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rH
+UV+rpDKmYYe2bg+G0jACl/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LM
+TXPb865Px1bVWqeWifrzq2jUI4ZZJ88JJ7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVU
+BBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4fOQtf/WsX+sWn7Et0brM
+kUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0cvW0QM8x
+AcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNV
+HQ8BAf8EBAMCAQYwDQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15y
+sHhE49wcrwn9I0j6vSrEuVUEtRCjjSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfL
+I9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1mS1FhIrlQgnXdAIv94nYmem8
+J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5ajZt3hrvJBW8qY
+VoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem
new file mode 100644
index 00000000000..d320b0972dd
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 407555286 (0x184accd6)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = CN, O = China Financial Certification Authority, CN = CFCA EV ROOT
+ Validity
+ Not Before: Aug 8 03:07:01 2012 GMT
+ Not After : Dec 31 03:07:01 2029 GMT
+ Subject: C = CN, O = China Financial Certification Authority, CN = CFCA EV ROOT
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:d7:5d:6b:cd:10:3f:1f:05:59:d5:05:4d:37:b1:
+ 0e:ec:98:2b:8e:15:1d:fa:93:4b:17:82:21:71:10:
+ 52:d7:51:64:70:16:c2:55:69:4d:8e:15:6d:9f:bf:
+ 0c:1b:c2:e0:a3:67:d6:0c:ac:cf:22:ae:af:77:54:
+ 2a:4b:4c:8a:53:52:7a:c3:ee:2e:de:b3:71:25:c1:
+ e9:5d:3d:ee:a1:2f:a3:f7:2a:3c:c9:23:1d:6a:ab:
+ 1d:a1:a7:f1:f3:ec:a0:d5:44:cf:15:cf:72:2f:1d:
+ 63:97:e8:99:f9:fd:93:a4:54:80:4c:52:d4:52:ab:
+ 2e:49:df:90:cd:b8:5f:be:3f:de:a1:ca:4d:20:d4:
+ 25:e8:84:29:53:b7:b1:88:1f:ff:fa:da:90:9f:0a:
+ a9:2d:41:3f:b1:f1:18:29:ee:16:59:2c:34:49:1a:
+ a8:06:d7:a8:88:d2:03:72:7a:32:e2:ea:68:4d:6e:
+ 2c:96:65:7b:ca:59:fa:f2:e2:dd:ee:30:2c:fb:cc:
+ 46:ac:c4:63:eb:6f:7f:36:2b:34:73:12:94:7f:df:
+ cc:26:9e:f1:72:5d:50:65:59:8f:69:b3:87:5e:32:
+ 6f:c3:18:8a:b5:95:8f:b0:7a:37:de:5a:45:3b:c7:
+ 36:e1:ef:67:d1:39:d3:97:5b:73:62:19:48:2d:87:
+ 1c:06:fb:74:98:20:49:73:f0:05:d2:1b:b1:a0:a3:
+ b7:1b:70:d3:88:69:b9:5a:d6:38:f4:62:dc:25:8b:
+ 78:bf:f8:e8:7e:b8:5c:c9:95:4f:5f:a7:2d:b9:20:
+ 6b:cf:6b:dd:f5:0d:f4:82:b7:f4:b2:66:2e:10:28:
+ f6:97:5a:7b:96:16:8f:01:19:2d:6c:6e:7f:39:58:
+ 06:64:83:01:83:83:c3:4d:92:dd:32:c6:87:a4:37:
+ e9:16:ce:aa:2d:68:af:0a:81:65:3a:70:c1:9b:ad:
+ 4d:6d:54:ca:2a:2d:4b:85:1b:b3:80:e6:70:45:0d:
+ 6b:5e:35:f0:7f:3b:b8:9c:e4:04:70:89:12:25:93:
+ da:0a:99:22:60:6a:63:60:4e:76:06:98:4e:bd:83:
+ ad:1d:58:8a:25:85:d2:c7:65:1e:2d:8e:c6:df:b6:
+ c6:e1:7f:8a:04:21:15:29:74:f0:3e:9c:90:9d:0c:
+ 2e:f1:8a:3e:5a:aa:0c:09:1e:c7:d5:3c:a3:ed:97:
+ c3:1e:34:fa:38:f9:08:0e:e3:c0:5d:2b:83:d1:56:
+ 6a:c9:b6:a8:54:53:2e:78:32:67:3d:82:7f:74:d0:
+ fb:e1:b6:05:60:b9:70:db:8e:0b:f9:13:58:6f:71:
+ 60:10:52:10:b9:c1:41:09:ef:72:1f:67:31:78:ff:
+ 96:05:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Authority Key Identifier:
+ keyid:E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ E3:FE:2D:FD:28:D0:0B:B5:BA:B6:A2:C4:BF:06:AA:05:8C:93:FB:2F
+ Signature Algorithm: sha256WithRSAEncryption
+ 25:c6:ba:6b:eb:87:cb:de:82:39:96:3d:f0:44:a7:6b:84:73:
+ 03:de:9d:2b:4f:ba:20:7f:bc:78:b2:cf:97:b0:1b:9c:f3:d7:
+ 79:2e:f5:48:b6:d2:fb:17:88:e6:d3:7a:3f:ed:53:13:d0:e2:
+ 2f:6a:79:cb:00:23:28:e6:1e:37:57:35:89:84:c2:76:4f:34:
+ 36:ad:67:c3:ce:41:06:88:c5:f7:ee:d8:1a:b8:d6:0b:7f:50:
+ ff:93:aa:17:4b:8c:ec:ed:52:60:b2:a4:06:ea:4e:eb:f4:6b:
+ 19:fd:eb:f5:1a:e0:25:2a:9a:dc:c7:41:36:f7:c8:74:05:84:
+ 39:95:39:d6:0b:3b:a4:27:fa:08:d8:5c:1e:f8:04:60:52:11:
+ 28:28:03:ff:ef:53:66:00:a5:4a:34:16:66:7c:fd:09:a4:ae:
+ 9e:67:1a:6f:41:0b:6b:06:13:9b:8f:86:71:05:b4:2f:8d:89:
+ 66:33:29:76:54:9a:11:f8:27:fa:b2:3f:91:e0:ce:0d:1b:f3:
+ 30:1a:ad:bf:22:5d:1b:d3:bf:25:05:4d:e1:92:1a:7f:99:9f:
+ 3c:44:93:ca:d4:40:49:6c:80:87:d7:04:3a:c3:32:52:35:0e:
+ 56:f8:a5:dd:7d:c4:8b:0d:11:1f:53:cb:1e:b2:17:b6:68:77:
+ 5a:e0:d4:cb:c8:07:ae:f5:3a:2e:8e:37:b7:d0:01:4b:43:29:
+ 77:8c:39:97:8f:82:5a:f8:51:e5:89:a0:18:e7:68:7f:5d:0a:
+ 2e:fb:a3:47:0e:3d:a6:23:7a:c6:01:c7:8f:c8:5e:bf:6d:80:
+ 56:be:8a:24:ba:33:ea:9f:e1:32:11:9e:f1:d2:4f:80:f6:1b:
+ 40:af:38:9e:11:50:79:73:12:12:cd:e6:6c:9d:2c:88:72:3c:
+ 30:81:06:91:22:ea:59:ad:da:19:2e:22:c2:8d:b9:8c:87:e0:
+ 66:bc:73:23:5f:21:64:63:80:48:f5:a0:3c:18:3d:94:c8:48:
+ 41:1d:40:ba:5e:fe:fe:56:39:a1:c8:cf:5e:9e:19:64:46:10:
+ da:17:91:b7:05:80:ac:8b:99:92:7d:e7:a2:d8:07:0b:36:27:
+ e7:48:79:60:8a:c3:d7:13:5c:f8:72:40:df:4a:cb:cf:99:00:
+ 0a:00:0b:11:95:da:56:45:03:88:0a:9f:67:d0:d5:79:b1:a8:
+ 8d:40:6d:0d:c2:7a:40:fa:f3:5f:64:47:92:cb:53:b9:bb:59:
+ ce:4f:fd:d0:15:53:01:d8:df:eb:d9:e6:76:ef:d0:23:bb:3b:
+ a9:79:b3:d5:02:29:cd:89:a3:96:0f:4a:35:e7:4e:42:c0:75:
+ cd:07:cf:e6:2c:eb:7b:2e
+-----BEGIN CERTIFICATE-----
+MIIFjTCCA3WgAwIBAgIEGErM1jANBgkqhkiG9w0BAQsFADBWMQswCQYDVQQGEwJD
+TjEwMC4GA1UECgwnQ2hpbmEgRmluYW5jaWFsIENlcnRpZmljYXRpb24gQXV0aG9y
+aXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJPT1QwHhcNMTIwODA4MDMwNzAxWhcNMjkx
+MjMxMDMwNzAxWjBWMQswCQYDVQQGEwJDTjEwMC4GA1UECgwnQ2hpbmEgRmluYW5j
+aWFsIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRUwEwYDVQQDDAxDRkNBIEVWIFJP
+T1QwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDXXWvNED8fBVnVBU03
+sQ7smCuOFR36k0sXgiFxEFLXUWRwFsJVaU2OFW2fvwwbwuCjZ9YMrM8irq93VCpL
+TIpTUnrD7i7es3ElweldPe6hL6P3KjzJIx1qqx2hp/Hz7KDVRM8Vz3IvHWOX6Jn5
+/ZOkVIBMUtRSqy5J35DNuF++P96hyk0g1CXohClTt7GIH//62pCfCqktQT+x8Rgp
+7hZZLDRJGqgG16iI0gNyejLi6mhNbiyWZXvKWfry4t3uMCz7zEasxGPrb382KzRz
+EpR/38wmnvFyXVBlWY9ps4deMm/DGIq1lY+wejfeWkU7xzbh72fROdOXW3NiGUgt
+hxwG+3SYIElz8AXSG7Ggo7cbcNOIabla1jj0Ytwli3i/+Oh+uFzJlU9fpy25IGvP
+a931DfSCt/SyZi4QKPaXWnuWFo8BGS1sbn85WAZkgwGDg8NNkt0yxoekN+kWzqot
+aK8KgWU6cMGbrU1tVMoqLUuFG7OA5nBFDWteNfB/O7ic5ARwiRIlk9oKmSJgamNg
+TnYGmE69g60dWIolhdLHZR4tjsbftsbhf4oEIRUpdPA+nJCdDC7xij5aqgwJHsfV
+PKPtl8MeNPo4+QgO48BdK4PRVmrJtqhUUy54Mmc9gn900PvhtgVguXDbjgv5E1hv
+cWAQUhC5wUEJ73IfZzF4/5YFjQIDAQABo2MwYTAfBgNVHSMEGDAWgBTj/i39KNAL
+tbq2osS/BqoFjJP7LzAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAd
+BgNVHQ4EFgQU4/4t/SjQC7W6tqLEvwaqBYyT+y8wDQYJKoZIhvcNAQELBQADggIB
+ACXGumvrh8vegjmWPfBEp2uEcwPenStPuiB/vHiyz5ewG5zz13ku9Ui20vsXiObT
+ej/tUxPQ4i9qecsAIyjmHjdXNYmEwnZPNDatZ8POQQaIxffu2Bq41gt/UP+TqhdL
+jOztUmCypAbqTuv0axn96/Ua4CUqmtzHQTb3yHQFhDmVOdYLO6Qn+gjYXB74BGBS
+ESgoA//vU2YApUo0FmZ8/Qmkrp5nGm9BC2sGE5uPhnEFtC+NiWYzKXZUmhH4J/qy
+P5Hgzg0b8zAarb8iXRvTvyUFTeGSGn+ZnzxEk8rUQElsgIfXBDrDMlI1Dlb4pd19
+xIsNER9Tyx6yF7Zod1rg1MvIB671Oi6ON7fQAUtDKXeMOZePglr4UeWJoBjnaH9d
+Ci77o0cOPaYjesYBx4/IXr9tgFa+iiS6M+qf4TIRnvHST4D2G0CvOJ4RUHlzEhLN
+5mydLIhyPDCBBpEi6lmt2hkuIsKNuYyH4Ga8cyNfIWRjgEj1oDwYPZTISEEdQLpe
+/v5WOaHIz16eGWRGENoXkbcFgKyLmZJ956LYBws2J+dIeWCKw9cTXPhyQN9Ky8+Z
+AAoACxGV2lZFA4gKn2fQ1XmxqI1AbQ3CekD6819kR5LLU7m7Wc5P/dAVUwHY3+vZ
+5nbv0CO7O6l5s9UCKc2Jo5YPSjXnTkLAdc0Hz+Ys63su
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem
new file mode 100644
index 00000000000..cfad8330593
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0a:01:42:80:00:00:01:45:23:c8:44:b5:00:00:00:02
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = IdenTrust, CN = IdenTrust Commercial Root CA 1
+ Validity
+ Not Before: Jan 16 18:12:23 2014 GMT
+ Not After : Jan 16 18:12:23 2034 GMT
+ Subject: C = US, O = IdenTrust, CN = IdenTrust Commercial Root CA 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a7:50:19:de:3f:99:3d:d4:33:46:f1:6f:51:61:
+ 82:b2:a9:4f:8f:67:89:5d:84:d9:53:dd:0c:28:d9:
+ d7:f0:ff:ae:95:43:72:99:f9:b5:5d:7c:8a:c1:42:
+ e1:31:50:74:d1:81:0d:7c:cd:9b:21:ab:43:e2:ac:
+ ad:5e:86:6e:f3:09:8a:1f:5a:32:bd:a2:eb:94:f9:
+ e8:5c:0a:ec:ff:98:d2:af:71:b3:b4:53:9f:4e:87:
+ ef:92:bc:bd:ec:4f:32:30:88:4b:17:5e:57:c4:53:
+ c2:f6:02:97:8d:d9:62:2b:bf:24:1f:62:8d:df:c3:
+ b8:29:4b:49:78:3c:93:60:88:22:fc:99:da:36:c8:
+ c2:a2:d4:2c:54:00:67:35:6e:73:bf:02:58:f0:a4:
+ dd:e5:b0:a2:26:7a:ca:e0:36:a5:19:16:f5:fd:b7:
+ ef:ae:3f:40:f5:6d:5a:04:fd:ce:34:ca:24:dc:74:
+ 23:1b:5d:33:13:12:5d:c4:01:25:f6:30:dd:02:5d:
+ 9f:e0:d5:47:bd:b4:eb:1b:a1:bb:49:49:d8:9f:5b:
+ 02:f3:8a:e4:24:90:e4:62:4f:4f:c1:af:8b:0e:74:
+ 17:a8:d1:72:88:6a:7a:01:49:cc:b4:46:79:c6:17:
+ b1:da:98:1e:07:59:fa:75:21:85:65:dd:90:56:ce:
+ fb:ab:a5:60:9d:c4:9d:f9:52:b0:8b:bd:87:f9:8f:
+ 2b:23:0a:23:76:3b:f7:33:e1:c9:00:f3:69:f9:4b:
+ a2:e0:4e:bc:7e:93:39:84:07:f7:44:70:7e:fe:07:
+ 5a:e5:b1:ac:d1:18:cc:f2:35:e5:49:49:08:ca:56:
+ c9:3d:fb:0f:18:7d:8b:3b:c1:13:c2:4d:8f:c9:4f:
+ 0e:37:e9:1f:a1:0e:6a:df:62:2e:cb:35:06:51:79:
+ 2c:c8:25:38:f4:fa:4b:a7:89:5c:9c:d2:e3:0d:39:
+ 86:4a:74:7c:d5:59:87:c2:3f:4e:0c:5c:52:f4:3d:
+ f7:52:82:f1:ea:a3:ac:fd:49:34:1a:28:f3:41:88:
+ 3a:13:ee:e8:de:ff:99:1d:5f:ba:cb:e8:1e:f2:b9:
+ 50:60:c0:31:d3:73:e5:ef:be:a0:ed:33:0b:74:be:
+ 20:20:c4:67:6c:f0:08:03:7a:55:80:7f:46:4e:96:
+ a7:f4:1e:3e:e1:f6:d8:09:e1:33:64:2b:63:d7:32:
+ 5e:9f:f9:c0:7b:0f:78:6f:97:bc:93:9a:f9:9c:12:
+ 90:78:7a:80:87:15:d7:72:74:9c:55:74:78:b1:ba:
+ e1:6e:70:04:ba:4f:a0:ba:68:c3:7b:ff:31:f0:73:
+ 3d:3d:94:2a:b1:0b:41:0e:a0:fe:4d:88:65:6b:79:
+ 33:b4:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ ED:44:19:C0:D3:F0:06:8B:EE:A4:7B:BE:42:E7:26:54:C8:8E:36:76
+ Signature Algorithm: sha256WithRSAEncryption
+ 0d:ae:90:32:f6:a6:4b:7c:44:76:19:61:1e:27:28:cd:5e:54:
+ ef:25:bc:e3:08:90:f9:29:d7:ae:68:08:e1:94:00:58:ef:2e:
+ 2e:7e:53:52:8c:b6:5c:07:ea:88:ba:99:8b:50:94:d7:82:80:
+ df:61:09:00:93:ad:0d:14:e6:ce:c1:f2:37:94:78:b0:5f:9c:
+ b3:a2:73:b8:8f:05:93:38:cd:8d:3e:b0:b8:fb:c0:cf:b1:f2:
+ ec:2d:2d:1b:cc:ec:aa:9a:b3:aa:60:82:1b:2d:3b:c3:84:3d:
+ 57:8a:96:1e:9c:75:b8:d3:30:cd:60:08:83:90:d3:8e:54:f1:
+ 4d:66:c0:5d:74:03:40:a3:ee:85:7e:c2:1f:77:9c:06:e8:c1:
+ a7:18:5d:52:95:ed:c9:dd:25:9e:6d:fa:a9:ed:a3:3a:34:d0:
+ 59:7b:da:ed:50:f3:35:bf:ed:eb:14:4d:31:c7:60:f4:da:f1:
+ 87:9c:e2:48:e2:c6:c5:37:fb:06:10:fa:75:59:66:31:47:29:
+ da:76:9a:1c:e9:82:ae:ef:9a:b9:51:f7:88:23:9a:69:95:62:
+ 3c:e5:55:80:36:d7:54:02:ff:f1:b9:5d:ce:d4:23:6f:d8:45:
+ 84:4a:5b:65:ef:89:0c:dd:14:a7:20:cb:18:a5:25:b4:0d:f9:
+ 01:f0:a2:d2:f4:00:c8:74:8e:a1:2a:48:8e:65:db:13:c4:e2:
+ 25:17:7d:eb:be:87:5b:17:20:54:51:93:4a:53:03:0b:ec:5d:
+ ca:33:ed:62:fd:45:c7:2f:5b:dc:58:a0:80:39:e6:fa:d7:fe:
+ 13:14:a6:ed:3d:94:4a:42:74:d4:c3:77:59:73:cd:8f:46:be:
+ 55:38:ef:fa:e8:91:32:ea:97:58:04:22:de:38:c3:cc:bc:6d:
+ c9:33:3a:6a:0a:69:3f:a0:c8:ea:72:8f:8c:63:86:23:bd:6d:
+ 3c:96:9e:95:e0:49:4c:aa:a2:b9:2a:1b:9c:36:81:78:ed:c3:
+ e8:46:e2:26:59:44:75:1e:d9:75:89:51:cd:10:84:9d:61:60:
+ cb:5d:f9:97:22:4d:8e:98:e6:e3:7f:f6:5b:bb:ae:cd:ca:4a:
+ 81:6b:5e:0b:f3:51:e1:74:2b:e9:7e:27:a7:d9:99:49:4e:f8:
+ a5:80:db:25:0f:1c:63:62:8a:c9:33:67:6b:3c:10:83:c6:ad:
+ de:a8:cd:16:8e:8d:f0:07:37:71:9f:f2:ab:fc:41:f5:c1:8b:
+ ec:00:37:5d:09:e5:4e:80:ef:fa:b1:5c:38:06:a5:1b:4a:e1:
+ dc:38:2d:3c:dc:ab:1f:90:1a:d5:4a:9c:ee:d1:70:6c:cc:ee:
+ f4:57:f8:18:ba:84:6e:87
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIQCgFCgAAAAUUjyES1AAAAAjANBgkqhkiG9w0BAQsFADBK
+MQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScwJQYDVQQDEx5JZGVu
+VHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwHhcNMTQwMTE2MTgxMjIzWhcNMzQw
+MTE2MTgxMjIzWjBKMQswCQYDVQQGEwJVUzESMBAGA1UEChMJSWRlblRydXN0MScw
+JQYDVQQDEx5JZGVuVHJ1c3QgQ29tbWVyY2lhbCBSb290IENBIDEwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCnUBneP5k91DNG8W9RYYKyqU+PZ4ldhNlT
+3Qwo2dfw/66VQ3KZ+bVdfIrBQuExUHTRgQ18zZshq0PirK1ehm7zCYofWjK9ouuU
++ehcCuz/mNKvcbO0U59Oh++SvL3sTzIwiEsXXlfEU8L2ApeN2WIrvyQfYo3fw7gp
+S0l4PJNgiCL8mdo2yMKi1CxUAGc1bnO/AljwpN3lsKImesrgNqUZFvX9t++uP0D1
+bVoE/c40yiTcdCMbXTMTEl3EASX2MN0CXZ/g1Ue9tOsbobtJSdifWwLziuQkkORi
+T0/Br4sOdBeo0XKIanoBScy0RnnGF7HamB4HWfp1IYVl3ZBWzvurpWCdxJ35UrCL
+vYf5jysjCiN2O/cz4ckA82n5S6LgTrx+kzmEB/dEcH7+B1rlsazRGMzyNeVJSQjK
+Vsk9+w8YfYs7wRPCTY/JTw436R+hDmrfYi7LNQZReSzIJTj0+kuniVyc0uMNOYZK
+dHzVWYfCP04MXFL0PfdSgvHqo6z9STQaKPNBiDoT7uje/5kdX7rL6B7yuVBgwDHT
+c+XvvqDtMwt0viAgxGds8AgDelWAf0ZOlqf0Hj7h9tgJ4TNkK2PXMl6f+cB7D3hv
+l7yTmvmcEpB4eoCHFddydJxVdHixuuFucAS6T6C6aMN7/zHwcz09lCqxC0EOoP5N
+iGVreTO01wIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQU7UQZwNPwBovupHu+QucmVMiONnYwDQYJKoZIhvcNAQELBQAD
+ggIBAA2ukDL2pkt8RHYZYR4nKM1eVO8lvOMIkPkp165oCOGUAFjvLi5+U1KMtlwH
+6oi6mYtQlNeCgN9hCQCTrQ0U5s7B8jeUeLBfnLOic7iPBZM4zY0+sLj7wM+x8uwt
+LRvM7Kqas6pgghstO8OEPVeKlh6cdbjTMM1gCIOQ045U8U1mwF10A0Cj7oV+wh93
+nAbowacYXVKV7cndJZ5t+qntozo00Fl72u1Q8zW/7esUTTHHYPTa8Yec4kjixsU3
++wYQ+nVZZjFHKdp2mhzpgq7vmrlR94gjmmmVYjzlVYA211QC//G5Xc7UI2/YRYRK
+W2XviQzdFKcgyxilJbQN+QHwotL0AMh0jqEqSI5l2xPE4iUXfeu+h1sXIFRRk0pT
+AwvsXcoz7WL9RccvW9xYoIA55vrX/hMUpu09lEpCdNTDd1lzzY9GvlU47/rokTLq
+l1gEIt44w8y8bckzOmoKaT+gyOpyj4xjhiO9bTyWnpXgSUyqorkqG5w2gXjtw+hG
+4iZZRHUe2XWJUc0QhJ1hYMtd+ZciTY6Y5uN/9lu7rs3KSoFrXgvzUeF0K+l+J6fZ
+mUlO+KWA2yUPHGNiiskzZ2s8EIPGrd6ozRaOjfAHN3Gf8qv8QfXBi+wAN10J5U6A
+7/qxXDgGpRtK4dw4LTzcqx+QGtVKnO7RcGzM7vRX+Bi6hG6H
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem
new file mode 100644
index 00000000000..9694db50418
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem
@@ -0,0 +1,128 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ bb:40:1c:43:f5:5e:4f:b0
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = CH, O = SwissSign AG, CN = SwissSign Gold CA - G2
+ Validity
+ Not Before: Oct 25 08:30:35 2006 GMT
+ Not After : Oct 25 08:30:35 2036 GMT
+ Subject: C = CH, O = SwissSign AG, CN = SwissSign Gold CA - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:af:e4:ee:7e:8b:24:0e:12:6e:a9:50:2d:16:44:
+ 3b:92:92:5c:ca:b8:5d:84:92:42:13:2a:bc:65:57:
+ 82:40:3e:57:24:cd:50:8b:25:2a:b7:6f:fc:ef:a2:
+ d0:c0:1f:02:24:4a:13:96:8f:23:13:e6:28:58:00:
+ a3:47:c7:06:a7:84:23:2b:bb:bd:96:2b:7f:55:cc:
+ 8b:c1:57:1f:0e:62:65:0f:dd:3d:56:8a:73:da:ae:
+ 7e:6d:ba:81:1c:7e:42:8c:20:35:d9:43:4d:84:fa:
+ 84:db:52:2c:f3:0e:27:77:0b:6b:bf:11:2f:72:78:
+ 9f:2e:d8:3e:e6:18:37:5a:2a:72:f9:da:62:90:92:
+ 95:ca:1f:9c:e9:b3:3c:2b:cb:f3:01:13:bf:5a:cf:
+ c1:b5:0a:60:bd:dd:b5:99:64:53:b8:a0:96:b3:6f:
+ e2:26:77:91:8c:e0:62:10:02:9f:34:0f:a4:d5:92:
+ 33:51:de:be:8d:ba:84:7a:60:3c:6a:db:9f:2b:ec:
+ de:de:01:3f:6e:4d:e5:50:86:cb:b4:af:ed:44:40:
+ c5:ca:5a:8c:da:d2:2b:7c:a8:ee:be:a6:e5:0a:aa:
+ 0e:a5:df:05:52:b7:55:c7:22:5d:32:6a:97:97:63:
+ 13:db:c9:db:79:36:7b:85:3a:4a:c5:52:89:f9:24:
+ e7:9d:77:a9:82:ff:55:1c:a5:71:69:2b:d1:02:24:
+ f2:b3:26:d4:6b:da:04:55:e5:c1:0a:c7:6d:30:37:
+ 90:2a:e4:9e:14:33:5e:16:17:55:c5:5b:b5:cb:34:
+ 89:92:f1:9d:26:8f:a1:07:d4:c6:b2:78:50:db:0c:
+ 0c:0b:7c:0b:8c:41:d7:b9:e9:dd:8c:88:f7:a3:4d:
+ b2:32:cc:d8:17:da:cd:b7:ce:66:9d:d4:fd:5e:ff:
+ bd:97:3e:29:75:e7:7e:a7:62:58:af:25:34:a5:41:
+ c7:3d:bc:0d:50:ca:03:03:0f:08:5a:1f:95:73:78:
+ 62:bf:af:72:14:69:0e:a5:e5:03:0e:78:8e:26:28:
+ 42:f0:07:0b:62:20:10:67:39:46:fa:a9:03:cc:04:
+ 38:7a:66:ef:20:83:b5:8c:4a:56:8e:91:00:fc:8e:
+ 5c:82:de:88:a0:c3:e2:68:6e:7d:8d:ef:3c:dd:65:
+ f4:5d:ac:51:ef:24:80:ae:aa:56:97:6f:f9:ad:7d:
+ da:61:3f:98:77:3c:a5:91:b6:1c:8c:26:da:65:a2:
+ 09:6d:c1:e2:54:e3:b9:ca:4c:4c:80:8f:77:7b:60:
+ 9a:1e:df:b6:f2:48:1e:0e:ba:4e:54:6d:98:e0:e1:
+ a2:1a:a2:77:50:cf:c4:63:92:ec:47:19:9d:eb:e6:
+ 6b:ce:c1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE
+ X509v3 Authority Key Identifier:
+ keyid:5B:25:7B:96:A4:65:51:7E:B8:39:F3:C0:78:66:5E:E8:3A:E7:F0:EE
+
+ X509v3 Certificate Policies:
+ Policy: 2.16.756.1.89.1.2.1.1
+ CPS: http://repository.swisssign.com/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 27:ba:e3:94:7c:f1:ae:c0:de:17:e6:e5:d8:d5:f5:54:b0:83:
+ f4:bb:cd:5e:05:7b:4f:9f:75:66:af:3c:e8:56:7e:fc:72:78:
+ 38:03:d9:2b:62:1b:00:b9:f8:e9:60:cd:cc:ce:51:8a:c7:50:
+ 31:6e:e1:4a:7e:18:2f:69:59:b6:3d:64:81:2b:e3:83:84:e6:
+ 22:87:8e:7d:e0:ee:02:99:61:b8:1e:f4:b8:2b:88:12:16:84:
+ c2:31:93:38:96:31:a6:b9:3b:53:3f:c3:24:93:56:5b:69:92:
+ ec:c5:c1:bb:38:00:e3:ec:17:a9:b8:dc:c7:7c:01:83:9f:32:
+ 47:ba:52:22:34:1d:32:7a:09:56:a7:7c:25:36:a9:3d:4b:da:
+ c0:82:6f:0a:bb:12:c8:87:4b:27:11:f9:1e:2d:c7:93:3f:9e:
+ db:5f:26:6b:52:d9:2e:8a:f1:14:c6:44:8d:15:a9:b7:bf:bd:
+ de:a6:1a:ee:ae:2d:fb:48:77:17:fe:bb:ec:af:18:f5:2a:51:
+ f0:39:84:97:95:6c:6e:1b:c3:2b:c4:74:60:79:25:b0:0a:27:
+ df:df:5e:d2:39:cf:45:7d:42:4b:df:b3:2c:1e:c5:c6:5d:ca:
+ 55:3a:a0:9c:69:9a:8f:da:ef:b2:b0:3c:9f:87:6c:12:2b:65:
+ 70:15:52:31:1a:24:cf:6f:31:23:50:1f:8c:4f:8f:23:c3:74:
+ 41:63:1c:55:a8:14:dd:3e:e0:51:50:cf:f1:1b:30:56:0e:92:
+ b0:82:85:d8:83:cb:22:64:bc:2d:b8:25:d5:54:a2:b8:06:ea:
+ ad:92:a4:24:a0:c1:86:b5:4a:13:6a:47:cf:2e:0b:56:95:54:
+ cb:ce:9a:db:6a:b4:a6:b2:db:41:08:86:27:77:f7:6a:a0:42:
+ 6c:0b:38:ce:d7:75:50:32:92:c2:df:2b:30:22:48:d0:d5:41:
+ 38:25:5d:a4:e9:5d:9f:c6:94:75:d0:45:fd:30:97:43:8f:90:
+ ab:0a:c7:86:73:60:4a:69:2d:de:a5:78:d7:06:da:6a:9e:4b:
+ 3e:77:3a:20:13:22:01:d0:bf:68:9e:63:60:6b:35:4d:0b:6d:
+ ba:a1:3d:c0:93:e0:7f:23:b3:55:ad:72:25:4e:46:f9:d2:16:
+ ef:b0:64:c1:01:9e:e9:ca:a0:6a:98:0e:cf:d8:60:f2:2f:49:
+ b8:e4:42:e1:38:35:16:f4:c8:6e:4f:f7:81:56:e8:ba:a3:be:
+ 23:af:ae:fd:6f:03:e0:02:3b:30:76:fa:1b:6d:41:cf:01:b1:
+ e9:b8:c9:66:f4:db:26:f3:3a:a4:74:f2:49:24:5b:c9:b0:d0:
+ 57:c1:fa:3e:7a:e1:97:c9
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
+BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
+biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
+MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
+d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
+CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
+76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
+bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
+6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
+emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
+MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
+MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
+MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
+FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
+aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
+gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
+qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
+lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
+8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
+45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
+UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
+O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
+bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
+GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
+77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
+hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
+92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
+Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
+ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
+Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem
new file mode 100644
index 00000000000..bed5a78dd88
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 11:00:34:b6:4e:c6:36:2d:36
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = RO, O = CERTSIGN SA, OU = certSIGN ROOT CA G2
+ Validity
+ Not Before: Feb 6 09:27:35 2017 GMT
+ Not After : Feb 6 09:27:35 2042 GMT
+ Subject: C = RO, O = CERTSIGN SA, OU = certSIGN ROOT CA G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c0:c5:75:19:91:7d:44:74:74:87:fe:0e:3b:96:
+ dc:d8:01:16:cc:ee:63:91:e7:0b:6f:ce:3b:0a:69:
+ 1a:7c:c2:e3:af:82:8e:86:d7:5e:8f:57:eb:d3:21:
+ 59:fd:39:37:42:30:be:50:ea:b6:0f:a9:88:d8:2e:
+ 2d:69:21:e7:d1:37:18:4e:7d:91:d5:16:5f:6b:5b:
+ 00:c2:39:43:0d:36:85:52:b9:53:65:0f:1d:42:e5:
+ 8f:cf:05:d3:ee:dc:0c:1a:d9:b8:8b:78:22:67:e4:
+ 69:b0:68:c5:3c:e4:6c:5a:46:e7:cd:c7:fa:ef:c4:
+ ec:4b:bd:6a:a4:ac:fd:cc:28:51:ef:92:b4:29:ab:
+ ab:35:9a:4c:e4:c4:08:c6:26:cc:f8:69:9f:e4:9c:
+ f0:29:d3:5c:f9:c6:16:25:9e:23:c3:20:c1:3d:0f:
+ 3f:38:40:b0:fe:82:44:38:aa:5a:1a:8a:6b:63:58:
+ 38:b4:15:d3:b6:11:69:7b:1e:54:ee:8c:1a:22:ac:
+ 72:97:3f:23:59:9b:c9:22:84:c1:07:4f:cc:7f:e2:
+ 57:ca:12:70:bb:a6:65:f3:69:75:63:bd:95:fb:1b:
+ 97:cd:e4:a8:af:f6:d1:4e:a8:d9:8a:71:24:cd:36:
+ 3d:bc:96:c4:f1:6c:a9:ae:e5:cf:0d:6e:28:0d:b0:
+ 0e:b5:ca:51:7b:78:14:c3:20:2f:7f:fb:14:55:e1:
+ 11:99:fd:d5:0a:a1:9e:02:e3:62:5f:eb:35:4b:2c:
+ b8:72:e8:3e:3d:4f:ac:2c:bb:2e:86:e2:a3:76:8f:
+ e5:93:2a:cf:a5:ab:c8:5c:8d:4b:06:ff:12:46:ac:
+ 78:cb:14:07:35:e0:a9:df:8b:e9:af:15:4f:16:89:
+ 5b:bd:f6:8d:c6:59:ae:88:85:0e:c1:89:eb:1f:67:
+ c5:45:8e:ff:6d:37:36:2b:78:66:83:91:51:2b:3d:
+ ff:51:77:76:62:a1:ec:67:3e:3e:81:83:e0:56:a9:
+ 50:1f:1f:7a:99:ab:63:bf:84:17:77:f1:0d:3b:df:
+ f7:9c:61:b3:35:98:8a:3a:b2:ec:3c:1a:37:3f:7e:
+ 8f:92:cf:d9:12:14:64:da:10:02:15:41:ff:4f:c4:
+ eb:1c:a3:c9:fa:99:f7:46:e9:e1:18:d9:b1:b8:32:
+ 2d:cb:14:0c:50:d8:83:65:83:ee:b9:5c:cf:cb:05:
+ 5a:4c:fa:19:97:6b:d6:5d:13:d3:c2:5c:54:bc:32:
+ 73:a0:78:f5:f1:6d:1e:cb:9f:a5:a6:9f:22:dc:d1:
+ 51:9e:82:79:64:60:29:13:3e:a3:fd:4f:72:6a:ab:
+ e2:d4:e5:b8:24:55:2c:44:4b:8a:88:44:9c:ca:84:
+ d3:2a:3b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 82:21:2D:66:C6:D7:A0:E0:15:EB:CE:4C:09:77:C4:60:9E:54:6E:03
+ Signature Algorithm: sha256WithRSAEncryption
+ 60:de:1a:b8:e7:f2:60:82:d5:03:33:81:cb:06:8a:f1:22:49:
+ e9:e8:ea:91:7f:c6:33:5e:68:19:03:86:3b:43:01:cf:07:70:
+ e4:08:1e:65:85:91:e6:11:22:b7:f5:02:23:8e:ae:b9:1e:7d:
+ 1f:7e:6c:e6:bd:25:d5:95:1a:f2:05:a6:af:85:02:6f:ae:f8:
+ d6:31:ff:25:c9:4a:c8:c7:8a:a9:d9:9f:4b:49:9b:11:57:99:
+ 92:43:11:de:b6:33:a4:cc:d7:8d:64:7d:d4:cd:3c:28:2c:b4:
+ 9a:96:ea:4d:f5:c4:44:c4:25:aa:20:80:d8:29:55:f7:e0:41:
+ fc:06:26:ff:b9:36:f5:43:14:03:66:78:e1:11:b1:da:20:5f:
+ 46:00:78:00:21:a5:1e:00:28:61:78:6f:a8:01:01:8f:9d:34:
+ 9a:ff:f4:38:90:fb:b8:d1:b3:72:06:c9:71:e6:81:c5:79:ed:
+ 0b:a6:79:f2:13:0b:9c:f7:5d:0e:7b:24:93:b4:48:db:86:5f:
+ de:50:86:78:e7:40:e6:31:a8:90:76:70:61:af:9c:37:2c:11:
+ b5:82:b7:aa:ae:24:34:5b:72:0c:69:0d:cd:59:9f:f6:71:af:
+ 9c:0b:d1:0a:38:f9:06:22:83:53:25:0c:fc:51:c4:e6:be:e2:
+ 39:95:0b:24:ad:af:d1:95:e4:96:d7:74:64:6b:71:4e:02:3c:
+ aa:85:f3:20:a3:43:39:76:5b:6c:50:fe:9a:9c:14:1e:65:14:
+ 8a:15:bd:a3:82:45:5a:49:56:6a:d2:9c:b1:63:32:e5:61:e0:
+ 53:22:0e:a7:0a:49:ea:cb:7e:1f:a8:e2:62:80:f6:10:45:52:
+ 98:06:18:de:a5:cd:2f:7f:aa:d4:e9:3e:08:72:ec:23:03:02:
+ 3c:a6:aa:d8:bc:67:74:3d:14:17:fb:54:4b:17:e3:d3:79:3d:
+ 6d:6b:49:c9:28:0e:2e:74:50:bf:0c:d9:46:3a:10:86:c9:a7:
+ 3f:e9:a0:ec:7f:eb:a5:77:58:69:71:e6:83:0a:37:f2:86:49:
+ 6a:be:79:08:90:f6:02:16:64:3e:e5:da:4c:7e:0c:34:c9:f9:
+ 5f:b6:b3:28:51:a7:a7:2b:aa:49:fa:8d:65:29:4e:e3:6b:13:
+ a7:94:a3:2d:51:6d:78:0c:44:cb:df:de:08:6f:ce:a3:64:ab:
+ d3:95:84:d4:b9:52:54:72:7b:96:25:cc:bc:69:e3:48:6e:0d:
+ d0:c7:9d:27:9a:aa:f8:13:92:dd:1e:df:63:9f:35:a9:16:36:
+ ec:8c:b8:83:f4:3d:89:8f:cd:b4:17:5e:d7:b3:17:41:10:5d:
+ 27:73:60:85:57:49:22:07
+-----BEGIN CERTIFICATE-----
+MIIFRzCCAy+gAwIBAgIJEQA0tk7GNi02MA0GCSqGSIb3DQEBCwUAMEExCzAJBgNV
+BAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJR04g
+Uk9PVCBDQSBHMjAeFw0xNzAyMDYwOTI3MzVaFw00MjAyMDYwOTI3MzVaMEExCzAJ
+BgNVBAYTAlJPMRQwEgYDVQQKEwtDRVJUU0lHTiBTQTEcMBoGA1UECxMTY2VydFNJ
+R04gUk9PVCBDQSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDF
+dRmRfUR0dIf+DjuW3NgBFszuY5HnC2/OOwppGnzC46+CjobXXo9X69MhWf05N0Iw
+vlDqtg+piNguLWkh59E3GE59kdUWX2tbAMI5Qw02hVK5U2UPHULlj88F0+7cDBrZ
+uIt4ImfkabBoxTzkbFpG583H+u/E7Eu9aqSs/cwoUe+StCmrqzWaTOTECMYmzPhp
+n+Sc8CnTXPnGFiWeI8MgwT0PPzhAsP6CRDiqWhqKa2NYOLQV07YRaXseVO6MGiKs
+cpc/I1mbySKEwQdPzH/iV8oScLumZfNpdWO9lfsbl83kqK/20U6o2YpxJM02PbyW
+xPFsqa7lzw1uKA2wDrXKUXt4FMMgL3/7FFXhEZn91QqhngLjYl/rNUssuHLoPj1P
+rCy7Lobio3aP5ZMqz6WryFyNSwb/EkaseMsUBzXgqd+L6a8VTxaJW732jcZZroiF
+DsGJ6x9nxUWO/203Nit4ZoORUSs9/1F3dmKh7Gc+PoGD4FapUB8fepmrY7+EF3fx
+DTvf95xhszWYijqy7DwaNz9+j5LP2RIUZNoQAhVB/0/E6xyjyfqZ90bp4RjZsbgy
+LcsUDFDYg2WD7rlcz8sFWkz6GZdr1l0T08JcVLwyc6B49fFtHsufpaafItzRUZ6C
+eWRgKRM+o/1Pcmqr4tTluCRVLERLiohEnMqE0yo7AgMBAAGjQjBAMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSCIS1mxteg4BXrzkwJ
+d8RgnlRuAzANBgkqhkiG9w0BAQsFAAOCAgEAYN4auOfyYILVAzOBywaK8SJJ6ejq
+kX/GM15oGQOGO0MBzwdw5AgeZYWR5hEit/UCI46uuR59H35s5r0l1ZUa8gWmr4UC
+b6741jH/JclKyMeKqdmfS0mbEVeZkkMR3rYzpMzXjWR91M08KCy0mpbqTfXERMQl
+qiCA2ClV9+BB/AYm/7k29UMUA2Z44RGx2iBfRgB4ACGlHgAoYXhvqAEBj500mv/0
+OJD7uNGzcgbJceaBxXntC6Z58hMLnPddDnskk7RI24Zf3lCGeOdA5jGokHZwYa+c
+NywRtYK3qq4kNFtyDGkNzVmf9nGvnAvRCjj5BiKDUyUM/FHE5r7iOZULJK2v0ZXk
+ltd0ZGtxTgI8qoXzIKNDOXZbbFD+mpwUHmUUihW9o4JFWklWatKcsWMy5WHgUyIO
+pwpJ6st+H6jiYoD2EEVSmAYY3qXNL3+q1Ok+CHLsIwMCPKaq2LxndD0UF/tUSxfj
+03k9bWtJySgOLnRQvwzZRjoQhsmnP+mg7H/rpXdYaXHmgwo38oZJar55CJD2AhZk
+PuXaTH4MNMn5X7azKFGnpyuqSfqNZSlO42sTp5SjLVFteAxEy9/eCG/Oo2Sr05WE
+1LlSVHJ7liXMvGnjSG4N0MedJ5qq+BOS3R7fY581qRY27Iy4g/Q9iY/NtBde17MX
+QRBdJ3NghVdJIgc=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem
new file mode 100644
index 00000000000..43ff39ec137
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 76:b1:20:52:74:f0:85:87:46:b3:f8:23:1a:f6:c2:c0
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = CH, O = WISeKey, OU = OISTE Foundation Endorsed, CN = OISTE WISeKey Global Root GB CA
+ Validity
+ Not Before: Dec 1 15:00:32 2014 GMT
+ Not After : Dec 1 15:10:31 2039 GMT
+ Subject: C = CH, O = WISeKey, OU = OISTE Foundation Endorsed, CN = OISTE WISeKey Global Root GB CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d8:17:b7:1c:4a:24:2a:d6:97:b1:ca:e2:1e:fb:
+ 7d:38:ef:98:f5:b2:39:98:4e:27:b8:11:5d:7b:d2:
+ 25:94:88:82:15:26:6a:1b:31:bb:a8:5b:21:21:2b:
+ d8:0f:4e:9f:5a:f1:b1:5a:e4:79:d6:32:23:2b:e1:
+ 53:cc:99:45:5c:7b:4f:ad:bc:bf:87:4a:0b:4b:97:
+ 5a:a8:f6:48:ec:7d:7b:0d:cd:21:06:df:9e:15:fd:
+ 41:8a:48:b7:20:f4:a1:7a:1b:57:d4:5d:50:ff:ba:
+ 67:d8:23:99:1f:c8:3f:e3:de:ff:6f:5b:77:b1:6b:
+ 6e:b8:c9:64:f7:e1:ca:41:46:0e:29:71:d0:b9:23:
+ fc:c9:81:5f:4e:f7:6f:df:bf:84:ad:73:64:bb:b7:
+ 42:8e:69:f6:d4:76:1d:7e:9d:a7:b8:57:8a:51:67:
+ 72:d7:d4:a8:b8:95:54:40:73:03:f6:ea:f4:eb:fe:
+ 28:42:77:3f:9d:23:1b:b2:b6:3d:80:14:07:4c:2e:
+ 4f:f7:d5:0a:16:0d:bd:66:43:37:7e:23:43:79:c3:
+ 40:86:f5:4c:29:da:8e:9a:ad:0d:a5:04:87:88:1e:
+ 85:e3:e9:53:d5:9b:c8:8b:03:63:78:eb:e0:19:4a:
+ 6e:bb:2f:6b:33:64:58:93:ad:69:bf:8f:1b:ef:82:
+ 48:c7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage:
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 35:0F:C8:36:63:5E:E2:A3:EC:F9:3B:66:15:CE:51:52:E3:91:9A:3D
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: sha256WithRSAEncryption
+ 40:4c:fb:87:b2:99:81:90:7e:9d:c5:b0:b0:26:cd:88:7b:2b:
+ 32:8d:6e:b8:21:71:58:97:7d:ae:37:14:af:3e:e7:f7:9a:e2:
+ 7d:f6:71:98:99:04:aa:43:74:78:a3:e3:49:61:3e:73:8c:4d:
+ 94:e0:f9:71:c4:b6:16:0e:53:78:1f:d6:a2:87:2f:02:39:81:
+ 29:3c:af:15:98:21:30:fe:28:90:00:8c:d1:e1:cb:fa:5e:c8:
+ fd:f8:10:46:3b:a2:78:42:91:17:74:55:0a:de:50:67:4d:66:
+ d1:a7:ff:fd:d9:c0:b5:a8:a3:8a:ce:66:f5:0f:43:cd:a7:2b:
+ 57:7b:63:46:6a:aa:2e:52:d8:f4:ed:e1:6d:ad:29:90:78:48:
+ ba:e1:23:aa:a3:89:ec:b5:ab:96:c0:b4:4b:a2:1d:97:9e:7a:
+ f2:6e:40:71:df:68:f1:65:4d:ce:7c:05:df:53:65:a9:a5:f0:
+ b1:97:04:70:15:46:03:98:d4:d2:bf:54:b4:a0:58:7d:52:6f:
+ da:56:26:62:d4:d8:db:89:31:6f:1c:f0:22:c2:d3:62:1c:35:
+ cd:4c:69:15:54:1a:90:98:de:eb:1e:5f:ca:77:c7:cb:8e:3d:
+ 43:69:9c:9a:58:d0:24:3b:df:1b:40:96:7e:35:ad:81:c7:4e:
+ 71:ba:88:13
+-----BEGIN CERTIFICATE-----
+MIIDtTCCAp2gAwIBAgIQdrEgUnTwhYdGs/gjGvbCwDANBgkqhkiG9w0BAQsFADBt
+MQswCQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUg
+Rm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9i
+YWwgUm9vdCBHQiBDQTAeFw0xNDEyMDExNTAwMzJaFw0zOTEyMDExNTEwMzFaMG0x
+CzAJBgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBG
+b3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2Jh
+bCBSb290IEdCIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2Be3
+HEokKtaXscriHvt9OO+Y9bI5mE4nuBFde9IllIiCFSZqGzG7qFshISvYD06fWvGx
+WuR51jIjK+FTzJlFXHtPrby/h0oLS5daqPZI7H17Dc0hBt+eFf1Biki3IPShehtX
+1F1Q/7pn2COZH8g/497/b1t3sWtuuMlk9+HKQUYOKXHQuSP8yYFfTvdv37+ErXNk
+u7dCjmn21HYdfp2nuFeKUWdy19SouJVUQHMD9ur06/4oQnc/nSMbsrY9gBQHTC5P
+99UKFg29ZkM3fiNDecNAhvVMKdqOmq0NpQSHiB6F4+lT1ZvIiwNjeOvgGUpuuy9r
+M2RYk61pv48b74JIxwIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUNQ/INmNe4qPs+TtmFc5RUuORmj0wEAYJKwYBBAGCNxUB
+BAMCAQAwDQYJKoZIhvcNAQELBQADggEBAEBM+4eymYGQfp3FsLAmzYh7KzKNbrgh
+cViXfa43FK8+5/ea4n32cZiZBKpDdHij40lhPnOMTZTg+XHEthYOU3gf1qKHLwI5
+gSk8rxWYITD+KJAAjNHhy/peyP34EEY7onhCkRd0VQreUGdNZtGn//3ZwLWoo4rO
+ZvUPQ82nK1d7Y0Zqqi5S2PTt4W2tKZB4SLrhI6qjiey1q5bAtEuiHZeeevJuQHHf
+aPFlTc58Bd9TZaml8LGXBHAVRgOY1NK/VLSgWH1Sb9pWJmLU2NuJMW8c8CLC02Ic
+Nc1MaRVUGpCY3useX8p3x8uOPUNpnJpY0CQ73xtAln41rYHHTnG6iBM=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem
new file mode 100644
index 00000000000..7319c655155
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem
@@ -0,0 +1,80 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 80544274841616 (0x49412ce40010)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = HU, L = Budapest, O = NetLock Kft., OU = Tan\C3\BAs\C3\ADtv\C3\A1nykiad\C3\B3k (Certification Services), CN = NetLock Arany (Class Gold) F\C5\91tan\C3\BAs\C3\ADtv\C3\A1ny
+ Validity
+ Not Before: Dec 11 15:08:21 2008 GMT
+ Not After : Dec 6 15:08:21 2028 GMT
+ Subject: C = HU, L = Budapest, O = NetLock Kft., OU = Tan\C3\BAs\C3\ADtv\C3\A1nykiad\C3\B3k (Certification Services), CN = NetLock Arany (Class Gold) F\C5\91tan\C3\BAs\C3\ADtv\C3\A1ny
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:c4:24:5e:73:be:4b:6d:14:c3:a1:f4:e3:97:90:
+ 6e:d2:30:45:1e:3c:ee:67:d9:64:e0:1a:8a:7f:ca:
+ 30:ca:83:e3:20:c1:e3:f4:3a:d3:94:5f:1a:7c:5b:
+ 6d:bf:30:4f:84:27:f6:9f:1f:49:bc:c6:99:0a:90:
+ f2:0f:f5:7f:43:84:37:63:51:8b:7a:a5:70:fc:7a:
+ 58:cd:8e:9b:ed:c3:46:6c:84:70:5d:da:f3:01:90:
+ 23:fc:4e:30:a9:7e:e1:27:63:e7:ed:64:3c:a0:b8:
+ c9:33:63:fe:16:90:ff:b0:b8:fd:d7:a8:c0:c0:94:
+ 43:0b:b6:d5:59:a6:9e:56:d0:24:1f:70:79:af:db:
+ 39:54:0d:65:75:d9:15:41:94:01:af:5e:ec:f6:8d:
+ f1:ff:ad:64:fe:20:9a:d7:5c:eb:fe:a6:1f:08:64:
+ a3:8b:76:55:ad:1e:3b:28:60:2e:87:25:e8:aa:af:
+ 1f:c6:64:46:20:b7:70:7f:3c:de:48:db:96:53:b7:
+ 39:77:e4:1a:e2:c7:16:84:76:97:5b:2f:bb:19:15:
+ 85:f8:69:85:f5:99:a7:a9:f2:34:a7:a9:b6:a6:03:
+ fc:6f:86:3d:54:7c:76:04:9b:6b:f9:40:5d:00:34:
+ c7:2e:99:75:9d:e5:88:03:aa:4d:f8:03:d2:42:76:
+ c0:1b
+ Exponent: 43147 (0xa88b)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:4
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ CC:FA:67:93:F0:B6:B8:D0:A5:C0:1E:F3:53:FD:8C:53:DF:83:D7:96
+ Signature Algorithm: sha256WithRSAEncryption
+ ab:7f:ee:1c:16:a9:9c:3c:51:00:a0:c0:11:08:05:a7:99:e6:
+ 6f:01:88:54:61:6e:f1:b9:18:ad:4a:ad:fe:81:40:23:94:2f:
+ fb:75:7c:2f:28:4b:62:24:81:82:0b:f5:61:f1:1c:6e:b8:61:
+ 38:eb:81:fa:62:a1:3b:5a:62:d3:94:65:c4:e1:e6:6d:82:f8:
+ 2f:25:70:b2:21:26:c1:72:51:1f:8c:2c:c3:84:90:c3:5a:8f:
+ ba:cf:f4:a7:65:a5:eb:98:d1:fb:05:b2:46:75:15:23:6a:6f:
+ 85:63:30:80:f0:d5:9e:1f:29:1c:c2:6c:b0:50:59:5d:90:5b:
+ 3b:a8:0d:30:cf:bf:7d:7f:ce:f1:9d:83:bd:c9:46:6e:20:a6:
+ f9:61:51:ba:21:2f:7b:be:a5:15:63:a1:d4:95:87:f1:9e:b9:
+ f3:89:f3:3d:85:b8:b8:db:be:b5:b9:29:f9:da:37:05:00:49:
+ 94:03:84:44:e7:bf:43:31:cf:75:8b:25:d1:f4:a6:64:f5:92:
+ f6:ab:05:eb:3d:e9:a5:0b:36:62:da:cc:06:5f:36:8b:b6:5e:
+ 31:b8:2a:fb:5e:f6:71:df:44:26:9e:c4:e6:0d:91:b4:2e:75:
+ 95:80:51:6a:4b:30:a6:b0:62:a1:93:f1:9b:d8:ce:c4:63:75:
+ 3f:59:47:b1
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
+EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
+MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
+cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
+dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
+pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
+b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
+aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
+IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
+lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
+AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
+VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
+ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
+BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
+AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
+U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
+bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
++C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
+uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
+XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem
new file mode 100644
index 00000000000..1ef5a0e0fed
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem
@@ -0,0 +1,81 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 946069240 (0x3863def8)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O = Entrust.net, OU = www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU = (c) 1999 Entrust.net Limited, CN = Entrust.net Certification Authority (2048)
+ Validity
+ Not Before: Dec 24 17:50:51 1999 GMT
+ Not After : Jul 24 14:15:12 2029 GMT
+ Subject: O = Entrust.net, OU = www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU = (c) 1999 Entrust.net Limited, CN = Entrust.net Certification Authority (2048)
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ad:4d:4b:a9:12:86:b2:ea:a3:20:07:15:16:64:
+ 2a:2b:4b:d1:bf:0b:4a:4d:8e:ed:80:76:a5:67:b7:
+ 78:40:c0:73:42:c8:68:c0:db:53:2b:dd:5e:b8:76:
+ 98:35:93:8b:1a:9d:7c:13:3a:0e:1f:5b:b7:1e:cf:
+ e5:24:14:1e:b1:81:a9:8d:7d:b8:cc:6b:4b:03:f1:
+ 02:0c:dc:ab:a5:40:24:00:7f:74:94:a1:9d:08:29:
+ b3:88:0b:f5:87:77:9d:55:cd:e4:c3:7e:d7:6a:64:
+ ab:85:14:86:95:5b:97:32:50:6f:3d:c8:ba:66:0c:
+ e3:fc:bd:b8:49:c1:76:89:49:19:fd:c0:a8:bd:89:
+ a3:67:2f:c6:9f:bc:71:19:60:b8:2d:e9:2c:c9:90:
+ 76:66:7b:94:e2:af:78:d6:65:53:5d:3c:d6:9c:b2:
+ cf:29:03:f9:2f:a4:50:b2:d4:48:ce:05:32:55:8a:
+ fd:b2:64:4c:0e:e4:98:07:75:db:7f:df:b9:08:55:
+ 60:85:30:29:f9:7b:48:a4:69:86:e3:35:3f:1e:86:
+ 5d:7a:7a:15:bd:ef:00:8e:15:22:54:17:00:90:26:
+ 93:bc:0e:49:68:91:bf:f8:47:d3:9d:95:42:c1:0e:
+ 4d:df:6f:26:cf:c3:18:21:62:66:43:70:d6:d5:c0:
+ 07:e1
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 55:E4:81:D1:11:80:BE:D8:89:B9:08:A3:31:F9:A1:24:09:16:B9:70
+ Signature Algorithm: sha1WithRSAEncryption
+ 3b:9b:8f:56:9b:30:e7:53:99:7c:7a:79:a7:4d:97:d7:19:95:
+ 90:fb:06:1f:ca:33:7c:46:63:8f:96:66:24:fa:40:1b:21:27:
+ ca:e6:72:73:f2:4f:fe:31:99:fd:c8:0c:4c:68:53:c6:80:82:
+ 13:98:fa:b6:ad:da:5d:3d:f1:ce:6e:f6:15:11:94:82:0c:ee:
+ 3f:95:af:11:ab:0f:d7:2f:de:1f:03:8f:57:2c:1e:c9:bb:9a:
+ 1a:44:95:eb:18:4f:a6:1f:cd:7d:57:10:2f:9b:04:09:5a:84:
+ b5:6e:d8:1d:3a:e1:d6:9e:d1:6c:79:5e:79:1c:14:c5:e3:d0:
+ 4c:93:3b:65:3c:ed:df:3d:be:a6:e5:95:1a:c3:b5:19:c3:bd:
+ 5e:5b:bb:ff:23:ef:68:19:cb:12:93:27:5c:03:2d:6f:30:d0:
+ 1e:b6:1a:ac:de:5a:f7:d1:aa:a8:27:a6:fe:79:81:c4:79:99:
+ 33:57:ba:12:b0:a9:e0:42:6c:93:ca:56:de:fe:6d:84:0b:08:
+ 8b:7e:8d:ea:d7:98:21:c6:f3:e7:3c:79:2f:5e:9c:d1:4c:15:
+ 8d:e1:ec:22:37:cc:9a:43:0b:97:dc:80:90:8d:b3:67:9b:6f:
+ 48:08:15:56:cf:bf:f1:2b:7c:5e:9a:76:e9:59:90:c5:7c:83:
+ 35:11:65:51
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIEOGPe+DANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
+RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
+bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
+IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0yOTA3
+MjQxNDE1MTJaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
+LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
+YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
+A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
+K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
+sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
+MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
+XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
+HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
+4QIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUVeSB0RGAvtiJuQijMfmhJAkWuXAwDQYJKoZIhvcNAQEFBQADggEBADub
+j1abMOdTmXx6eadNl9cZlZD7Bh/KM3xGY4+WZiT6QBshJ8rmcnPyT/4xmf3IDExo
+U8aAghOY+rat2l098c5u9hURlIIM7j+VrxGrD9cv3h8Dj1csHsm7mhpElesYT6Yf
+zX1XEC+bBAlahLVu2B064dae0Wx5XnkcFMXj0EyTO2U87d89vqbllRrDtRnDvV5b
+u/8j72gZyxKTJ1wDLW8w0B62GqzeWvfRqqgnpv55gcR5mTNXuhKwqeBCbJPKVt7+
+bYQLCIt+jerXmCHG8+c8eS9enNFMFY3h7CI3zJpDC5fcgJCNs2ebb0gIFVbPv/Er
+fF6adulZkMV8gzURZVE=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem
new file mode 100644
index 00000000000..07d8cff72ab
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem
@@ -0,0 +1,118 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee)
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = AffirmTrust, CN = AffirmTrust Premium
+ Validity
+ Not Before: Jan 29 14:10:36 2010 GMT
+ Not After : Dec 31 14:10:36 2040 GMT
+ Subject: C = US, O = AffirmTrust, CN = AffirmTrust Premium
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c4:12:df:a9:5f:fe:41:dd:dd:f5:9f:8a:e3:f6:
+ ac:e1:3c:78:9a:bc:d8:f0:7f:7a:a0:33:2a:dc:8d:
+ 20:5b:ae:2d:6f:e7:93:d9:36:70:6a:68:cf:8e:51:
+ a3:85:5b:67:04:a0:10:24:6f:5d:28:82:c1:97:57:
+ d8:48:29:13:b6:e1:be:91:4d:df:85:0c:53:18:9a:
+ 1e:24:a2:4f:8f:f0:a2:85:0b:cb:f4:29:7f:d2:a4:
+ 58:ee:26:4d:c9:aa:a8:7b:9a:d9:fa:38:de:44:57:
+ 15:e5:f8:8c:c8:d9:48:e2:0d:16:27:1d:1e:c8:83:
+ 85:25:b7:ba:aa:55:41:cc:03:22:4b:2d:91:8d:8b:
+ e6:89:af:66:c7:e9:ff:2b:e9:3c:ac:da:d2:b3:c3:
+ e1:68:9c:89:f8:7a:00:56:de:f4:55:95:6c:fb:ba:
+ 64:dd:62:8b:df:0b:77:32:eb:62:cc:26:9a:9b:bb:
+ aa:62:83:4c:b4:06:7a:30:c8:29:bf:ed:06:4d:97:
+ b9:1c:c4:31:2b:d5:5f:bc:53:12:17:9c:99:57:29:
+ 66:77:61:21:31:07:2e:25:49:9d:18:f2:ee:f3:2b:
+ 71:8c:b5:ba:39:07:49:77:fc:ef:2e:92:90:05:8d:
+ 2d:2f:77:7b:ef:43:bf:35:bb:9a:d8:f9:73:a7:2c:
+ f2:d0:57:ee:28:4e:26:5f:8f:90:68:09:2f:b8:f8:
+ dc:06:e9:2e:9a:3e:51:a7:d1:22:c4:0a:a7:38:48:
+ 6c:b3:f9:ff:7d:ab:86:57:e3:ba:d6:85:78:77:ba:
+ 43:ea:48:7f:f6:d8:be:23:6d:1e:bf:d1:36:6c:58:
+ 5c:f1:ee:a4:19:54:1a:f5:03:d2:76:e6:e1:8c:bd:
+ 3c:b3:d3:48:4b:e2:c8:f8:7f:92:a8:76:46:9c:42:
+ 65:3e:a4:1e:c1:07:03:5a:46:2d:b8:97:f3:b7:d5:
+ b2:55:21:ef:ba:dc:4c:00:97:fb:14:95:27:33:bf:
+ e8:43:47:46:d2:08:99:16:60:3b:9a:7e:d2:e6:ed:
+ 38:ea:ec:01:1e:3c:48:56:49:09:c7:4c:37:00:9e:
+ 88:0e:c0:73:e1:6f:66:e9:72:47:30:3e:10:e5:0b:
+ 03:c9:9a:42:00:6c:c5:94:7e:61:c4:8a:df:7f:82:
+ 1a:0b:59:c4:59:32:77:b3:bc:60:69:56:39:fd:b4:
+ 06:7b:2c:d6:64:36:d9:bd:48:ed:84:1f:7e:a5:22:
+ 8f:2a:b8:42:f4:82:b7:d4:53:90:78:4e:2d:1a:fd:
+ 81:6f:44:d7:3b:01:74:96:42:e0:00:e2:2e:6b:ea:
+ c5:ee:72:ac:bb:bf:fe:ea:aa:a8:f8:dc:f6:b2:79:
+ 8a:b6:67
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 9D:C0:67:A6:0C:22:D9:26:F5:45:AB:A6:65:52:11:27:D8:45:AC:63
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha384WithRSAEncryption
+ b3:57:4d:10:62:4e:3a:e4:ac:ea:b8:1c:af:32:23:c8:b3:49:
+ 5a:51:9c:76:28:8d:79:aa:57:46:17:d5:f5:52:f6:b7:44:e8:
+ 08:44:bf:18:84:d2:0b:80:cd:c5:12:fd:00:55:05:61:87:41:
+ dc:b5:24:9e:3c:c4:d8:c8:fb:70:9e:2f:78:96:83:20:36:de:
+ 7c:0f:69:13:88:a5:75:36:98:08:a6:c6:df:ac:ce:e3:58:d6:
+ b7:3e:de:ba:f3:eb:34:40:d8:a2:81:f5:78:3f:2f:d5:a5:fc:
+ d9:a2:d4:5e:04:0e:17:ad:fe:41:f0:e5:b2:72:fa:44:82:33:
+ 42:e8:2d:58:f7:56:8c:62:3f:ba:42:b0:9c:0c:5c:7e:2e:65:
+ 26:5c:53:4f:00:b2:78:7e:a1:0d:99:2d:8d:b8:1d:8e:a2:c4:
+ b0:fd:60:d0:30:a4:8e:c8:04:62:a9:c4:ed:35:de:7a:97:ed:
+ 0e:38:5e:92:2f:93:70:a5:a9:9c:6f:a7:7d:13:1d:7e:c6:08:
+ 48:b1:5e:67:eb:51:08:25:e9:e6:25:6b:52:29:91:9c:d2:39:
+ 73:08:57:de:99:06:b4:5b:9d:10:06:e1:c2:00:a8:b8:1c:4a:
+ 02:0a:14:d0:c1:41:ca:fb:8c:35:21:7d:82:38:f2:a9:54:91:
+ 19:35:93:94:6d:6a:3a:c5:b2:d0:bb:89:86:93:e8:9b:c9:0f:
+ 3a:a7:7a:b8:a1:f0:78:46:fa:fc:37:2f:e5:8a:84:f3:df:fe:
+ 04:d9:a1:68:a0:2f:24:e2:09:95:06:d5:95:ca:e1:24:96:eb:
+ 7c:f6:93:05:bb:ed:73:e9:2d:d1:75:39:d7:e7:24:db:d8:4e:
+ 5f:43:8f:9e:d0:14:39:bf:55:70:48:99:57:31:b4:9c:ee:4a:
+ 98:03:96:30:1f:60:06:ee:1b:23:fe:81:60:23:1a:47:62:85:
+ a5:cc:19:34:80:6f:b3:ac:1a:e3:9f:f0:7b:48:ad:d5:01:d9:
+ 67:b6:a9:72:93:ea:2d:66:b5:b2:b8:e4:3d:3c:b2:ef:4c:8c:
+ ea:eb:07:bf:ab:35:9a:55:86:bc:18:a6:b5:a8:5e:b4:83:6c:
+ 6b:69:40:d3:9f:dc:f1:c3:69:6b:b9:e1:6d:09:f4:f1:aa:50:
+ 76:0a:7a:7d:7a:17:a1:55:96:42:99:31:09:dd:60:11:8d:05:
+ 30:7e:e6:8e:46:d1:9d:14:da:c7:17:e4:05:96:8c:c4:24:b5:
+ 1b:cf:14:07:b2:40:f8:a3:9e:41:86:bc:04:d0:6b:96:c8:2a:
+ 80:34:fd:bf:ef:06:a3:dd:58:c5:85:3d:3e:8f:fe:9e:29:e0:
+ b6:b8:09:68:19:1c:18:43
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UE
+BhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVz
+dCBQcmVtaXVtMB4XDTEwMDEyOTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkG
+A1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1U
+cnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxBLf
+qV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtnBKAQ
+JG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ
++jjeRFcV5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrS
+s8PhaJyJ+HoAVt70VZVs+7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5
+HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmdGPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d7
+70O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5Rp9EixAqnOEhss/n/fauG
+V+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NIS+LI+H+S
+qHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S
+5u046uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4Ia
+C1nEWTJ3s7xgaVY5/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TX
+OwF0lkLgAOIua+rF7nKsu7/+6qqo+Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYE
+FJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByvMiPIs0laUZx2
+KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B
+8OWycvpEgjNC6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQ
+MKSOyARiqcTtNd56l+0OOF6SL5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc
+0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK+4w1IX2COPKpVJEZNZOUbWo6xbLQ
+u4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmVBtWVyuEklut89pMF
+u+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFgIxpH
+YoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8
+GKa1qF60g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaO
+RtGdFNrHF+QFlozEJLUbzxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6e
+KeC2uAloGRwYQw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem
new file mode 100644
index 00000000000..7b9eb25a5c4
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem
@@ -0,0 +1,51 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 6e:47:a9:c8:8b:94:b6:e8:bb:3b:2a:d8:a2:b2:c1:99
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R4
+ Validity
+ Not Before: Jun 22 00:00:00 2016 GMT
+ Not After : Jun 22 00:00:00 2036 GMT
+ Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R4
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:f3:74:73:a7:68:8b:60:ae:43:b8:35:c5:81:30:
+ 7b:4b:49:9d:fb:c1:61:ce:e6:de:46:bd:6b:d5:61:
+ 18:35:ae:40:dd:73:f7:89:91:30:5a:eb:3c:ee:85:
+ 7c:a2:40:76:3b:a9:c6:b8:47:d8:2a:e7:92:91:6a:
+ 73:e9:b1:72:39:9f:29:9f:a2:98:d3:5f:5e:58:86:
+ 65:0f:a1:84:65:06:d1:dc:8b:c9:c7:73:c8:8c:6a:
+ 2f:e5:c4:ab:d1:1d:8a
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 80:4C:D6:EB:74:FF:49:36:A3:D5:D8:FC:B5:3E:C5:6A:F0:94:1D:8C
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:6a:50:52:74:08:c4:70:dc:9e:50:74:21:e8:8d:
+ 7a:21:c3:4f:96:6e:15:d1:22:35:61:2d:fa:08:37:ee:19:6d:
+ ad:db:b2:cc:7d:07:34:f5:60:19:2c:b5:34:d9:6f:20:02:30:
+ 03:71:b1:ba:a3:60:0b:86:ed:9a:08:6a:95:68:9f:e2:b3:e1:
+ 93:64:7c:5e:93:a6:df:79:2d:8d:85:e3:94:cf:23:5d:71:cc:
+ f2:b0:4d:d6:fe:99:c8:94:a9:75:a2:e3
+-----BEGIN CERTIFICATE-----
+MIICCjCCAZGgAwIBAgIQbkepyIuUtui7OyrYorLBmTAKBggqhkjOPQQDAzBHMQsw
+CQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExMQzEU
+MBIGA1UEAxMLR1RTIFJvb3QgUjQwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIyMDAw
+MDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZp
+Y2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjQwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAATzdHOnaItgrkO4NcWBMHtLSZ37wWHO5t5GvWvVYRg1rkDdc/eJkTBa6zzu
+hXyiQHY7qca4R9gq55KRanPpsXI5nymfopjTX15YhmUPoYRlBtHci8nHc8iMai/l
+xKvRHYqjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
+DgQWBBSATNbrdP9JNqPV2Py1PsVq8JQdjDAKBggqhkjOPQQDAwNnADBkAjBqUFJ0
+CMRw3J5QdCHojXohw0+WbhXRIjVhLfoIN+4Zba3bssx9BzT1YBkstTTZbyACMANx
+sbqjYAuG7ZoIapVon+Kz4ZNkfF6Tpt95LY2F45TPI11xzPKwTdb+mciUqXWi4w==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem
new file mode 100644
index 00000000000..1ba9311177f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem
@@ -0,0 +1,90 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1164660820 (0x456b5054)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = "Entrust, Inc.", OU = www.entrust.net/CPS is incorporated by reference, OU = "(c) 2006 Entrust, Inc.", CN = Entrust Root Certification Authority
+ Validity
+ Not Before: Nov 27 20:23:42 2006 GMT
+ Not After : Nov 27 20:53:42 2026 GMT
+ Subject: C = US, O = "Entrust, Inc.", OU = www.entrust.net/CPS is incorporated by reference, OU = "(c) 2006 Entrust, Inc.", CN = Entrust Root Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b6:95:b6:43:42:fa:c6:6d:2a:6f:48:df:94:4c:
+ 39:57:05:ee:c3:79:11:41:68:36:ed:ec:fe:9a:01:
+ 8f:a1:38:28:fc:f7:10:46:66:2e:4d:1e:1a:b1:1a:
+ 4e:c6:d1:c0:95:88:b0:c9:ff:31:8b:33:03:db:b7:
+ 83:7b:3e:20:84:5e:ed:b2:56:28:a7:f8:e0:b9:40:
+ 71:37:c5:cb:47:0e:97:2a:68:c0:22:95:62:15:db:
+ 47:d9:f5:d0:2b:ff:82:4b:c9:ad:3e:de:4c:db:90:
+ 80:50:3f:09:8a:84:00:ec:30:0a:3d:18:cd:fb:fd:
+ 2a:59:9a:23:95:17:2c:45:9e:1f:6e:43:79:6d:0c:
+ 5c:98:fe:48:a7:c5:23:47:5c:5e:fd:6e:e7:1e:b4:
+ f6:68:45:d1:86:83:5b:a2:8a:8d:b1:e3:29:80:fe:
+ 25:71:88:ad:be:bc:8f:ac:52:96:4b:aa:51:8d:e4:
+ 13:31:19:e8:4e:4d:9f:db:ac:b3:6a:d5:bc:39:54:
+ 71:ca:7a:7a:7f:90:dd:7d:1d:80:d9:81:bb:59:26:
+ c2:11:fe:e6:93:e2:f7:80:e4:65:fb:34:37:0e:29:
+ 80:70:4d:af:38:86:2e:9e:7f:57:af:9e:17:ae:eb:
+ 1c:cb:28:21:5f:b6:1c:d8:e7:a2:04:22:f9:d3:da:
+ d8:cb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Private Key Usage Period:
+ Not Before: Nov 27 20:23:42 2006 GMT, Not After: Nov 27 20:53:42 2026 GMT
+ X509v3 Authority Key Identifier:
+ keyid:68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D
+
+ X509v3 Subject Key Identifier:
+ 68:90:E4:67:A4:A6:53:80:C7:86:66:A4:F1:F7:4B:43:FB:84:BD:6D
+ 1.2.840.113533.7.65.0:
+ 0...V7.1:4.0....
+ Signature Algorithm: sha1WithRSAEncryption
+ 93:d4:30:b0:d7:03:20:2a:d0:f9:63:e8:91:0c:05:20:a9:5f:
+ 19:ca:7b:72:4e:d4:b1:db:d0:96:fb:54:5a:19:2c:0c:08:f7:
+ b2:bc:85:a8:9d:7f:6d:3b:52:b3:2a:db:e7:d4:84:8c:63:f6:
+ 0f:cb:26:01:91:50:6c:f4:5f:14:e2:93:74:c0:13:9e:30:3a:
+ 50:e3:b4:60:c5:1c:f0:22:44:8d:71:47:ac:c8:1a:c9:e9:9b:
+ 9a:00:60:13:ff:70:7e:5f:11:4d:49:1b:b3:15:52:7b:c9:54:
+ da:bf:9d:95:af:6b:9a:d8:9e:e9:f1:e4:43:8d:e2:11:44:3a:
+ bf:af:bd:83:42:73:52:8b:aa:bb:a7:29:cf:f5:64:1c:0a:4d:
+ d1:bc:aa:ac:9f:2a:d0:ff:7f:7f:da:7d:ea:b1:ed:30:25:c1:
+ 84:da:34:d2:5b:78:83:56:ec:9c:36:c3:26:e2:11:f6:67:49:
+ 1d:92:ab:8c:fb:eb:ff:7a:ee:85:4a:a7:50:80:f0:a7:5c:4a:
+ 94:2e:5f:05:99:3c:52:41:e0:cd:b4:63:cf:01:43:ba:9c:83:
+ dc:8f:60:3b:f3:5a:b4:b4:7b:ae:da:0b:90:38:75:ef:81:1d:
+ 66:d2:f7:57:70:36:b3:bf:fc:28:af:71:25:85:5b:13:fe:1e:
+ 7f:5a:b4:3c
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
+Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
+KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
+NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
+NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
+ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
+BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
+Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
+4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
+KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
+rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
+94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
+sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
+gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
+kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
+vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
+O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
+AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
+9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
+eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
+0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem
new file mode 100644
index 00000000000..99291c53c24
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 02:ac:5c:26:6a:0b:40:9b:8f:0b:79:f2:ae:46:25:77
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
+ Validity
+ Not Before: Nov 10 00:00:00 2006 GMT
+ Not After : Nov 10 00:00:00 2031 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert High Assurance EV Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:c6:cc:e5:73:e6:fb:d4:bb:e5:2d:2d:32:a6:df:
+ e5:81:3f:c9:cd:25:49:b6:71:2a:c3:d5:94:34:67:
+ a2:0a:1c:b0:5f:69:a6:40:b1:c4:b7:b2:8f:d0:98:
+ a4:a9:41:59:3a:d3:dc:94:d6:3c:db:74:38:a4:4a:
+ cc:4d:25:82:f7:4a:a5:53:12:38:ee:f3:49:6d:71:
+ 91:7e:63:b6:ab:a6:5f:c3:a4:84:f8:4f:62:51:be:
+ f8:c5:ec:db:38:92:e3:06:e5:08:91:0c:c4:28:41:
+ 55:fb:cb:5a:89:15:7e:71:e8:35:bf:4d:72:09:3d:
+ be:3a:38:50:5b:77:31:1b:8d:b3:c7:24:45:9a:a7:
+ ac:6d:00:14:5a:04:b7:ba:13:eb:51:0a:98:41:41:
+ 22:4e:65:61:87:81:41:50:a6:79:5c:89:de:19:4a:
+ 57:d5:2e:e6:5d:1c:53:2c:7e:98:cd:1a:06:16:a4:
+ 68:73:d0:34:04:13:5c:a1:71:d3:5a:7c:55:db:5e:
+ 64:e1:37:87:30:56:04:e5:11:b4:29:80:12:f1:79:
+ 39:88:a2:02:11:7c:27:66:b7:88:b7:78:f2:ca:0a:
+ a8:38:ab:0a:64:c2:bf:66:5d:95:84:c1:a1:25:1e:
+ 87:5d:1a:50:0b:20:12:cc:41:bb:6e:0b:51:38:b8:
+ 4b:cb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
+ X509v3 Authority Key Identifier:
+ keyid:B1:3E:C3:69:03:F8:BF:47:01:D4:98:26:1A:08:02:EF:63:64:2B:C3
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 1c:1a:06:97:dc:d7:9c:9f:3c:88:66:06:08:57:21:db:21:47:
+ f8:2a:67:aa:bf:18:32:76:40:10:57:c1:8a:f3:7a:d9:11:65:
+ 8e:35:fa:9e:fc:45:b5:9e:d9:4c:31:4b:b8:91:e8:43:2c:8e:
+ b3:78:ce:db:e3:53:79:71:d6:e5:21:94:01:da:55:87:9a:24:
+ 64:f6:8a:66:cc:de:9c:37:cd:a8:34:b1:69:9b:23:c8:9e:78:
+ 22:2b:70:43:e3:55:47:31:61:19:ef:58:c5:85:2f:4e:30:f6:
+ a0:31:16:23:c8:e7:e2:65:16:33:cb:bf:1a:1b:a0:3d:f8:ca:
+ 5e:8b:31:8b:60:08:89:2d:0c:06:5c:52:b7:c4:f9:0a:98:d1:
+ 15:5f:9f:12:be:7c:36:63:38:bd:44:a4:7f:e4:26:2b:0a:c4:
+ 97:69:0d:e9:8c:e2:c0:10:57:b8:c8:76:12:91:55:f2:48:69:
+ d8:bc:2a:02:5b:0f:44:d4:20:31:db:f4:ba:70:26:5d:90:60:
+ 9e:bc:4b:17:09:2f:b4:cb:1e:43:68:c9:07:27:c1:d2:5c:f7:
+ ea:21:b9:68:12:9c:3c:9c:bf:9e:fc:80:5c:9b:63:cd:ec:47:
+ aa:25:27:67:a0:37:f3:00:82:7d:54:d7:a9:f8:e9:2e:13:a3:
+ 77:e8:1f:4a
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
+ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
+MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
+LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
+RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
++9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
+PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
+xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
+Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
+hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
+EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
+FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
+nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
+eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
+hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
+Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
++OkuE6N36B9K
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem
new file mode 100644
index 00000000000..9b467d7764e
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem
@@ -0,0 +1,75 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 29 (0x1d)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = FI, O = Sonera, CN = Sonera Class2 CA
+ Validity
+ Not Before: Apr 6 07:29:40 2001 GMT
+ Not After : Apr 6 07:29:40 2021 GMT
+ Subject: C = FI, O = Sonera, CN = Sonera Class2 CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:90:17:4a:35:9d:ca:f0:0d:96:c7:44:fa:16:37:
+ fc:48:bd:bd:7f:80:2d:35:3b:e1:6f:a8:67:a9:bf:
+ 03:1c:4d:8c:6f:32:47:d5:41:68:a4:13:04:c1:35:
+ 0c:9a:84:43:fc:5c:1d:ff:89:b3:e8:17:18:cd:91:
+ 5f:fb:89:e3:ea:bf:4e:5d:7c:1b:26:d3:75:79:ed:
+ e6:84:e3:57:e5:ad:29:c4:f4:3a:28:e7:a5:7b:84:
+ 36:69:b3:fd:5e:76:bd:a3:2d:99:d3:90:4e:23:28:
+ 7d:18:63:f1:54:3b:26:9d:76:5b:97:42:b2:ff:ae:
+ f0:4e:ec:dd:39:95:4e:83:06:7f:e7:49:40:c8:c5:
+ 01:b2:54:5a:66:1d:3d:fc:f9:e9:3c:0a:9e:81:b8:
+ 70:f0:01:8b:e4:23:54:7c:c8:ae:f8:90:1e:00:96:
+ 72:d4:54:cf:61:23:bc:ea:fb:9d:02:95:d1:b6:b9:
+ 71:3a:69:08:3f:0f:b4:e1:42:c7:88:f5:3f:98:a8:
+ a7:ba:1c:e0:71:71:ef:58:57:81:50:7a:5c:6b:74:
+ 46:0e:83:03:98:c3:8e:a8:6e:f2:76:32:6e:27:83:
+ c2:73:f3:dc:18:e8:b4:93:ea:75:44:6b:04:60:20:
+ 71:57:87:9d:f3:be:a0:90:23:3d:8a:24:e1:da:21:
+ db:c3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 4A:A0:AA:58:84:D3:5E:3C
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ 5a:ce:87:f9:16:72:15:57:4b:1d:d9:9b:e7:a2:26:30:ec:93:
+ 67:df:d6:2d:d2:34:af:f7:38:a5:ce:ab:16:b9:ab:2f:7c:35:
+ cb:ac:d0:0f:b4:4c:2b:fc:80:ef:6b:8c:91:5f:36:76:f7:db:
+ b3:1b:19:ea:f4:b2:11:fd:61:71:44:bf:28:b3:3a:1d:bf:b3:
+ 43:e8:9f:bf:dc:31:08:71:b0:9d:8d:d6:34:47:32:90:c6:65:
+ 24:f7:a0:4a:7c:04:73:8f:39:6f:17:8c:72:b5:bd:4b:c8:7a:
+ f8:7b:83:c3:28:4e:9c:09:ea:67:3f:b2:67:04:1b:c3:14:da:
+ f8:e7:49:24:91:d0:1d:6a:fa:61:39:ef:6b:e7:21:75:06:07:
+ d8:12:b4:21:20:70:42:71:81:da:3c:9a:36:be:a6:5b:0d:6a:
+ 6c:9a:1f:91:7b:f9:f9:ef:42:ba:4e:4e:9e:cc:0c:8d:94:dc:
+ d9:45:9c:5e:ec:42:50:63:ae:f4:5d:c4:b1:12:dc:ca:3b:a8:
+ 2e:9d:14:5a:05:75:b7:ec:d7:63:e2:ba:35:b6:04:08:91:e8:
+ da:9d:9c:f6:66:b5:18:ac:0a:a6:54:26:34:33:d2:1b:c1:d4:
+ 7f:1a:3a:8e:0b:aa:32:6e:db:fc:4f:25:9f:d9:32:c7:96:5a:
+ 70:ac:df:4c
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
+MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
+MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
+BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
+Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
+5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
+3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
+vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
+8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
+DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
+MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
+zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
+3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
+FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
+Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
+ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem
new file mode 100644
index 00000000000..41bdf8673d6
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0b:93:1c:3a:d6:39:67:ea:67:23:bf:c3:af:9a:f4:4b
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root G2
+ Validity
+ Not Before: Aug 1 12:00:00 2013 GMT
+ Not After : Jan 15 12:00:00 2038 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:d9:e7:28:2f:52:3f:36:72:49:88:93:34:f3:f8:
+ 6a:1e:31:54:80:9f:ad:54:41:b5:47:df:96:a8:d4:
+ af:80:2d:b9:0a:cf:75:fd:89:a5:7d:24:fa:e3:22:
+ 0c:2b:bc:95:17:0b:33:bf:19:4d:41:06:90:00:bd:
+ 0c:4d:10:fe:07:b5:e7:1c:6e:22:55:31:65:97:bd:
+ d3:17:d2:1e:62:f3:db:ea:6c:50:8c:3f:84:0c:96:
+ cf:b7:cb:03:e0:ca:6d:a1:14:4c:1b:89:dd:ed:00:
+ b0:52:7c:af:91:6c:b1:38:13:d1:e9:12:08:c0:00:
+ b0:1c:2b:11:da:77:70:36:9b:ae:ce:79:87:dc:82:
+ 70:e6:09:74:70:55:69:af:a3:68:9f:bf:dd:b6:79:
+ b3:f2:9d:70:29:55:f4:ab:ff:95:61:f3:c9:40:6f:
+ 1d:d1:be:93:bb:d3:88:2a:bb:9d:bf:72:5a:56:71:
+ 3b:3f:d4:f3:d1:0a:fe:28:ef:a3:ee:d9:99:af:03:
+ d3:8f:60:b7:f2:92:a1:b1:bd:89:89:1f:30:cd:c3:
+ a6:2e:62:33:ae:16:02:77:44:5a:e7:81:0a:3c:a7:
+ 44:2e:79:b8:3f:04:bc:5c:a0:87:e1:1b:af:51:8e:
+ cd:ec:2c:fa:f8:fe:6d:f0:3a:7c:aa:8b:e4:67:95:
+ 31:8d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ CE:C3:4A:B9:99:55:F2:B8:DB:60:BF:A9:7E:BD:56:B5:97:36:A7:D6
+ Signature Algorithm: sha256WithRSAEncryption
+ ca:a5:55:8c:e3:c8:41:6e:69:27:a7:75:11:ef:3c:86:36:6f:
+ d2:9d:c6:78:38:1d:69:96:a2:92:69:2e:38:6c:9b:7d:04:d4:
+ 89:a5:b1:31:37:8a:c9:21:cc:ab:6c:cd:8b:1c:9a:d6:bf:48:
+ d2:32:66:c1:8a:c0:f3:2f:3a:ef:c0:e3:d4:91:86:d1:50:e3:
+ 03:db:73:77:6f:4a:39:53:ed:de:26:c7:b5:7d:af:2b:42:d1:
+ 75:62:e3:4a:2b:02:c7:50:4b:e0:69:e2:96:6c:0e:44:66:10:
+ 44:8f:ad:05:eb:f8:79:ac:a6:1b:e8:37:34:9d:53:c9:61:aa:
+ a2:52:af:4a:70:16:86:c2:3a:c8:b1:13:70:36:d8:cf:ee:f4:
+ 0a:34:d5:5b:4c:fd:07:9c:a2:ba:d9:01:72:5c:f3:4d:c1:dd:
+ 0e:b1:1c:0d:c4:63:be:ad:f4:14:fb:89:ec:a2:41:0e:4c:cc:
+ c8:57:40:d0:6e:03:aa:cd:0c:8e:89:99:99:6c:f0:3c:30:af:
+ 38:df:6f:bc:a3:be:29:20:27:ab:74:ff:13:22:78:de:97:52:
+ 55:1e:83:b5:54:20:03:ee:ae:c0:4f:56:de:37:cc:c3:7f:aa:
+ 04:27:bb:d3:77:b8:62:db:17:7c:9c:28:22:13:73:6c:cf:26:
+ f5:8a:29:e7
+-----BEGIN CERTIFICATE-----
+MIIDljCCAn6gAwIBAgIQC5McOtY5Z+pnI7/Dr5r0SzANBgkqhkiG9w0BAQsFADBl
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
+b3QgRzIwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
+cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzIwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDZ5ygvUj82ckmIkzTz+GoeMVSA
+n61UQbVH35ao1K+ALbkKz3X9iaV9JPrjIgwrvJUXCzO/GU1BBpAAvQxNEP4Htecc
+biJVMWWXvdMX0h5i89vqbFCMP4QMls+3ywPgym2hFEwbid3tALBSfK+RbLE4E9Hp
+EgjAALAcKxHad3A2m67OeYfcgnDmCXRwVWmvo2ifv922ebPynXApVfSr/5Vh88lA
+bx3RvpO704gqu52/clpWcTs/1PPRCv4o76Pu2ZmvA9OPYLfykqGxvYmJHzDNw6Yu
+YjOuFgJ3RFrngQo8p0Quebg/BLxcoIfhG69Rjs3sLPr4/m3wOnyqi+RnlTGNAgMB
+AAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMB0GA1UdDgQW
+BBTOw0q5mVXyuNtgv6l+vVa1lzan1jANBgkqhkiG9w0BAQsFAAOCAQEAyqVVjOPI
+QW5pJ6d1Ee88hjZv0p3GeDgdaZaikmkuOGybfQTUiaWxMTeKySHMq2zNixya1r9I
+0jJmwYrA8y8678Dj1JGG0VDjA9tzd29KOVPt3ibHtX2vK0LRdWLjSisCx1BL4Gni
+lmwORGYQRI+tBev4eaymG+g3NJ1TyWGqolKvSnAWhsI6yLETcDbYz+70CjTVW0z9
+B5yiutkBclzzTcHdDrEcDcRjvq30FPuJ7KJBDkzMyFdA0G4Dqs0MjomZmWzwPDCv
+ON9vvKO+KSAnq3T/EyJ43pdSVR6DtVQgA+6uwE9W3jfMw3+qBCe703e4YtsXfJwo
+IhNzbM8m9Yop5w==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem
new file mode 100644
index 00000000000..5a8515c9f5c
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0b:a1:5a:fa:1d:df:a0:b5:49:44:af:cd:24:a0:6c:ec
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root G3
+ Validity
+ Not Before: Aug 1 12:00:00 2013 GMT
+ Not After : Jan 15 12:00:00 2038 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Assured ID Root G3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:19:e7:bc:ac:44:65:ed:cd:b8:3f:58:fb:8d:b1:
+ 57:a9:44:2d:05:15:f2:ef:0b:ff:10:74:9f:b5:62:
+ 52:5f:66:7e:1f:e5:dc:1b:45:79:0b:cc:c6:53:0a:
+ 9d:8d:5d:02:d9:a9:59:de:02:5a:f6:95:2a:0e:8d:
+ 38:4a:8a:49:c6:bc:c6:03:38:07:5f:55:da:7e:09:
+ 6e:e2:7f:5e:d0:45:20:0f:59:76:10:d6:a0:24:f0:
+ 2d:de:36:f2:6c:29:39
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ CB:D0:BD:A9:E1:98:05:51:A1:4D:37:A2:83:79:CE:8D:1D:2A:E4:84
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:25:a4:81:45:02:6b:12:4b:75:74:4f:c8:23:e3:
+ 70:f2:75:72:de:7c:89:f0:cf:91:72:61:9e:5e:10:92:59:56:
+ b9:83:c7:10:e7:38:e9:58:26:36:7d:d5:e4:34:86:39:02:30:
+ 7c:36:53:f0:30:e5:62:63:3a:99:e2:b6:a3:3b:9b:34:fa:1e:
+ da:10:92:71:5e:91:13:a7:dd:a4:6e:92:cc:32:d6:f5:21:66:
+ c7:2f:ea:96:63:6a:65:45:92:95:01:b4
+-----BEGIN CERTIFICATE-----
+MIICRjCCAc2gAwIBAgIQC6Fa+h3foLVJRK/NJKBs7DAKBggqhkjOPQQDAzBlMQsw
+CQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cu
+ZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3Qg
+RzMwHhcNMTMwODAxMTIwMDAwWhcNMzgwMTE1MTIwMDAwWjBlMQswCQYDVQQGEwJV
+UzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQu
+Y29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgRzMwdjAQBgcq
+hkjOPQIBBgUrgQQAIgNiAAQZ57ysRGXtzbg/WPuNsVepRC0FFfLvC/8QdJ+1YlJf
+Zn4f5dwbRXkLzMZTCp2NXQLZqVneAlr2lSoOjThKiknGvMYDOAdfVdp+CW7if17Q
+RSAPWXYQ1qAk8C3eNvJsKTmjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgGGMB0GA1UdDgQWBBTL0L2p4ZgFUaFNN6KDec6NHSrkhDAKBggqhkjOPQQD
+AwNnADBkAjAlpIFFAmsSS3V0T8gj43DydXLefInwz5FyYZ5eEJJZVrmDxxDnOOlY
+JjZ91eQ0hjkCMHw2U/Aw5WJjOpnitqM7mzT6HtoQknFekROn3aRukswy1vUhZscv
+6pZjamVFkpUBtA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem
new file mode 100644
index 00000000000..7f67e8e5069
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem
@@ -0,0 +1,55 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 21:2a:56:0c:ae:da:0c:ab:40:45:bf:2b:a2:2d:3a:ea
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = CH, O = WISeKey, OU = OISTE Foundation Endorsed, CN = OISTE WISeKey Global Root GC CA
+ Validity
+ Not Before: May 9 09:48:34 2017 GMT
+ Not After : May 9 09:58:33 2042 GMT
+ Subject: C = CH, O = WISeKey, OU = OISTE Foundation Endorsed, CN = OISTE WISeKey Global Root GC CA
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:4c:e9:50:c0:c6:0f:72:18:bc:d8:f1:ba:b3:89:
+ e2:79:4a:a3:16:a7:6b:54:24:db:51:ff:ea:f4:09:
+ 24:c3:0b:22:9f:cb:6a:27:82:81:0d:d2:c0:af:31:
+ e4:74:82:6e:ca:25:d9:8c:75:9d:f1:db:d0:9a:a2:
+ 4b:21:7e:16:a7:63:90:d2:39:d4:b1:87:78:5f:18:
+ 96:0f:50:1b:35:37:0f:6a:c6:dc:d9:13:4d:a4:8e:
+ 90:37:e6:bd:5b:31:91
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 48:87:14:AC:E3:C3:9E:90:60:3A:D7:CA:89:EE:D3:AD:8C:B4:50:66
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:30:26:c7:69:5b:dc:d5:e7:b2:e7:c8:0c:8c:8c:c3:
+ dd:79:8c:1b:63:d5:c9:52:94:4e:4d:82:4a:73:1e:b2:80:84:
+ a9:25:c0:4c:5a:6d:49:29:60:78:13:e2:7e:48:eb:64:02:31:
+ 00:db:34:20:32:08:ff:9a:49:02:b6:88:de:14:af:5d:6c:99:
+ 71:8d:1a:3f:8b:d7:e0:a2:36:86:1c:07:82:3a:76:53:fd:c2:
+ a2:ed:ef:7b:b0:80:4f:58:0f:4b:53:39:bd
+-----BEGIN CERTIFICATE-----
+MIICaTCCAe+gAwIBAgIQISpWDK7aDKtARb8roi066jAKBggqhkjOPQQDAzBtMQsw
+CQYDVQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEiMCAGA1UECxMZT0lTVEUgRm91
+bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwg
+Um9vdCBHQyBDQTAeFw0xNzA1MDkwOTQ4MzRaFw00MjA1MDkwOTU4MzNaMG0xCzAJ
+BgNVBAYTAkNIMRAwDgYDVQQKEwdXSVNlS2V5MSIwIAYDVQQLExlPSVNURSBGb3Vu
+ZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5IEdsb2JhbCBS
+b290IEdDIENBMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAETOlQwMYPchi82PG6s4ni
+eUqjFqdrVCTbUf/q9Akkwwsin8tqJ4KBDdLArzHkdIJuyiXZjHWd8dvQmqJLIX4W
+p2OQ0jnUsYd4XxiWD1AbNTcPasbc2RNNpI6QN+a9WzGRo1QwUjAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUSIcUrOPDnpBgOtfKie7T
+rYy0UGYwEAYJKwYBBAGCNxUBBAMCAQAwCgYIKoZIzj0EAwMDaAAwZQIwJsdpW9zV
+57LnyAyMjMPdeYwbY9XJUpROTYJKcx6ygISpJcBMWm1JKWB4E+J+SOtkAjEA2zQg
+Mgj/mkkCtojeFK9dbJlxjRo/i9fgojaGHAeCOnZT/cKi7e97sIBPWA9LUzm9
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem
new file mode 100644
index 00000000000..2831415fd3a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem
@@ -0,0 +1,124 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8875640296558310041 (0x7b2c9bd316803299)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com Root Certification Authority RSA
+ Validity
+ Not Before: Feb 12 17:39:39 2016 GMT
+ Not After : Feb 12 17:39:39 2041 GMT
+ Subject: C = US, ST = Texas, L = Houston, O = SSL Corporation, CN = SSL.com Root Certification Authority RSA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:f9:0f:dd:a3:2b:7d:cb:d0:2a:fe:ec:67:85:a6:
+ e7:2e:1b:ba:77:e1:e3:f5:af:a4:ec:fa:4a:5d:91:
+ c4:57:47:6b:18:77:6b:76:f2:fd:93:e4:3d:0f:c2:
+ 16:9e:0b:66:c3:56:94:9e:17:83:85:ce:56:ef:f2:
+ 16:fd:00:62:f5:22:09:54:e8:65:17:4e:41:b9:e0:
+ 4f:46:97:aa:1b:c8:b8:6e:62:5e:69:b1:5f:db:2a:
+ 02:7e:fc:6c:ca:f3:41:d8:ed:d0:e8:fc:3f:61:48:
+ ed:b0:03:14:1d:10:0e:4b:19:e0:bb:4e:ec:86:65:
+ ff:36:f3:5e:67:02:0b:9d:86:55:61:fd:7a:38:ed:
+ fe:e2:19:00:b7:6f:a1:50:62:75:74:3c:a0:fa:c8:
+ 25:92:b4:6e:7a:22:c7:f8:1e:a1:e3:b2:dd:91:31:
+ ab:2b:1d:04:ff:a5:4a:04:37:e9:85:a4:33:2b:fd:
+ e2:d6:55:34:7c:19:a4:4a:68:c7:b2:a8:d3:b7:ca:
+ a1:93:88:eb:c1:97:bc:8c:f9:1d:d9:22:84:24:74:
+ c7:04:3d:6a:a9:29:93:cc:eb:b8:5b:e1:fe:5f:25:
+ aa:34:58:c8:c1:23:54:9d:1b:98:11:c3:38:9c:7e:
+ 3d:86:6c:a5:0f:40:86:7c:02:f4:5c:02:4f:28:cb:
+ ae:71:9f:0f:3a:c8:33:fe:11:25:35:ea:fc:ba:c5:
+ 60:3d:d9:7c:18:d5:b2:a9:d3:75:78:03:72:22:ca:
+ 3a:c3:1f:ef:2c:e5:2e:a9:fa:9e:2c:b6:51:46:fd:
+ af:03:d6:ea:60:68:ea:85:16:36:6b:85:e9:1e:c0:
+ b3:dd:c4:24:dc:80:2a:81:41:6d:94:3e:c8:e0:c9:
+ 81:41:00:9e:5e:bf:7f:c5:08:98:a2:18:2c:42:40:
+ b3:f9:6f:38:27:4b:4e:80:f4:3d:81:47:e0:88:7c:
+ ea:1c:ce:b5:75:5c:51:2e:1c:2b:7f:1a:72:28:e7:
+ 00:b5:d1:74:c6:d7:e4:9f:ad:07:93:b6:53:35:35:
+ fc:37:e4:c3:f6:5d:16:be:21:73:de:92:0a:f8:a0:
+ 63:6a:bc:96:92:6a:3e:f8:bc:65:55:9b:de:f5:0d:
+ 89:26:04:fc:25:1a:a6:25:69:cb:c2:6d:ca:7c:e2:
+ 59:5f:97:ac:eb:ef:2e:c8:bc:d7:1b:59:3c:2b:cc:
+ f2:19:c8:93:6b:27:63:19:cf:fc:e9:26:f8:ca:71:
+ 9b:7f:93:fe:34:67:84:4e:99:eb:fc:b3:78:09:33:
+ 70:ba:66:a6:76:ed:1b:73:eb:1a:a5:0d:c4:22:13:
+ 20:94:56:0a:4e:2c:6c:4e:b1:fd:cf:9c:09:ba:a2:
+ 33:ed:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:DD:04:09:07:A2:F5:7A:7D:52:53:12:92:95:EE:38:80:25:0D:A6:59
+
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 20:18:11:94:29:fb:26:9d:1c:1e:1e:70:61:f1:95:72:93:71:
+ 24:ad:68:93:58:8e:32:af:1b:b3:70:03:fc:25:2b:74:85:90:
+ 3d:78:6a:f4:b9:8b:a5:97:3b:b5:18:91:bb:1e:a7:f9:40:5b:
+ 91:f9:55:99:af:1e:11:d0:5c:1d:a7:66:e3:b1:94:07:0c:32:
+ 39:a6:ea:1b:b0:79:d8:1d:9c:70:44:e3:8a:dd:c4:f9:95:1f:
+ 8a:38:43:3f:01:85:a5:47:a7:3d:46:b2:bc:e5:22:68:f7:7b:
+ 9c:d8:2c:3e:0a:21:c8:2d:33:ac:bf:c5:81:99:31:74:c1:75:
+ 71:c5:be:b1:f0:23:45:f4:9d:6b:fc:19:63:9d:a3:bc:04:c6:
+ 18:0b:25:bb:53:89:0f:b3:80:50:de:45:ee:44:7f:ab:94:78:
+ 64:98:d3:f6:28:dd:87:d8:70:65:74:fb:0e:b9:13:eb:a7:0f:
+ 61:a9:32:96:cc:de:bb:ed:63:4c:18:bb:a9:40:f7:a0:54:6e:
+ 20:88:71:75:18:ea:7a:b4:34:72:e0:23:27:77:5c:b6:90:ea:
+ 86:25:40:ab:ef:33:0f:cb:9f:82:be:a2:20:fb:f6:b5:2d:1a:
+ e6:c2:85:b1:74:0f:fb:c8:65:02:a4:52:01:47:dd:49:22:c1:
+ bf:d8:eb:6b:ac:7e:de:ec:63:33:15:b7:23:08:8f:c6:0f:8d:
+ 41:5a:dd:8e:c5:b9:8f:e5:45:3f:78:db:ba:d2:1b:40:b1:fe:
+ 71:4d:3f:e0:81:a2:ba:5e:b4:ec:15:e0:93:dd:08:1f:7e:e1:
+ 55:99:0b:21:de:93:9e:0a:fb:e6:a3:49:bd:36:30:fe:e7:77:
+ b2:a0:75:97:b5:2d:81:88:17:65:20:f7:da:90:00:9f:c9:52:
+ cc:32:ca:35:7c:f5:3d:0f:d8:2b:d7:f5:26:6c:c9:06:34:96:
+ 16:ea:70:59:1a:32:79:79:0b:b6:88:7f:0f:52:48:3d:bf:6c:
+ d8:a2:44:2e:d1:4e:b7:72:58:d3:89:13:95:fe:44:ab:f8:d7:
+ 8b:1b:6e:9c:bc:2c:a0:5b:d5:6a:00:af:5f:37:e1:d5:fa:10:
+ 0b:98:9c:86:e7:26:8f:ce:f0:ec:6e:8a:57:0b:80:e3:4e:b2:
+ c0:a0:63:61:90:ba:55:68:37:74:6a:b6:92:db:9f:a1:86:22:
+ b6:65:27:0e:ec:b6:9f:42:60:e4:67:c2:b5:da:41:0b:c4:d3:
+ 8b:61:1b:bc:fa:1f:91:2b:d7:44:07:5e:ba:29:ac:d9:c5:e9:
+ ef:53:48:5a:eb:80:f1:28:58:21:cd:b0:06:55:fb:27:3f:53:
+ 90:70:a9:04:1e:57:27:b9
+-----BEGIN CERTIFICATE-----
+MIIF3TCCA8WgAwIBAgIIeyyb0xaAMpkwDQYJKoZIhvcNAQELBQAwfDELMAkGA1UE
+BhMCVVMxDjAMBgNVBAgMBVRleGFzMRAwDgYDVQQHDAdIb3VzdG9uMRgwFgYDVQQK
+DA9TU0wgQ29ycG9yYXRpb24xMTAvBgNVBAMMKFNTTC5jb20gUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSBSU0EwHhcNMTYwMjEyMTczOTM5WhcNNDEwMjEyMTcz
+OTM5WjB8MQswCQYDVQQGEwJVUzEOMAwGA1UECAwFVGV4YXMxEDAOBgNVBAcMB0hv
+dXN0b24xGDAWBgNVBAoMD1NTTCBDb3Jwb3JhdGlvbjExMC8GA1UEAwwoU1NMLmNv
+bSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFJTQTCCAiIwDQYJKoZIhvcN
+AQEBBQADggIPADCCAgoCggIBAPkP3aMrfcvQKv7sZ4Wm5y4bunfh4/WvpOz6Sl2R
+xFdHaxh3a3by/ZPkPQ/CFp4LZsNWlJ4Xg4XOVu/yFv0AYvUiCVToZRdOQbngT0aX
+qhvIuG5iXmmxX9sqAn78bMrzQdjt0Oj8P2FI7bADFB0QDksZ4LtO7IZl/zbzXmcC
+C52GVWH9ejjt/uIZALdvoVBidXQ8oPrIJZK0bnoix/geoeOy3ZExqysdBP+lSgQ3
+6YWkMyv94tZVNHwZpEpox7Ko07fKoZOI68GXvIz5HdkihCR0xwQ9aqkpk8zruFvh
+/l8lqjRYyMEjVJ0bmBHDOJx+PYZspQ9AhnwC9FwCTyjLrnGfDzrIM/4RJTXq/LrF
+YD3ZfBjVsqnTdXgDciLKOsMf7yzlLqn6niy2UUb9rwPW6mBo6oUWNmuF6R7As93E
+JNyAKoFBbZQ+yODJgUEAnl6/f8UImKIYLEJAs/lvOCdLToD0PYFH4Ih86hzOtXVc
+US4cK38acijnALXRdMbX5J+tB5O2UzU1/Dfkw/ZdFr4hc96SCvigY2q8lpJqPvi8
+ZVWb3vUNiSYE/CUapiVpy8JtynziWV+XrOvvLsi81xtZPCvM8hnIk2snYxnP/Okm
++Mpxm3+T/jRnhE6Z6/yzeAkzcLpmpnbtG3PrGqUNxCITIJRWCk4sbE6x/c+cCbqi
+M+2HAgMBAAGjYzBhMB0GA1UdDgQWBBTdBAkHovV6fVJTEpKV7jiAJQ2mWTAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFN0ECQei9Xp9UlMSkpXuOIAlDaZZMA4G
+A1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAIBgRlCn7Jp0cHh5wYfGV
+cpNxJK1ok1iOMq8bs3AD/CUrdIWQPXhq9LmLpZc7tRiRux6n+UBbkflVma8eEdBc
+Hadm47GUBwwyOabqG7B52B2ccETjit3E+ZUfijhDPwGFpUenPUayvOUiaPd7nNgs
+PgohyC0zrL/FgZkxdMF1ccW+sfAjRfSda/wZY52jvATGGAslu1OJD7OAUN5F7kR/
+q5R4ZJjT9ijdh9hwZXT7DrkT66cPYakylszeu+1jTBi7qUD3oFRuIIhxdRjqerQ0
+cuAjJ3dctpDqhiVAq+8zD8ufgr6iIPv2tS0a5sKFsXQP+8hlAqRSAUfdSSLBv9jr
+a6x+3uxjMxW3IwiPxg+NQVrdjsW5j+VFP3jbutIbQLH+cU0/4IGiul607BXgk90I
+H37hVZkLId6Tngr75qNJvTYw/ud3sqB1l7UtgYgXZSD32pAAn8lSzDLKNXz1PQ/Y
+K9f1JmzJBjSWFupwWRoyeXkLtoh/D1JIPb9s2KJELtFOt3JY04kTlf5Eq/jXixtu
+nLwsoFvVagCvXzfh1foQC5ichucmj87w7G6KVwuA406ywKBjYZC6VWg3dGq2ktuf
+oYYitmUnDuy2n0Jg5GfCtdpBC8TTi2EbvPofkSvXRAdeuims2cXp71NIWuuA8ShY
+Ic2wBlX7Jz9TkHCpBB5XJ7k=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem
new file mode 100644
index 00000000000..c7b52d7b80c
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem
@@ -0,0 +1,125 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1289 (0x509)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
+ Validity
+ Not Before: Nov 24 18:27:00 2006 GMT
+ Not After : Nov 24 18:23:33 2031 GMT
+ Subject: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:9a:18:ca:4b:94:0d:00:2d:af:03:29:8a:f0:0f:
+ 81:c8:ae:4c:19:85:1d:08:9f:ab:29:44:85:f3:2f:
+ 81:ad:32:1e:90:46:bf:a3:86:26:1a:1e:fe:7e:1c:
+ 18:3a:5c:9c:60:17:2a:3a:74:83:33:30:7d:61:54:
+ 11:cb:ed:ab:e0:e6:d2:a2:7e:f5:6b:6f:18:b7:0a:
+ 0b:2d:fd:e9:3e:ef:0a:c6:b3:10:e9:dc:c2:46:17:
+ f8:5d:fd:a4:da:ff:9e:49:5a:9c:e6:33:e6:24:96:
+ f7:3f:ba:5b:2b:1c:7a:35:c2:d6:67:fe:ab:66:50:
+ 8b:6d:28:60:2b:ef:d7:60:c3:c7:93:bc:8d:36:91:
+ f3:7f:f8:db:11:13:c4:9c:77:76:c1:ae:b7:02:6a:
+ 81:7a:a9:45:83:e2:05:e6:b9:56:c1:94:37:8f:48:
+ 71:63:22:ec:17:65:07:95:8a:4b:df:8f:c6:5a:0a:
+ e5:b0:e3:5f:5e:6b:11:ab:0c:f9:85:eb:44:e9:f8:
+ 04:73:f2:e9:fe:5c:98:8c:f5:73:af:6b:b4:7e:cd:
+ d4:5c:02:2b:4c:39:e1:b2:95:95:2d:42:87:d7:d5:
+ b3:90:43:b7:6c:13:f1:de:dd:f6:c4:f8:89:3f:d1:
+ 75:f5:92:c3:91:d5:8a:88:d0:90:ec:dc:6d:de:89:
+ c2:65:71:96:8b:0d:03:fd:9c:bf:5b:16:ac:92:db:
+ ea:fe:79:7c:ad:eb:af:f7:16:cb:db:cd:25:2b:e5:
+ 1f:fb:9a:9f:e2:51:cc:3a:53:0c:48:e6:0e:bd:c9:
+ b4:76:06:52:e6:11:13:85:72:63:03:04:e0:04:36:
+ 2b:20:19:02:e8:74:a7:1f:b6:c9:56:66:f0:75:25:
+ dc:67:c1:0e:61:60:88:b3:3e:d1:a8:fc:a3:da:1d:
+ b0:d1:b1:23:54:df:44:76:6d:ed:41:d8:c1:b2:22:
+ b6:53:1c:df:35:1d:dc:a1:77:2a:31:e4:2d:f5:e5:
+ e5:db:c8:e0:ff:e5:80:d7:0b:63:a0:ff:33:a1:0f:
+ ba:2c:15:15:ea:97:b3:d2:a2:b5:be:f2:8c:96:1e:
+ 1a:8f:1d:6c:a4:61:37:b9:86:73:33:d7:97:96:9e:
+ 23:7d:82:a4:4c:81:e2:a1:d1:ba:67:5f:95:07:a3:
+ 27:11:ee:16:10:7b:bc:45:4a:4c:b2:04:d2:ab:ef:
+ d5:fd:0c:51:ce:50:6a:08:31:f9:91:da:0c:8f:64:
+ 5c:03:c3:3a:8b:20:3f:6e:8d:67:3d:3a:d6:fe:7d:
+ 5b:88:c9:5e:fb:cc:61:dc:8b:33:77:d3:44:32:35:
+ 09:62:04:92:16:10:d8:9e:27:47:fb:3b:21:e3:f8:
+ eb:1d:5b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B
+ X509v3 Authority Key Identifier:
+ keyid:1A:84:62:BC:48:4C:33:25:04:D4:EE:D0:F6:03:C4:19:46:D1:94:6B
+ DirName:/C=BM/O=QuoVadis Limited/CN=QuoVadis Root CA 2
+ serial:05:09
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 3e:0a:16:4d:9f:06:5b:a8:ae:71:5d:2f:05:2f:67:e6:13:45:
+ 83:c4:36:f6:f3:c0:26:0c:0d:b5:47:64:5d:f8:b4:72:c9:46:
+ a5:03:18:27:55:89:78:7d:76:ea:96:34:80:17:20:dc:e7:83:
+ f8:8d:fc:07:b8:da:5f:4d:2e:67:b2:84:fd:d9:44:fc:77:50:
+ 81:e6:7c:b4:c9:0d:0b:72:53:f8:76:07:07:41:47:96:0c:fb:
+ e0:82:26:93:55:8c:fe:22:1f:60:65:7c:5f:e7:26:b3:f7:32:
+ 90:98:50:d4:37:71:55:f6:92:21:78:f7:95:79:fa:f8:2d:26:
+ 87:66:56:30:77:a6:37:78:33:52:10:58:ae:3f:61:8e:f2:6a:
+ b1:ef:18:7e:4a:59:63:ca:8d:a2:56:d5:a7:2f:bc:56:1f:cf:
+ 39:c1:e2:fb:0a:a8:15:2c:7d:4d:7a:63:c6:6c:97:44:3c:d2:
+ 6f:c3:4a:17:0a:f8:90:d2:57:a2:19:51:a5:2d:97:41:da:07:
+ 4f:a9:50:da:90:8d:94:46:e1:3e:f0:94:fd:10:00:38:f5:3b:
+ e8:40:e1:b4:6e:56:1a:20:cc:6f:58:8d:ed:2e:45:8f:d6:e9:
+ 93:3f:e7:b1:2c:df:3a:d6:22:8c:dc:84:bb:22:6f:d0:f8:e4:
+ c6:39:e9:04:88:3c:c3:ba:eb:55:7a:6d:80:99:24:f5:6c:01:
+ fb:f8:97:b0:94:5b:eb:fd:d2:6f:f1:77:68:0d:35:64:23:ac:
+ b8:55:a1:03:d1:4d:42:19:dc:f8:75:59:56:a3:f9:a8:49:79:
+ f8:af:0e:b9:11:a0:7c:b7:6a:ed:34:d0:b6:26:62:38:1a:87:
+ 0c:f8:e8:fd:2e:d3:90:7f:07:91:2a:1d:d6:7e:5c:85:83:99:
+ b0:38:08:3f:e9:5e:f9:35:07:e4:c9:62:6e:57:7f:a7:50:95:
+ f7:ba:c8:9b:e6:8e:a2:01:c5:d6:66:bf:79:61:f3:3c:1c:e1:
+ b9:82:5c:5d:a0:c3:e9:d8:48:bd:19:a2:11:14:19:6e:b2:86:
+ 1b:68:3e:48:37:1a:88:b7:5d:96:5e:9c:c7:ef:27:62:08:e2:
+ 91:19:5c:d2:f1:21:dd:ba:17:42:82:97:71:81:53:31:a9:9f:
+ f6:7d:62:bf:72:e1:a3:93:1d:cc:8a:26:5a:09:38:d0:ce:d7:
+ 0d:80:16:b4:78:a5:3a:87:4c:8d:8a:a5:d5:46:97:f2:2c:10:
+ b9:bc:54:22:c0:01:50:69:43:9e:f4:b2:ef:6d:f8:ec:da:f1:
+ e3:b1:ef:df:91:8f:54:2a:0b:25:c1:26:19:c4:52:10:05:65:
+ d5:82:10:ea:c2:31:cd:2e
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
+GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
+b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
+BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
+YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
+GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
+Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
+WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
+rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
++ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
+ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
+Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
+PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
+/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
+oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
+yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
+EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
+A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
+MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
+BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
+g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
+fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
+WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
+B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
+hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
+TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
+mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
+ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
+4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
+8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem
new file mode 100644
index 00000000000..deef6cb8014
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem
@@ -0,0 +1,53 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 3c:f6:07:a9:68:70:0e:da:8b:84
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = IN, OU = emSign PKI, O = eMudhra Technologies Limited, CN = emSign ECC Root CA - G3
+ Validity
+ Not Before: Feb 18 18:30:00 2018 GMT
+ Not After : Feb 18 18:30:00 2043 GMT
+ Subject: C = IN, OU = emSign PKI, O = eMudhra Technologies Limited, CN = emSign ECC Root CA - G3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:23:a5:0c:b8:2d:12:f5:28:f3:b1:b2:dd:e2:02:
+ 12:80:9e:39:5f:49:4d:9f:c9:25:34:59:74:ec:bb:
+ 06:1c:e7:c0:72:af:e8:ae:2f:e1:41:54:87:14:a8:
+ 4a:b2:e8:7c:82:e6:5b:6a:b5:dc:b3:75:ce:8b:06:
+ d0:86:23:bf:46:d5:8e:0f:3f:04:f4:d7:1c:92:7e:
+ f6:a5:63:c2:f5:5f:8e:2e:4f:a1:18:19:02:2b:32:
+ 0a:82:64:7d:16:93:d1
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 7C:5D:02:84:13:D4:CC:8A:9B:81:CE:17:1C:2E:29:1E:9C:48:63:42
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:66:02:31:00:be:f3:61:cf:02:10:1d:64:95:07:b8:18:6e:
+ 88:85:05:2f:83:08:17:90:ca:1f:8a:4c:e8:0d:1b:7a:b1:ad:
+ d5:81:09:47:ef:3b:ac:08:04:7c:5c:99:b1:ed:47:07:d2:02:
+ 31:00:9d:ba:55:fc:a9:4a:e8:ed:ed:e6:76:01:42:7b:c8:f8:
+ 60:d9:8d:51:8b:55:3b:fb:8c:7b:eb:65:09:c3:f8:96:cd:47:
+ a8:82:f2:16:55:77:24:7e:12:10:95:04:2c:a3
+-----BEGIN CERTIFICATE-----
+MIICTjCCAdOgAwIBAgIKPPYHqWhwDtqLhDAKBggqhkjOPQQDAzBrMQswCQYDVQQG
+EwJJTjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNo
+bm9sb2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0g
+RzMwHhcNMTgwMjE4MTgzMDAwWhcNNDMwMjE4MTgzMDAwWjBrMQswCQYDVQQGEwJJ
+TjETMBEGA1UECxMKZW1TaWduIFBLSTElMCMGA1UEChMcZU11ZGhyYSBUZWNobm9s
+b2dpZXMgTGltaXRlZDEgMB4GA1UEAxMXZW1TaWduIEVDQyBSb290IENBIC0gRzMw
+djAQBgcqhkjOPQIBBgUrgQQAIgNiAAQjpQy4LRL1KPOxst3iAhKAnjlfSU2fySU0
+WXTsuwYc58Byr+iuL+FBVIcUqEqy6HyC5ltqtdyzdc6LBtCGI79G1Y4PPwT01xyS
+fvalY8L1X44uT6EYGQIrMgqCZH0Wk9GjQjBAMB0GA1UdDgQWBBR8XQKEE9TMipuB
+zhccLikenEhjQjAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggq
+hkjOPQQDAwNpADBmAjEAvvNhzwIQHWSVB7gYboiFBS+DCBeQyh+KTOgNG3qxrdWB
+CUfvO6wIBHxcmbHtRwfSAjEAnbpV/KlK6O3t5nYBQnvI+GDZjVGLVTv7jHvrZQnD
++JbNR6iC8hZVdyR+EhCVBCyj
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem
new file mode 100644
index 00000000000..0a7dcd039c4
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 2e:f5:9b:02:28:a7:db:7a:ff:d5:a3:a9:ee:bd:03:a0:cf:12:6a:1d
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 3 G3
+ Validity
+ Not Before: Jan 12 20:26:32 2012 GMT
+ Not After : Jan 12 20:26:32 2042 GMT
+ Subject: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 3 G3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b3:cb:0e:10:67:8e:ea:14:97:a7:32:2a:0a:56:
+ 36:7f:68:4c:c7:b3:6f:3a:23:14:91:ff:19:7f:a5:
+ ca:ac:ee:b3:76:9d:7a:e9:8b:1b:ab:6b:31:db:fa:
+ 0b:53:4c:af:c5:a5:1a:79:3c:8a:4c:ff:ac:df:25:
+ de:4e:d9:82:32:0b:44:de:ca:db:8c:ac:a3:6e:16:
+ 83:3b:a6:64:4b:32:89:fb:16:16:38:7e:eb:43:e2:
+ d3:74:4a:c2:62:0a:73:0a:dd:49:b3:57:d2:b0:0a:
+ 85:9d:71:3c:de:a3:cb:c0:32:f3:01:39:20:43:1b:
+ 35:d1:53:b3:b1:ee:c5:93:69:82:3e:16:b5:28:46:
+ a1:de:ea:89:09:ed:43:b8:05:46:8a:86:f5:59:47:
+ be:1b:6f:01:21:10:b9:fd:a9:d2:28:ca:10:39:09:
+ ca:13:36:cf:9c:ad:ad:40:74:79:2b:02:3f:34:ff:
+ fa:20:69:7d:d3:ee:61:f5:ba:b3:e7:30:d0:37:23:
+ 86:72:61:45:29:48:59:68:6f:77:a6:2e:81:be:07:
+ 4d:6f:af:ce:c4:45:13:91:14:70:06:8f:1f:9f:f8:
+ 87:69:b1:0e:ef:c3:89:19:eb:ea:1c:61:fc:7a:6c:
+ 8a:dc:d6:03:0b:9e:26:ba:12:dd:d4:54:39:ab:26:
+ a3:33:ea:75:81:da:2d:cd:0f:4f:e4:03:d1:ef:15:
+ 97:1b:6b:90:c5:02:90:93:66:02:21:b1:47:de:8b:
+ 9a:4a:80:b9:55:8f:b5:a2:2f:c0:d6:33:67:da:7e:
+ c4:a7:b4:04:44:eb:47:fb:e6:58:b9:f7:0c:f0:7b:
+ 2b:b1:c0:70:29:c3:40:62:2d:3b:48:69:dc:23:3c:
+ 48:eb:7b:09:79:a9:6d:da:a8:30:98:cf:80:72:03:
+ 88:a6:5b:46:ae:72:79:7c:08:03:21:65:ae:b7:e1:
+ 1c:a5:b1:2a:a2:31:de:66:04:f7:c0:74:e8:71:de:
+ ff:3d:59:cc:96:26:12:8b:85:95:57:1a:ab:6b:75:
+ 0b:44:3d:11:28:3c:7b:61:b7:e2:8f:67:4f:e5:ec:
+ 3c:4c:60:80:69:57:38:1e:01:5b:8d:55:e8:c7:df:
+ c0:cc:77:23:34:49:75:7c:f6:98:11:eb:2d:de:ed:
+ 41:2e:14:05:02:7f:e0:fe:20:eb:35:e7:11:ac:22:
+ ce:57:3d:de:c9:30:6d:10:03:85:cd:f1:ff:8c:16:
+ b5:c1:b2:3e:88:6c:60:7f:90:4f:95:f7:f6:2d:ad:
+ 01:39:07:04:fa:75:80:7d:bf:49:50:ed:ef:c9:c4:
+ 7c:1c:eb:80:7e:db:b6:d0:dd:13:fe:c9:d3:9c:d7:
+ b2:97:a9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ C6:17:D0:BC:A8:EA:02:43:F2:1B:06:99:5D:2B:90:20:B9:D7:9C:E4
+ Signature Algorithm: sha256WithRSAEncryption
+ 34:61:d9:56:b5:12:87:55:4d:dd:a3:35:31:46:bb:a4:07:72:
+ bc:5f:61:62:e8:a5:fb:0b:37:b1:3c:b6:b3:fa:29:9d:7f:02:
+ f5:a4:c9:a8:93:b7:7a:71:28:69:8f:73:e1:52:90:da:d5:be:
+ 3a:e5:b7:76:6a:56:80:21:df:5d:e6:e9:3a:9e:e5:3e:f6:a2:
+ 69:c7:2a:0a:b0:18:47:dc:20:70:7d:52:a3:3e:59:7c:c1:ba:
+ c9:c8:15:40:61:ca:72:d6:70:ac:d2:b7:f0:1c:e4:86:29:f0:
+ ce:ef:68:63:d0:b5:20:8a:15:61:9a:7e:86:98:b4:c9:c2:76:
+ fb:cc:ba:30:16:cc:a3:61:c6:74:13:e5:6b:ef:a3:15:ea:03:
+ fe:13:8b:64:e4:d3:c1:d2:e8:84:fb:49:d1:10:4d:79:66:eb:
+ aa:fd:f4:8d:31:1e:70:14:ad:dc:de:67:13:4c:81:15:61:bc:
+ b7:d9:91:77:71:19:81:60:bb:f0:58:a5:b5:9c:0b:f7:8f:22:
+ 55:27:c0:4b:01:6d:3b:99:0d:d4:1d:9b:63:67:2f:d0:ee:0d:
+ ca:66:bc:94:4f:a6:ad:ed:fc:ee:63:ac:57:3f:65:25:cf:b2:
+ 86:8f:d0:08:ff:b8:76:14:6e:de:e5:27:ec:ab:78:b5:53:b9:
+ b6:3f:e8:20:f9:d2:a8:be:61:46:ca:87:8c:84:f3:f9:f1:a0:
+ 68:9b:22:1e:81:26:9b:10:04:91:71:c0:06:1f:dc:a0:d3:b9:
+ 56:a7:e3:98:2d:7f:83:9d:df:8c:2b:9c:32:8e:32:94:f0:01:
+ 3c:22:2a:9f:43:c2:2e:c3:98:39:07:38:7b:fc:5e:00:42:1f:
+ f3:32:26:79:83:84:f6:e5:f0:c1:51:12:c0:0b:1e:04:23:0c:
+ 54:a5:4c:2f:49:c5:4a:d1:b6:6e:60:0d:6b:fc:6b:8b:85:24:
+ 64:b7:89:0e:ab:25:47:5b:3c:cf:7e:49:bd:c7:e9:0a:c6:da:
+ f7:7e:0e:17:08:d3:48:97:d0:71:92:f0:0f:39:3e:34:6a:1c:
+ 7d:d8:f2:22:ae:bb:69:f4:33:b4:a6:48:55:d1:0f:0e:26:e8:
+ ec:b6:0b:2d:a7:85:35:cd:fd:59:c8:9f:d1:cd:3e:5a:29:34:
+ b9:3d:84:ce:b1:65:d4:59:91:91:56:75:21:c1:77:9e:f9:7a:
+ e1:60:9d:d3:ad:04:18:f4:7c:eb:5e:93:8f:53:4a:22:29:f8:
+ 48:2b:3e:4d:86:ac:5b:7f:cb:06:99:59:60:d8:58:65:95:8d:
+ 44:d1:f7:7f:7e:27:7f:7d:ae:80:f5:07:4c:b6:3e:9c:71:54:
+ 99:04:4b:fd:58:f9:98:f4
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIULvWbAiin23r/1aOp7r0DoM8Sah0wDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMyBHMzAeFw0xMjAxMTIyMDI2MzJaFw00
+MjAxMTIyMDI2MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDMgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCzyw4QZ47qFJenMioKVjZ/aEzHs286IxSR
+/xl/pcqs7rN2nXrpixurazHb+gtTTK/FpRp5PIpM/6zfJd5O2YIyC0TeytuMrKNu
+FoM7pmRLMon7FhY4futD4tN0SsJiCnMK3UmzV9KwCoWdcTzeo8vAMvMBOSBDGzXR
+U7Ox7sWTaYI+FrUoRqHe6okJ7UO4BUaKhvVZR74bbwEhELn9qdIoyhA5CcoTNs+c
+ra1AdHkrAj80//ogaX3T7mH1urPnMNA3I4ZyYUUpSFlob3emLoG+B01vr87ERROR
+FHAGjx+f+IdpsQ7vw4kZ6+ocYfx6bIrc1gMLnia6Et3UVDmrJqMz6nWB2i3ND0/k
+A9HvFZcba5DFApCTZgIhsUfei5pKgLlVj7WiL8DWM2fafsSntARE60f75li59wzw
+eyuxwHApw0BiLTtIadwjPEjrewl5qW3aqDCYz4ByA4imW0aucnl8CAMhZa634Ryl
+sSqiMd5mBPfAdOhx3v89WcyWJhKLhZVXGqtrdQtEPREoPHtht+KPZ0/l7DxMYIBp
+VzgeAVuNVejH38DMdyM0SXV89pgR6y3e7UEuFAUCf+D+IOs15xGsIs5XPd7JMG0Q
+A4XN8f+MFrXBsj6IbGB/kE+V9/YtrQE5BwT6dYB9v0lQ7e/JxHwc64B+27bQ3RP+
+ydOc17KXqQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUxhfQvKjqAkPyGwaZXSuQILnXnOQwDQYJKoZIhvcNAQELBQAD
+ggIBADRh2Va1EodVTd2jNTFGu6QHcrxfYWLopfsLN7E8trP6KZ1/AvWkyaiTt3px
+KGmPc+FSkNrVvjrlt3ZqVoAh313m6Tqe5T72omnHKgqwGEfcIHB9UqM+WXzBusnI
+FUBhynLWcKzSt/Ac5IYp8M7vaGPQtSCKFWGafoaYtMnCdvvMujAWzKNhxnQT5Wvv
+oxXqA/4Ti2Tk08HS6IT7SdEQTXlm66r99I0xHnAUrdzeZxNMgRVhvLfZkXdxGYFg
+u/BYpbWcC/ePIlUnwEsBbTuZDdQdm2NnL9DuDcpmvJRPpq3t/O5jrFc/ZSXPsoaP
+0Aj/uHYUbt7lJ+yreLVTubY/6CD50qi+YUbKh4yE8/nxoGibIh6BJpsQBJFxwAYf
+3KDTuVan45gtf4Od34wrnDKOMpTwATwiKp9Dwi7DmDkHOHv8XgBCH/MyJnmDhPbl
+8MFREsALHgQjDFSlTC9JxUrRtm5gDWv8a4uFJGS3iQ6rJUdbPM9+Sb3H6QrG2vd+
+DhcI00iX0HGS8A85PjRqHH3Y8iKuu2n0M7SmSFXRDw4m6Oy2Cy2nhTXN/VnIn9HN
+PlopNLk9hM6xZdRZkZFWdSHBd575euFgndOtBBj0fOtek49TSiIp+EgrPk2GrFt/
+ywaZWWDYWGWVjUTR939+J399roD1B0y2PpxxVJkES/1Y+Zj0
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem
new file mode 100644
index 00000000000..7b8ce2da4be
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 78:58:5f:2e:ad:2c:19:4b:e3:37:07:35:34:13:28:b5:96:d4:65:93
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 1 G3
+ Validity
+ Not Before: Jan 12 17:27:44 2012 GMT
+ Not After : Jan 12 17:27:44 2042 GMT
+ Subject: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 1 G3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a0:be:50:10:8e:e9:f2:6c:40:b4:04:9c:85:b9:
+ 31:ca:dc:2d:e4:11:a9:04:3c:1b:55:c1:e7:58:30:
+ 1d:24:b4:c3:ef:85:de:8c:2c:e1:c1:3d:df:82:e6:
+ 4f:ad:47:87:6c:ec:5b:49:c1:4a:d5:bb:8f:ec:87:
+ ac:7f:82:9a:86:ec:3d:03:99:52:01:d2:35:9e:ac:
+ da:f0:53:c9:66:3c:d4:ac:02:01:da:24:d3:3b:a8:
+ 02:46:af:a4:1c:e3:f8:73:58:76:b7:f6:0e:90:0d:
+ b5:f0:cf:cc:fa:f9:c6:4c:e5:c3:86:30:0a:8d:17:
+ 7e:35:eb:c5:df:bb:0e:9c:c0:8d:87:e3:88:38:85:
+ 67:fa:3e:c7:ab:e0:13:9c:05:18:98:cf:93:f5:b1:
+ 92:b4:fc:23:d3:cf:d5:c4:27:49:e0:9e:3c:9b:08:
+ a3:8b:5d:2a:21:e0:fc:39:aa:53:da:7d:7e:cf:1a:
+ 09:53:bc:5d:05:04:cf:a1:4a:8f:8b:76:82:0d:a1:
+ f8:d2:c7:14:77:5b:90:36:07:81:9b:3e:06:fa:52:
+ 5e:63:c5:a6:00:fe:a5:e9:52:1b:52:b5:92:39:72:
+ 03:09:62:bd:b0:60:16:6e:a6:dd:25:c2:03:66:dd:
+ f3:04:d1:40:e2:4e:8b:86:f4:6f:e5:83:a0:27:84:
+ 5e:04:c1:f5:90:bd:30:3d:c4:ef:a8:69:bc:38:9b:
+ a4:a4:96:d1:62:da:69:c0:01:96:ae:cb:c4:51:34:
+ ea:0c:aa:ff:21:8e:59:8f:4a:5c:e4:61:9a:a7:d2:
+ e9:2a:78:8d:51:3d:3a:15:ee:a2:59:8e:a9:5c:de:
+ c5:f9:90:22:e5:88:45:71:dd:91:99:6c:7a:9f:3d:
+ 3d:98:7c:5e:f6:be:16:68:a0:5e:ae:0b:23:fc:5a:
+ 0f:aa:22:76:2d:c9:a1:10:1d:e4:d3:44:23:90:88:
+ 9f:c6:2a:e6:d7:f5:9a:b3:58:1e:2f:30:89:08:1b:
+ 54:a2:b5:98:23:ec:08:77:1c:95:5d:61:d1:cb:89:
+ 9c:5f:a2:4a:91:9a:ef:21:aa:49:16:08:a8:bd:61:
+ 28:31:c9:74:ad:85:f6:d9:c5:b1:8b:d1:e5:10:32:
+ 4d:5f:8b:20:3a:3c:49:1f:33:85:59:0d:db:cb:09:
+ 75:43:69:73:fb:6b:71:7d:f0:df:c4:4c:7d:c6:a3:
+ 2e:c8:95:79:cb:73:a2:8e:4e:4d:24:fb:5e:e4:04:
+ be:72:1b:a6:27:2d:49:5a:99:7a:d7:5c:09:20:b7:
+ 7f:94:b9:4f:f1:0d:1c:5e:88:42:1b:11:b7:e7:91:
+ db:9e:6c:f4:6a:df:8c:06:98:03:ad:cc:28:ef:a5:
+ 47:f3:53
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ A3:97:D6:F3:5E:A2:10:E1:AB:45:9F:3C:17:64:3C:EE:01:70:9C:CC
+ Signature Algorithm: sha256WithRSAEncryption
+ 18:fa:5b:75:fc:3e:7a:c7:5f:77:c7:ca:df:cf:5f:c3:12:c4:
+ 40:5d:d4:32:aa:b8:6a:d7:d5:15:15:46:98:23:a5:e6:90:5b:
+ 18:99:4c:e3:ad:42:a3:82:31:36:88:cd:e9:fb:c4:04:96:48:
+ 8b:01:c7:8d:01:cf:5b:33:06:96:46:66:74:1d:4f:ed:c1:b6:
+ b9:b4:0d:61:cc:63:7e:d7:2e:77:8c:96:1c:2a:23:68:6b:85:
+ 57:76:70:33:13:fe:e1:4f:a6:23:77:18:fa:1a:8c:e8:bd:65:
+ c9:cf:3f:f4:c9:17:dc:eb:c7:bc:c0:04:2e:2d:46:2f:69:66:
+ c3:1b:8f:fe:ec:3e:d3:ca:94:bf:76:0a:25:0d:a9:7b:02:1c:
+ a9:d0:3b:5f:0b:c0:81:3a:3d:64:e1:bf:a7:2d:4e:bd:4d:c4:
+ d8:29:c6:22:18:d0:c5:ac:72:02:82:3f:aa:3a:a2:3a:22:97:
+ 31:dd:08:63:c3:75:14:b9:60:28:2d:5b:68:e0:16:a9:66:82:
+ 23:51:f5:eb:53:d8:31:9b:7b:e9:b7:9d:4b:eb:88:16:cf:f9:
+ 5d:38:8a:49:30:8f:ed:f1:eb:19:f4:77:1a:31:18:4d:67:54:
+ 6c:2f:6f:65:f9:db:3d:ec:21:ec:5e:f4:f4:8b:ca:60:65:54:
+ d1:71:64:f4:f9:a6:a3:81:33:36:33:71:f0:a4:78:5f:4e:ad:
+ 83:21:de:34:49:8d:e8:59:ac:9d:f2:76:5a:36:f2:13:f4:af:
+ e0:09:c7:61:2a:6c:f7:e0:9d:ae:bb:86:4a:28:6f:2e:ee:b4:
+ 79:cd:90:33:c3:b3:76:fa:f5:f0:6c:9d:01:90:fa:9e:90:f6:
+ 9c:72:cf:47:da:c3:1f:e4:35:20:53:f2:54:d1:df:61:83:a6:
+ 02:e2:25:38:de:85:32:2d:5e:73:90:52:5d:42:c4:ce:3d:4b:
+ e1:f9:19:84:1d:d5:a2:50:cc:41:fb:41:14:c3:bd:d6:c9:5a:
+ a3:63:66:02:80:bd:05:3a:3b:47:9c:ec:00:26:4c:f5:88:51:
+ bf:a8:23:7f:18:07:b0:0b:ed:8b:26:a1:64:d3:61:4a:eb:5c:
+ 9f:de:b3:af:67:03:b3:1f:dd:6d:5d:69:68:69:ab:5e:3a:ec:
+ 7c:69:bc:c7:3b:85:4e:9e:15:b9:b4:15:4f:c3:95:7a:58:d7:
+ c9:6c:e9:6c:b9:f3:29:63:5e:b4:2c:f0:2d:3d:ed:5a:65:e0:
+ a9:5b:40:c2:48:99:81:6d:9e:1f:06:2a:3c:12:b4:8b:0f:9b:
+ a2:24:f0:a6:8d:d6:7a:e0:4b:b6:64:96:63:95:84:c2:4a:cd:
+ 1c:2e:24:87:33:60:e5:c3
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIUeFhfLq0sGUvjNwc1NBMotZbUZZMwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMSBHMzAeFw0xMjAxMTIxNzI3NDRaFw00
+MjAxMTIxNzI3NDRaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDEgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQCgvlAQjunybEC0BJyFuTHK3C3kEakEPBtV
+wedYMB0ktMPvhd6MLOHBPd+C5k+tR4ds7FtJwUrVu4/sh6x/gpqG7D0DmVIB0jWe
+rNrwU8lmPNSsAgHaJNM7qAJGr6Qc4/hzWHa39g6QDbXwz8z6+cZM5cOGMAqNF341
+68Xfuw6cwI2H44g4hWf6Pser4BOcBRiYz5P1sZK0/CPTz9XEJ0ngnjybCKOLXSoh
+4Pw5qlPafX7PGglTvF0FBM+hSo+LdoINofjSxxR3W5A2B4GbPgb6Ul5jxaYA/qXp
+UhtStZI5cgMJYr2wYBZupt0lwgNm3fME0UDiTouG9G/lg6AnhF4EwfWQvTA9xO+o
+abw4m6SkltFi2mnAAZauy8RRNOoMqv8hjlmPSlzkYZqn0ukqeI1RPToV7qJZjqlc
+3sX5kCLliEVx3ZGZbHqfPT2YfF72vhZooF6uCyP8Wg+qInYtyaEQHeTTRCOQiJ/G
+KubX9ZqzWB4vMIkIG1SitZgj7Ah3HJVdYdHLiZxfokqRmu8hqkkWCKi9YSgxyXSt
+hfbZxbGL0eUQMk1fiyA6PEkfM4VZDdvLCXVDaXP7a3F98N/ETH3Goy7IlXnLc6KO
+Tk0k+17kBL5yG6YnLUlamXrXXAkgt3+UuU/xDRxeiEIbEbfnkduebPRq34wGmAOt
+zCjvpUfzUwIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUo5fW816iEOGrRZ88F2Q87gFwnMwwDQYJKoZIhvcNAQELBQAD
+ggIBABj6W3X8PnrHX3fHyt/PX8MSxEBd1DKquGrX1RUVRpgjpeaQWxiZTOOtQqOC
+MTaIzen7xASWSIsBx40Bz1szBpZGZnQdT+3Btrm0DWHMY37XLneMlhwqI2hrhVd2
+cDMT/uFPpiN3GPoajOi9ZcnPP/TJF9zrx7zABC4tRi9pZsMbj/7sPtPKlL92CiUN
+qXsCHKnQO18LwIE6PWThv6ctTr1NxNgpxiIY0MWscgKCP6o6ojoilzHdCGPDdRS5
+YCgtW2jgFqlmgiNR9etT2DGbe+m3nUvriBbP+V04ikkwj+3x6xn0dxoxGE1nVGwv
+b2X52z3sIexe9PSLymBlVNFxZPT5pqOBMzYzcfCkeF9OrYMh3jRJjehZrJ3ydlo2
+8hP0r+AJx2EqbPfgna67hkooby7utHnNkDPDs3b69fBsnQGQ+p6Q9pxyz0fawx/k
+NSBT8lTR32GDpgLiJTjehTItXnOQUl1CxM49S+H5GYQd1aJQzEH7QRTDvdbJWqNj
+ZgKAvQU6O0ec7AAmTPWIUb+oI38YB7AL7YsmoWTTYUrrXJ/es69nA7Mf3W1daWhp
+q1467HxpvMc7hU6eFbm0FU/DlXpY18ls6Wy58yljXrQs8C097Vpl4KlbQMJImYFt
+nh8GKjwStIsPm6Ik8KaN1nrgS7ZklmOVhMJKzRwuJIczYOXD
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem
new file mode 100644
index 00000000000..35cffa17648
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 06:6c:9f:cf:99:bf:8c:0a:39:e2:f0:78:8a:43:e6:96:36:5b:ca
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = Amazon, CN = Amazon Root CA 1
+ Validity
+ Not Before: May 26 00:00:00 2015 GMT
+ Not After : Jan 17 00:00:00 2038 GMT
+ Subject: C = US, O = Amazon, CN = Amazon Root CA 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b2:78:80:71:ca:78:d5:e3:71:af:47:80:50:74:
+ 7d:6e:d8:d7:88:76:f4:99:68:f7:58:21:60:f9:74:
+ 84:01:2f:ac:02:2d:86:d3:a0:43:7a:4e:b2:a4:d0:
+ 36:ba:01:be:8d:db:48:c8:07:17:36:4c:f4:ee:88:
+ 23:c7:3e:eb:37:f5:b5:19:f8:49:68:b0:de:d7:b9:
+ 76:38:1d:61:9e:a4:fe:82:36:a5:e5:4a:56:e4:45:
+ e1:f9:fd:b4:16:fa:74:da:9c:9b:35:39:2f:fa:b0:
+ 20:50:06:6c:7a:d0:80:b2:a6:f9:af:ec:47:19:8f:
+ 50:38:07:dc:a2:87:39:58:f8:ba:d5:a9:f9:48:67:
+ 30:96:ee:94:78:5e:6f:89:a3:51:c0:30:86:66:a1:
+ 45:66:ba:54:eb:a3:c3:91:f9:48:dc:ff:d1:e8:30:
+ 2d:7d:2d:74:70:35:d7:88:24:f7:9e:c4:59:6e:bb:
+ 73:87:17:f2:32:46:28:b8:43:fa:b7:1d:aa:ca:b4:
+ f2:9f:24:0e:2d:4b:f7:71:5c:5e:69:ff:ea:95:02:
+ cb:38:8a:ae:50:38:6f:db:fb:2d:62:1b:c5:c7:1e:
+ 54:e1:77:e0:67:c8:0f:9c:87:23:d6:3f:40:20:7f:
+ 20:80:c4:80:4c:3e:3b:24:26:8e:04:ae:6c:9a:c8:
+ aa:0d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 84:18:CC:85:34:EC:BC:0C:94:94:2E:08:59:9C:C7:B2:10:4E:0A:08
+ Signature Algorithm: sha256WithRSAEncryption
+ 98:f2:37:5a:41:90:a1:1a:c5:76:51:28:20:36:23:0e:ae:e6:
+ 28:bb:aa:f8:94:ae:48:a4:30:7f:1b:fc:24:8d:4b:b4:c8:a1:
+ 97:f6:b6:f1:7a:70:c8:53:93:cc:08:28:e3:98:25:cf:23:a4:
+ f9:de:21:d3:7c:85:09:ad:4e:9a:75:3a:c2:0b:6a:89:78:76:
+ 44:47:18:65:6c:8d:41:8e:3b:7f:9a:cb:f4:b5:a7:50:d7:05:
+ 2c:37:e8:03:4b:ad:e9:61:a0:02:6e:f5:f2:f0:c5:b2:ed:5b:
+ b7:dc:fa:94:5c:77:9e:13:a5:7f:52:ad:95:f2:f8:93:3b:de:
+ 8b:5c:5b:ca:5a:52:5b:60:af:14:f7:4b:ef:a3:fb:9f:40:95:
+ 6d:31:54:fc:42:d3:c7:46:1f:23:ad:d9:0f:48:70:9a:d9:75:
+ 78:71:d1:72:43:34:75:6e:57:59:c2:02:5c:26:60:29:cf:23:
+ 19:16:8e:88:43:a5:d4:e4:cb:08:fb:23:11:43:e8:43:29:72:
+ 62:a1:a9:5d:5e:08:d4:90:ae:b8:d8:ce:14:c2:d0:55:f2:86:
+ f6:c4:93:43:77:66:61:c0:b9:e8:41:d7:97:78:60:03:6e:4a:
+ 72:ae:a5:d1:7d:ba:10:9e:86:6c:1b:8a:b9:59:33:f8:eb:c4:
+ 90:be:f1:b9
+-----BEGIN CERTIFICATE-----
+MIIDQTCCAimgAwIBAgITBmyfz5m/jAo54vB4ikPmljZbyjANBgkqhkiG9w0BAQsF
+ADA5MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6
+b24gUm9vdCBDQSAxMB4XDTE1MDUyNjAwMDAwMFoXDTM4MDExNzAwMDAwMFowOTEL
+MAkGA1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJv
+b3QgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALJ4gHHKeNXj
+ca9HgFB0fW7Y14h29Jlo91ghYPl0hAEvrAIthtOgQ3pOsqTQNroBvo3bSMgHFzZM
+9O6II8c+6zf1tRn4SWiw3te5djgdYZ6k/oI2peVKVuRF4fn9tBb6dNqcmzU5L/qw
+IFAGbHrQgLKm+a/sRxmPUDgH3KKHOVj4utWp+UhnMJbulHheb4mjUcAwhmahRWa6
+VOujw5H5SNz/0egwLX0tdHA114gk957EWW67c4cX8jJGKLhD+rcdqsq08p8kDi1L
+93FcXmn/6pUCyziKrlA4b9v7LWIbxcceVOF34GfID5yHI9Y/QCB/IIDEgEw+OyQm
+jgSubJrIqg0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFIQYzIU07LwMlJQuCFmcx7IQTgoIMA0GCSqGSIb3DQEBCwUA
+A4IBAQCY8jdaQZChGsV2USggNiMOruYou6r4lK5IpDB/G/wkjUu0yKGX9rbxenDI
+U5PMCCjjmCXPI6T53iHTfIUJrU6adTrCC2qJeHZERxhlbI1Bjjt/msv0tadQ1wUs
+N+gDS63pYaACbvXy8MWy7Vu33PqUXHeeE6V/Uq2V8viTO96LXFvKWlJbYK8U90vv
+o/ufQJVtMVT8QtPHRh8jrdkPSHCa2XV4cdFyQzR1bldZwgJcJmApzyMZFo6IQ6XU
+5MsI+yMRQ+hDKXJioaldXgjUkK642M4UwtBV8ob2xJNDd2ZhwLnoQdeXeGADbkpy
+rqXRfboQnoZsG4q5WTP468SQvvG5
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem
new file mode 100644
index 00000000000..610203c0311
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 44:57:34:24:5b:81:89:9b:35:f2:ce:b8:2b:3b:5b:a7:26:f0:75:28
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
+ Validity
+ Not Before: Jan 12 18:59:32 2012 GMT
+ Not After : Jan 12 18:59:32 2042 GMT
+ Subject: C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 G3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a1:ae:25:b2:01:18:dc:57:88:3f:46:eb:f9:af:
+ e2:eb:23:71:e2:9a:d1:61:66:21:5f:aa:af:27:51:
+ e5:6e:1b:16:d4:2d:7d:50:b0:53:77:bd:78:3a:60:
+ e2:64:02:9b:7c:86:9b:d6:1a:8e:ad:ff:1f:15:7f:
+ d5:95:1e:12:cb:e6:14:84:04:c1:df:36:b3:16:9f:
+ 8a:e3:c9:db:98:34:ce:d8:33:17:28:46:fc:a7:c9:
+ f0:d2:b4:d5:4d:09:72:49:f9:f2:87:e3:a9:da:7d:
+ a1:7d:6b:b2:3a:25:a9:6d:52:44:ac:f8:be:6e:fb:
+ dc:a6:73:91:90:61:a6:03:14:20:f2:e7:87:a3:88:
+ ad:ad:a0:8c:ff:a6:0b:25:52:25:e7:16:01:d5:cb:
+ b8:35:81:0c:a3:3b:f0:e1:e1:fc:5a:5d:ce:80:71:
+ 6d:f8:49:ab:3e:3b:ba:b8:d7:80:01:fb:a5:eb:5b:
+ b3:c5:5e:60:2a:31:a0:af:37:e8:20:3a:9f:a8:32:
+ 2c:0c:cc:09:1d:d3:9e:8e:5d:bc:4c:98:ee:c5:1a:
+ 68:7b:ec:53:a6:e9:14:35:a3:df:cd:80:9f:0c:48:
+ fb:1c:f4:f1:bf:4a:b8:fa:d5:8c:71:4a:c7:1f:ad:
+ fe:41:9a:b3:83:5d:f2:84:56:ef:a5:57:43:ce:29:
+ ad:8c:ab:55:bf:c4:fb:5b:01:dd:23:21:a1:58:00:
+ 8e:c3:d0:6a:13:ed:13:e3:12:2b:80:dc:67:e6:95:
+ b2:cd:1e:22:6e:2a:f8:41:d4:f2:ca:14:07:8d:8a:
+ 55:12:c6:69:f5:b8:86:68:2f:53:5e:b0:d2:aa:21:
+ c1:98:e6:30:e3:67:55:c7:9b:6e:ac:19:a8:55:a6:
+ 45:06:d0:23:3a:db:eb:65:5d:2a:11:11:f0:3b:4f:
+ ca:6d:f4:34:c4:71:e4:ff:00:5a:f6:5c:ae:23:60:
+ 85:73:f1:e4:10:b1:25:ae:d5:92:bb:13:c1:0c:e0:
+ 39:da:b4:39:57:b5:ab:35:aa:72:21:3b:83:35:e7:
+ 31:df:7a:21:6e:b8:32:08:7d:1d:32:91:15:4a:62:
+ 72:cf:e3:77:a1:bc:d5:11:1b:76:01:67:08:e0:41:
+ 0b:c3:eb:15:6e:f8:a4:19:d9:a2:ab:af:e2:27:52:
+ 56:2b:02:8a:2c:14:24:f9:bf:42:02:bf:26:c8:c6:
+ 8f:e0:6e:38:7d:53:2d:e5:ed:98:b3:95:63:68:7f:
+ f9:35:f4:df:88:c5:60:35:92:c0:7c:69:1c:61:95:
+ 16:d0:eb:de:0b:af:3e:04:10:45:65:58:50:38:af:
+ 48:f2:59:b6:16:f2:3c:0d:90:02:c6:70:2e:01:ad:
+ 3c:15:d7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ ED:E7:6F:76:5A:BF:60:EC:49:5B:C6:A5:77:BB:72:16:71:9B:C4:3D
+ Signature Algorithm: sha256WithRSAEncryption
+ 91:df:80:3f:43:09:7e:71:c2:f7:eb:b3:88:8f:e1:51:b2:bc:
+ 3d:75:f9:28:5d:c8:bc:99:9b:7b:5d:aa:e5:ca:e1:0a:f7:e8:
+ b2:d3:9f:dd:67:31:7e:ba:01:aa:c7:6a:41:3b:90:d4:08:5c:
+ b2:60:6a:90:f0:c8:ce:03:62:f9:8b:ed:fb:6e:2a:dc:06:4d:
+ 3c:29:0f:89:16:8a:58:4c:48:0f:e8:84:61:ea:3c:72:a6:77:
+ e4:42:ae:88:a3:43:58:79:7e:ae:ca:a5:53:0d:a9:3d:70:bd:
+ 20:19:61:a4:6c:38:fc:43:32:e1:c1:47:ff:f8:ec:f1:11:22:
+ 32:96:9c:c2:f6:5b:69:96:7b:20:0c:43:41:9a:5b:f6:59:19:
+ 88:de:55:88:37:51:0b:78:5c:0a:1e:a3:42:fd:c7:9d:88:0f:
+ c0:f2:78:02:24:54:93:af:89:87:88:c9:4a:80:1d:ea:d0:6e:
+ 3e:61:2e:36:bb:35:0e:27:96:fd:66:34:3b:61:72:73:f1:16:
+ 5c:47:06:54:49:00:7a:58:12:b0:0a:ef:85:fd:b1:b8:33:75:
+ 6a:93:1c:12:e6:60:5e:6f:1d:7f:c9:1f:23:cb:84:61:9f:1e:
+ 82:44:f9:5f:ad:62:55:24:9a:52:98:ed:51:e7:a1:7e:97:3a:
+ e6:2f:1f:11:da:53:80:2c:85:9e:ab:35:10:db:22:5f:6a:c5:
+ 5e:97:53:f2:32:02:09:30:a3:58:f0:0d:01:d5:72:c6:b1:7c:
+ 69:7b:c3:f5:36:45:cc:61:6e:5e:4c:94:c5:5e:ae:e8:0e:5e:
+ 8b:bf:f7:cd:e0:ed:a1:0e:1b:33:ee:54:18:fe:0f:be:ef:7e:
+ 84:6b:43:e3:70:98:db:5d:75:b2:0d:59:07:85:15:23:39:d6:
+ f1:df:a9:26:0f:d6:48:c7:b3:a6:22:f5:33:37:5a:95:47:9f:
+ 7b:ba:18:15:6f:ff:d6:14:64:83:49:d2:0a:67:21:db:0f:35:
+ 63:60:28:22:e3:b1:95:83:cd:85:a6:dd:2f:0f:e7:67:52:6e:
+ bb:2f:85:7c:f5:4a:73:e7:c5:3e:c0:bd:21:12:05:3f:fc:b7:
+ 03:49:02:5b:c8:25:e6:e2:54:38:f5:79:87:8c:1d:53:b2:4e:
+ 85:7b:06:38:c7:2c:f8:f8:b0:72:8d:25:e5:77:52:f4:03:1c:
+ 48:a6:50:5f:88:20:30:6e:f2:82:43:ab:3d:97:84:e7:53:fb:
+ 21:c1:4f:0f:22:9a:86:b8:59:2a:f6:47:3d:19:88:2d:e8:85:
+ e1:9e:ec:85:08:6a:b1:6c:34:c9:1d:ec:48:2b:3b:78:ed:66:
+ c4:8e:79:69:83:de:7f:8c
+-----BEGIN CERTIFICATE-----
+MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL
+BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc
+BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00
+MjAxMTIxODU5MzJaMEgxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMR4wHAYDVQQDExVRdW9WYWRpcyBSb290IENBIDIgRzMwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQChriWyARjcV4g/Ruv5r+LrI3HimtFhZiFf
+qq8nUeVuGxbULX1QsFN3vXg6YOJkApt8hpvWGo6t/x8Vf9WVHhLL5hSEBMHfNrMW
+n4rjyduYNM7YMxcoRvynyfDStNVNCXJJ+fKH46nafaF9a7I6JaltUkSs+L5u+9ym
+c5GQYaYDFCDy54ejiK2toIz/pgslUiXnFgHVy7g1gQyjO/Dh4fxaXc6AcW34Sas+
+O7q414AB+6XrW7PFXmAqMaCvN+ggOp+oMiwMzAkd056OXbxMmO7FGmh77FOm6RQ1
+o9/NgJ8MSPsc9PG/Srj61YxxSscfrf5BmrODXfKEVu+lV0POKa2Mq1W/xPtbAd0j
+IaFYAI7D0GoT7RPjEiuA3GfmlbLNHiJuKvhB1PLKFAeNilUSxmn1uIZoL1NesNKq
+IcGY5jDjZ1XHm26sGahVpkUG0CM62+tlXSoREfA7T8pt9DTEceT/AFr2XK4jYIVz
+8eQQsSWu1ZK7E8EM4DnatDlXtas1qnIhO4M15zHfeiFuuDIIfR0ykRVKYnLP43eh
+vNURG3YBZwjgQQvD6xVu+KQZ2aKrr+InUlYrAoosFCT5v0ICvybIxo/gbjh9Uy3l
+7ZizlWNof/k19N+IxWA1ksB8aRxhlRbQ694Lrz4EEEVlWFA4r0jyWbYW8jwNkALG
+cC4BrTwV1wIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQU7edvdlq/YOxJW8ald7tyFnGbxD0wDQYJKoZIhvcNAQELBQAD
+ggIBAJHfgD9DCX5xwvfrs4iP4VGyvD11+ShdyLyZm3tdquXK4Qr36LLTn91nMX66
+AarHakE7kNQIXLJgapDwyM4DYvmL7ftuKtwGTTwpD4kWilhMSA/ohGHqPHKmd+RC
+roijQ1h5fq7KpVMNqT1wvSAZYaRsOPxDMuHBR//47PERIjKWnML2W2mWeyAMQ0Ga
+W/ZZGYjeVYg3UQt4XAoeo0L9x52ID8DyeAIkVJOviYeIyUqAHerQbj5hLja7NQ4n
+lv1mNDthcnPxFlxHBlRJAHpYErAK74X9sbgzdWqTHBLmYF5vHX/JHyPLhGGfHoJE
++V+tYlUkmlKY7VHnoX6XOuYvHxHaU4AshZ6rNRDbIl9qxV6XU/IyAgkwo1jwDQHV
+csaxfGl7w/U2Rcxhbl5MlMVerugOXou/983g7aEOGzPuVBj+D77vfoRrQ+NwmNtd
+dbINWQeFFSM51vHfqSYP1kjHs6Yi9TM3WpVHn3u6GBVv/9YUZINJ0gpnIdsPNWNg
+KCLjsZWDzYWm3S8P52dSbrsvhXz1SnPnxT7AvSESBT/8twNJAlvIJebiVDj1eYeM
+HVOyToV7BjjHLPj4sHKNJeV3UvQDHEimUF+IIDBu8oJDqz2XhOdT+yHBTw8imoa4
+WSr2Rz0ZiC3oheGe7IUIarFsNMkd7EgrO3jtZsSOeWmD3n+M
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem
new file mode 100644
index 00000000000..a45b70c3c3f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = DE, O = T-Systems Enterprise Services GmbH, OU = T-Systems Trust Center, CN = T-TeleSec GlobalRoot Class 2
+ Validity
+ Not Before: Oct 1 10:40:14 2008 GMT
+ Not After : Oct 1 23:59:59 2033 GMT
+ Subject: C = DE, O = T-Systems Enterprise Services GmbH, OU = T-Systems Trust Center, CN = T-TeleSec GlobalRoot Class 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:aa:5f:da:1b:5f:e8:73:91:e5:da:5c:f4:a2:e6:
+ 47:e5:f3:68:55:60:05:1d:02:a4:b3:9b:59:f3:1e:
+ 8a:af:34:ad:fc:0d:c2:d9:48:19:ee:69:8f:c9:20:
+ fc:21:aa:07:19:ed:b0:5c:ac:65:c7:5f:ed:02:7c:
+ 7b:7c:2d:1b:d6:ba:b9:80:c2:18:82:16:84:fa:66:
+ b0:08:c6:54:23:81:e4:cd:b9:49:3f:f6:4f:6e:37:
+ 48:28:38:0f:c5:be:e7:68:70:fd:39:97:4d:d2:c7:
+ 98:91:50:aa:c4:44:b3:23:7d:39:47:e9:52:62:d6:
+ 12:93:5e:b7:31:96:42:05:fb:76:a7:1e:a3:f5:c2:
+ fc:e9:7a:c5:6c:a9:71:4f:ea:cb:78:bc:60:af:c7:
+ de:f4:d9:cb:be:7e:33:a5:6e:94:83:f0:34:fa:21:
+ ab:ea:8e:72:a0:3f:a4:de:30:5b:ef:86:4d:6a:95:
+ 5b:43:44:a8:10:15:1c:e5:01:57:c5:98:f1:e6:06:
+ 28:91:aa:20:c5:b7:53:26:51:43:b2:0b:11:95:58:
+ e1:c0:0f:76:d9:c0:8d:7c:81:f3:72:70:9e:6f:fe:
+ 1a:8e:d9:5f:35:c6:b2:6f:34:7c:be:48:4f:e2:5a:
+ 39:d7:d8:9d:78:9e:9f:86:3e:03:5e:19:8b:44:a2:
+ d5:c7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ BF:59:20:36:00:79:A0:A0:22:6B:8C:D5:F2:61:D2:B8:2C:CB:82:4A
+ Signature Algorithm: sha256WithRSAEncryption
+ 31:03:a2:61:0b:1f:74:e8:72:36:c6:6d:f9:4d:9e:fa:22:a8:
+ e1:81:56:cf:cd:bb:9f:ea:ab:91:19:38:af:aa:7c:15:4d:f3:
+ b6:a3:8d:a5:f4:8e:f6:44:a9:a7:e8:21:95:ad:3e:00:62:16:
+ 88:f0:02:ba:fc:61:23:e6:33:9b:30:7a:6b:36:62:7b:ad:04:
+ 23:84:58:65:e2:db:2b:8a:e7:25:53:37:62:53:5f:bc:da:01:
+ 62:29:a2:a6:27:71:e6:3a:22:7e:c1:6f:1d:95:70:20:4a:07:
+ 34:df:ea:ff:15:80:e5:ba:d7:7a:d8:5b:75:7c:05:7a:29:47:
+ 7e:40:a8:31:13:77:cd:40:3b:b4:51:47:7a:2e:11:e3:47:11:
+ de:9d:66:d0:8b:d5:54:66:fa:83:55:ea:7c:c2:29:89:1b:e9:
+ 6f:b3:ce:e2:05:84:c9:2f:3e:78:85:62:6e:c9:5f:c1:78:63:
+ 74:58:c0:48:18:0c:99:39:eb:a4:cc:1a:b5:79:5a:8d:15:9c:
+ d8:14:0d:f6:7a:07:57:c7:22:83:05:2d:3c:9b:25:26:3d:18:
+ b3:a9:43:7c:c8:c8:ab:64:8f:0e:a3:bf:9c:1b:9d:30:db:da:
+ d0:19:2e:aa:3c:f1:fb:33:80:76:e4:cd:ad:19:4f:05:27:8e:
+ 13:a1:6e:c2
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDIwHhcNMDgxMDAxMTA0MDE0WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDIwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqX9obX+hzkeXaXPSi5kfl82hVYAUd
+AqSzm1nzHoqvNK38DcLZSBnuaY/JIPwhqgcZ7bBcrGXHX+0CfHt8LRvWurmAwhiC
+FoT6ZrAIxlQjgeTNuUk/9k9uN0goOA/FvudocP05l03Sx5iRUKrERLMjfTlH6VJi
+1hKTXrcxlkIF+3anHqP1wvzpesVsqXFP6st4vGCvx9702cu+fjOlbpSD8DT6Iavq
+jnKgP6TeMFvvhk1qlVtDRKgQFRzlAVfFmPHmBiiRqiDFt1MmUUOyCxGVWOHAD3bZ
+wI18gfNycJ5v/hqO2V81xrJvNHy+SE/iWjnX2J14np+GPgNeGYtEotXHAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS/
+WSA2AHmgoCJrjNXyYdK4LMuCSjANBgkqhkiG9w0BAQsFAAOCAQEAMQOiYQsfdOhy
+NsZt+U2e+iKo4YFWz827n+qrkRk4r6p8FU3ztqONpfSO9kSpp+ghla0+AGIWiPAC
+uvxhI+YzmzB6azZie60EI4RYZeLbK4rnJVM3YlNfvNoBYimipidx5joifsFvHZVw
+IEoHNN/q/xWA5brXethbdXwFeilHfkCoMRN3zUA7tFFHei4R40cR3p1m0IvVVGb6
+g1XqfMIpiRvpb7PO4gWEyS8+eIVibslfwXhjdFjASBgMmTnrpMwatXlajRWc2BQN
+9noHV8cigwUtPJslJj0Ys6lDfMjIq2SPDqO/nBudMNva0Bkuqjzx+zOAduTNrRlP
+BSeOE6Fuwg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem
new file mode 100644
index 00000000000..ccf91e39d2f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem
@@ -0,0 +1,49 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0d:6a:5f:08:3f:28:5c:3e:51:95:df:5d
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global ECC P256 Certification Authority
+ Validity
+ Not Before: Aug 23 19:35:10 2017 GMT
+ Not After : Aug 23 19:35:10 2042 GMT
+ Subject: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global ECC P256 Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:7e:fb:6c:e6:23:e3:73:32:08:ca:60:e6:53:9c:
+ ba:74:8d:18:b0:78:90:52:80:dd:38:c0:4a:1d:d1:
+ a8:cc:93:a4:97:06:38:ca:0d:15:62:c6:8e:01:2a:
+ 65:9d:aa:df:34:91:2e:81:c1:e4:33:92:31:c4:fd:
+ 09:3a:a6:3f:ad
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ A3:41:06:AC:90:6D:D1:4A:EB:75:A5:4A:10:99:B3:B1:A1:8B:4A:F7
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:44:02:20:07:e6:54:da:0e:a0:5a:b2:ae:11:9f:87:c5:b6:
+ ff:69:de:25:be:f8:a0:b7:08:f3:44:ce:2a:df:08:21:0c:37:
+ 02:20:2d:26:03:a0:05:bd:6b:d1:f6:5c:f8:65:cc:86:6d:b3:
+ 9c:34:48:63:84:09:c5:8d:77:1a:e2:cc:9c:e1:74:7b
+-----BEGIN CERTIFICATE-----
+MIICYDCCAgegAwIBAgIMDWpfCD8oXD5Rld9dMAoGCCqGSM49BAMCMIGRMQswCQYD
+VQQGEwJVUzERMA8GA1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAf
+BgNVBAoTGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3
+YXZlIEdsb2JhbCBFQ0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0x
+NzA4MjMxOTM1MTBaFw00MjA4MjMxOTM1MTBaMIGRMQswCQYDVQQGEwJVUzERMA8G
+A1UECBMISWxsaW5vaXMxEDAOBgNVBAcTB0NoaWNhZ28xITAfBgNVBAoTGFRydXN0
+d2F2ZSBIb2xkaW5ncywgSW5jLjE6MDgGA1UEAxMxVHJ1c3R3YXZlIEdsb2JhbCBF
+Q0MgUDI1NiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTBZMBMGByqGSM49AgEGCCqG
+SM49AwEHA0IABH77bOYj43MyCMpg5lOcunSNGLB4kFKA3TjASh3RqMyTpJcGOMoN
+FWLGjgEqZZ2q3zSRLoHB5DOSMcT9CTqmP62jQzBBMA8GA1UdEwEB/wQFMAMBAf8w
+DwYDVR0PAQH/BAUDAwcGADAdBgNVHQ4EFgQUo0EGrJBt0UrrdaVKEJmzsaGLSvcw
+CgYIKoZIzj0EAwIDRwAwRAIgB+ZU2g6gWrKuEZ+Hxbb/ad4lvvigtwjzRM4q3wgh
+DDcCIC0mA6AFvWvR9lz4ZcyGbbOcNEhjhAnFjXca4syc4XR7
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem
new file mode 100644
index 00000000000..d00d0551d29
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem
@@ -0,0 +1,87 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:00:00:00:00:01:0f:85:aa:2d:48
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O = "Cybertrust, Inc", CN = Cybertrust Global Root
+ Validity
+ Not Before: Dec 15 08:00:00 2006 GMT
+ Not After : Dec 15 08:00:00 2021 GMT
+ Subject: O = "Cybertrust, Inc", CN = Cybertrust Global Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:f8:c8:bc:bd:14:50:66:13:ff:f0:d3:79:ec:23:
+ f2:b7:1a:c7:8e:85:f1:12:73:a6:19:aa:10:db:9c:
+ a2:65:74:5a:77:3e:51:7d:56:f6:dc:23:b6:d4:ed:
+ 5f:58:b1:37:4d:d5:49:0e:6e:f5:6a:87:d6:d2:8c:
+ d2:27:c6:e2:ff:36:9f:98:65:a0:13:4e:c6:2a:64:
+ 9b:d5:90:12:cf:14:06:f4:3b:e3:d4:28:be:e8:0e:
+ f8:ab:4e:48:94:6d:8e:95:31:10:5c:ed:a2:2d:bd:
+ d5:3a:6d:b2:1c:bb:60:c0:46:4b:01:f5:49:ae:7e:
+ 46:8a:d0:74:8d:a1:0c:02:ce:ee:fc:e7:8f:b8:6b:
+ 66:f3:7f:44:00:bf:66:25:14:2b:dd:10:30:1d:07:
+ 96:3f:4d:f6:6b:b8:8f:b7:7b:0c:a5:38:eb:de:47:
+ db:d5:5d:39:fc:88:a7:f3:d7:2a:74:f1:e8:5a:a2:
+ 3b:9f:50:ba:a6:8c:45:35:c2:50:65:95:dc:63:82:
+ ef:dd:bf:77:4d:9c:62:c9:63:73:16:d0:29:0f:49:
+ a9:48:f0:b3:aa:b7:6c:c5:a7:30:39:40:5d:ae:c4:
+ e2:5d:26:53:f0:ce:1c:23:08:61:a8:94:19:ba:04:
+ 62:40:ec:1f:38:70:77:12:06:71:a7:30:18:5d:25:
+ 27:a5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ B6:08:7B:0D:7A:CC:AC:20:4C:86:56:32:5E:CF:AB:6E:85:2D:70:57
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www2.public-trust.com/crl/ct/ctroot.crl
+
+ X509v3 Authority Key Identifier:
+ keyid:B6:08:7B:0D:7A:CC:AC:20:4C:86:56:32:5E:CF:AB:6E:85:2D:70:57
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 56:ef:0a:23:a0:54:4e:95:97:c9:f8:89:da:45:c1:d4:a3:00:
+ 25:f4:1f:13:ab:b7:a3:85:58:69:c2:30:ad:d8:15:8a:2d:e3:
+ c9:cd:81:5a:f8:73:23:5a:a7:7c:05:f3:fd:22:3b:0e:d1:06:
+ c4:db:36:4c:73:04:8e:e5:b0:22:e4:c5:f3:2e:a5:d9:23:e3:
+ b8:4e:4a:20:a7:6e:02:24:9f:22:60:67:7b:8b:1d:72:09:c5:
+ 31:5c:e9:79:9f:80:47:3d:ad:a1:0b:07:14:3d:47:ff:03:69:
+ 1a:0c:0b:44:e7:63:25:a7:7f:b2:c9:b8:76:84:ed:23:f6:7d:
+ 07:ab:45:7e:d3:df:b3:bf:e9:8a:b6:cd:a8:a2:67:2b:52:d5:
+ b7:65:f0:39:4c:63:a0:91:79:93:52:0f:54:dd:83:bb:9f:d1:
+ 8f:a7:53:73:c3:cb:ff:30:ec:7c:04:b8:d8:44:1f:93:5f:71:
+ 09:22:b7:6e:3e:ea:1c:03:4e:9d:1a:20:61:fb:81:37:ec:5e:
+ fc:0a:45:ab:d7:e7:17:55:d0:a0:ea:60:9b:a6:f6:e3:8c:5b:
+ 29:c2:06:60:14:9d:2d:97:4c:a9:93:15:9d:61:c4:01:5f:48:
+ d6:58:bd:56:31:12:4e:11:c8:21:e0:b3:11:91:65:db:b4:a6:
+ 88:38:ce:55
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
+A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
+bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
+ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
+b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
+7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
+J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
+HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
+t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
+FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
+XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
+MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
+hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
+MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
+A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
+Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
+XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
+omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
+A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem
new file mode 100644
index 00000000000..933b322cd31
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 82:10:cf:b0:d2:40:e3:59:44:63:e0:bb:63:82:8b:00
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = Internet Security Research Group, CN = ISRG Root X1
+ Validity
+ Not Before: Jun 4 11:04:38 2015 GMT
+ Not After : Jun 4 11:04:38 2035 GMT
+ Subject: C = US, O = Internet Security Research Group, CN = ISRG Root X1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ad:e8:24:73:f4:14:37:f3:9b:9e:2b:57:28:1c:
+ 87:be:dc:b7:df:38:90:8c:6e:3c:e6:57:a0:78:f7:
+ 75:c2:a2:fe:f5:6a:6e:f6:00:4f:28:db:de:68:86:
+ 6c:44:93:b6:b1:63:fd:14:12:6b:bf:1f:d2:ea:31:
+ 9b:21:7e:d1:33:3c:ba:48:f5:dd:79:df:b3:b8:ff:
+ 12:f1:21:9a:4b:c1:8a:86:71:69:4a:66:66:6c:8f:
+ 7e:3c:70:bf:ad:29:22:06:f3:e4:c0:e6:80:ae:e2:
+ 4b:8f:b7:99:7e:94:03:9f:d3:47:97:7c:99:48:23:
+ 53:e8:38:ae:4f:0a:6f:83:2e:d1:49:57:8c:80:74:
+ b6:da:2f:d0:38:8d:7b:03:70:21:1b:75:f2:30:3c:
+ fa:8f:ae:dd:da:63:ab:eb:16:4f:c2:8e:11:4b:7e:
+ cf:0b:e8:ff:b5:77:2e:f4:b2:7b:4a:e0:4c:12:25:
+ 0c:70:8d:03:29:a0:e1:53:24:ec:13:d9:ee:19:bf:
+ 10:b3:4a:8c:3f:89:a3:61:51:de:ac:87:07:94:f4:
+ 63:71:ec:2e:e2:6f:5b:98:81:e1:89:5c:34:79:6c:
+ 76:ef:3b:90:62:79:e6:db:a4:9a:2f:26:c5:d0:10:
+ e1:0e:de:d9:10:8e:16:fb:b7:f7:a8:f7:c7:e5:02:
+ 07:98:8f:36:08:95:e7:e2:37:96:0d:36:75:9e:fb:
+ 0e:72:b1:1d:9b:bc:03:f9:49:05:d8:81:dd:05:b4:
+ 2a:d6:41:e9:ac:01:76:95:0a:0f:d8:df:d5:bd:12:
+ 1f:35:2f:28:17:6c:d2:98:c1:a8:09:64:77:6e:47:
+ 37:ba:ce:ac:59:5e:68:9d:7f:72:d6:89:c5:06:41:
+ 29:3e:59:3e:dd:26:f5:24:c9:11:a7:5a:a3:4c:40:
+ 1f:46:a1:99:b5:a7:3a:51:6e:86:3b:9e:7d:72:a7:
+ 12:05:78:59:ed:3e:51:78:15:0b:03:8f:8d:d0:2f:
+ 05:b2:3e:7b:4a:1c:4b:73:05:12:fc:c6:ea:e0:50:
+ 13:7c:43:93:74:b3:ca:74:e7:8e:1f:01:08:d0:30:
+ d4:5b:71:36:b4:07:ba:c1:30:30:5c:48:b7:82:3b:
+ 98:a6:7d:60:8a:a2:a3:29:82:cc:ba:bd:83:04:1b:
+ a2:83:03:41:a1:d6:05:f1:1b:c2:b6:f0:a8:7c:86:
+ 3b:46:a8:48:2a:88:dc:76:9a:76:bf:1f:6a:a5:3d:
+ 19:8f:eb:38:f3:64:de:c8:2b:0d:0a:28:ff:f7:db:
+ e2:15:42:d4:22:d0:27:5d:e1:79:fe:18:e7:70:88:
+ ad:4e:e6:d9:8b:3a:c6:dd:27:51:6e:ff:bc:64:f5:
+ 33:43:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 79:B4:59:E6:7B:B6:E5:E4:01:73:80:08:88:C8:1A:58:F6:E9:9B:6E
+ Signature Algorithm: sha256WithRSAEncryption
+ 55:1f:58:a9:bc:b2:a8:50:d0:0c:b1:d8:1a:69:20:27:29:08:
+ ac:61:75:5c:8a:6e:f8:82:e5:69:2f:d5:f6:56:4b:b9:b8:73:
+ 10:59:d3:21:97:7e:e7:4c:71:fb:b2:d2:60:ad:39:a8:0b:ea:
+ 17:21:56:85:f1:50:0e:59:eb:ce:e0:59:e9:ba:c9:15:ef:86:
+ 9d:8f:84:80:f6:e4:e9:91:90:dc:17:9b:62:1b:45:f0:66:95:
+ d2:7c:6f:c2:ea:3b:ef:1f:cf:cb:d6:ae:27:f1:a9:b0:c8:ae:
+ fd:7d:7e:9a:fa:22:04:eb:ff:d9:7f:ea:91:2b:22:b1:17:0e:
+ 8f:f2:8a:34:5b:58:d8:fc:01:c9:54:b9:b8:26:cc:8a:88:33:
+ 89:4c:2d:84:3c:82:df:ee:96:57:05:ba:2c:bb:f7:c4:b7:c7:
+ 4e:3b:82:be:31:c8:22:73:73:92:d1:c2:80:a4:39:39:10:33:
+ 23:82:4c:3c:9f:86:b2:55:98:1d:be:29:86:8c:22:9b:9e:e2:
+ 6b:3b:57:3a:82:70:4d:dc:09:c7:89:cb:0a:07:4d:6c:e8:5d:
+ 8e:c9:ef:ce:ab:c7:bb:b5:2b:4e:45:d6:4a:d0:26:cc:e5:72:
+ ca:08:6a:a5:95:e3:15:a1:f7:a4:ed:c9:2c:5f:a5:fb:ff:ac:
+ 28:02:2e:be:d7:7b:bb:e3:71:7b:90:16:d3:07:5e:46:53:7c:
+ 37:07:42:8c:d3:c4:96:9c:d5:99:b5:2a:e0:95:1a:80:48:ae:
+ 4c:39:07:ce:cc:47:a4:52:95:2b:ba:b8:fb:ad:d2:33:53:7d:
+ e5:1d:4d:6d:d5:a1:b1:c7:42:6f:e6:40:27:35:5c:a3:28:b7:
+ 07:8d:e7:8d:33:90:e7:23:9f:fb:50:9c:79:6c:46:d5:b4:15:
+ b3:96:6e:7e:9b:0c:96:3a:b8:52:2d:3f:d6:5b:e1:fb:08:c2:
+ 84:fe:24:a8:a3:89:da:ac:6a:e1:18:2a:b1:a8:43:61:5b:d3:
+ 1f:dc:3b:8d:76:f2:2d:e8:8d:75:df:17:33:6c:3d:53:fb:7b:
+ cb:41:5f:ff:dc:a2:d0:61:38:e1:96:b8:ac:5d:8b:37:d7:75:
+ d5:33:c0:99:11:ae:9d:41:c1:72:75:84:be:02:41:42:5f:67:
+ 24:48:94:d1:9b:27:be:07:3f:b9:b8:4f:81:74:51:e1:7a:b7:
+ ed:9d:23:e2:be:e0:d5:28:04:13:3c:31:03:9e:dd:7a:6c:8f:
+ c6:07:18:c6:7f:de:47:8e:3f:28:9e:04:06:cf:a5:54:34:77:
+ bd:ec:89:9b:e9:17:43:df:5b:db:5f:fe:8e:1e:57:a2:cd:40:
+ 9d:7e:62:22:da:de:18:27
+-----BEGIN CERTIFICATE-----
+MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw
+TzELMAkGA1UEBhMCVVMxKTAnBgNVBAoTIEludGVybmV0IFNlY3VyaXR5IFJlc2Vh
+cmNoIEdyb3VwMRUwEwYDVQQDEwxJU1JHIFJvb3QgWDEwHhcNMTUwNjA0MTEwNDM4
+WhcNMzUwNjA0MTEwNDM4WjBPMQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJu
+ZXQgU2VjdXJpdHkgUmVzZWFyY2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBY
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAK3oJHP0FDfzm54rVygc
+h77ct984kIxuPOZXoHj3dcKi/vVqbvYATyjb3miGbESTtrFj/RQSa78f0uoxmyF+
+0TM8ukj13Xnfs7j/EvEhmkvBioZxaUpmZmyPfjxwv60pIgbz5MDmgK7iS4+3mX6U
+A5/TR5d8mUgjU+g4rk8Kb4Mu0UlXjIB0ttov0DiNewNwIRt18jA8+o+u3dpjq+sW
+T8KOEUt+zwvo/7V3LvSye0rgTBIlDHCNAymg4VMk7BPZ7hm/ELNKjD+Jo2FR3qyH
+B5T0Y3HsLuJvW5iB4YlcNHlsdu87kGJ55tukmi8mxdAQ4Q7e2RCOFvu396j3x+UC
+B5iPNgiV5+I3lg02dZ77DnKxHZu8A/lJBdiB3QW0KtZB6awBdpUKD9jf1b0SHzUv
+KBds0pjBqAlkd25HN7rOrFleaJ1/ctaJxQZBKT5ZPt0m9STJEadao0xAH0ahmbWn
+OlFuhjuefXKnEgV4We0+UXgVCwOPjdAvBbI+e0ocS3MFEvzG6uBQE3xDk3SzynTn
+jh8BCNAw1FtxNrQHusEwMFxIt4I7mKZ9YIqioymCzLq9gwQbooMDQaHWBfEbwrbw
+qHyGO0aoSCqI3Haadr8faqU9GY/rOPNk3sgrDQoo//fb4hVC1CLQJ13hef4Y53CI
+rU7m2Ys6xt0nUW7/vGT1M0NPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR5tFnme7bl5AFzgAiIyBpY9umbbjANBgkq
+hkiG9w0BAQsFAAOCAgEAVR9YqbyyqFDQDLHYGmkgJykIrGF1XIpu+ILlaS/V9lZL
+ubhzEFnTIZd+50xx+7LSYK05qAvqFyFWhfFQDlnrzuBZ6brJFe+GnY+EgPbk6ZGQ
+3BebYhtF8GaV0nxvwuo77x/Py9auJ/GpsMiu/X1+mvoiBOv/2X/qkSsisRcOj/KK
+NFtY2PwByVS5uCbMiogziUwthDyC3+6WVwW6LLv3xLfHTjuCvjHIInNzktHCgKQ5
+ORAzI4JMPJ+GslWYHb4phowim57iaztXOoJwTdwJx4nLCgdNbOhdjsnvzqvHu7Ur
+TkXWStAmzOVyyghqpZXjFaH3pO3JLF+l+/+sKAIuvtd7u+Nxe5AW0wdeRlN8NwdC
+jNPElpzVmbUq4JUagEiuTDkHzsxHpFKVK7q4+63SM1N95R1NbdWhscdCb+ZAJzVc
+oyi3B43njTOQ5yOf+1CceWxG1bQVs5ZufpsMljq4Ui0/1lvh+wjChP4kqKOJ2qxq
+4RgqsahDYVvTH9w7jXbyLeiNdd8XM2w9U/t7y0Ff/9yi0GE44Za4rF2LN9d11TPA
+mRGunUHBcnWEvgJBQl9nJEiU0Zsnvgc/ubhPgXRR4Xq37Z0j4r7g1SgEEzwxA57d
+emyPxgcYxn/eR44/KJ4EBs+lVDR3veyJm+kXQ99b21/+jh5Xos1AnX5iItreGCc=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem
new file mode 100644
index 00000000000..4ca27a47e47
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 05:f7:0e:86:da:49:f3:46:35:2e:ba:b2
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global Certification Authority
+ Validity
+ Not Before: Aug 23 19:34:12 2017 GMT
+ Not After : Aug 23 19:34:12 2042 GMT
+ Subject: C = US, ST = Illinois, L = Chicago, O = "Trustwave Holdings, Inc.", CN = Trustwave Global Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b9:5d:51:28:4b:3c:37:92:d1:82:ce:bd:1d:bd:
+ cd:dd:b8:ab:cf:0a:3e:e1:5d:e5:dc:aa:09:b9:57:
+ 02:3e:e6:63:61:df:f2:0f:82:63:ae:a3:f7:ac:73:
+ d1:7c:e7:b3:0b:af:08:00:09:59:7f:cd:29:2a:88:
+ 93:87:17:18:80:ed:88:b2:b4:b6:10:1f:2d:d6:5f:
+ 55:a2:13:5d:d1:c6:eb:06:56:89:88:fe:ac:32:9d:
+ fd:5c:c3:05:c7:6e:ee:86:89:ba:88:03:9d:72:21:
+ 86:90:ae:8f:03:a5:dc:9f:88:28:cb:a3:92:49:0f:
+ ec:d0:0f:e2:6d:44:4f:80:6a:b2:d4:e7:a0:0a:53:
+ 01:ba:8e:97:91:76:6e:bc:fc:d5:6b:36:e6:40:88:
+ d6:7b:2f:5f:05:e8:2c:6d:11:f3:e7:b2:be:92:44:
+ 4c:d2:97:a4:fe:d2:72:81:43:07:9c:e9:11:3e:f5:
+ 8b:1a:59:7d:1f:68:58:dd:04:00:2c:96:f3:43:b3:
+ 7e:98:19:74:d9:9c:73:d9:18:be:41:c7:34:79:d9:
+ f4:62:c2:43:b9:b3:27:b0:22:cb:f9:3d:52:c7:30:
+ 47:b3:c9:3e:b8:6a:e2:e7:e8:81:70:5e:42:8b:4f:
+ 26:a5:fe:3a:c2:20:6e:bb:f8:16:8e:cd:0c:a9:b4:
+ 1b:6c:76:10:e1:58:79:46:3e:54:ce:80:a8:57:09:
+ 37:29:1b:99:13:8f:0c:c8:d6:2c:1c:fb:05:e8:08:
+ 95:3d:65:46:dc:ee:cd:69:e2:4d:8f:87:28:4e:34:
+ 0b:3e:cf:14:d9:bb:dd:b6:50:9a:ad:77:d4:19:d6:
+ da:1a:88:c8:4e:1b:27:75:d8:b2:08:f1:ae:83:30:
+ b9:11:0e:cd:87:f0:84:8d:15:72:7c:a1:ef:cc:f2:
+ 88:61:ba:f4:69:bb:0c:8c:0b:75:57:04:b8:4e:2a:
+ 14:2e:3d:0f:1c:1e:32:a6:62:36:ee:66:e2:22:b8:
+ 05:40:63:10:22:f3:33:1d:74:72:8a:2c:f5:39:29:
+ a0:d3:e7:1b:80:84:2d:c5:3d:e3:4d:b1:fd:1a:6f:
+ ba:65:07:3b:58:ec:42:45:26:fb:d8:da:25:72:c4:
+ f6:00:b1:22:79:bd:e3:7c:59:62:4a:9c:05:6f:3d:
+ ce:e6:d6:47:63:99:c6:24:6f:72:12:c8:ac:7f:90:
+ b4:0b:91:70:e8:b7:e6:16:10:71:17:ce:de:06:4f:
+ 48:41:7d:35:4a:a3:89:f2:c9:4b:7b:41:11:6d:67:
+ b7:08:98:4c:e5:11:19:ae:42:80:dc:fb:90:05:d4:
+ f8:50:ca:be:e4:ad:c7:c2:94:d7:16:9d:e6:17:8f:
+ af:36:fb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 99:E0:19:67:0D:62:DB:76:B3:DA:3D:B8:5B:E8:FD:42:D2:31:0E:87
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 98:73:70:e2:b0:d3:ed:39:ec:4c:60:d9:a9:12:86:17:1e:96:
+ d0:e8:54:28:3b:64:2d:21:a6:f8:9d:56:13:6a:48:3d:4f:c7:
+ 3e:29:db:6d:58:83:54:3d:87:7d:23:05:d4:e4:1c:dc:e8:38:
+ 65:86:c5:75:a7:5a:db:35:05:bd:77:de:bb:29:37:40:05:07:
+ c3:94:52:9f:ca:64:dd:f1:1b:2b:dc:46:0a:10:02:31:fd:4a:
+ 68:0d:07:64:90:e6:1e:f5:2a:a1:a8:bb:3c:5d:f9:a3:08:0b:
+ 11:0c:f1:3f:2d:10:94:6f:fe:e2:34:87:83:d6:cf:e5:1b:35:
+ 6d:d2:03:e1:b0:0d:a8:a0:aa:46:27:82:36:a7:15:b6:08:a6:
+ 42:54:57:b6:99:5a:e2:0b:79:90:d7:57:12:51:35:19:88:41:
+ 68:25:d4:37:17:84:15:fb:01:72:dc:95:de:52:26:20:98:26:
+ e2:76:f5:27:6f:fa:00:3b:4a:61:d9:0d:cb:51:93:2a:fd:16:
+ 06:96:a7:23:9a:23:48:fe:51:bd:b6:c4:b0:b1:54:ce:de:6c:
+ 41:ad:16:67:7e:db:fd:38:cd:b9:38:4e:b2:c1:60:cb:9d:17:
+ df:58:9e:7a:62:b2:26:8f:74:95:9b:e4:5b:1d:d2:0f:dd:98:
+ 1c:9b:59:b9:23:d3:31:a0:a6:ff:38:dd:cf:20:4f:e9:58:56:
+ 3a:67:c3:d1:f6:99:99:9d:ba:36:b6:80:2f:88:47:4f:86:bf:
+ 44:3a:80:e4:37:1c:a6:ba:ea:97:98:11:d0:84:62:47:64:1e:
+ aa:ee:40:bf:34:b1:9c:8f:4e:e1:f2:92:4f:1f:8e:f3:9e:97:
+ de:f3:a6:79:6a:89:71:4f:4b:27:17:48:fe:ec:f4:50:0f:4f:
+ 49:7d:cc:45:e3:bd:7a:40:c5:41:dc:61:56:27:06:69:e5:72:
+ 41:81:d3:b6:01:89:a0:2f:3a:72:79:fe:3a:30:bf:41:ec:c7:
+ 62:3e:91:4b:c7:d9:31:76:42:f9:f7:3c:63:ec:26:8c:73:0c:
+ 7d:1a:1d:ea:a8:7c:87:a8:c2:27:7c:e1:33:41:0f:cf:cf:fc:
+ 00:a0:22:80:9e:4a:a7:6f:00:b0:41:45:b7:22:ca:68:48:c5:
+ 42:a2:ae:dd:1d:f2:e0:6e:4e:05:58:b1:c0:90:16:2a:a4:3d:
+ 10:40:be:8f:62:63:83:a9:9c:82:7d:2d:02:e9:83:30:7c:cb:
+ 27:c9:fd:1e:66:00:b0:2e:d3:21:2f:8e:33:16:6c:98:ed:10:
+ a8:07:d6:cc:93:cf:db:d1:69:1c:e4:ca:c9:e0:b6:9c:e9:ce:
+ 71:71:de:6c:3f:16:a4:79
+-----BEGIN CERTIFICATE-----
+MIIF2jCCA8KgAwIBAgIMBfcOhtpJ80Y1LrqyMA0GCSqGSIb3DQEBCwUAMIGIMQsw
+CQYDVQQGEwJVUzERMA8GA1UECAwISWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28x
+ITAfBgNVBAoMGFRydXN0d2F2ZSBIb2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1
+c3R3YXZlIEdsb2JhbCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xNzA4MjMx
+OTM0MTJaFw00MjA4MjMxOTM0MTJaMIGIMQswCQYDVQQGEwJVUzERMA8GA1UECAwI
+SWxsaW5vaXMxEDAOBgNVBAcMB0NoaWNhZ28xITAfBgNVBAoMGFRydXN0d2F2ZSBI
+b2xkaW5ncywgSW5jLjExMC8GA1UEAwwoVHJ1c3R3YXZlIEdsb2JhbCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
+ALldUShLPDeS0YLOvR29zd24q88KPuFd5dyqCblXAj7mY2Hf8g+CY66j96xz0Xzn
+swuvCAAJWX/NKSqIk4cXGIDtiLK0thAfLdZfVaITXdHG6wZWiYj+rDKd/VzDBcdu
+7oaJuogDnXIhhpCujwOl3J+IKMujkkkP7NAP4m1ET4BqstTnoApTAbqOl5F2brz8
+1Ws25kCI1nsvXwXoLG0R8+eyvpJETNKXpP7ScoFDB5zpET71ixpZfR9oWN0EACyW
+80OzfpgZdNmcc9kYvkHHNHnZ9GLCQ7mzJ7Aiy/k9UscwR7PJPrhq4ufogXBeQotP
+JqX+OsIgbrv4Fo7NDKm0G2x2EOFYeUY+VM6AqFcJNykbmROPDMjWLBz7BegIlT1l
+RtzuzWniTY+HKE40Cz7PFNm73bZQmq131BnW2hqIyE4bJ3XYsgjxroMwuREOzYfw
+hI0Vcnyh78zyiGG69Gm7DIwLdVcEuE4qFC49DxweMqZiNu5m4iK4BUBjECLzMx10
+coos9TkpoNPnG4CELcU9402x/RpvumUHO1jsQkUm+9jaJXLE9gCxInm943xZYkqc
+BW89zubWR2OZxiRvchLIrH+QtAuRcOi35hYQcRfO3gZPSEF9NUqjifLJS3tBEW1n
+twiYTOURGa5CgNz7kAXU+FDKvuStx8KU1xad5hePrzb7AgMBAAGjQjBAMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFJngGWcNYtt2s9o9uFvo/ULSMQ6HMA4GA1Ud
+DwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAmHNw4rDT7TnsTGDZqRKGFx6W
+0OhUKDtkLSGm+J1WE2pIPU/HPinbbViDVD2HfSMF1OQc3Og4ZYbFdada2zUFvXfe
+uyk3QAUHw5RSn8pk3fEbK9xGChACMf1KaA0HZJDmHvUqoai7PF35owgLEQzxPy0Q
+lG/+4jSHg9bP5Rs1bdID4bANqKCqRieCNqcVtgimQlRXtpla4gt5kNdXElE1GYhB
+aCXUNxeEFfsBctyV3lImIJgm4nb1J2/6ADtKYdkNy1GTKv0WBpanI5ojSP5RvbbE
+sLFUzt5sQa0WZ37b/TjNuThOssFgy50X31ieemKyJo90lZvkWx3SD92YHJtZuSPT
+MaCm/zjdzyBP6VhWOmfD0faZmZ26NraAL4hHT4a/RDqA5Dccprrql5gR0IRiR2Qe
+qu5AvzSxnI9O4fKSTx+O856X3vOmeWqJcU9LJxdI/uz0UA9PSX3MReO9ekDFQdxh
+VicGaeVyQYHTtgGJoC86cnn+OjC/QezHYj6RS8fZMXZC+fc8Y+wmjHMMfRod6qh8
+h6jCJ3zhM0EPz8/8AKAigJ5Kp28AsEFFtyLKaEjFQqKu3R3y4G5OBVixwJAWKqQ9
+EEC+j2Jjg6mcgn0tAumDMHzLJ8n9HmYAsC7TIS+OMxZsmO0QqAfWzJPP29FpHOTK
+yeC2nOnOcXHebD8WpHk=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem
new file mode 100644
index 00000000000..562f6f0e683
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem
@@ -0,0 +1,118 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = NO, O = Buypass AS-983163327, CN = Buypass Class 2 Root CA
+ Validity
+ Not Before: Oct 26 08:38:03 2010 GMT
+ Not After : Oct 26 08:38:03 2040 GMT
+ Subject: C = NO, O = Buypass AS-983163327, CN = Buypass Class 2 Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:d7:c7:5e:f7:c1:07:d4:77:fb:43:21:f4:f4:f5:
+ 69:e4:ee:32:01:db:a3:86:1f:e4:59:0d:ba:e7:75:
+ 83:52:eb:ea:1c:61:15:48:bb:1d:07:ca:8c:ae:b0:
+ dc:96:9d:ea:c3:60:92:86:82:28:73:9c:56:06:ff:
+ 4b:64:f0:0c:2a:37:49:b5:e5:cf:0c:7c:ee:f1:4a:
+ bb:73:30:65:f3:d5:2f:83:b6:7e:e3:e7:f5:9e:ab:
+ 60:f9:d3:f1:9d:92:74:8a:e4:1c:96:ac:5b:80:e9:
+ b5:f4:31:87:a3:51:fc:c7:7e:a1:6f:8e:53:77:d4:
+ 97:c1:55:33:92:3e:18:2f:75:d4:ad:86:49:cb:95:
+ af:54:06:6c:d8:06:13:8d:5b:ff:e1:26:19:59:c0:
+ 24:ba:81:71:79:90:44:50:68:24:94:5f:b8:b3:11:
+ f1:29:41:61:a3:41:cb:23:36:d5:c1:f1:32:50:10:
+ 4e:7f:f4:86:93:ec:84:d3:8e:bc:4b:bf:5c:01:4e:
+ 07:3d:dc:14:8a:94:0a:a4:ea:73:fb:0b:51:e8:13:
+ 07:18:fa:0e:f1:2b:d1:54:15:7d:3c:e1:f7:b4:19:
+ 42:67:62:5e:77:e0:a2:55:ec:b6:d9:69:17:d5:3a:
+ af:44:ed:4a:c5:9e:e4:7a:27:7c:e5:75:d7:aa:cb:
+ 25:e7:df:6b:0a:db:0f:4d:93:4e:a8:a0:cd:7b:2e:
+ f2:59:01:6a:b7:0d:b8:07:81:7e:8b:38:1b:38:e6:
+ 0a:57:99:3d:ee:21:e8:a3:f5:0c:16:dd:8b:ec:34:
+ 8e:9c:2a:1c:00:15:17:8d:68:83:d2:70:9f:18:08:
+ cd:11:68:d5:c9:6b:52:cd:c4:46:8f:dc:b5:f3:d8:
+ 57:73:1e:e9:94:39:04:bf:d3:de:38:de:b4:53:ec:
+ 69:1c:a2:7e:c4:8f:e4:1b:70:ad:f2:a2:f9:fb:f7:
+ 16:64:66:69:9f:49:51:a2:e2:15:18:67:06:4a:7f:
+ d5:6c:b5:4d:b3:33:e0:61:eb:5d:be:e9:98:0f:32:
+ d7:1d:4b:3c:2e:5a:01:52:91:09:f2:df:ea:8d:d8:
+ 06:40:63:aa:11:e4:fe:c3:37:9e:14:52:3f:f4:e2:
+ cc:f2:61:93:d1:fd:67:6b:d7:52:ae:bf:68:ab:40:
+ 43:a0:57:35:53:78:f0:53:f8:61:42:07:64:c6:d7:
+ 6f:9b:4c:38:0d:63:ac:62:af:36:8b:a2:73:0a:0d:
+ f5:21:bd:74:aa:4d:ea:72:03:49:db:c7:5f:1d:62:
+ 63:c7:fd:dd:91:ec:33:ee:f5:6d:b4:6e:30:68:de:
+ c8:d6:26:b0:75:5e:7b:b4:07:20:98:a1:76:32:b8:
+ 4d:6c:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ C9:80:77:E0:62:92:82:F5:46:9C:F3:BA:F7:4C:C3:DE:B8:A3:AD:39
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 53:5f:21:f5:ba:b0:3a:52:39:2c:92:b0:6c:00:c9:ef:ce:20:
+ ef:06:f2:96:9e:e9:a4:74:7f:7a:16:fc:b7:f5:b6:fb:15:1b:
+ 3f:ab:a6:c0:72:5d:10:b1:71:ee:bc:4f:e3:ad:ac:03:6d:2e:
+ 71:2e:af:c4:e3:ad:a3:bd:0c:11:a7:b4:ff:4a:b2:7b:10:10:
+ 1f:a7:57:41:b2:c0:ae:f4:2c:59:d6:47:10:88:f3:21:51:29:
+ 30:ca:60:86:af:46:ab:1d:ed:3a:5b:b0:94:de:44:e3:41:08:
+ a2:c1:ec:1d:d6:fd:4f:b6:d6:47:d0:14:0b:ca:e6:ca:b5:7b:
+ 77:7e:41:1f:5e:83:c7:b6:8c:39:96:b0:3f:96:81:41:6f:60:
+ 90:e2:e8:f9:fb:22:71:d9:7d:b3:3d:46:bf:b4:84:af:90:1c:
+ 0f:8f:12:6a:af:ef:ee:1e:7a:ae:02:4a:8a:17:2b:76:fe:ac:
+ 54:89:24:2c:4f:3f:b6:b2:a7:4e:8c:a8:91:97:fb:29:c6:7b:
+ 5c:2d:b9:cb:66:b6:b7:a8:5b:12:51:85:b5:09:7e:62:78:70:
+ fe:a9:6a:60:b6:1d:0e:79:0c:fd:ca:ea:24:80:72:c3:97:3f:
+ f2:77:ab:43:22:0a:c7:eb:b6:0c:84:82:2c:80:6b:41:8a:08:
+ c0:eb:a5:6b:df:99:12:cb:8a:d5:5e:80:0c:91:e0:26:08:36:
+ 48:c5:fa:38:11:35:ff:25:83:2d:f2:7a:bf:da:fd:8e:fe:a5:
+ cb:45:2c:1f:c4:88:53:ae:77:0e:d9:9a:76:c5:8e:2c:1d:a3:
+ ba:d5:ec:32:ae:c0:aa:ac:f7:d1:7a:4d:eb:d4:07:e2:48:f7:
+ 22:8e:b0:a4:9f:6a:ce:8e:b2:b2:60:f4:a3:22:d0:23:eb:94:
+ 5a:7a:69:dd:0f:bf:40:57:ac:6b:59:50:d9:a3:99:e1:6e:fe:
+ 8d:01:79:27:23:15:de:92:9d:7b:09:4d:5a:e7:4b:48:30:5a:
+ 18:e6:0a:6d:e6:8f:e0:d2:bb:e6:df:7c:6e:21:82:c1:68:39:
+ 4d:b4:98:58:66:62:cc:4a:90:5e:c3:fa:27:04:b1:79:15:74:
+ 99:cc:be:ad:20:de:26:60:1c:eb:56:51:a6:a3:ea:e4:a3:3f:
+ a7:ff:61:dc:f1:5a:4d:6c:32:23:43:ee:ac:a8:ee:ee:4a:12:
+ 09:3c:5d:71:c2:be:79:fa:c2:87:68:1d:0b:fd:5c:69:cc:06:
+ d0:9a:7d:54:99:2a:c9:39:1a:19:af:4b:2a:43:f3:63:5d:5a:
+ 58:e2:2f:e3:1d:e4:a9:d6:d0:0a:d0:9e:bf:d7:81:09:f1:c9:
+ c7:26:0d:ac:98:16:56:a0
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMiBSb290IENBMB4XDTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1ow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1g1Lr
+6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPV
+L4O2fuPn9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC91
+1K2GScuVr1QGbNgGE41b/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHx
+MlAQTn/0hpPshNOOvEu/XAFOBz3cFIqUCqTqc/sLUegTBxj6DvEr0VQVfTzh97QZ
+QmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeffawrbD02TTqigzXsu8lkB
+arcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgIzRFo1clr
+Us3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLi
+FRhnBkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRS
+P/TizPJhk9H9Z2vXUq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN
+9SG9dKpN6nIDSdvHXx1iY8f93ZHsM+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxP
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMmAd+BikoL1Rpzz
+uvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAU18h
+9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3t
+OluwlN5E40EIosHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo
++fsicdl9sz1Gv7SEr5AcD48Saq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7
+KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYdDnkM/crqJIByw5c/8nerQyIKx+u2
+DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWDLfJ6v9r9jv6ly0Us
+H8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0oyLQ
+I+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK7
+5t98biGCwWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h
+3PFaTWwyI0PurKju7koSCTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPz
+Y11aWOIv4x3kqdbQCtCev9eBCfHJxyYNrJgWVqA=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem
new file mode 100644
index 00000000000..68b4f4b8e3e
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem
@@ -0,0 +1,151 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6828503384748696800 (0x5ec3b7a6437fa4e0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES
+ Validity
+ Not Before: May 5 09:37:37 2011 GMT
+ Not After : Dec 31 09:37:37 2030 GMT
+ Subject: CN = ACCVRAIZ1, OU = PKIACCV, O = ACCV, C = ES
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:9b:a9:ab:bf:61:4a:97:af:2f:97:66:9a:74:5f:
+ d0:d9:96:fd:cf:e2:e4:66:ef:1f:1f:47:33:c2:44:
+ a3:df:9a:de:1f:b5:54:dd:15:7c:69:35:11:6f:bb:
+ c8:0c:8e:6a:18:1e:d8:8f:d9:16:bc:10:48:36:5c:
+ f0:63:b3:90:5a:5c:24:37:d7:a3:d6:cb:09:71:b9:
+ f1:01:72:84:b0:7d:db:4d:80:cd:fc:d3:6f:c9:f8:
+ da:b6:0e:82:d2:45:85:a8:1b:68:a8:3d:e8:f4:44:
+ 6c:bd:a1:c2:cb:03:be:8c:3e:13:00:84:df:4a:48:
+ c0:e3:22:0a:e8:e9:37:a7:18:4c:b1:09:0d:23:56:
+ 7f:04:4d:d9:17:84:18:a5:c8:da:40:94:73:eb:ce:
+ 0e:57:3c:03:81:3a:9d:0a:a1:57:43:69:ac:57:6d:
+ 79:90:78:e5:b5:b4:3b:d8:bc:4c:8d:28:a1:a7:a3:
+ a7:ba:02:4e:25:d1:2a:ae:ed:ae:03:22:b8:6b:20:
+ 0f:30:28:54:95:7f:e0:ee:ce:0a:66:9d:d1:40:2d:
+ 6e:22:af:9d:1a:c1:05:19:d2:6f:c0:f2:9f:f8:7b:
+ b3:02:42:fb:50:a9:1d:2d:93:0f:23:ab:c6:c1:0f:
+ 92:ff:d0:a2:15:f5:53:09:71:1c:ff:45:13:84:e6:
+ 26:5e:f8:e0:88:1c:0a:fc:16:b6:a8:73:06:b8:f0:
+ 63:84:02:a0:c6:5a:ec:e7:74:df:70:ae:a3:83:25:
+ ea:d6:c7:97:87:93:a7:c6:8a:8a:33:97:60:37:10:
+ 3e:97:3e:6e:29:15:d6:a1:0f:d1:88:2c:12:9f:6f:
+ aa:a4:c6:42:eb:41:a2:e3:95:43:d3:01:85:6d:8e:
+ bb:3b:f3:23:36:c7:fe:3b:e0:a1:25:07:48:ab:c9:
+ 89:74:ff:08:8f:80:bf:c0:96:65:f3:ee:ec:4b:68:
+ bd:9d:88:c3:31:b3:40:f1:e8:cf:f6:38:bb:9c:e4:
+ d1:7f:d4:e5:58:9b:7c:fa:d4:f3:0e:9b:75:91:e4:
+ ba:52:2e:19:7e:d1:f5:cd:5a:19:fc:ba:06:f6:fb:
+ 52:a8:4b:99:04:dd:f8:f9:b4:8b:50:a3:4e:62:89:
+ f0:87:24:fa:83:42:c1:87:fa:d5:2d:29:2a:5a:71:
+ 7a:64:6a:d7:27:60:63:0d:db:ce:49:f5:8d:1f:90:
+ 89:32:17:f8:73:43:b8:d2:5a:93:86:61:d6:e1:75:
+ 0a:ea:79:66:76:88:4f:71:eb:04:25:d6:0a:5a:7a:
+ 93:e5:b9:4b:17:40:0f:b1:b6:b9:f5:de:4f:dc:e0:
+ b3:ac:3b:11:70:60:84:4a:43:6e:99:20:c0:29:71:
+ 0a:c0:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ CA Issuers - URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1.crt
+ OCSP - URI:http://ocsp.accv.es
+
+ X509v3 Subject Key Identifier:
+ D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:D2:87:B4:E3:DF:37:27:93:55:F6:56:EA:81:E5:36:CC:8C:1E:3F:BD
+
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ User Notice:
+ Explicit Text:
+ CPS: http://www.accv.es/legislacion_c.htm
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://www.accv.es/fileadmin/Archivos/certificados/raizaccv1_der.crl
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Alternative Name:
+ email:accv@accv.es
+ Signature Algorithm: sha1WithRSAEncryption
+ 97:31:02:9f:e7:fd:43:67:48:44:14:e4:29:87:ed:4c:28:66:
+ d0:8f:35:da:4d:61:b7:4a:97:4d:b5:db:90:e0:05:2e:0e:c6:
+ 79:d0:f2:97:69:0f:bd:04:47:d9:be:db:b5:29:da:9b:d9:ae:
+ a9:99:d5:d3:3c:30:93:f5:8d:a1:a8:fc:06:8d:44:f4:ca:16:
+ 95:7c:33:dc:62:8b:a8:37:f8:27:d8:09:2d:1b:ef:c8:14:27:
+ 20:a9:64:44:ff:2e:d6:75:aa:6c:4d:60:40:19:49:43:54:63:
+ da:e2:cc:ba:66:e5:4f:44:7a:5b:d9:6a:81:2b:40:d5:7f:f9:
+ 01:27:58:2c:c8:ed:48:91:7c:3f:a6:00:cf:c4:29:73:11:36:
+ de:86:19:3e:9d:ee:19:8a:1b:d5:b0:ed:8e:3d:9c:2a:c0:0d:
+ d8:3d:66:e3:3c:0d:bd:d5:94:5c:e2:e2:a7:35:1b:04:00:f6:
+ 3f:5a:8d:ea:43:bd:5f:89:1d:a9:c1:b0:cc:99:e2:4d:00:0a:
+ da:c9:27:5b:e7:13:90:5c:e4:f5:33:a2:55:6d:dc:e0:09:4d:
+ 2f:b1:26:5b:27:75:00:09:c4:62:77:29:08:5f:9e:59:ac:b6:
+ 7e:ad:9f:54:30:22:03:c1:1e:71:64:fe:f9:38:0a:96:18:dd:
+ 02:14:ac:23:cb:06:1c:1e:a4:7d:8d:0d:de:27:41:e8:ad:da:
+ 15:b7:b0:23:dd:2b:a8:d3:da:25:87:ed:e8:55:44:4d:88:f4:
+ 36:7e:84:9a:78:ac:f7:0e:56:49:0e:d6:33:25:d6:84:50:42:
+ 6c:20:12:1d:2a:d5:be:bc:f2:70:81:a4:70:60:be:05:b5:9b:
+ 9e:04:44:be:61:23:ac:e9:a5:24:8c:11:80:94:5a:a2:a2:b9:
+ 49:d2:c1:dc:d1:a7:ed:31:11:2c:9e:19:a6:ee:e1:55:e1:c0:
+ ea:cf:0d:84:e4:17:b7:a2:7c:a5:de:55:25:06:ee:cc:c0:87:
+ 5c:40:da:cc:95:3f:55:e0:35:c7:b8:84:be:b4:5d:cd:7a:83:
+ 01:72:ee:87:e6:5f:1d:ae:b5:85:c6:26:df:e6:c1:9a:e9:1e:
+ 02:47:9f:2a:a8:6d:a9:5b:cf:ec:45:77:7f:98:27:9a:32:5d:
+ 2a:e3:84:ee:c5:98:66:2f:96:20:1d:dd:d8:c3:27:d7:b0:f9:
+ fe:d9:7d:cd:d0:9f:8f:0b:14:58:51:9f:2f:8b:c3:38:2d:de:
+ e8:8f:d6:8d:87:a4:f5:56:43:16:99:2c:f4:a4:56:b4:34:b8:
+ 61:37:c9:c2:58:80:1b:a0:97:a1:fc:59:8d:e9:11:f6:d1:0f:
+ 4b:55:34:46:2a:8b:86:3b
+-----BEGIN CERTIFICATE-----
+MIIH0zCCBbugAwIBAgIIXsO3pkN/pOAwDQYJKoZIhvcNAQEFBQAwQjESMBAGA1UE
+AwwJQUNDVlJBSVoxMRAwDgYDVQQLDAdQS0lBQ0NWMQ0wCwYDVQQKDARBQ0NWMQsw
+CQYDVQQGEwJFUzAeFw0xMTA1MDUwOTM3MzdaFw0zMDEyMzEwOTM3MzdaMEIxEjAQ
+BgNVBAMMCUFDQ1ZSQUlaMTEQMA4GA1UECwwHUEtJQUNDVjENMAsGA1UECgwEQUND
+VjELMAkGA1UEBhMCRVMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCb
+qau/YUqXry+XZpp0X9DZlv3P4uRm7x8fRzPCRKPfmt4ftVTdFXxpNRFvu8gMjmoY
+HtiP2Ra8EEg2XPBjs5BaXCQ316PWywlxufEBcoSwfdtNgM3802/J+Nq2DoLSRYWo
+G2ioPej0RGy9ocLLA76MPhMAhN9KSMDjIgro6TenGEyxCQ0jVn8ETdkXhBilyNpA
+lHPrzg5XPAOBOp0KoVdDaaxXbXmQeOW1tDvYvEyNKKGno6e6Ak4l0Squ7a4DIrhr
+IA8wKFSVf+DuzgpmndFALW4ir50awQUZ0m/A8p/4e7MCQvtQqR0tkw8jq8bBD5L/
+0KIV9VMJcRz/RROE5iZe+OCIHAr8Fraocwa48GOEAqDGWuzndN9wrqODJerWx5eH
+k6fGioozl2A3ED6XPm4pFdahD9GILBKfb6qkxkLrQaLjlUPTAYVtjrs78yM2x/47
+4KElB0iryYl0/wiPgL/AlmXz7uxLaL2diMMxs0Dx6M/2OLuc5NF/1OVYm3z61PMO
+m3WR5LpSLhl+0fXNWhn8ugb2+1KoS5kE3fj5tItQo05iifCHJPqDQsGH+tUtKSpa
+cXpkatcnYGMN285J9Y0fkIkyF/hzQ7jSWpOGYdbhdQrqeWZ2iE9x6wQl1gpaepPl
+uUsXQA+xtrn13k/c4LOsOxFwYIRKQ26ZIMApcQrAZQIDAQABo4ICyzCCAscwfQYI
+KwYBBQUHAQEEcTBvMEwGCCsGAQUFBzAChkBodHRwOi8vd3d3LmFjY3YuZXMvZmls
+ZWFkbWluL0FyY2hpdm9zL2NlcnRpZmljYWRvcy9yYWl6YWNjdjEuY3J0MB8GCCsG
+AQUFBzABhhNodHRwOi8vb2NzcC5hY2N2LmVzMB0GA1UdDgQWBBTSh7Tj3zcnk1X2
+VuqB5TbMjB4/vTAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFNKHtOPfNyeT
+VfZW6oHlNsyMHj+9MIIBcwYDVR0gBIIBajCCAWYwggFiBgRVHSAAMIIBWDCCASIG
+CCsGAQUFBwICMIIBFB6CARAAQQB1AHQAbwByAGkAZABhAGQAIABkAGUAIABDAGUA
+cgB0AGkAZgBpAGMAYQBjAGkA8wBuACAAUgBhAO0AegAgAGQAZQAgAGwAYQAgAEEA
+QwBDAFYAIAAoAEEAZwBlAG4AYwBpAGEAIABkAGUAIABUAGUAYwBuAG8AbABvAGcA
+7QBhACAAeQAgAEMAZQByAHQAaQBmAGkAYwBhAGMAaQDzAG4AIABFAGwAZQBjAHQA
+cgDzAG4AaQBjAGEALAAgAEMASQBGACAAUQA0ADYAMAAxADEANQA2AEUAKQAuACAA
+QwBQAFMAIABlAG4AIABoAHQAdABwADoALwAvAHcAdwB3AC4AYQBjAGMAdgAuAGUA
+czAwBggrBgEFBQcCARYkaHR0cDovL3d3dy5hY2N2LmVzL2xlZ2lzbGFjaW9uX2Mu
+aHRtMFUGA1UdHwROMEwwSqBIoEaGRGh0dHA6Ly93d3cuYWNjdi5lcy9maWxlYWRt
+aW4vQXJjaGl2b3MvY2VydGlmaWNhZG9zL3JhaXphY2N2MV9kZXIuY3JsMA4GA1Ud
+DwEB/wQEAwIBBjAXBgNVHREEEDAOgQxhY2N2QGFjY3YuZXMwDQYJKoZIhvcNAQEF
+BQADggIBAJcxAp/n/UNnSEQU5CmH7UwoZtCPNdpNYbdKl02125DgBS4OxnnQ8pdp
+D70ER9m+27Up2pvZrqmZ1dM8MJP1jaGo/AaNRPTKFpV8M9xii6g3+CfYCS0b78gU
+JyCpZET/LtZ1qmxNYEAZSUNUY9rizLpm5U9EelvZaoErQNV/+QEnWCzI7UiRfD+m
+AM/EKXMRNt6GGT6d7hmKG9Ww7Y49nCrADdg9ZuM8Db3VlFzi4qc1GwQA9j9ajepD
+vV+JHanBsMyZ4k0ACtrJJ1vnE5Bc5PUzolVt3OAJTS+xJlsndQAJxGJ3KQhfnlms
+tn6tn1QwIgPBHnFk/vk4CpYY3QIUrCPLBhwepH2NDd4nQeit2hW3sCPdK6jT2iWH
+7ehVRE2I9DZ+hJp4rPcOVkkO1jMl1oRQQmwgEh0q1b688nCBpHBgvgW1m54ERL5h
+I6zppSSMEYCUWqKiuUnSwdzRp+0xESyeGabu4VXhwOrPDYTkF7eifKXeVSUG7szA
+h1xA2syVP1XgNce4hL60Xc16gwFy7ofmXx2utYXGJt/mwZrpHgJHnyqobalbz+xF
+d3+YJ5oyXSrjhO7FmGYvliAd3djDJ9ew+f7Zfc3Qn48LFFhRny+Lwzgt3uiP1o2H
+pPVWQxaZLPSkVrQ0uGE3ycJYgBugl6H8WY3pEfbRD0tVNEYqi4Y7
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem
new file mode 100644
index 00000000000..93caac99427
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 5d:df:b1:da:5a:a3:ed:5d:be:5a:65:20:65:03:90:ef
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = CN, O = UniTrust, CN = UCA Global G2 Root
+ Validity
+ Not Before: Mar 11 00:00:00 2016 GMT
+ Not After : Dec 31 00:00:00 2040 GMT
+ Subject: C = CN, O = UniTrust, CN = UCA Global G2 Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c5:e6:2b:6f:7c:ef:26:05:27:a3:81:24:da:6f:
+ cb:01:f9:99:9a:a9:32:c2:22:87:61:41:91:3b:cb:
+ c3:68:1b:06:c5:4c:a9:2b:c1:67:17:22:1d:2b:ed:
+ f9:29:89:93:a2:78:bd:92:6b:a0:a3:0d:a2:7e:ca:
+ 93:b3:a6:d1:8c:35:d5:75:f9:17:f6:cf:45:c5:e5:
+ 7a:ec:77:93:a0:8f:23:ae:0e:1a:03:7f:be:d4:d0:
+ ed:2e:7b:ab:46:23:5b:ff:2c:e6:54:7a:94:c0:2a:
+ 15:f0:c9:8d:b0:7a:3b:24:e1:d7:68:e2:31:3c:06:
+ 33:46:b6:54:11:a6:a5:2f:22:54:2a:58:0d:01:02:
+ f1:fa:15:51:67:6c:c0:fa:d7:b6:1b:7f:d1:56:88:
+ 2f:1a:3a:8d:3b:bb:82:11:e0:47:00:d0:52:87:ab:
+ fb:86:7e:0f:24:6b:40:9d:34:67:bc:8d:c7:2d:86:
+ 6f:79:3e:8e:a9:3c:17:4b:7f:b0:99:e3:b0:71:60:
+ dc:0b:f5:64:c3:ce:43:bc:6d:71:b9:d2:de:27:5b:
+ 8a:e8:d8:c6:ae:e1:59:7d:cf:28:2d:35:b8:95:56:
+ 1a:f1:b2:58:4b:b7:12:37:c8:7c:b3:ed:4b:80:e1:
+ 8d:fa:32:23:b6:6f:b7:48:95:08:b1:44:4e:85:8c:
+ 3a:02:54:20:2f:df:bf:57:4f:3b:3a:90:21:d7:c1:
+ 26:35:54:20:ec:c7:3f:47:ec:ef:5a:bf:4b:7a:c1:
+ ad:3b:17:50:5c:62:d8:0f:4b:4a:dc:2b:fa:6e:bc:
+ 73:92:cd:ec:c7:50:e8:41:96:d7:a9:7e:6d:d8:e9:
+ 1d:8f:8a:b5:b9:58:92:ba:4a:92:2b:0c:56:fd:80:
+ eb:08:f0:5e:29:6e:1b:1c:0c:af:8f:93:89:ad:db:
+ bd:a3:9e:21:ca:89:19:ec:df:b5:c3:1a:eb:16:fe:
+ 78:36:4c:d6:6e:d0:3e:17:1c:90:17:6b:26:ba:fb:
+ 7a:2f:bf:11:1c:18:0e:2d:73:03:8f:a0:e5:35:a0:
+ 5a:e2:4c:75:1d:71:e1:39:38:53:78:40:cc:83:93:
+ d7:0a:9e:9d:5b:8f:8a:e4:e5:e0:48:e4:48:b2:47:
+ cd:4e:2a:75:2a:7b:f2:22:f6:c9:be:09:91:96:57:
+ 7a:88:88:ac:ee:70:ac:f9:dc:29:e3:0c:1c:3b:12:
+ 4e:44:d6:a7:4e:b0:26:c8:f3:d9:1a:97:91:68:ea:
+ ef:8d:46:06:d2:56:45:58:9a:3c:0c:0f:83:b8:05:
+ 25:c3:39:cf:3b:a4:34:89:b7:79:12:2f:47:c5:e7:
+ a9:97:69:fc:a6:77:67:b5:df:7b:f1:7a:65:15:e4:
+ 61:56:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 81:C4:8C:CC:F5:E4:30:FF:A5:0C:08:5F:8C:15:67:21:74:01:DF:DF
+ Signature Algorithm: sha256WithRSAEncryption
+ 13:65:22:f5:8e:2b:ad:44:e4:cb:ff:b9:68:e6:c3:80:48:3d:
+ 04:7b:fa:23:2f:7a:ed:36:da:b2:ce:6d:f6:e6:9e:e5:5f:58:
+ 8f:cb:37:32:a1:c8:65:b6:ae:38:3d:35:1b:3e:bc:3b:b6:04:
+ d0:bc:f9:49:f5:9b:f7:85:c5:36:b6:cb:bc:f8:c8:39:d5:e4:
+ 5f:07:bd:15:54:97:74:ca:ca:ed:4f:ba:ba:64:76:9f:81:b8:
+ 84:45:49:4c:8d:6f:a2:eb:b1:cc:d1:c3:94:da:44:c2:e6:e2:
+ ea:18:e8:a2:1f:27:05:ba:d7:e5:d6:a9:cd:dd:ef:76:98:8d:
+ 00:0e:cd:1b:fa:03:b7:8e:80:58:0e:27:3f:52:fb:94:a2:ca:
+ 5e:65:c9:d6:84:da:b9:35:71:f3:26:c0:4f:77:e6:81:27:d2:
+ 77:3b:9a:14:6f:79:f4:f6:d0:e1:d3:94:ba:d0:57:51:bd:27:
+ 05:0d:c1:fd:c8:12:30:ee:6f:8d:11:2b:08:9d:d4:d4:bf:80:
+ 45:14:9a:88:44:da:30:ea:b4:a7:e3:ee:ef:5b:82:d5:3e:d6:
+ ad:78:92:db:5c:3c:f3:d8:ad:fa:b8:6b:7f:c4:36:28:b6:02:
+ 15:8a:54:2c:9c:b0:17:73:8e:d0:37:a3:14:3c:98:95:00:0c:
+ 29:05:5b:9e:49:49:b1:5f:c7:e3:cb:cf:27:65:8e:35:17:b7:
+ 57:c8:30:d9:41:5b:b9:14:b6:e8:c2:0f:94:31:a7:94:98:cc:
+ 6a:eb:b5:e1:27:f5:10:a8:01:e8:8e:12:62:e8:88:cc:b5:7f:
+ 46:97:c0:9b:10:66:38:1a:36:46:5f:22:68:3d:df:c9:c6:13:
+ 27:ab:53:06:ac:a2:3c:86:06:65:6f:b1:7e:b1:29:44:9a:a3:
+ ba:49:69:28:69:8f:d7:e5:5f:ad:04:86:64:6f:1a:a0:0c:c5:
+ 08:62:ce:80:a3:d0:f3:ec:68:de:be:33:c7:17:5b:7f:80:c4:
+ 4c:4c:b1:a6:84:8a:c3:3b:b8:09:cd:14:81:ba:18:e3:54:57:
+ 36:fe:db:2f:7c:47:a1:3a:33:c8:f9:58:3b:44:4f:b1:ca:02:
+ 89:04:96:28:68:c5:4b:b8:26:89:bb:d6:33:2f:50:d5:fe:9a:
+ 89:ba:18:32:92:54:c6:5b:e0:9d:f9:5e:e5:0d:22:9b:f6:da:
+ e2:c8:21:b2:62:21:aa:86:40:b2:2e:64:d3:5f:c8:e3:7e:11:
+ 67:45:1f:05:fe:e3:a2:ef:b3:a8:b3:f3:7d:8f:f8:0c:1f:22:
+ 1f:2d:70:b4:b8:01:34:76:30:00:e5:23:78:a7:56:d7:50:1f:
+ 8a:fb:06:f5:c2:19:f0:d0
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIQXd+x2lqj7V2+WmUgZQOQ7zANBgkqhkiG9w0BAQsFADA9
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxGzAZBgNVBAMMElVDQSBH
+bG9iYWwgRzIgUm9vdDAeFw0xNjAzMTEwMDAwMDBaFw00MDEyMzEwMDAwMDBaMD0x
+CzAJBgNVBAYTAkNOMREwDwYDVQQKDAhVbmlUcnVzdDEbMBkGA1UEAwwSVUNBIEds
+b2JhbCBHMiBSb290MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAxeYr
+b3zvJgUno4Ek2m/LAfmZmqkywiKHYUGRO8vDaBsGxUypK8FnFyIdK+35KYmToni9
+kmugow2ifsqTs6bRjDXVdfkX9s9FxeV67HeToI8jrg4aA3++1NDtLnurRiNb/yzm
+VHqUwCoV8MmNsHo7JOHXaOIxPAYzRrZUEaalLyJUKlgNAQLx+hVRZ2zA+te2G3/R
+VogvGjqNO7uCEeBHANBSh6v7hn4PJGtAnTRnvI3HLYZveT6OqTwXS3+wmeOwcWDc
+C/Vkw85DvG1xudLeJ1uK6NjGruFZfc8oLTW4lVYa8bJYS7cSN8h8s+1LgOGN+jIj
+tm+3SJUIsUROhYw6AlQgL9+/V087OpAh18EmNVQg7Mc/R+zvWr9LesGtOxdQXGLY
+D0tK3Cv6brxzks3sx1DoQZbXqX5t2Okdj4q1uViSukqSKwxW/YDrCPBeKW4bHAyv
+j5OJrdu9o54hyokZ7N+1wxrrFv54NkzWbtA+FxyQF2smuvt6L78RHBgOLXMDj6Dl
+NaBa4kx1HXHhOThTeEDMg5PXCp6dW4+K5OXgSORIskfNTip1KnvyIvbJvgmRlld6
+iIis7nCs+dwp4wwcOxJORNanTrAmyPPZGpeRaOrvjUYG0lZFWJo8DA+DuAUlwznP
+O6Q0ibd5Ei9Hxeepl2n8pndntd978XplFeRhVmUCAwEAAaNCMEAwDgYDVR0PAQH/
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFIHEjMz15DD/pQwIX4wV
+ZyF0Ad/fMA0GCSqGSIb3DQEBCwUAA4ICAQATZSL1jiutROTL/7lo5sOASD0Ee/oj
+L3rtNtqyzm325p7lX1iPyzcyochltq44PTUbPrw7tgTQvPlJ9Zv3hcU2tsu8+Mg5
+1eRfB70VVJd0ysrtT7q6ZHafgbiERUlMjW+i67HM0cOU2kTC5uLqGOiiHycFutfl
+1qnN3e92mI0ADs0b+gO3joBYDic/UvuUospeZcnWhNq5NXHzJsBPd+aBJ9J3O5oU
+b3n09tDh05S60FdRvScFDcH9yBIw7m+NESsIndTUv4BFFJqIRNow6rSn4+7vW4LV
+PtateJLbXDzz2K36uGt/xDYotgIVilQsnLAXc47QN6MUPJiVAAwpBVueSUmxX8fj
+y88nZY41F7dXyDDZQVu5FLbowg+UMaeUmMxq67XhJ/UQqAHojhJi6IjMtX9Gl8Cb
+EGY4GjZGXyJoPd/JxhMnq1MGrKI8hgZlb7F+sSlEmqO6SWkoaY/X5V+tBIZkbxqg
+DMUIYs6Ao9Dz7GjevjPHF1t/gMRMTLGmhIrDO7gJzRSBuhjjVFc2/tsvfEehOjPI
++Vg7RE+xygKJBJYoaMVLuCaJu9YzL1DV/pqJuhgyklTGW+Cd+V7lDSKb9triyCGy
+YiGqhkCyLmTTX8jjfhFnRR8F/uOi77Oos/N9j/gMHyIfLXC0uAE0djAA5SN4p1bX
+UB+K+wb1whnw0A==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem
new file mode 100644
index 00000000000..1c4d5dbc45f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = GR, L = Athens, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions RootCA 2015
+ Validity
+ Not Before: Jul 7 10:11:21 2015 GMT
+ Not After : Jun 30 10:11:21 2040 GMT
+ Subject: C = GR, L = Athens, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions RootCA 2015
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c2:f8:a9:3f:1b:89:fc:3c:3c:04:5d:3d:90:36:
+ b0:91:3a:79:3c:66:5a:ef:6d:39:01:49:1a:b4:b7:
+ cf:7f:4d:23:53:b7:90:00:e3:13:2a:28:a6:31:f1:
+ 91:00:e3:28:ec:ae:21:41:ce:1f:da:fd:7d:12:5b:
+ 01:83:0f:b9:b0:5f:99:e1:f2:12:83:80:4d:06:3e:
+ df:ac:af:e7:a1:88:6b:31:af:f0:8b:d0:18:33:b8:
+ db:45:6a:34:f4:02:80:24:28:0a:02:15:95:5e:76:
+ 2a:0d:99:3a:14:5b:f6:cb:cb:53:bc:13:4d:01:88:
+ 37:94:25:1b:42:bc:22:d8:8e:a3:96:5e:3a:d9:32:
+ db:3e:e8:f0:10:65:ed:74:e1:2f:a7:7c:af:27:34:
+ bb:29:7d:9b:b6:cf:09:c8:e5:d3:0a:fc:88:65:65:
+ 74:0a:dc:73:1c:5c:cd:40:b1:1c:d4:b6:84:8c:4c:
+ 50:cf:68:8e:a8:59:ae:c2:27:4e:82:a2:35:dd:14:
+ f4:1f:ff:b2:77:d5:87:2f:aa:6e:7d:24:27:e7:c6:
+ cb:26:e6:e5:fe:67:07:63:d8:45:0d:dd:3a:59:65:
+ 39:58:7a:92:99:72:3d:9c:84:5e:88:21:b8:d5:f4:
+ 2c:fc:d9:70:52:4f:78:b8:bd:3c:2b:8b:95:98:f5:
+ b3:d1:68:cf:20:14:7e:4c:5c:5f:e7:8b:e5:f5:35:
+ 81:19:37:d7:11:08:b7:66:be:d3:4a:ce:83:57:00:
+ 3a:c3:81:f8:17:cb:92:36:5d:d1:a3:d8:75:1b:e1:
+ 8b:27:ea:7a:48:41:fd:45:19:06:ad:27:99:4e:c1:
+ 70:47:dd:b5:9f:81:53:12:e5:b1:8c:48:5d:31:43:
+ 17:e3:8c:c6:7a:63:96:4b:29:30:4e:84:4e:62:19:
+ 5e:3c:ce:97:90:a5:7f:01:eb:9d:e0:f8:8b:89:dd:
+ 25:98:3d:92:b6:7e:ef:d9:f1:51:51:7d:2d:26:c8:
+ 69:59:61:e0:ac:6a:b8:2a:36:11:04:7a:50:bd:32:
+ 84:be:2f:dc:72:d5:d7:1d:16:47:e4:47:66:20:3f:
+ f4:96:c5:af:8e:01:7a:a5:0f:7a:64:f5:0d:18:87:
+ d9:ae:88:d5:fa:84:c1:3a:c0:69:28:2d:f2:0d:68:
+ 51:aa:e3:a5:77:c6:a4:90:0e:a1:37:8b:31:23:47:
+ c1:09:08:eb:6e:f7:78:9b:d7:82:fc:84:20:99:49:
+ 19:b6:12:46:b1:fb:45:55:16:a9:a3:65:ac:9c:07:
+ 0f:ea:6b:dc:1f:2e:06:72:ec:86:88:12:e4:2d:db:
+ 5f:05:2f:e4:f0:03:d3:26:33:e7:80:c2:cd:42:a1:
+ 17:34:0b
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 71:15:67:C8:C8:C9:BD:75:5D:72:D0:38:18:6A:9D:F3:71:24:54:0B
+ Signature Algorithm: sha256WithRSAEncryption
+ 75:bb:6d:54:4b:aa:10:58:46:34:f2:62:d7:16:36:5d:08:5e:
+ d5:6c:c8:87:bd:b4:2e:46:f2:31:f8:7c:ea:42:b5:93:16:55:
+ dc:a1:0c:12:a0:da:61:7e:0f:58:58:73:64:72:c7:e8:45:8e:
+ dc:a9:f2:26:3f:c6:79:8c:b1:53:08:33:81:b0:56:13:be:e6:
+ 51:5c:d8:9b:0a:4f:4b:9c:56:53:02:e9:4f:f6:0d:60:ea:4d:
+ 42:55:e8:7c:1b:21:21:d3:1b:3a:cc:77:f2:b8:90:f1:68:c7:
+ f9:5a:fe:fa:2d:f4:bf:c9:f5:45:1b:ce:38:10:2a:37:8a:79:
+ a3:b4:e3:09:6c:85:86:93:ff:89:96:27:78:81:8f:67:e3:46:
+ 74:54:8e:d9:0d:69:e2:4a:f4:4d:74:03:ff:b2:77:ed:95:67:
+ 97:e4:b1:c5:ab:bf:6a:23:e8:d4:94:e2:44:28:62:c4:4b:e2:
+ f0:d8:e2:29:6b:1a:70:7e:24:61:93:7b:4f:03:32:25:0d:45:
+ 24:2b:96:b4:46:6a:bf:4a:0b:f7:9a:8f:c1:ac:1a:c5:67:f3:
+ 6f:34:d2:fa:73:63:8c:ef:16:b0:a8:a4:46:2a:f8:eb:12:ec:
+ 72:b4:ef:f8:2b:7e:8c:52:c0:8b:84:54:f9:2f:3e:e3:55:a8:
+ dc:66:b1:d9:e1:5f:d8:b3:8c:59:34:59:a4:ab:4f:6c:bb:1f:
+ 18:db:75:ab:d8:cb:92:cd:94:38:61:0e:07:06:1f:4b:46:10:
+ f1:15:be:8d:85:5c:3b:4a:2b:81:79:0f:b4:69:9f:49:50:97:
+ 4d:f7:0e:56:5d:c0:95:6a:c2:36:c3:1b:68:c9:f5:2a:dc:47:
+ 9a:be:b2:ce:c5:25:e8:fa:03:b9:da:f9:16:6e:91:84:f5:1c:
+ 28:c8:fc:26:cc:d7:1c:90:56:a7:5f:6f:3a:04:bc:cd:78:89:
+ 0b:8e:0f:2f:a3:aa:4f:a2:1b:12:3d:16:08:40:0f:f1:46:4c:
+ d7:aa:7b:08:c1:0a:f5:6d:27:de:02:8f:ca:c3:b5:2b:ca:e9:
+ eb:c8:21:53:38:a5:cc:3b:d8:77:37:30:a2:4f:d9:6f:d1:f2:
+ 40:ad:41:7a:17:c5:d6:4a:35:89:b7:41:d5:7c:86:7f:55:4d:
+ 83:4a:a5:73:20:c0:3a:af:90:f1:9a:24:8e:d9:8e:71:ca:7b:
+ b8:86:da:b2:8f:99:3e:1d:13:0d:12:11:ee:d4:ab:f0:e9:15:
+ 76:02:e4:e0:df:aa:20:1e:5b:61:85:64:40:a9:90:97:0d:ad:
+ 53:d2:5a:1d:87:6a:00:97:65:62:b4:be:6f:6a:a7:f5:2c:42:
+ ed:32:ad:b6:21:9e:be:bc
+-----BEGIN CERTIFICATE-----
+MIIGCzCCA/OgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBpjELMAkGA1UEBhMCR1Ix
+DzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNhZGVtaWMgYW5k
+IFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkxQDA+BgNVBAMT
+N0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgUm9v
+dENBIDIwMTUwHhcNMTUwNzA3MTAxMTIxWhcNNDAwNjMwMTAxMTIxWjCBpjELMAkG
+A1UEBhMCR1IxDzANBgNVBAcTBkF0aGVuczFEMEIGA1UEChM7SGVsbGVuaWMgQWNh
+ZGVtaWMgYW5kIFJlc2VhcmNoIEluc3RpdHV0aW9ucyBDZXJ0LiBBdXRob3JpdHkx
+QDA+BgNVBAMTN0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgUm9vdENBIDIwMTUwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQDC+Kk/G4n8PDwEXT2QNrCROnk8ZlrvbTkBSRq0t89/TSNTt5AA4xMqKKYx8ZEA
+4yjsriFBzh/a/X0SWwGDD7mwX5nh8hKDgE0GPt+sr+ehiGsxr/CL0BgzuNtFajT0
+AoAkKAoCFZVedioNmToUW/bLy1O8E00BiDeUJRtCvCLYjqOWXjrZMts+6PAQZe10
+4S+nfK8nNLspfZu2zwnI5dMK/IhlZXQK3HMcXM1AsRzUtoSMTFDPaI6oWa7CJ06C
+ojXdFPQf/7J31Ycvqm59JCfnxssm5uX+Zwdj2EUN3TpZZTlYepKZcj2chF6IIbjV
+9Cz82XBST3i4vTwri5WY9bPRaM8gFH5MXF/ni+X1NYEZN9cRCLdmvtNKzoNXADrD
+gfgXy5I2XdGj2HUb4Ysn6npIQf1FGQatJ5lOwXBH3bWfgVMS5bGMSF0xQxfjjMZ6
+Y5ZLKTBOhE5iGV48zpeQpX8B653g+IuJ3SWYPZK2fu/Z8VFRfS0myGlZYeCsargq
+NhEEelC9MoS+L9xy1dcdFkfkR2YgP/SWxa+OAXqlD3pk9Q0Yh9muiNX6hME6wGko
+LfINaFGq46V3xqSQDqE3izEjR8EJCOtu93ib14L8hCCZSRm2Ekax+0VVFqmjZayc
+Bw/qa9wfLgZy7IaIEuQt218FL+TwA9MmM+eAws1CoRc0CwIDAQABo0IwQDAPBgNV
+HRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUcRVnyMjJvXVd
+ctA4GGqd83EkVAswDQYJKoZIhvcNAQELBQADggIBAHW7bVRLqhBYRjTyYtcWNl0I
+XtVsyIe9tC5G8jH4fOpCtZMWVdyhDBKg2mF+D1hYc2Ryx+hFjtyp8iY/xnmMsVMI
+M4GwVhO+5lFc2JsKT0ucVlMC6U/2DWDqTUJV6HwbISHTGzrMd/K4kPFox/la/vot
+9L/J9UUbzjgQKjeKeaO04wlshYaT/4mWJ3iBj2fjRnRUjtkNaeJK9E10A/+yd+2V
+Z5fkscWrv2oj6NSU4kQoYsRL4vDY4ilrGnB+JGGTe08DMiUNRSQrlrRGar9KC/ea
+j8GsGsVn82800vpzY4zvFrCopEYq+OsS7HK07/grfoxSwIuEVPkvPuNVqNxmsdnh
+X9izjFk0WaSrT2y7HxjbdavYy5LNlDhhDgcGH0tGEPEVvo2FXDtKK4F5D7Rpn0lQ
+l033DlZdwJVqwjbDG2jJ9SrcR5q+ss7FJej6A7na+RZukYT1HCjI/CbM1xyQVqdf
+bzoEvM14iQuODy+jqk+iGxI9FghAD/FGTNeqewjBCvVtJ94Cj8rDtSvK6evIIVM4
+pcw72Hc3MKJP2W/R8kCtQXoXxdZKNYm3QdV8hn9VTYNKpXMgwDqvkPGaJI7ZjnHK
+e7iG2rKPmT4dEw0SEe7Uq/DpFXYC5ODfqiAeW2GFZECpkJcNrVPSWh2HagCXZWK0
+vm9qp/UsQu0yrbYhnr68
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem
new file mode 100644
index 00000000000..e28f222b6ad
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 3e:8a:5d:07:ec:55:d2:32:d5:b7:e3:b6:5f:01:eb:2d:dc:e4:d6:e4
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = PL, O = Krajowa Izba Rozliczeniowa S.A., CN = SZAFIR ROOT CA2
+ Validity
+ Not Before: Oct 19 07:43:30 2015 GMT
+ Not After : Oct 19 07:43:30 2035 GMT
+ Subject: C = PL, O = Krajowa Izba Rozliczeniowa S.A., CN = SZAFIR ROOT CA2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b7:bc:3e:50:a8:4b:cd:40:b5:ce:61:e7:96:ca:
+ b4:a1:da:0c:22:b0:fa:b5:7b:76:00:77:8c:0b:cf:
+ 7d:a8:86:cc:26:51:e4:20:3d:85:0c:d6:58:e3:e7:
+ f4:2a:18:9d:da:d1:ae:26:ee:eb:53:dc:f4:90:d6:
+ 13:4a:0c:90:3c:c3:f4:da:d2:8e:0d:92:3a:dc:b1:
+ b1:ff:38:de:c3:ba:2d:5f:80:b9:02:bd:4a:9d:1b:
+ 0f:b4:c3:c2:c1:67:03:dd:dc:1b:9c:3d:b3:b0:de:
+ 00:1e:a8:34:47:bb:9a:eb:fe:0b:14:bd:36:84:da:
+ 0d:20:bf:fa:5b:cb:a9:16:20:ad:39:60:ee:2f:75:
+ b6:e7:97:9c:f9:3e:fd:7e:4d:6f:4d:2f:ef:88:0d:
+ 6a:fa:dd:f1:3d:6e:20:a5:a0:12:b4:4d:70:b9:ce:
+ d7:72:3b:89:93:a7:80:84:1c:27:49:72:49:b5:ff:
+ 3b:95:9e:c1:cc:c8:01:ec:e8:0e:8a:0a:96:e7:b3:
+ a6:87:e5:d6:f9:05:2b:0d:97:40:70:3c:ba:ac:75:
+ 5a:9c:d5:4d:9d:02:0a:d2:4b:9b:66:4b:46:07:17:
+ 65:ad:9f:6c:88:00:dc:22:89:e0:e1:64:d4:67:bc:
+ 31:79:61:3c:bb:ca:41:cd:5c:6a:00:c8:3c:38:8e:
+ 58:af
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 2E:16:A9:4A:18:B5:CB:CC:F5:6F:50:F3:23:5F:F8:5D:E7:AC:F0:C8
+ Signature Algorithm: sha256WithRSAEncryption
+ b5:73:f8:03:dc:59:5b:1d:76:e9:a3:2a:7b:90:28:b2:4d:c0:
+ 33:4f:aa:9a:b1:d4:b8:e4:27:ff:a9:96:99:ce:46:e0:6d:7c:
+ 4c:a2:38:a4:06:70:f0:f4:41:11:ec:3f:47:8d:3f:72:87:f9:
+ 3b:fd:a4:6f:2b:53:00:e0:ff:39:b9:6a:07:0e:eb:1d:1c:f6:
+ a2:72:90:cb:82:3d:11:82:8b:d2:bb:9f:2a:af:21:e6:63:86:
+ 9d:79:19:ef:f7:bb:0c:35:90:c3:8a:ed:4f:0f:f5:cc:12:d9:
+ a4:3e:bb:a0:fc:20:95:5f:4f:26:2f:11:23:83:4e:75:07:0f:
+ bf:9b:d1:b4:1d:e9:10:04:fe:ca:60:8f:a2:4c:b8:ad:cf:e1:
+ 90:0f:cd:ae:0a:c7:5d:7b:b7:50:d2:d4:61:fa:d5:15:db:d7:
+ 9f:87:51:54:eb:a5:e3:eb:c9:85:a0:25:20:37:fb:8e:ce:0c:
+ 34:84:e1:3c:81:b2:77:4e:43:a5:88:5f:86:67:a1:3d:e6:b4:
+ 5c:61:b6:3e:db:fe:b7:28:c5:a2:07:ae:b5:ca:ca:8d:2a:12:
+ ef:97:ed:c2:30:a4:c9:2a:7a:fb:f3:4d:23:1b:99:33:34:a0:
+ 2e:f5:a9:0b:3f:d4:5d:e1:cf:84:9f:e2:19:c2:5f:8a:d6:20:
+ 1e:e3:73:b7
+-----BEGIN CERTIFICATE-----
+MIIDcjCCAlqgAwIBAgIUPopdB+xV0jLVt+O2XwHrLdzk1uQwDQYJKoZIhvcNAQEL
+BQAwUTELMAkGA1UEBhMCUEwxKDAmBgNVBAoMH0tyYWpvd2EgSXpiYSBSb3psaWN6
+ZW5pb3dhIFMuQS4xGDAWBgNVBAMMD1NaQUZJUiBST09UIENBMjAeFw0xNTEwMTkw
+NzQzMzBaFw0zNTEwMTkwNzQzMzBaMFExCzAJBgNVBAYTAlBMMSgwJgYDVQQKDB9L
+cmFqb3dhIEl6YmEgUm96bGljemVuaW93YSBTLkEuMRgwFgYDVQQDDA9TWkFGSVIg
+Uk9PVCBDQTIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC3vD5QqEvN
+QLXOYeeWyrSh2gwisPq1e3YAd4wLz32ohswmUeQgPYUM1ljj5/QqGJ3a0a4m7utT
+3PSQ1hNKDJA8w/Ta0o4NkjrcsbH/ON7Dui1fgLkCvUqdGw+0w8LBZwPd3BucPbOw
+3gAeqDRHu5rr/gsUvTaE2g0gv/pby6kWIK05YO4vdbbnl5z5Pv1+TW9NL++IDWr6
+3fE9biCloBK0TXC5ztdyO4mTp4CEHCdJckm1/zuVnsHMyAHs6A6KCpbns6aH5db5
+BSsNl0BwPLqsdVqc1U2dAgrSS5tmS0YHF2Wtn2yIANwiieDhZNRnvDF5YTy7ykHN
+XGoAyDw4jlivAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
+AgEGMB0GA1UdDgQWBBQuFqlKGLXLzPVvUPMjX/hd56zwyDANBgkqhkiG9w0BAQsF
+AAOCAQEAtXP4A9xZWx126aMqe5Aosk3AM0+qmrHUuOQn/6mWmc5G4G18TKI4pAZw
+8PRBEew/R40/cof5O/2kbytTAOD/OblqBw7rHRz2onKQy4I9EYKL0rufKq8h5mOG
+nXkZ7/e7DDWQw4rtTw/1zBLZpD67oPwglV9PJi8RI4NOdQcPv5vRtB3pEAT+ymCP
+oky4rc/hkA/NrgrHXXu3UNLUYfrVFdvXn4dRVOul4+vJhaAlIDf7js4MNIThPIGy
+d05DpYhfhmehPea0XGG2Ptv+tyjFogeutcrKjSoS75ftwjCkySp6+/NNIxuZMzSg
+LvWpCz/UXeHPhJ/iGcJfitYgHuNztw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem
new file mode 100644
index 00000000000..9bfe4637341
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem
@@ -0,0 +1,104 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 985026699 (0x3ab6508b)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = BM, O = QuoVadis Limited, OU = Root Certification Authority, CN = QuoVadis Root Certification Authority
+ Validity
+ Not Before: Mar 19 18:33:33 2001 GMT
+ Not After : Mar 17 18:33:33 2021 GMT
+ Subject: C = BM, O = QuoVadis Limited, OU = Root Certification Authority, CN = QuoVadis Root Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:61:b5:95:53:ba:57:fc:fa:f2:67:0b:3a:1a:
+ df:11:80:64:95:b4:d1:bc:cd:7a:cf:f6:29:96:2e:
+ 24:54:40:24:38:f7:1a:85:dc:58:4c:cb:a4:27:42:
+ 97:d0:9f:83:8a:c3:e4:06:03:5b:00:a5:51:1e:70:
+ 04:74:e2:c1:d4:3a:ab:d7:ad:3b:07:18:05:8e:fd:
+ 83:ac:ea:66:d9:18:1b:68:8a:f5:57:1a:98:ba:f5:
+ ed:76:3d:7c:d9:de:94:6a:3b:4b:17:c1:d5:8f:bd:
+ 65:38:3a:95:d0:3d:55:36:4e:df:79:57:31:2a:1e:
+ d8:59:65:49:58:20:98:7e:ab:5f:7e:9f:e9:d6:4d:
+ ec:83:74:a9:c7:6c:d8:ee:29:4a:85:2a:06:14:f9:
+ 54:e6:d3:da:65:07:8b:63:37:12:d7:d0:ec:c3:7b:
+ 20:41:44:a3:ed:cb:a0:17:e1:71:65:ce:1d:66:31:
+ f7:76:01:19:c8:7d:03:58:b6:95:49:1d:a6:12:26:
+ e8:c6:0c:76:e0:e3:66:cb:ea:5d:a6:26:ee:e5:cc:
+ 5f:bd:67:a7:01:27:0e:a2:ca:54:c5:b1:7a:95:1d:
+ 71:1e:4a:29:8a:03:dc:6a:45:c1:a4:19:5e:6f:36:
+ cd:c3:a2:b0:b7:fe:5c:38:e2:52:bc:f8:44:43:e6:
+ 90:bb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ Authority Information Access:
+ OCSP - URI:https://ocsp.quovadisoffshore.com
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.8024.0.1
+ User Notice:
+ Explicit Text: Reliance on the QuoVadis Root Certificate by any party assumes acceptance of the then applicable standard terms and conditions of use, certification practices, and the QuoVadis Certificate Policy.
+ CPS: http://www.quovadis.bm
+
+ X509v3 Subject Key Identifier:
+ 8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF
+ X509v3 Authority Key Identifier:
+ keyid:8B:4B:6D:ED:D3:29:B9:06:19:EC:39:39:A9:F0:97:84:6A:CB:EF:DF
+ DirName:/C=BM/O=QuoVadis Limited/OU=Root Certification Authority/CN=QuoVadis Root Certification Authority
+ serial:3A:B6:50:8B
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ 8a:d4:14:b5:fe:f4:9a:92:a7:19:d4:a4:7e:72:18:8f:d9:68:
+ 7c:52:24:dd:67:6f:39:7a:c4:aa:5e:3d:e2:58:b0:4d:70:98:
+ 84:61:e8:1b:e3:69:18:0e:ce:fb:47:50:a0:4e:ff:f0:24:1f:
+ bd:b2:ce:f5:27:fc:ec:2f:53:aa:73:7b:03:3d:74:6e:e6:16:
+ 9e:eb:a5:2e:c4:bf:56:27:50:2b:62:ba:be:4b:1c:3c:55:5c:
+ 41:1d:24:be:82:20:47:5d:d5:44:7e:7a:16:68:df:7d:4d:51:
+ 70:78:57:1d:33:1e:fd:02:99:9c:0c:cd:0a:05:4f:c7:bb:8e:
+ a4:75:fa:4a:6d:b1:80:8e:09:56:b9:9c:1a:60:fe:5d:c1:d7:
+ 7a:dc:11:78:d0:d6:5d:c1:b7:d5:ad:32:99:03:3a:8a:cc:54:
+ 25:39:31:81:7b:13:22:51:ba:46:6c:a1:bb:9e:fa:04:6c:49:
+ 26:74:8f:d2:73:eb:cc:30:a2:e6:ea:59:22:87:f8:97:f5:0e:
+ fd:ea:cc:92:a4:16:c4:52:18:ea:21:ce:b1:f1:e6:84:81:e5:
+ ba:a9:86:28:f2:43:5a:5d:12:9d:ac:1e:d9:a8:e5:0a:6a:a7:
+ 7f:a0:87:29:cf:f2:89:4d:d4:ec:c5:e2:e6:7a:d0:36:23:8a:
+ 4a:74:36:f9
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
+TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
+aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
+MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
+IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
+dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
+li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
+rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
+WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
+F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
+xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
+Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
+dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
+ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
+IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
+c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
+ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
+KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
+KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
+y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
+dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
+VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
+MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
+fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
+7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
+cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
+mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
+xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
+SnQ2+Q==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem
new file mode 100644
index 00000000000..d4d4b08c2cb
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem
@@ -0,0 +1,126 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 7667447206703254355 (0x6a683e9c519bcb53)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = TR, L = Ankara, O = E-Tu\C4\9Fra EBG Bili\C5\9Fim Teknolojileri ve Hizmetleri A.\C5\9E., OU = E-Tugra Sertifikasyon Merkezi, CN = E-Tugra Certification Authority
+ Validity
+ Not Before: Mar 5 12:09:48 2013 GMT
+ Not After : Mar 3 12:09:48 2023 GMT
+ Subject: C = TR, L = Ankara, O = E-Tu\C4\9Fra EBG Bili\C5\9Fim Teknolojileri ve Hizmetleri A.\C5\9E., OU = E-Tugra Sertifikasyon Merkezi, CN = E-Tugra Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:e2:f5:3f:93:05:51:1e:85:62:54:5e:7a:0b:f5:
+ 18:07:83:ae:7e:af:7c:f7:d4:8a:6b:a5:63:43:39:
+ b9:4b:f7:c3:c6:64:89:3d:94:2e:54:80:52:39:39:
+ 07:4b:4b:dd:85:07:76:87:cc:bf:2f:95:4c:cc:7d:
+ a7:3d:bc:47:0f:98:70:f8:8c:85:1e:74:8e:92:6d:
+ 1b:40:d1:99:0d:bb:75:6e:c8:a9:6b:9a:c0:84:31:
+ af:ca:43:cb:eb:2b:34:e8:8f:97:6b:01:9b:d5:0e:
+ 4a:08:aa:5b:92:74:85:43:d3:80:ae:a1:88:5b:ae:
+ b3:ea:5e:cb:16:9a:77:44:c8:a1:f6:54:68:ce:de:
+ 8f:97:2b:ba:5b:40:02:0c:64:17:c0:b5:93:cd:e1:
+ f1:13:66:ce:0c:79:ef:d1:91:28:ab:5f:a0:12:52:
+ 30:73:19:8e:8f:e1:8c:07:a2:c3:bb:4a:f0:ea:1f:
+ 15:a8:ee:25:cc:a4:46:f8:1b:22:ef:b3:0e:43:ba:
+ 2c:24:b8:c5:2c:5c:d4:1c:f8:5d:64:bd:c3:93:5e:
+ 28:a7:3f:27:f1:8e:1e:d3:2a:50:05:a3:55:d9:cb:
+ e7:39:53:c0:98:9e:8c:54:62:8b:26:b0:f7:7d:8d:
+ 7c:e4:c6:9e:66:42:55:82:47:e7:b2:58:8d:66:f7:
+ 07:7c:2e:36:e6:50:1c:3f:db:43:24:c5:bf:86:47:
+ 79:b3:79:1c:f7:5a:f4:13:ec:6c:f8:3f:e2:59:1f:
+ 95:ee:42:3e:b9:ad:a8:32:85:49:97:46:fe:4b:31:
+ 8f:5a:cb:ad:74:47:1f:e9:91:b7:df:28:04:22:a0:
+ d4:0f:5d:e2:79:4f:ea:6c:85:86:bd:a8:a6:ce:e4:
+ fa:c3:e1:b3:ae:de:3c:51:ee:cb:13:7c:01:7f:84:
+ 0e:5d:51:94:9e:13:0c:b6:2e:a5:4c:f9:39:70:36:
+ 6f:96:ca:2e:0c:44:55:c5:ca:fa:5d:02:a3:df:d6:
+ 64:8c:5a:b3:01:0a:a9:b5:0a:47:17:ff:ef:91:40:
+ 2a:8e:a1:46:3a:31:98:e5:11:fc:cc:bb:49:56:8a:
+ fc:b9:d0:61:9a:6f:65:6c:e6:c3:cb:3e:75:49:fe:
+ 8f:a7:e2:89:c5:67:d7:9d:46:13:4e:31:76:3b:24:
+ b3:9e:11:65:86:ab:7f:ef:1d:d4:f8:bc:e7:ac:5a:
+ 5c:b7:5a:47:5c:55:ce:55:b4:22:71:5b:5b:0b:f0:
+ cf:dc:a0:61:64:ea:a9:d7:68:0a:63:a7:e0:0d:3f:
+ a0:af:d3:aa:d2:7e:ef:51:a0:e6:51:2b:55:92:15:
+ 17:53:cb:b7:66:0e:66:4c:f8:f9:75:4c:90:e7:12:
+ 70:c7:45
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:2E:E3:DB:B2:49:D0:9C:54:79:5C:FA:27:2A:FE:CC:4E:D2:E8:4E:54
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 05:37:3a:f4:4d:b7:45:e2:45:75:24:8f:b6:77:52:e8:1c:d8:
+ 10:93:65:f3:f2:59:06:a4:3e:1e:29:ec:5d:d1:d0:ab:7c:e0:
+ 0a:90:48:78:ed:4e:98:03:99:fe:28:60:91:1d:30:1d:b8:63:
+ 7c:a8:e6:35:b5:fa:d3:61:76:e6:d6:07:4b:ca:69:9a:b2:84:
+ 7a:77:93:45:17:15:9f:24:d0:98:13:12:ff:bb:a0:2e:fd:4e:
+ 4c:87:f8:ce:5c:aa:98:1b:05:e0:00:46:4a:82:80:a5:33:8b:
+ 28:dc:ed:38:d3:df:e5:3e:e9:fe:fb:59:dd:61:84:4f:d2:54:
+ 96:13:61:13:3e:8f:80:69:be:93:47:b5:35:43:d2:5a:bb:3d:
+ 5c:ef:b3:42:47:cd:3b:55:13:06:b0:09:db:fd:63:f6:3a:88:
+ 0a:99:6f:7e:e1:ce:1b:53:6a:44:66:23:51:08:7b:bc:5b:52:
+ a2:fd:06:37:38:40:61:8f:4a:96:b8:90:37:f8:66:c7:78:90:
+ 00:15:2e:8b:ad:51:35:53:07:a8:6b:68:ae:f9:4e:3c:07:26:
+ cd:08:05:70:cc:39:3f:76:bd:a5:d3:67:26:01:86:a6:53:d2:
+ 60:3b:7c:43:7f:55:8a:bc:95:1a:c1:28:39:4c:1f:43:d2:91:
+ f4:72:59:8a:b9:56:fc:3f:b4:9d:da:70:9c:76:5a:8c:43:50:
+ ee:8e:30:72:4d:df:ff:49:f7:c6:a9:67:d9:6d:ac:02:11:e2:
+ 3a:16:25:a7:58:08:cb:6f:53:41:9c:48:38:47:68:33:d1:d7:
+ c7:8f:d4:74:21:d4:c3:05:90:7a:ff:ce:96:88:b1:15:29:5d:
+ 23:ab:d0:60:a1:12:4f:de:f4:17:cd:32:e5:c9:bf:c8:43:ad:
+ fd:2e:8e:f1:af:e2:f4:98:fa:12:1f:20:d8:c0:a7:0c:85:c5:
+ 90:f4:3b:2d:96:26:b1:2c:be:4c:ab:eb:b1:d2:8a:c9:db:78:
+ 13:0f:1e:09:9d:6d:8f:00:9f:02:da:c1:fa:1f:7a:7a:09:c4:
+ 4a:e6:88:2a:97:9f:89:8b:fd:37:5f:5f:3a:ce:38:59:86:4b:
+ af:71:0b:b4:d8:f2:70:4f:9f:32:13:e3:b0:a7:57:e5:da:da:
+ 43:cb:84:34:f2:28:c4:ea:6d:f4:2a:ef:c1:6b:76:da:fb:7e:
+ bb:85:3c:d2:53:c2:4d:be:71:e1:45:d1:fd:23:67:0d:13:75:
+ fb:cf:65:67:22:9d:ae:b0:09:d1:09:ff:1d:34:bf:fe:23:97:
+ 37:d2:39:fa:3d:0d:06:0b:b4:db:3b:a3:ab:6f:5c:1d:b6:7e:
+ e8:b3:82:34:ed:06:5c:24
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIIamg+nFGby1MwDQYJKoZIhvcNAQELBQAwgbIxCzAJBgNV
+BAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+BgNVBAoMN0UtVHXEn3JhIEVCRyBC
+aWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhpem1ldGxlcmkgQS7Fni4xJjAkBgNV
+BAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBNZXJrZXppMSgwJgYDVQQDDB9FLVR1
+Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTEzMDMwNTEyMDk0OFoXDTIz
+MDMwMzEyMDk0OFowgbIxCzAJBgNVBAYTAlRSMQ8wDQYDVQQHDAZBbmthcmExQDA+
+BgNVBAoMN0UtVHXEn3JhIEVCRyBCaWxpxZ9pbSBUZWtub2xvamlsZXJpIHZlIEhp
+em1ldGxlcmkgQS7Fni4xJjAkBgNVBAsMHUUtVHVncmEgU2VydGlmaWthc3lvbiBN
+ZXJrZXppMSgwJgYDVQQDDB9FLVR1Z3JhIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA4vU/kwVRHoViVF56C/UY
+B4Oufq9899SKa6VjQzm5S/fDxmSJPZQuVIBSOTkHS0vdhQd2h8y/L5VMzH2nPbxH
+D5hw+IyFHnSOkm0bQNGZDbt1bsipa5rAhDGvykPL6ys06I+XawGb1Q5KCKpbknSF
+Q9OArqGIW66z6l7LFpp3RMih9lRozt6Plyu6W0ACDGQXwLWTzeHxE2bODHnv0ZEo
+q1+gElIwcxmOj+GMB6LDu0rw6h8VqO4lzKRG+Bsi77MOQ7osJLjFLFzUHPhdZL3D
+k14opz8n8Y4e0ypQBaNV2cvnOVPAmJ6MVGKLJrD3fY185MaeZkJVgkfnsliNZvcH
+fC425lAcP9tDJMW/hkd5s3kc91r0E+xs+D/iWR+V7kI+ua2oMoVJl0b+SzGPWsut
+dEcf6ZG33ygEIqDUD13ieU/qbIWGvaimzuT6w+Gzrt48Ue7LE3wBf4QOXVGUnhMM
+ti6lTPk5cDZvlsouDERVxcr6XQKj39ZkjFqzAQqptQpHF//vkUAqjqFGOjGY5RH8
+zLtJVor8udBhmm9lbObDyz51Sf6Pp+KJxWfXnUYTTjF2OySznhFlhqt/7x3U+Lzn
+rFpct1pHXFXOVbQicVtbC/DP3KBhZOqp12gKY6fgDT+gr9Oq0n7vUaDmUStVkhUX
+U8u3Zg5mTPj5dUyQ5xJwx0UCAwEAAaNjMGEwHQYDVR0OBBYEFC7j27JJ0JxUeVz6
+Jyr+zE7S6E5UMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAULuPbsknQnFR5
+XPonKv7MTtLoTlQwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQAF
+Nzr0TbdF4kV1JI+2d1LoHNgQk2Xz8lkGpD4eKexd0dCrfOAKkEh47U6YA5n+KGCR
+HTAduGN8qOY1tfrTYXbm1gdLymmasoR6d5NFFxWfJNCYExL/u6Au/U5Mh/jOXKqY
+GwXgAEZKgoClM4so3O0409/lPun++1ndYYRP0lSWE2ETPo+Aab6TR7U1Q9Jauz1c
+77NCR807VRMGsAnb/WP2OogKmW9+4c4bU2pEZiNRCHu8W1Ki/QY3OEBhj0qWuJA3
++GbHeJAAFS6LrVE1Uweoa2iu+U48BybNCAVwzDk/dr2l02cmAYamU9JgO3xDf1WK
+vJUawSg5TB9D0pH0clmKuVb8P7Sd2nCcdlqMQ1DujjByTd//SffGqWfZbawCEeI6
+FiWnWAjLb1NBnEg4R2gz0dfHj9R0IdTDBZB6/86WiLEVKV0jq9BgoRJP3vQXzTLl
+yb/IQ639Lo7xr+L0mPoSHyDYwKcMhcWQ9DstliaxLL5Mq+ux0orJ23gTDx4JnW2P
+AJ8C2sH6H3p6CcRK5ogql5+Ji/03X186zjhZhkuvcQu02PJwT58yE+Owp1fl2tpD
+y4Q08ijE6m30Ku/Ba3ba+367hTzSU8JNvnHhRdH9I2cNE3X7z2VnIp2usAnRCf8d
+NL/+I5c30jn6PQ0GC7TbO6Orb1wdtn7os4I07QZcJA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem
new file mode 100644
index 00000000000..69ca4e7c118
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 21:d6:d0:4a:4f:25:0f:c9:32:37:fc:aa:5e:12:8d:e9
+ Signature Algorithm: sha512WithRSAEncryption
+ Issuer: C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA 2
+ Validity
+ Not Before: Oct 6 08:39:56 2011 GMT
+ Not After : Oct 6 08:39:56 2046 GMT
+ Subject: C = PL, O = Unizeto Technologies S.A., OU = Certum Certification Authority, CN = Certum Trusted Network CA 2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:bd:f9:78:f8:e6:d5:80:0c:64:9d:86:1b:96:64:
+ 67:3f:22:3a:1e:75:01:7d:ef:fb:5c:67:8c:c9:cc:
+ 5c:6b:a9:91:e6:b9:42:e5:20:4b:9b:da:9b:7b:b9:
+ 99:5d:d9:9b:80:4b:d7:84:40:2b:27:d3:e8:ba:30:
+ bb:3e:09:1a:a7:49:95:ef:2b:40:24:c2:97:c7:a7:
+ ee:9b:25:ef:a8:0a:00:97:85:5a:aa:9d:dc:29:c9:
+ e2:35:07:eb:70:4d:4a:d6:c1:b3:56:b8:a1:41:38:
+ 9b:d1:fb:31:7f:8f:e0:5f:e1:b1:3f:0f:8e:16:49:
+ 60:d7:06:8d:18:f9:aa:26:10:ab:2a:d3:d0:d1:67:
+ 8d:1b:46:be:47:30:d5:2e:72:d1:c5:63:da:e7:63:
+ 79:44:7e:4b:63:24:89:86:2e:34:3f:29:4c:52:8b:
+ 2a:a7:c0:e2:91:28:89:b9:c0:5b:f9:1d:d9:e7:27:
+ ad:ff:9a:02:97:c1:c6:50:92:9b:02:2c:bd:a9:b9:
+ 34:59:0a:bf:84:4a:ff:df:fe:b3:9f:eb:d9:9e:e0:
+ 98:23:ec:a6:6b:77:16:2a:db:cc:ad:3b:1c:a4:87:
+ dc:46:73:5e:19:62:68:45:57:e4:90:82:42:bb:42:
+ d6:f0:61:e0:c1:a3:3d:66:a3:5d:f4:18:ee:88:c9:
+ 8d:17:45:29:99:32:75:02:31:ee:29:26:c8:6b:02:
+ e6:b5:62:45:7f:37:15:5a:23:68:89:d4:3e:de:4e:
+ 27:b0:f0:40:0c:bc:4d:17:cb:4d:a2:b3:1e:d0:06:
+ 5a:dd:f6:93:cf:57:75:99:f5:fa:86:1a:67:78:b3:
+ bf:96:fe:34:dc:bd:e7:52:56:e5:b3:e5:75:7b:d7:
+ 41:91:05:dc:5d:69:e3:95:0d:43:b9:fc:83:96:39:
+ 95:7b:6c:80:5a:4f:13:72:c6:d7:7d:29:7a:44:ba:
+ 52:a4:2a:d5:41:46:09:20:fe:22:a0:b6:5b:30:8d:
+ bc:89:0c:d5:d7:70:f8:87:52:fd:da:ef:ac:51:2e:
+ 07:b3:4e:fe:d0:09:da:70:ef:98:fa:56:e6:6d:db:
+ b5:57:4b:dc:e5:2c:25:15:c8:9e:2e:78:4e:f8:da:
+ 9c:9e:86:2c:ca:57:f3:1a:e5:c8:92:8b:1a:82:96:
+ 7a:c3:bc:50:12:69:d8:0e:5a:46:8b:3a:eb:26:fa:
+ 23:c9:b6:b0:81:be:42:00:a4:f8:d6:fe:30:2e:c7:
+ d2:46:f6:e5:8e:75:fd:f2:cc:b9:d0:87:5b:cc:06:
+ 10:60:bb:83:35:b7:5e:67:de:47:ec:99:48:f1:a4:
+ a1:15:fe:ad:8c:62:8e:39:55:4f:39:16:b9:b1:63:
+ 9d:ff:b7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ B6:A1:54:39:02:C3:A0:3F:8E:8A:BC:FA:D4:F8:1C:A6:D1:3A:0E:FD
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha512WithRSAEncryption
+ 71:a5:0e:ce:e4:e9:bf:3f:38:d5:89:5a:c4:02:61:fb:4c:c5:
+ 14:17:2d:8b:4f:53:6b:10:17:fc:65:84:c7:10:49:90:de:db:
+ c7:26:93:88:26:6f:70:d6:02:5e:39:a0:f7:8f:ab:96:b5:a5:
+ 13:5c:81:14:6d:0e:81:82:11:1b:8a:4e:c6:4f:a5:dd:62:1e:
+ 44:df:09:59:f4:5b:77:0b:37:e9:8b:20:c6:f8:0a:4e:2e:58:
+ 1c:eb:33:d0:cf:86:60:c9:da:fb:80:2f:9e:4c:60:84:78:3d:
+ 21:64:d6:fb:41:1f:18:0f:e7:c9:75:71:bd:bd:5c:de:34:87:
+ 3e:41:b0:0e:f6:b9:d6:3f:09:13:96:14:2f:de:9a:1d:5a:b9:
+ 56:ce:35:3a:b0:5f:70:4d:5e:e3:29:f1:23:28:72:59:b6:ab:
+ c2:8c:66:26:1c:77:2c:26:76:35:8b:28:a7:69:a0:f9:3b:f5:
+ 23:dd:85:10:74:c9:90:03:56:91:e7:af:ba:47:d4:12:97:11:
+ 22:e3:a2:49:94:6c:e7:b7:94:4b:ba:2d:a4:da:33:8b:4c:a6:
+ 44:ff:5a:3c:c6:1d:64:d8:b5:31:e4:a6:3c:7a:a8:57:0b:db:
+ ed:61:1a:cb:f1:ce:73:77:63:a4:87:6f:4c:51:38:d6:e4:5f:
+ c7:9f:b6:81:2a:e4:85:48:79:58:5e:3b:f8:db:02:82:67:c1:
+ 39:db:c3:74:4b:3d:36:1e:f9:29:93:88:68:5b:a8:44:19:21:
+ f0:a7:e8:81:0d:2c:e8:93:36:b4:37:b2:ca:b0:1b:26:7a:9a:
+ 25:1f:9a:9a:80:9e:4b:2a:3f:fb:a3:9a:fe:73:32:71:c2:9e:
+ c6:72:e1:8a:68:27:f1:e4:0f:b4:c4:4c:a5:61:93:f8:97:10:
+ 07:2a:30:25:a9:b9:c8:71:b8:ef:68:cc:2d:7e:f5:e0:7e:0f:
+ 82:a8:6f:b6:ba:6c:83:43:77:cd:8a:92:17:a1:9e:5b:78:16:
+ 3d:45:e2:33:72:dd:e1:66:ca:99:d3:c9:c5:26:fd:0d:68:04:
+ 46:ae:b6:d9:9b:8c:be:19:be:b1:c6:f2:19:e3:5c:02:ca:2c:
+ d8:6f:4a:07:d9:c9:35:da:40:75:f2:c4:a7:19:6f:9e:42:10:
+ 98:75:e6:95:8b:60:bc:ed:c5:12:d7:8a:ce:d5:98:5c:56:96:
+ 03:c5:ee:77:06:35:ff:cf:e4:ee:3f:13:61:ee:db:da:2d:85:
+ f0:cd:ae:9d:b2:18:09:45:c3:92:a1:72:17:fc:47:b6:a0:0b:
+ 2c:f1:c4:de:43:68:08:6a:5f:3b:f0:76:63:fb:cc:06:2c:a6:
+ c6:e2:0e:b5:b9:be:24:8f
+-----BEGIN CERTIFICATE-----
+MIIF0jCCA7qgAwIBAgIQIdbQSk8lD8kyN/yqXhKN6TANBgkqhkiG9w0BAQ0FADCB
+gDELMAkGA1UEBhMCUEwxIjAgBgNVBAoTGVVuaXpldG8gVGVjaG5vbG9naWVzIFMu
+QS4xJzAlBgNVBAsTHkNlcnR1bSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEkMCIG
+A1UEAxMbQ2VydHVtIFRydXN0ZWQgTmV0d29yayBDQSAyMCIYDzIwMTExMDA2MDgz
+OTU2WhgPMjA0NjEwMDYwODM5NTZaMIGAMQswCQYDVQQGEwJQTDEiMCAGA1UEChMZ
+VW5pemV0byBUZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MSQwIgYDVQQDExtDZXJ0dW0gVHJ1c3RlZCBOZXR3
+b3JrIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC9+Xj45tWA
+DGSdhhuWZGc/IjoedQF97/tcZ4zJzFxrqZHmuULlIEub2pt7uZld2ZuAS9eEQCsn
+0+i6MLs+CRqnSZXvK0AkwpfHp+6bJe+oCgCXhVqqndwpyeI1B+twTUrWwbNWuKFB
+OJvR+zF/j+Bf4bE/D44WSWDXBo0Y+aomEKsq09DRZ40bRr5HMNUuctHFY9rnY3lE
+fktjJImGLjQ/KUxSiyqnwOKRKIm5wFv5HdnnJ63/mgKXwcZQkpsCLL2puTRZCr+E
+Sv/f/rOf69me4Jgj7KZrdxYq28ytOxykh9xGc14ZYmhFV+SQgkK7QtbwYeDBoz1m
+o130GO6IyY0XRSmZMnUCMe4pJshrAua1YkV/NxVaI2iJ1D7eTiew8EAMvE0Xy02i
+sx7QBlrd9pPPV3WZ9fqGGmd4s7+W/jTcvedSVuWz5XV710GRBdxdaeOVDUO5/IOW
+OZV7bIBaTxNyxtd9KXpEulKkKtVBRgkg/iKgtlswjbyJDNXXcPiHUv3a76xRLgez
+Tv7QCdpw75j6VuZt27VXS9zlLCUVyJ4ueE742pyehizKV/Ma5ciSixqClnrDvFAS
+adgOWkaLOusm+iPJtrCBvkIApPjW/jAux9JG9uWOdf3yzLnQh1vMBhBgu4M1t15n
+3kfsmUjxpKEV/q2MYo45VU85FrmxY53/twIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBS2oVQ5AsOgP46KvPrU+Bym0ToO/TAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQENBQADggIBAHGlDs7k6b8/ONWJWsQCYftMxRQXLYtPU2sQ
+F/xlhMcQSZDe28cmk4gmb3DWAl45oPePq5a1pRNcgRRtDoGCERuKTsZPpd1iHkTf
+CVn0W3cLN+mLIMb4Ck4uWBzrM9DPhmDJ2vuAL55MYIR4PSFk1vtBHxgP58l1cb29
+XN40hz5BsA72udY/CROWFC/emh1auVbONTqwX3BNXuMp8SMoclm2q8KMZiYcdywm
+djWLKKdpoPk79SPdhRB0yZADVpHnr7pH1BKXESLjokmUbOe3lEu6LaTaM4tMpkT/
+WjzGHWTYtTHkpjx6qFcL2+1hGsvxznN3Y6SHb0xRONbkX8eftoEq5IVIeVheO/jb
+AoJnwTnbw3RLPTYe+SmTiGhbqEQZIfCn6IENLOiTNrQ3ssqwGyZ6miUfmpqAnksq
+P/ujmv5zMnHCnsZy4YpoJ/HkD7TETKVhk/iXEAcqMCWpuchxuO9ozC1+9eB+D4Ko
+b7a6bINDd82Kkhehnlt4Fj1F4jNy3eFmypnTycUm/Q1oBEauttmbjL4ZvrHG8hnj
+XALKLNhvSgfZyTXaQHXyxKcZb55CEJh15pWLYLztxRLXis7VmFxWlgPF7ncGNf/P
+5O4/E2Hu29othfDNrp2yGAlFw5Khchf8R7agCyzxxN5DaAhqXzvwdmP7zAYspsbi
+DrW5viSP
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem
new file mode 100644
index 00000000000..e61ea56d3e7
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem
@@ -0,0 +1,92 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = GR, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions RootCA 2011
+ Validity
+ Not Before: Dec 6 13:49:52 2011 GMT
+ Not After : Dec 1 13:49:52 2031 GMT
+ Subject: C = GR, O = Hellenic Academic and Research Institutions Cert. Authority, CN = Hellenic Academic and Research Institutions RootCA 2011
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:a9:53:00:e3:2e:a6:f6:8e:fa:60:d8:2d:95:3e:
+ f8:2c:2a:54:4e:cd:b9:84:61:94:58:4f:8f:3d:8b:
+ e4:43:f3:75:89:8d:51:e4:c3:37:d2:8a:88:4d:79:
+ 1e:b7:12:dd:43:78:4a:8a:92:e6:d7:48:d5:0f:a4:
+ 3a:29:44:35:b8:07:f6:68:1d:55:cd:38:51:f0:8c:
+ 24:31:85:af:83:c9:7d:e9:77:af:ed:1a:7b:9d:17:
+ f9:b3:9d:38:50:0f:a6:5a:79:91:80:af:37:ae:a6:
+ d3:31:fb:b5:26:09:9d:3c:5a:ef:51:c5:2b:df:96:
+ 5d:eb:32:1e:02:da:70:49:ec:6e:0c:c8:9a:37:8d:
+ f7:f1:36:60:4b:26:2c:82:9e:d0:78:f3:0d:0f:63:
+ a4:51:30:e1:f9:2b:27:12:07:d8:ea:bd:18:62:98:
+ b0:59:37:7d:be:ee:f3:20:51:42:5a:83:ef:93:ba:
+ 69:15:f1:62:9d:9f:99:39:82:a1:b7:74:2e:8b:d4:
+ c5:0b:7b:2f:f0:c8:0a:da:3d:79:0a:9a:93:1c:a5:
+ 28:72:73:91:43:9a:a7:d1:4d:85:84:b9:a9:74:8f:
+ 14:40:c7:dc:de:ac:41:64:6c:b4:19:9b:02:63:6d:
+ 24:64:8f:44:b2:25:ea:ce:5d:74:0c:63:32:5c:8d:
+ 87:e5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ A6:91:42:FD:13:61:4A:23:9E:08:A4:29:E5:D8:13:04:23:EE:41:25
+ X509v3 Name Constraints:
+ Permitted:
+ DNS:.gr
+ DNS:.eu
+ DNS:.edu
+ DNS:.org
+ email:.gr
+ email:.eu
+ email:.edu
+ email:.org
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 1f:ef:79:41:e1:7b:6e:3f:b2:8c:86:37:42:4a:4e:1c:37:1e:
+ 8d:66:ba:24:81:c9:4f:12:0f:21:c0:03:97:86:25:6d:5d:d3:
+ 22:29:a8:6c:a2:0d:a9:eb:3d:06:5b:99:3a:c7:cc:c3:9a:34:
+ 7f:ab:0e:c8:4e:1c:e1:fa:e4:dc:cd:0d:be:bf:24:fe:6c:e7:
+ 6b:c2:0d:c8:06:9e:4e:8d:61:28:a6:6a:fd:e5:f6:62:ea:18:
+ 3c:4e:a0:53:9d:b2:3a:9c:eb:a5:9c:91:16:b6:4d:82:e0:0c:
+ 05:48:a9:6c:f5:cc:f8:cb:9d:49:b4:f0:02:a5:fd:70:03:ed:
+ 8a:21:a5:ae:13:86:49:c3:33:73:be:87:3b:74:8b:17:45:26:
+ 4c:16:91:83:fe:67:7d:cd:4d:63:67:fa:f3:03:12:96:78:06:
+ 8d:b1:67:ed:8e:3f:be:9f:4f:02:f5:b3:09:2f:f3:4c:87:df:
+ 2a:cb:95:7c:01:cc:ac:36:7a:bf:a2:73:7a:f7:8f:c1:b5:9a:
+ a1:14:b2:8f:33:9f:0d:ef:22:dc:66:7b:84:bd:45:17:06:3d:
+ 3c:ca:b9:77:34:8f:ca:ea:cf:3f:31:3e:e3:88:e3:80:49:25:
+ c8:97:b5:9d:9a:99:4d:b0:3c:f8:4a:00:9b:64:dd:9f:39:4b:
+ d1:27:d7:b8
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1Ix
+RDBCBgNVBAoTO0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1
+dGlvbnMgQ2VydC4gQXV0aG9yaXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1p
+YyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIFJvb3RDQSAyMDExMB4XDTExMTIw
+NjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYTAkdSMUQwQgYDVQQK
+EztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25zIENl
+cnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJl
+c2VhcmNoIEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPz
+dYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJ
+fel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa71HFK9+WXesyHgLacEns
+bgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u8yBRQlqD
+75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSP
+FEDH3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNV
+HRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp
+5dgTBCPuQSUwRwYDVR0eBEAwPqA8MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQu
+b3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQub3JnMA0GCSqGSIb3DQEBBQUA
+A4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVtXdMiKahsog2p
+6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7
+dIsXRSZMFpGD/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8Acys
+Nnq/onN694/BtZqhFLKPM58N7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXI
+l7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem
new file mode 100644
index 00000000000..a9f1901fc9a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem
@@ -0,0 +1,52 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 7b:71:b6:82:56:b8:12:7c:9c:a8
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, OU = emSign PKI, O = eMudhra Inc, CN = emSign ECC Root CA - C3
+ Validity
+ Not Before: Feb 18 18:30:00 2018 GMT
+ Not After : Feb 18 18:30:00 2043 GMT
+ Subject: C = US, OU = emSign PKI, O = eMudhra Inc, CN = emSign ECC Root CA - C3
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:fd:a5:61:ae:7b:26:10:1d:e9:b7:22:30:ae:06:
+ f4:81:b3:b1:42:71:95:39:bc:d3:52:e3:af:af:f9:
+ f2:97:35:92:36:46:0e:87:95:8d:b9:39:5a:e9:bb:
+ df:d0:fe:c8:07:41:3c:bb:55:6f:83:a3:6a:fb:62:
+ b0:81:89:02:70:7d:48:c5:4a:e3:e9:22:54:22:4d:
+ 93:bb:42:0c:af:77:9c:23:a6:7d:d7:61:11:ce:65:
+ c7:f8:7f:fe:f5:f2:a9
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ FB:5A:48:D0:80:20:40:F2:A8:E9:00:07:69:19:77:A7:E6:C3:F4:CF
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:31:00:b4:d8:2f:02:89:fd:b6:4c:62:ba:43:4e:13:
+ 84:72:b5:ae:dd:1c:de:d6:b5:dc:56:8f:58:40:5a:2d:de:20:
+ 4c:22:83:ca:93:a8:7e:ee:12:40:c7:d6:87:4f:f8:df:85:02:
+ 30:1c:14:64:e4:7c:96:83:11:9c:b0:d1:5a:61:4b:a6:0f:49:
+ d3:00:fc:a1:fc:e4:a5:ff:7f:ad:d7:30:d0:c7:77:7f:be:81:
+ 07:55:30:50:20:14:f5:57:38:0a:a8:31:51
+-----BEGIN CERTIFICATE-----
+MIICKzCCAbGgAwIBAgIKe3G2gla4EnycqDAKBggqhkjOPQQDAzBaMQswCQYDVQQG
+EwJVUzETMBEGA1UECxMKZW1TaWduIFBLSTEUMBIGA1UEChMLZU11ZGhyYSBJbmMx
+IDAeBgNVBAMTF2VtU2lnbiBFQ0MgUm9vdCBDQSAtIEMzMB4XDTE4MDIxODE4MzAw
+MFoXDTQzMDIxODE4MzAwMFowWjELMAkGA1UEBhMCVVMxEzARBgNVBAsTCmVtU2ln
+biBQS0kxFDASBgNVBAoTC2VNdWRocmEgSW5jMSAwHgYDVQQDExdlbVNpZ24gRUND
+IFJvb3QgQ0EgLSBDMzB2MBAGByqGSM49AgEGBSuBBAAiA2IABP2lYa57JhAd6bci
+MK4G9IGzsUJxlTm801Ljr6/58pc1kjZGDoeVjbk5Wum739D+yAdBPLtVb4Ojavti
+sIGJAnB9SMVK4+kiVCJNk7tCDK93nCOmfddhEc5lx/h//vXyqaNCMEAwHQYDVR0O
+BBYEFPtaSNCAIEDyqOkAB2kZd6fmw/TPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMB
+Af8EBTADAQH/MAoGCCqGSM49BAMDA2gAMGUCMQC02C8Cif22TGK6Q04ThHK1rt0c
+3ta13FaPWEBaLd4gTCKDypOofu4SQMfWh0/434UCMBwUZOR8loMRnLDRWmFLpg9J
+0wD8ofzkpf9/rdcw0Md3f76BB1UwUCAU9Vc4CqgxUQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem
new file mode 100644
index 00000000000..dc5f776ed59
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem
@@ -0,0 +1,50 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 8401224907861490260 (0x7497258ac73f7a54)
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = AffirmTrust, CN = AffirmTrust Premium ECC
+ Validity
+ Not Before: Jan 29 14:20:24 2010 GMT
+ Not After : Dec 31 14:20:24 2040 GMT
+ Subject: C = US, O = AffirmTrust, CN = AffirmTrust Premium ECC
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:0d:30:5e:1b:15:9d:03:d0:a1:79:35:b7:3a:3c:
+ 92:7a:ca:15:1c:cd:62:f3:9c:26:5c:07:3d:e5:54:
+ fa:a3:d6:cc:12:ea:f4:14:5f:e8:8e:19:ab:2f:2e:
+ 48:e6:ac:18:43:78:ac:d0:37:c3:bd:b2:cd:2c:e6:
+ 47:e2:1a:e6:63:b8:3d:2e:2f:78:c4:4f:db:f4:0f:
+ a4:68:4c:55:72:6b:95:1d:4e:18:42:95:78:cc:37:
+ 3c:91:e2:9b:65:2b:29
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 9A:AF:29:7A:C0:11:35:35:26:51:30:00:C3:6A:FE:40:D5:AE:D6:3C
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:64:02:30:17:09:f3:87:88:50:5a:af:c8:c0:42:bf:47:5f:
+ f5:6c:6a:86:e0:c4:27:74:e4:38:53:d7:05:7f:1b:34:e3:c6:
+ 2f:b3:ca:09:3c:37:9d:d7:e7:b8:46:f1:fd:a1:e2:71:02:30:
+ 42:59:87:43:d4:51:df:ba:d3:09:32:5a:ce:88:7e:57:3d:9c:
+ 5f:42:6b:f5:07:2d:b5:f0:82:93:f9:59:6f:ae:64:fa:58:e5:
+ 8b:1e:e3:63:be:b5:81:cd:6f:02:8c:79
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMC
+VVMxFDASBgNVBAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQ
+cmVtaXVtIEVDQzAeFw0xMDAxMjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJ
+BgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1UcnVzdDEgMB4GA1UEAwwXQWZmaXJt
+VHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQNMF4bFZ0D
+0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQN8O9
+ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0G
+A1UdDgQWBBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4G
+A1UdDwEB/wQEAwIBBjAKBggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/Vs
+aobgxCd05DhT1wV/GzTjxi+zygk8N53X57hG8f2h4nECMEJZh0PUUd+60wkyWs6I
+flc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKMeQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem
new file mode 100644
index 00000000000..5e7f9413d59
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem
@@ -0,0 +1,127 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 5700383053117599563 (0x4f1bd42f54bb2f4b)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = CH, O = SwissSign AG, CN = SwissSign Silver CA - G2
+ Validity
+ Not Before: Oct 25 08:32:46 2006 GMT
+ Not After : Oct 25 08:32:46 2036 GMT
+ Subject: C = CH, O = SwissSign AG, CN = SwissSign Silver CA - G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c4:f1:87:7f:d3:78:31:f7:38:c9:f8:c3:99:43:
+ bc:c7:f7:bc:37:e7:4e:71:ba:4b:8f:a5:73:1d:5c:
+ 6e:98:ae:03:57:ae:38:37:43:2f:17:3d:1f:c8:ce:
+ 68:10:c1:78:ae:19:03:2b:10:fa:2c:79:83:f6:e8:
+ b9:68:b9:55:f2:04:44:a7:39:f9:fc:04:8b:1e:f1:
+ a2:4d:27:f9:61:7b:ba:b7:e5:a2:13:b6:eb:61:3e:
+ d0:6c:d1:e6:fb:fa:5e:ed:1d:b4:9e:a0:35:5b:a1:
+ 92:cb:f0:49:92:fe:85:0a:05:3e:e6:d9:0b:e2:4f:
+ bb:dc:95:37:fc:91:e9:32:35:22:d1:1f:3a:4e:27:
+ 85:9d:b0:15:94:32:da:61:0d:47:4d:60:42:ae:92:
+ 47:e8:83:5a:50:58:e9:8a:8b:b9:5d:a1:dc:dd:99:
+ 4a:1f:36:67:bb:48:e4:83:b6:37:eb:48:3a:af:0f:
+ 67:8f:17:07:e8:04:ca:ef:6a:31:87:d4:c0:b6:f9:
+ 94:71:7b:67:64:b8:b6:91:4a:42:7b:65:2e:30:6a:
+ 0c:f5:90:ee:95:e6:f2:cd:82:ec:d9:a1:4a:ec:f6:
+ b2:4b:e5:45:85:e6:6d:78:93:04:2e:9c:82:6d:36:
+ a9:c4:31:64:1f:86:83:0b:2a:f4:35:0a:78:c9:55:
+ cf:41:b0:47:e9:30:9f:99:be:61:a8:06:84:b9:28:
+ 7a:5f:38:d9:1b:a9:38:b0:83:7f:73:c1:c3:3b:48:
+ 2a:82:0f:21:9b:b8:cc:a8:35:c3:84:1b:83:b3:3e:
+ be:a4:95:69:01:3a:89:00:78:04:d9:c9:f4:99:19:
+ ab:56:7e:5b:8b:86:39:15:91:a4:10:2c:09:32:80:
+ 60:b3:93:c0:2a:b6:18:0b:9d:7e:8d:49:f2:10:4a:
+ 7f:f9:d5:46:2f:19:92:a3:99:a7:26:ac:bb:8c:3c:
+ e6:0e:bc:47:07:dc:73:51:f1:70:64:2f:08:f9:b4:
+ 47:1d:30:6c:44:ea:29:37:85:92:68:66:bc:83:38:
+ fe:7b:39:2e:d3:50:f0:1f:fb:5e:60:b6:a9:a6:fa:
+ 27:41:f1:9b:18:72:f2:f5:84:74:4a:c9:67:c4:54:
+ ae:48:64:df:8c:d1:6e:b0:1d:e1:07:8f:08:1e:99:
+ 9c:71:e9:4c:d8:a5:f7:47:12:1f:74:d1:51:9e:86:
+ f3:c2:a2:23:40:0b:73:db:4b:a6:e7:73:06:8c:c1:
+ a0:e9:c1:59:ac:46:fa:e6:2f:f8:cf:71:9c:46:6d:
+ b9:c4:15:8d:38:79:03:45:48:ef:c4:5d:d7:08:ee:
+ 87:39:22:86:b2:0d:0f:58:43:f7:71:a9:48:2e:fd:
+ ea:d6:1f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58
+ X509v3 Authority Key Identifier:
+ keyid:17:A0:CD:C1:E4:41:B6:3A:5B:3B:CB:45:9D:BD:1C:C2:98:FA:86:58
+
+ X509v3 Certificate Policies:
+ Policy: 2.16.756.1.89.1.3.1.1
+ CPS: http://repository.swisssign.com/
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 73:c6:81:e0:27:d2:2d:0f:e0:95:30:e2:9a:41:7f:50:2c:5f:
+ 5f:62:61:a9:86:6a:69:18:0c:74:49:d6:5d:84:ea:41:52:18:
+ 6f:58:ad:50:56:20:6a:c6:bd:28:69:58:91:dc:91:11:35:a9:
+ 3a:1d:bc:1a:a5:60:9e:d8:1f:7f:45:91:69:d9:7e:bb:78:72:
+ c1:06:0f:2a:ce:8f:85:70:61:ac:a0:cd:0b:b8:39:29:56:84:
+ 32:4e:86:bb:3d:c4:2a:d9:d7:1f:72:ee:fe:51:a1:22:41:b1:
+ 71:02:63:1a:82:b0:62:ab:5e:57:12:1f:df:cb:dd:75:a0:c0:
+ 5d:79:90:8c:1b:e0:50:e6:de:31:fe:98:7b:70:5f:a5:90:d8:
+ ad:f8:02:b6:6f:d3:60:dd:40:4b:22:c5:3d:ad:3a:7a:9f:1a:
+ 1a:47:91:79:33:ba:82:dc:32:69:03:96:6e:1f:4b:f0:71:fe:
+ e3:67:72:a0:b1:bf:5c:8b:e4:fa:99:22:c7:84:b9:1b:8d:23:
+ 97:3f:ed:25:e0:cf:65:bb:f5:61:04:ef:dd:1e:b2:5a:41:22:
+ 5a:a1:9f:5d:2c:e8:5b:c9:6d:a9:0c:0c:78:aa:60:c6:56:8f:
+ 01:5a:0c:68:bc:69:19:79:c4:1f:7e:97:05:bf:c5:e9:24:51:
+ 5e:d4:d5:4b:53:ed:d9:23:5a:36:03:65:a3:c1:03:ad:41:30:
+ f3:46:1b:85:90:af:65:b5:d5:b1:e4:16:5b:78:75:1d:97:7a:
+ 6d:59:a9:2a:8f:7b:de:c3:87:89:10:99:49:73:78:c8:3d:bd:
+ 51:35:74:2a:d5:f1:7e:69:1b:2a:bb:3b:bd:25:b8:9a:5a:3d:
+ 72:61:90:66:87:ee:0c:d6:4d:d4:11:74:0b:6a:fe:0b:03:fc:
+ a3:55:57:89:fe:4a:cb:ae:5b:17:05:c8:f2:8d:23:31:53:38:
+ d2:2d:6a:3f:82:b9:8d:08:6a:f7:5e:41:74:6e:c3:11:7e:07:
+ ac:29:60:91:3f:38:ca:57:10:0d:bd:30:2f:c7:a5:e6:41:a0:
+ da:ae:05:87:9a:a0:a4:65:6c:4c:09:0c:89:ba:b8:d3:b9:c0:
+ 93:8a:30:fa:8d:e5:9a:6b:15:01:4e:67:aa:da:62:56:3e:84:
+ 08:66:d2:c4:36:7d:a7:3e:10:fc:88:e0:d4:80:e5:00:bd:aa:
+ f3:4e:06:a3:7a:6a:f9:62:72:e3:09:4f:eb:9b:0e:01:23:f1:
+ 9f:bb:7c:dc:dc:6c:11:97:25:b2:f2:b4:63:14:d2:06:2a:67:
+ 8c:83:f5:ce:ea:07:d8:9a:6a:1e:ec:e4:0a:bb:2a:4c:eb:09:
+ 60:39:ce:ca:62:d8:2e:6e
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
+BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
+IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
+RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
+U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
+Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
+YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
+nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
+6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
+eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
+c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
+MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
+HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
+jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
+5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
+rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
+F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
+wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
+AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
+WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
+xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
+2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
+IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
+aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
+em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
+dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
+OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
+tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem
new file mode 100644
index 00000000000..fcf8ccfbcec
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem
@@ -0,0 +1,52 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 01:54:48:ef:21:fd:97:59:0d:f5:04:0a
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: C = HU, L = Budapest, O = Microsec Ltd., organizationIdentifier = VATHU-23584497, CN = e-Szigno Root CA 2017
+ Validity
+ Not Before: Aug 22 12:07:06 2017 GMT
+ Not After : Aug 22 12:07:06 2042 GMT
+ Subject: C = HU, L = Budapest, O = Microsec Ltd., organizationIdentifier = VATHU-23584497, CN = e-Szigno Root CA 2017
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:96:dc:3d:8a:d8:b0:7b:6f:c6:27:be:44:90:b1:
+ b3:56:15:7b:8e:43:24:7d:1a:84:59:ee:63:68:b2:
+ c6:5e:87:d0:15:48:1e:a8:90:ad:bd:53:a2:da:de:
+ 3a:90:a6:60:5f:68:32:b5:86:41:df:87:5b:2c:7b:
+ c5:fe:7c:7a:da
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 87:11:15:08:D1:AA:C1:78:0C:B1:AF:CE:C6:C9:90:EF:BF:30:04:C0
+ X509v3 Authority Key Identifier:
+ keyid:87:11:15:08:D1:AA:C1:78:0C:B1:AF:CE:C6:C9:90:EF:BF:30:04:C0
+
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:46:02:21:00:b5:57:dd:d7:8a:55:0b:36:e1:86:44:fa:d4:
+ d9:68:8d:b8:dc:23:8a:8a:0d:d4:2f:7d:ea:73:ec:bf:4d:6c:
+ a8:02:21:00:cb:a5:b4:12:fa:e7:b5:e8:cf:7e:93:fc:f3:35:
+ 8f:6f:4e:5a:7c:b4:bc:4e:b2:fc:72:aa:5b:59:f9:e7:dc:31
+-----BEGIN CERTIFICATE-----
+MIICQDCCAeWgAwIBAgIMAVRI7yH9l1kN9QQKMAoGCCqGSM49BAMCMHExCzAJBgNV
+BAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMgTHRk
+LjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25vIFJv
+b3QgQ0EgMjAxNzAeFw0xNzA4MjIxMjA3MDZaFw00MjA4MjIxMjA3MDZaMHExCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHDAhCdWRhcGVzdDEWMBQGA1UECgwNTWljcm9zZWMg
+THRkLjEXMBUGA1UEYQwOVkFUSFUtMjM1ODQ0OTcxHjAcBgNVBAMMFWUtU3ppZ25v
+IFJvb3QgQ0EgMjAxNzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABJbcPYrYsHtv
+xie+RJCxs1YVe45DJH0ahFnuY2iyxl6H0BVIHqiQrb1TotreOpCmYF9oMrWGQd+H
+Wyx7xf58etqjYzBhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBSHERUI0arBeAyxr87GyZDvvzAEwDAfBgNVHSMEGDAWgBSHERUI0arB
+eAyxr87GyZDvvzAEwDAKBggqhkjOPQQDAgNJADBGAiEAtVfd14pVCzbhhkT61Nlo
+jbjcI4qKDdQvfepz7L9NbKgCIQDLpbQS+ue16M9+k/zzNY9vTlp8tLxOsvxyqltZ
++efcMQ==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem
new file mode 100644
index 00000000000..b48d43cb3bb
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem
@@ -0,0 +1,47 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 2a:38:a4:1c:96:0a:04:de:42:b2:28:a5:0b:e8:34:98:02
+ Signature Algorithm: ecdsa-with-SHA256
+ Issuer: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
+ Validity
+ Not Before: Nov 13 00:00:00 2012 GMT
+ Not After : Jan 19 03:14:07 2038 GMT
+ Subject: OU = GlobalSign ECC Root CA - R4, O = GlobalSign, CN = GlobalSign
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (256 bit)
+ pub:
+ 04:b8:c6:79:d3:8f:6c:25:0e:9f:2e:39:19:1c:03:
+ a4:ae:9a:e5:39:07:09:16:ca:63:b1:b9:86:f8:8a:
+ 57:c1:57:ce:42:fa:73:a1:f7:65:42:ff:1e:c1:00:
+ b2:6e:73:0e:ff:c7:21:e5:18:a4:aa:d9:71:3f:a8:
+ d4:b9:ce:8c:1d
+ ASN1 OID: prime256v1
+ NIST CURVE: P-256
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 54:B0:7B:AD:45:B8:E2:40:7F:FB:0A:6E:FB:BE:33:C9:3C:A3:84:D5
+ Signature Algorithm: ecdsa-with-SHA256
+ 30:45:02:21:00:dc:92:a1:a0:13:a6:cf:03:b0:e6:c4:21:97:
+ 90:fa:14:57:2d:03:ec:ee:3c:d3:6e:ca:a8:6c:76:bc:a2:de:
+ bb:02:20:27:a8:85:27:35:9b:56:c6:a3:f2:47:d2:b7:6e:1b:
+ 02:00:17:aa:67:a6:15:91:de:fa:94:ec:7b:0b:f8:9f:84
+-----BEGIN CERTIFICATE-----
+MIIB4TCCAYegAwIBAgIRKjikHJYKBN5CsiilC+g0mAIwCgYIKoZIzj0EAwIwUDEk
+MCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBDQSAtIFI0MRMwEQYDVQQKEwpH
+bG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWduMB4XDTEyMTExMzAwMDAwMFoX
+DTM4MDExOTAzMTQwN1owUDEkMCIGA1UECxMbR2xvYmFsU2lnbiBFQ0MgUm9vdCBD
+QSAtIFI0MRMwEQYDVQQKEwpHbG9iYWxTaWduMRMwEQYDVQQDEwpHbG9iYWxTaWdu
+MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEuMZ5049sJQ6fLjkZHAOkrprlOQcJ
+FspjsbmG+IpXwVfOQvpzofdlQv8ewQCybnMO/8ch5RikqtlxP6jUuc6MHaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFFSwe61F
+uOJAf/sKbvu+M8k8o4TVMAoGCCqGSM49BAMCA0gAMEUCIQDckqGgE6bPA7DmxCGX
+kPoUVy0D7O48027KqGx2vKLeuwIgJ6iFJzWbVsaj8kfSt24bAgAXqmemFZHe+pTs
+ewv4n4Q=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem
new file mode 100644
index 00000000000..b4587b1f0c9
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = JP, O = "Japan Certification Services, Inc.", CN = SecureSign RootCA11
+ Validity
+ Not Before: Apr 8 04:56:47 2009 GMT
+ Not After : Apr 8 04:56:47 2029 GMT
+ Subject: C = JP, O = "Japan Certification Services, Inc.", CN = SecureSign RootCA11
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:fd:77:aa:a5:1c:90:05:3b:cb:4c:9b:33:8b:5a:
+ 14:45:a4:e7:90:16:d1:df:57:d2:21:10:a4:17:fd:
+ df:ac:d6:1f:a7:e4:db:7c:f7:ec:df:b8:03:da:94:
+ 58:fd:5d:72:7c:8c:3f:5f:01:67:74:15:96:e3:02:
+ 3c:87:db:ae:cb:01:8e:c2:f3:66:c6:85:45:f4:02:
+ c6:3a:b5:62:b2:af:fa:9c:bf:a4:e6:d4:80:30:98:
+ f3:0d:b6:93:8f:a9:d4:d8:36:f2:b0:fc:8a:ca:2c:
+ a1:15:33:95:31:da:c0:1b:f2:ee:62:99:86:63:3f:
+ bf:dd:93:2a:83:a8:76:b9:13:1f:b7:ce:4e:42:85:
+ 8f:22:e7:2e:1a:f2:95:09:b2:05:b5:44:4e:77:a1:
+ 20:bd:a9:f2:4e:0a:7d:50:ad:f5:05:0d:45:4f:46:
+ 71:fd:28:3e:53:fb:04:d8:2d:d7:65:1d:4a:1b:fa:
+ cf:3b:b0:31:9a:35:6e:c8:8b:06:d3:00:91:f2:94:
+ 08:65:4c:b1:34:06:00:7a:89:e2:f0:c7:03:59:cf:
+ d5:d6:e8:a7:32:b3:e6:98:40:86:c5:cd:27:12:8b:
+ cc:7b:ce:b7:11:3c:62:60:07:23:3e:2b:40:6e:94:
+ 80:09:6d:b6:b3:6f:77:6f:35:08:50:fb:02:87:c5:
+ 3e:89
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 5B:F8:4D:4F:B2:A5:86:D4:3A:D2:F1:63:9A:A0:BE:09:F6:57:B7:DE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ a0:a1:38:16:66:2e:a7:56:1f:21:9c:06:fa:1d:ed:b9:22:c5:
+ 38:26:d8:4e:4f:ec:a3:7f:79:de:46:21:a1:87:77:8f:07:08:
+ 9a:b2:a4:c5:af:0f:32:98:0b:7c:66:29:b6:9b:7d:25:52:49:
+ 43:ab:4c:2e:2b:6e:7a:70:af:16:0e:e3:02:6c:fb:42:e6:18:
+ 9d:45:d8:55:c8:e8:3b:dd:e7:e1:f4:2e:0b:1c:34:5c:6c:58:
+ 4a:fb:8c:88:50:5f:95:1c:bf:ed:ab:22:b5:65:b3:85:ba:9e:
+ 0f:b8:ad:e5:7a:1b:8a:50:3a:1d:bd:0d:bc:7b:54:50:0b:b9:
+ 42:af:55:a0:18:81:ad:65:99:ef:be:e4:9c:bf:c4:85:ab:41:
+ b2:54:6f:dc:25:cd:ed:78:e2:8e:0c:8d:09:49:dd:63:7b:5a:
+ 69:96:02:21:a8:bd:52:59:e9:7d:35:cb:c8:52:ca:7f:81:fe:
+ d9:6b:d3:f7:11:ed:25:df:f8:e7:f9:a4:fa:72:97:84:53:0d:
+ a5:d0:32:18:51:76:59:14:6c:0f:eb:ec:5f:80:8c:75:43:83:
+ c3:85:98:ff:4c:9e:2d:0d:e4:77:83:93:4e:b5:96:07:8b:28:
+ 13:9b:8c:19:8d:41:27:49:40:ee:de:e6:23:44:39:dc:a1:22:
+ d6:ba:03:f2
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
+MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
+A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
+MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
+Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
+QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
+i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
+h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
+MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
+UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
+8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
+h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
+VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
+AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
+KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
+X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
+QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
+pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
+QSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem
new file mode 100644
index 00000000000..05b6e5b8644
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem
@@ -0,0 +1,77 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = TW, O = TAIWAN-CA, OU = Root CA, CN = TWCA Root Certification Authority
+ Validity
+ Not Before: Aug 28 07:24:33 2008 GMT
+ Not After : Dec 31 15:59:59 2030 GMT
+ Subject: C = TW, O = TAIWAN-CA, OU = Root CA, CN = TWCA Root Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b0:7e:72:b8:a4:03:94:e6:a7:de:09:38:91:4a:
+ 11:40:87:a7:7c:59:64:14:7b:b5:11:10:dd:fe:bf:
+ d5:c0:bb:56:e2:85:25:f4:35:72:0f:f8:53:d0:41:
+ e1:44:01:c2:b4:1c:c3:31:42:16:47:85:33:22:76:
+ b2:0a:6f:0f:e5:25:50:4f:85:86:be:bf:98:2e:10:
+ 67:1e:be:11:05:86:05:90:c4:59:d0:7c:78:10:b0:
+ 80:5c:b7:e1:c7:2b:75:cb:7c:9f:ae:b5:d1:9d:23:
+ 37:63:a7:dc:42:a2:2d:92:04:1b:50:c1:7b:b8:3e:
+ 1b:c9:56:04:8b:2f:52:9b:ad:a9:56:e9:c1:ff:ad:
+ a9:58:87:30:b6:81:f7:97:45:fc:19:57:3b:2b:6f:
+ e4:47:f4:99:45:fe:1d:f1:f8:97:a3:88:1d:37:1c:
+ 5c:8f:e0:76:25:9a:50:f8:a0:54:ff:44:90:76:23:
+ d2:32:c6:c3:ab:06:bf:fc:fb:bf:f3:ad:7d:92:62:
+ 02:5b:29:d3:35:a3:93:9a:43:64:60:5d:b2:fa:32:
+ ff:3b:04:af:4d:40:6a:f9:c7:e3:ef:23:fd:6b:cb:
+ e5:0f:8b:38:0d:ee:0a:fc:fe:0f:98:9f:30:31:dd:
+ 6c:52:65:f9:8b:81:be:22:e1:1c:58:03:ba:91:1b:
+ 89:07
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 6A:38:5B:26:8D:DE:8B:5A:F2:4F:7A:54:83:19:18:E3:08:35:A6:BA
+ Signature Algorithm: sha1WithRSAEncryption
+ 3c:d5:77:3d:da:df:89:ba:87:0c:08:54:6a:20:50:92:be:b0:
+ 41:3d:b9:26:64:83:0a:2f:e8:40:c0:97:28:27:82:30:4a:c9:
+ 93:ff:6a:e7:a6:00:7f:89:42:9a:d6:11:e5:53:ce:2f:cc:f2:
+ da:05:c4:fe:e2:50:c4:3a:86:7d:cc:da:7e:10:09:3b:92:35:
+ 2a:53:b2:fe:eb:2b:05:d9:6c:5d:e6:d0:ef:d3:6a:66:9e:15:
+ 28:85:7a:e8:82:00:ac:1e:a7:09:69:56:42:d3:68:51:18:be:
+ 54:9a:bf:44:41:ba:49:be:20:ba:69:5c:ee:b8:77:cd:ce:6c:
+ 1f:ad:83:96:18:7d:0e:b5:14:39:84:f1:28:e9:2d:a3:9e:7b:
+ 1e:7a:72:5a:83:b3:79:6f:ef:b4:fc:d0:0a:a5:58:4f:46:df:
+ fb:6d:79:59:f2:84:22:52:ae:0f:cc:fb:7c:3b:e7:6a:ca:47:
+ 61:c3:7a:f8:d3:92:04:1f:b8:20:84:e1:36:54:16:c7:40:de:
+ 3b:8a:73:dc:df:c6:09:4c:df:ec:da:ff:d4:53:42:a1:c9:f2:
+ 62:1d:22:83:3c:97:c5:f9:19:62:27:ac:65:22:d7:d3:3c:c6:
+ e5:8e:b2:53:cc:49:ce:bc:30:fe:7b:0e:33:90:fb:ed:d2:14:
+ 91:1f:07:af
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzES
+MBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFU
+V0NBIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMz
+WhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJVEFJV0FO
+LUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlm
+aWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFE
+AcK0HMMxQhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HH
+K3XLfJ+utdGdIzdjp9xCoi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeX
+RfwZVzsrb+RH9JlF/h3x+JejiB03HFyP4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/z
+rX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1ry+UPizgN7gr8/g+YnzAx
+3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkq
+hkiG9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeC
+MErJk/9q56YAf4lCmtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdls
+XebQ79NqZp4VKIV66IIArB6nCWlWQtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62D
+lhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVYT0bf+215WfKEIlKuD8z7fDvn
+aspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocnyYh0igzyXxfkZ
+YiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem
new file mode 100644
index 00000000000..b16deeaab43
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 9009899650740120186 (0x7d0997fef047ea7a)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = CN, O = "GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.", CN = GDCA TrustAUTH R5 ROOT
+ Validity
+ Not Before: Nov 26 05:13:15 2014 GMT
+ Not After : Dec 31 15:59:59 2040 GMT
+ Subject: C = CN, O = "GUANG DONG CERTIFICATE AUTHORITY CO.,LTD.", CN = GDCA TrustAUTH R5 ROOT
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:d9:a3:16:f0:c8:74:74:77:9b:ef:33:0d:3b:06:
+ 7e:55:fc:b5:60:8f:76:86:12:42:7d:56:66:3e:88:
+ 82:ed:72:63:0e:9e:8b:dd:34:2c:02:51:51:c3:19:
+ fd:59:54:84:c9:f1:6b:b3:4c:b0:e9:e8:46:5d:38:
+ c6:a2:a7:2e:11:57:ba:82:15:a2:9c:8f:6d:b0:99:
+ 4a:0a:f2:eb:89:70:63:4e:79:c4:b7:5b:bd:a2:5d:
+ b1:f2:41:02:2b:ad:a9:3a:a3:ec:79:0a:ec:5f:3a:
+ e3:fd:ef:80:3c:ad:34:9b:1a:ab:88:26:7b:56:a2:
+ 82:86:1f:eb:35:89:83:7f:5f:ae:29:4e:3d:b6:6e:
+ ec:ae:c1:f0:27:9b:ae:e3:f4:ec:ef:ae:7f:f7:86:
+ 3d:72:7a:eb:a5:fb:59:4e:a7:eb:95:8c:22:39:79:
+ e1:2d:08:8f:cc:bc:91:b8:41:f7:14:c1:23:a9:c3:
+ ad:9a:45:44:b3:b2:d7:2c:cd:c6:29:e2:50:10:ae:
+ 5c:cb:82:8e:17:18:36:7d:97:e6:88:9a:b0:4d:34:
+ 09:f4:2c:b9:5a:66:2a:b0:17:9b:9e:1e:76:9d:4a:
+ 66:31:41:df:3f:fb:c5:06:ef:1b:b6:7e:1a:46:36:
+ f7:64:63:3b:e3:39:18:23:e7:67:75:14:d5:75:57:
+ 92:37:bd:be:6a:1b:26:50:f2:36:26:06:90:c5:70:
+ 01:64:6d:76:66:e1:91:db:6e:07:c0:61:80:2e:b2:
+ 2e:2f:8c:70:a7:d1:3b:3c:b3:91:e4:6e:b6:c4:3b:
+ 70:f2:6c:92:97:09:cd:47:7d:18:c0:f3:bb:9e:0f:
+ d6:8b:ae:07:b6:5a:0f:ce:0b:0c:47:a7:e5:3e:b8:
+ bd:7d:c7:9b:35:a0:61:97:3a:41:75:17:cc:2b:96:
+ 77:2a:92:21:1e:d9:95:76:20:67:68:cf:0d:bd:df:
+ d6:1f:09:6a:9a:e2:cc:73:71:a4:2f:7d:12:80:b7:
+ 53:30:46:5e:4b:54:99:0f:67:c9:a5:c8:f2:20:c1:
+ 82:ec:9d:11:df:c2:02:fb:1a:3b:d1:ed:20:9a:ef:
+ 65:64:92:10:0d:2a:e2:de:70:f1:18:67:82:8c:61:
+ de:b8:bc:d1:2f:9c:fb:0f:d0:2b:ed:1b:76:b9:e4:
+ 39:55:f8:f8:a1:1d:b8:aa:80:00:4c:82:e7:b2:7f:
+ 09:b8:bc:30:a0:2f:0d:f5:52:9e:8e:f7:92:b3:0a:
+ 00:1d:00:54:97:06:e0:b1:07:d9:c7:0f:5c:65:7d:
+ 3c:6d:59:57:e4:ed:a5:8d:e9:40:53:9f:15:4b:a0:
+ 71:f6:1a:21:e3:da:70:06:21:58:14:87:85:77:79:
+ aa:82:79
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ E2:C9:40:9F:4D:CE:E8:9A:A1:7C:CF:0E:3F:65:C5:29:88:6A:19:51
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ d1:49:57:e0:a7:cc:68:58:ba:01:0f:2b:19:cd:8d:b0:61:45:
+ ac:11:ed:63:50:69:f8:1f:7f:be:16:8f:fd:9d:eb:0b:aa:32:
+ 47:76:d2:67:24:ed:bd:7c:33:32:97:2a:c7:05:86:66:0d:17:
+ 7d:14:15:1b:d4:eb:fd:1f:9a:f6:5e:97:69:b7:1a:25:a4:0a:
+ b3:91:3f:5f:36:ac:8b:ec:57:a8:3e:e7:81:8a:18:57:39:85:
+ 74:1a:42:c7:e9:5b:13:5f:8f:f9:08:e9:92:74:8d:f5:47:d2:
+ ab:3b:d6:fb:78:66:4e:36:7d:f9:e9:92:e9:04:de:fd:49:63:
+ fc:6d:fb:14:71:93:67:2f:47:4a:b7:b9:ff:1e:2a:73:70:46:
+ 30:bf:5a:f2:2f:79:a5:e1:8d:0c:d9:f9:b2:63:37:8c:37:65:
+ 85:70:6a:5c:5b:09:72:b9:ad:63:3c:b1:dd:f8:fc:32:bf:37:
+ 86:e4:bb:8e:98:27:7e:ba:1f:16:e1:70:11:f2:03:df:25:62:
+ 32:27:26:18:32:84:9f:ff:00:3a:13:ba:9a:4d:f4:4f:b8:14:
+ 70:22:b1:ca:2b:90:ce:29:c1:70:f4:2f:9d:7f:f2:90:1e:d6:
+ 5a:df:b7:46:fc:e6:86:fa:cb:e0:20:76:7a:ba:a6:cb:f5:7c:
+ de:62:a5:b1:8b:ee:de:82:66:8a:4e:3a:30:1f:3f:80:cb:ad:
+ 27:ba:0c:5e:d7:d0:b1:56:ca:77:71:b2:b5:75:a1:50:a9:40:
+ 43:17:c2:28:d9:cf:52:8b:5b:c8:63:d4:42:3e:a0:33:7a:46:
+ 2e:f7:0a:20:46:54:7e:6a:4f:31:f1:81:7e:42:74:38:65:73:
+ 27:ee:c6:7c:b8:8e:d7:a5:3a:d7:98:a1:9c:8c:10:55:d3:db:
+ 4b:ec:40:90:f2:cd:6e:57:d2:62:0e:7c:57:93:b1:a7:6d:cd:
+ 9d:83:bb:2a:e7:e5:b6:3b:71:58:ad:fd:d1:45:bc:5a:91:ee:
+ 53:15:6f:d3:45:09:75:6e:ba:90:5d:1e:04:cf:37:df:1e:a8:
+ 66:b1:8c:e6:20:6a:ef:fc:48:4e:74:98:42:af:29:6f:2e:6a:
+ c7:fb:7d:d1:66:31:22:cc:86:00:7e:66:83:0c:42:f4:bd:34:
+ 92:c3:1a:ea:4f:ca:7e:72:4d:0b:70:8c:a6:48:bb:a6:a1:14:
+ f6:fb:58:44:99:14:ae:aa:0b:93:69:a0:29:25:4a:a5:cb:2b:
+ dd:8a:66:07:16:78:15:57:71:1b:ec:f5:47:84:f3:9e:31:37:
+ 7a:d5:7f:24:ad:e4:bc:fd:fd:cc:6e:83:e8:0c:a8:b7:41:6c:
+ 07:dd:bd:3c:86:97:2f:d2
+-----BEGIN CERTIFICATE-----
+MIIFiDCCA3CgAwIBAgIIfQmX/vBH6nowDQYJKoZIhvcNAQELBQAwYjELMAkGA1UE
+BhMCQ04xMjAwBgNVBAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZ
+IENPLixMVEQuMR8wHQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMB4XDTE0
+MTEyNjA1MTMxNVoXDTQwMTIzMTE1NTk1OVowYjELMAkGA1UEBhMCQ04xMjAwBgNV
+BAoMKUdVQU5HIERPTkcgQ0VSVElGSUNBVEUgQVVUSE9SSVRZIENPLixMVEQuMR8w
+HQYDVQQDDBZHRENBIFRydXN0QVVUSCBSNSBST09UMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA2aMW8Mh0dHeb7zMNOwZ+Vfy1YI92hhJCfVZmPoiC7XJj
+Dp6L3TQsAlFRwxn9WVSEyfFrs0yw6ehGXTjGoqcuEVe6ghWinI9tsJlKCvLriXBj
+TnnEt1u9ol2x8kECK62pOqPseQrsXzrj/e+APK00mxqriCZ7VqKChh/rNYmDf1+u
+KU49tm7srsHwJ5uu4/Ts765/94Y9cnrrpftZTqfrlYwiOXnhLQiPzLyRuEH3FMEj
+qcOtmkVEs7LXLM3GKeJQEK5cy4KOFxg2fZfmiJqwTTQJ9Cy5WmYqsBebnh52nUpm
+MUHfP/vFBu8btn4aRjb3ZGM74zkYI+dndRTVdVeSN72+ahsmUPI2JgaQxXABZG12
+ZuGR224HwGGALrIuL4xwp9E7PLOR5G62xDtw8mySlwnNR30YwPO7ng/Wi64HtloP
+zgsMR6flPri9fcebNaBhlzpBdRfMK5Z3KpIhHtmVdiBnaM8Nvd/WHwlqmuLMc3Gk
+L30SgLdTMEZeS1SZD2fJpcjyIMGC7J0R38IC+xo70e0gmu9lZJIQDSri3nDxGGeC
+jGHeuLzRL5z7D9Ar7Rt2ueQ5Vfj4oR24qoAATILnsn8JuLwwoC8N9VKejveSswoA
+HQBUlwbgsQfZxw9cZX08bVlX5O2ljelAU58VS6Bx9hoh49pwBiFYFIeFd3mqgnkC
+AwEAAaNCMEAwHQYDVR0OBBYEFOLJQJ9NzuiaoXzPDj9lxSmIahlRMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBCwUAA4ICAQDRSVfg
+p8xoWLoBDysZzY2wYUWsEe1jUGn4H3++Fo/9nesLqjJHdtJnJO29fDMylyrHBYZm
+DRd9FBUb1Ov9H5r2XpdptxolpAqzkT9fNqyL7FeoPueBihhXOYV0GkLH6VsTX4/5
+COmSdI31R9KrO9b7eGZONn356ZLpBN79SWP8bfsUcZNnL0dKt7n/HipzcEYwv1ry
+L3ml4Y0M2fmyYzeMN2WFcGpcWwlyua1jPLHd+PwyvzeG5LuOmCd+uh8W4XAR8gPf
+JWIyJyYYMoSf/wA6E7qaTfRPuBRwIrHKK5DOKcFw9C+df/KQHtZa37dG/OaG+svg
+IHZ6uqbL9XzeYqWxi+7egmaKTjowHz+Ay60nugxe19CxVsp3cbK1daFQqUBDF8Io
+2c9Si1vIY9RCPqAzekYu9wogRlR+ak8x8YF+QnQ4ZXMn7sZ8uI7XpTrXmKGcjBBV
+09tL7ECQ8s1uV9JiDnxXk7Gnbc2dg7sq5+W2O3FYrf3RRbxake5TFW/TRQl1brqQ
+XR4EzzffHqhmsYzmIGrv/EhOdJhCrylvLmrH+33RZjEizIYAfmaDDEL0vTSSwxrq
+T8p+ck0LcIymSLumoRT2+1hEmRSuqguTaaApJUqlyyvdimYHFngVV3Eb7PVHhPOe
+MTd61X8kreS8/f3MboPoDKi3QWwH3b08hpcv0g==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem
new file mode 100644
index 00000000000..273786e29c3
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 15:c8:bd:65:47:5c:af:b8:97:00:5e:e4:06:d2:bc:9d
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = TW, O = "Chunghwa Telecom Co., Ltd.", OU = ePKI Root Certification Authority
+ Validity
+ Not Before: Dec 20 02:31:27 2004 GMT
+ Not After : Dec 20 02:31:27 2034 GMT
+ Subject: C = TW, O = "Chunghwa Telecom Co., Ltd.", OU = ePKI Root Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:e1:25:0f:ee:8d:db:88:33:75:67:cd:ad:1f:7d:
+ 3a:4e:6d:9d:d3:2f:14:f3:63:74:cb:01:21:6a:37:
+ ea:84:50:07:4b:26:5b:09:43:6c:21:9e:6a:c8:d5:
+ 03:f5:60:69:8f:cc:f0:22:e4:1f:e7:f7:6a:22:31:
+ b7:2c:15:f2:e0:fe:00:6a:43:ff:87:65:c6:b5:1a:
+ c1:a7:4c:6d:22:70:21:8a:31:f2:97:74:89:09:12:
+ 26:1c:9e:ca:d9:12:a2:95:3c:da:e9:67:bf:08:a0:
+ 64:e3:d6:42:b7:45:ef:97:f4:f6:f5:d7:b5:4a:15:
+ 02:58:7d:98:58:4b:60:bc:cd:d7:0d:9a:13:33:53:
+ d1:61:f9:7a:d5:d7:78:b3:9a:33:f7:00:86:ce:1d:
+ 4d:94:38:af:a8:ec:78:51:70:8a:5c:10:83:51:21:
+ f7:11:3d:34:86:5e:e5:48:cd:97:81:82:35:4c:19:
+ ec:65:f6:6b:c5:05:a1:ee:47:13:d6:b3:21:27:94:
+ 10:0a:d9:24:3b:ba:be:44:13:46:30:3f:97:3c:d8:
+ d7:d7:6a:ee:3b:38:e3:2b:d4:97:0e:b9:1b:e7:07:
+ 49:7f:37:2a:f9:77:78:cf:54:ed:5b:46:9d:a3:80:
+ 0e:91:43:c1:d6:5b:5f:14:ba:9f:a6:8d:24:47:40:
+ 59:bf:72:38:b2:36:6c:37:ff:99:d1:5d:0e:59:0a:
+ ab:69:f7:c0:b2:04:45:7a:54:00:ae:be:53:f6:b5:
+ e7:e1:f8:3c:a3:31:d2:a9:fe:21:52:64:c5:a6:67:
+ f0:75:07:06:94:14:81:55:c6:27:e4:01:8f:17:c1:
+ 6a:71:d7:be:4b:fb:94:58:7d:7e:11:33:b1:42:f7:
+ 62:6c:18:d6:cf:09:68:3e:7f:6c:f6:1e:8f:62:ad:
+ a5:63:db:09:a7:1f:22:42:41:1e:6f:99:8a:3e:d7:
+ f9:3f:40:7a:79:b0:a5:01:92:d2:9d:3d:08:15:a5:
+ 10:01:2d:b3:32:76:a8:95:0d:b3:7a:9a:fb:07:10:
+ 78:11:6f:e1:8f:c7:ba:0f:25:1a:74:2a:e5:1c:98:
+ 41:99:df:21:87:e8:95:06:6a:0a:b3:6a:47:76:65:
+ f6:3a:cf:8f:62:17:19:7b:0a:28:cd:1a:d2:83:1e:
+ 21:c7:2c:bf:be:ff:61:68:b7:67:1b:bb:78:4d:8d:
+ ce:67:e5:e4:c1:8e:b7:23:66:e2:9d:90:75:34:98:
+ a9:36:2b:8a:9a:94:b9:9d:ec:cc:8a:b1:f8:25:89:
+ 5c:5a:b6:2f:8c:1f:6d:79:24:a7:52:68:c3:84:35:
+ e2:66:8d:63:0e:25:4d:d5:19:b2:e6:79:37:a7:22:
+ 9d:54:31
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 1E:0C:F7:B6:67:F2:E1:92:26:09:45:C0:55:39:2E:77:3F:42:4A:A2
+ X509v3 Basic Constraints:
+ CA:TRUE
+ setCext-hashedRoot:
+ 0/0-...0...+......0...g*.....E...
+V|.[x....S.....
+ Signature Algorithm: sha1WithRSAEncryption
+ 09:b3:83:53:59:01:3e:95:49:b9:f1:81:ba:f9:76:20:23:b5:
+ 27:60:74:d4:6a:99:34:5e:6c:00:53:d9:9f:f2:a6:b1:24:07:
+ 44:6a:2a:c6:a5:8e:78:12:e8:47:d9:58:1b:13:2a:5e:79:9b:
+ 9f:0a:2a:67:a6:25:3f:06:69:56:73:c3:8a:66:48:fb:29:81:
+ 57:74:06:ca:9c:ea:28:e8:38:67:26:2b:f1:d5:b5:3f:65:93:
+ f8:36:5d:8e:8d:8d:40:20:87:19:ea:ef:27:c0:3d:b4:39:0f:
+ 25:7b:68:50:74:55:9c:0c:59:7d:5a:3d:41:94:25:52:08:e0:
+ 47:2c:15:31:19:d5:bf:07:55:c6:bb:12:b5:97:f4:5f:83:85:
+ ba:71:c1:d9:6c:81:11:76:0a:0a:b0:bf:82:97:f7:ea:3d:fa:
+ fa:ec:2d:a9:28:94:3b:56:dd:d2:51:2e:ae:c0:bd:08:15:8c:
+ 77:52:34:96:d6:9b:ac:d3:1d:8e:61:0f:35:7b:9b:ae:39:69:
+ 0b:62:60:40:20:36:8f:af:fb:36:ee:2d:08:4a:1d:b8:bf:9b:
+ 5c:f8:ea:a5:1b:a0:73:a6:d8:f8:6e:e0:33:04:5f:68:aa:27:
+ 87:ed:d9:c1:90:9c:ed:bd:e3:6a:35:af:63:df:ab:18:d9:ba:
+ e6:e9:4a:ea:50:8a:0f:61:93:1e:e2:2d:19:e2:30:94:35:92:
+ 5d:0e:b6:07:af:19:80:8f:47:90:51:4b:2e:4d:dd:85:e2:d2:
+ 0a:52:0a:17:9a:fc:1a:b0:50:02:e5:01:a3:63:37:21:4c:44:
+ c4:9b:51:99:11:0e:73:9c:06:8f:54:2e:a7:28:5e:44:39:87:
+ 56:2d:37:bd:85:44:94:e1:0c:4b:2c:9c:c3:92:85:34:61:cb:
+ 0f:b8:9b:4a:43:52:fe:34:3a:7d:b8:e9:29:dc:76:a9:c8:30:
+ f8:14:71:80:c6:1e:36:48:74:22:41:5c:87:82:e8:18:71:8b:
+ 41:89:44:e7:7e:58:5b:a8:b8:8d:13:e9:a7:6c:c3:47:ed:b3:
+ 1a:9d:62:ae:8d:82:ea:94:9e:dd:59:10:c3:ad:dd:e2:4d:e3:
+ 31:d5:c7:ec:e8:f2:b0:fe:92:1e:16:0a:1a:fc:d9:f3:f8:27:
+ b6:c9:be:1d:b4:6c:64:90:7f:f4:e4:c4:5b:d7:37:ae:42:0e:
+ dd:a4:1a:6f:7c:88:54:c5:16:6e:e1:7a:68:2e:f8:3a:bf:0d:
+ a4:3c:89:3b:78:a7:4e:63:83:04:21:08:67:8d:f2:82:49:d0:
+ 5b:fd:b1:cd:0f:83:84:d4:3e:20:85:f7:4a:3d:2b:9c:fd:2a:
+ 0a:09:4d:ea:81:f8:11:9c
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
+MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
+ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
+Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
+IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
+SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
+SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
+ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
+DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
+TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
+fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
+sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
+WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
+nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
+dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
+NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
+AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
+MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
+uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
+PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
+JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
+gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
+j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
+5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
+o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
+/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
+Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
+W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
+hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem
new file mode 100644
index 00000000000..2252802ecaa
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = "The Go Daddy Group, Inc.", OU = Go Daddy Class 2 Certification Authority
+ Validity
+ Not Before: Jun 29 17:06:20 2004 GMT
+ Not After : Jun 29 17:06:20 2034 GMT
+ Subject: C = US, O = "The Go Daddy Group, Inc.", OU = Go Daddy Class 2 Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:de:9d:d7:ea:57:18:49:a1:5b:eb:d7:5f:48:86:
+ ea:be:dd:ff:e4:ef:67:1c:f4:65:68:b3:57:71:a0:
+ 5e:77:bb:ed:9b:49:e9:70:80:3d:56:18:63:08:6f:
+ da:f2:cc:d0:3f:7f:02:54:22:54:10:d8:b2:81:d4:
+ c0:75:3d:4b:7f:c7:77:c3:3e:78:ab:1a:03:b5:20:
+ 6b:2f:6a:2b:b1:c5:88:7e:c4:bb:1e:b0:c1:d8:45:
+ 27:6f:aa:37:58:f7:87:26:d7:d8:2d:f6:a9:17:b7:
+ 1f:72:36:4e:a6:17:3f:65:98:92:db:2a:6e:5d:a2:
+ fe:88:e0:0b:de:7f:e5:8d:15:e1:eb:cb:3a:d5:e2:
+ 12:a2:13:2d:d8:8e:af:5f:12:3d:a0:08:05:08:b6:
+ 5c:a5:65:38:04:45:99:1e:a3:60:60:74:c5:41:a5:
+ 72:62:1b:62:c5:1f:6f:5f:1a:42:be:02:51:65:a8:
+ ae:23:18:6a:fc:78:03:a9:4d:7f:80:c3:fa:ab:5a:
+ fc:a1:40:a4:ca:19:16:fe:b2:c8:ef:5e:73:0d:ee:
+ 77:bd:9a:f6:79:98:bc:b1:07:67:a2:15:0d:dd:a0:
+ 58:c6:44:7b:0a:3e:62:28:5f:ba:41:07:53:58:cf:
+ 11:7e:38:74:c5:f8:ff:b5:69:90:8f:84:74:ea:97:
+ 1b:af
+ Exponent: 3 (0x3)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
+ X509v3 Authority Key Identifier:
+ keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
+ DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
+ serial:00
+
+ X509v3 Basic Constraints:
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 32:4b:f3:b2:ca:3e:91:fc:12:c6:a1:07:8c:8e:77:a0:33:06:
+ 14:5c:90:1e:18:f7:08:a6:3d:0a:19:f9:87:80:11:6e:69:e4:
+ 96:17:30:ff:34:91:63:72:38:ee:cc:1c:01:a3:1d:94:28:a4:
+ 31:f6:7a:c4:54:d7:f6:e5:31:58:03:a2:cc:ce:62:db:94:45:
+ 73:b5:bf:45:c9:24:b5:d5:82:02:ad:23:79:69:8d:b8:b6:4d:
+ ce:cf:4c:ca:33:23:e8:1c:88:aa:9d:8b:41:6e:16:c9:20:e5:
+ 89:9e:cd:3b:da:70:f7:7e:99:26:20:14:54:25:ab:6e:73:85:
+ e6:9b:21:9d:0a:6c:82:0e:a8:f8:c2:0c:fa:10:1e:6c:96:ef:
+ 87:0d:c4:0f:61:8b:ad:ee:83:2b:95:f8:8e:92:84:72:39:eb:
+ 20:ea:83:ed:83:cd:97:6e:08:bc:eb:4e:26:b6:73:2b:e4:d3:
+ f6:4c:fe:26:71:e2:61:11:74:4a:ff:57:1a:87:0f:75:48:2e:
+ cf:51:69:17:a0:02:12:61:95:d5:d1:40:b2:10:4c:ee:c4:ac:
+ 10:43:a6:a5:9e:0a:d5:95:62:9a:0d:cf:88:82:c5:32:0c:e4:
+ 2b:9f:45:e6:0d:9f:28:9c:b1:b9:2a:5a:57:ad:37:0f:af:1d:
+ 7f:db:bd:9f
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
+MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
+YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
+MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
+ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
+MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
+ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
+PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
+wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
+EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
+avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
+sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
+/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
+IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
+ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
+OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
+TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
+dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
+ReYNnyicsbkqWletNw+vHX/bvZ8=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem
new file mode 100644
index 00000000000..4c43a2dee70
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 6e:47:a9:c6:5a:b3:e7:20:c5:30:9a:3f:68:52:f2:6f
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = Google Trust Services LLC, CN = GTS Root R2
+ Validity
+ Not Before: Jun 22 00:00:00 2016 GMT
+ Not After : Jun 22 00:00:00 2036 GMT
+ Subject: C = US, O = Google Trust Services LLC, CN = GTS Root R2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ce:de:fd:a6:fb:ec:ec:14:34:3c:07:06:5a:6c:
+ 59:f7:19:35:dd:f7:c1:9d:55:aa:d3:cd:3b:a4:93:
+ 72:ef:0a:fa:6d:9d:f6:f0:85:80:5b:a1:48:52:9f:
+ 39:c5:b7:ee:28:ac:ef:cb:76:68:14:b9:df:ad:01:
+ 6c:99:1f:c4:22:1d:9f:fe:72:77:e0:2c:5b:af:e4:
+ 04:bf:4f:72:a0:1a:34:98:e8:39:68:ec:95:25:7b:
+ 76:a1:e6:69:b9:85:19:bd:89:8c:fe:ad:ed:36:ea:
+ 73:bc:ff:83:e2:cb:7d:c1:d2:ce:4a:b3:8d:05:9e:
+ 8b:49:93:df:c1:5b:d0:6e:5e:f0:2e:30:2e:82:fc:
+ fa:bc:b4:17:0a:48:e5:88:9b:c5:9b:6b:de:b0:ca:
+ b4:03:f0:da:f4:90:b8:65:64:f7:5c:4c:ad:e8:7e:
+ 66:5e:99:d7:b8:c2:3e:c8:d0:13:9d:ad:ee:e4:45:
+ 7b:89:55:f7:8a:1f:62:52:84:12:b3:c2:40:97:e3:
+ 8a:1f:47:91:a6:74:5a:d2:f8:b1:63:28:10:b8:b3:
+ 09:b8:56:77:40:a2:26:98:79:c6:fe:df:25:ee:3e:
+ e5:a0:7f:d4:61:0f:51:4b:3c:3f:8c:da:e1:70:74:
+ d8:c2:68:a1:f9:c1:0c:e9:a1:e2:7f:bb:55:3c:76:
+ 06:ee:6a:4e:cc:92:88:30:4d:9a:bd:4f:0b:48:9a:
+ 84:b5:98:a3:d5:fb:73:c1:57:61:dd:28:56:75:13:
+ ae:87:8e:e7:0c:51:09:10:75:88:4c:bc:8d:f9:7b:
+ 3c:d4:22:48:1f:2a:dc:eb:6b:bb:44:b1:cb:33:71:
+ 32:46:af:ad:4a:f1:8c:e8:74:3a:ac:e7:1a:22:73:
+ 80:d2:30:f7:25:42:c7:22:3b:3b:12:ad:96:2e:c6:
+ c3:76:07:aa:20:b7:35:49:57:e9:92:49:e8:76:16:
+ 72:31:67:2b:96:7e:8a:a3:c7:94:56:22:bf:6a:4b:
+ 7e:01:21:b2:23:32:df:e4:9a:44:6d:59:5b:5d:f5:
+ 00:a0:1c:9b:c6:78:97:8d:90:ff:9b:c8:aa:b4:af:
+ 11:51:39:5e:d9:fb:67:ad:d5:5b:11:9d:32:9a:1b:
+ bd:d5:ba:5b:a5:c9:cb:25:69:53:55:27:5c:e0:ca:
+ 36:cb:88:61:fb:1e:b7:d0:cb:ee:16:fb:d3:a6:4c:
+ de:92:a5:d4:e2:df:f5:06:54:de:2e:9d:4b:b4:93:
+ 30:aa:81:ce:dd:1a:dc:51:73:0d:4f:70:e9:e5:b6:
+ 16:21:19:79:b2:e6:89:0b:75:64:ca:d5:ab:bc:09:
+ c1:18:a1:ff:d4:54:a1:85:3c:fd:14:24:03:b2:87:
+ d3:a4:b7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ BB:FF:CA:8E:23:9F:4F:99:CA:DB:E2:68:A6:A5:15:27:17:1E:D9:0E
+ Signature Algorithm: sha384WithRSAEncryption
+ b6:69:f0:a6:77:fe:9e:ee:0b:81:ad:e1:c0:a9:c7:f9:35:1d:
+ 40:82:ab:e6:04:b4:df:cb:f7:1d:0f:83:f0:7e:13:4d:8d:8c:
+ ee:e3:33:22:c3:39:fc:40:df:6e:41:4b:42:53:be:16:88:f1:
+ d2:38:5e:c4:68:99:1c:98:52:93:8c:e7:68:ed:1b:6a:73:7a:
+ 05:40:4d:7f:65:3b:d6:58:f1:ce:83:47:60:e3:ff:97:a9:9c:
+ 60:77:18:55:b5:7e:08:93:cf:d0:f6:3c:67:03:15:61:09:f9:
+ 81:79:f5:ec:53:a4:9f:c9:8f:01:8b:73:c4:77:76:dc:83:a2:
+ f5:0c:49:1a:a8:76:de:92:9b:64:f8:b3:2c:c5:27:d3:07:c0:
+ 08:80:a4:98:92:e3:01:96:02:aa:02:ee:8f:3b:c5:d1:6d:0a:
+ 33:30:73:78:b9:4f:54:16:bf:0b:07:a1:a4:5c:e6:cb:c9:5c:
+ 84:8f:0f:e0:15:77:2c:7e:26:7e:da:c4:4b:db:a7:16:77:07:
+ b0:cd:75:e8:72:42:d6:95:84:9d:86:83:f2:e4:90:cd:09:47:
+ d4:8b:03:70:da:5a:c6:03:42:f4:ed:37:a2:f0:1b:50:54:4b:
+ 0e:d8:84:de:19:28:99:81:47:ae:09:1b:3f:48:d1:c3:6f:e2:
+ b0:60:17:f5:ee:23:02:a5:da:00:5b:6d:90:ab:ee:a2:e9:1b:
+ 3b:e9:c7:44:27:45:8e:6b:9f:f5:a4:84:bc:77:f9:6b:97:ac:
+ 3e:51:45:a2:11:a6:cc:85:ee:0a:68:f2:3e:50:38:7a:24:62:
+ 1e:17:20:37:6d:6a:4d:b7:09:9b:c9:fc:a4:58:f5:b6:fb:9c:
+ 4e:18:bb:95:02:e7:a1:ad:9b:07:ee:36:6b:24:d2:39:86:c1:
+ 93:83:50:d2:81:46:a8:5f:62:57:2c:bb:6c:64:88:08:6e:ef:
+ 13:54:5f:dd:2d:c4:67:63:d3:cf:89:37:bf:9d:20:f4:fb:7a:
+ 83:9b:a0:1e:81:00:50:c2:e4:0c:22:59:52:10:ed:43:56:87:
+ 00:f8:14:52:a7:1d:8b:93:8c:a2:4d:46:7f:27:c6:71:9b:24:
+ de:e4:da:86:8b:0d:7e:6b:20:c1:c0:9e:e1:65:d8:6a:a3:a6:
+ e8:85:8b:3a:07:08:1c:ba:f5:8f:55:9a:18:75:7e:e5:ec:81:
+ 66:d1:21:73:a1:35:44:0b:80:3d:5b:9c:5e:6f:2a:17:96:d1:
+ 83:23:88:66:6d:e6:86:e2:70:32:2f:52:22:e7:c8:e7:7f:c4:
+ 2c:60:5d:2f:c3:af:9e:45:05:c3:84:02:b7:fd:2c:08:52:4f:
+ 82:dd:a3:f0:d4:86:09:02
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQbkepxlqz5yDFMJo/aFLybzANBgkqhkiG9w0BAQwFADBH
+MQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNlcnZpY2VzIExM
+QzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwHhcNMTYwNjIyMDAwMDAwWhcNMzYwNjIy
+MDAwMDAwWjBHMQswCQYDVQQGEwJVUzEiMCAGA1UEChMZR29vZ2xlIFRydXN0IFNl
+cnZpY2VzIExMQzEUMBIGA1UEAxMLR1RTIFJvb3QgUjIwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQDO3v2m++zsFDQ8BwZabFn3GTXd98GdVarTzTukk3Lv
+CvptnfbwhYBboUhSnznFt+4orO/LdmgUud+tAWyZH8QiHZ/+cnfgLFuv5AS/T3Kg
+GjSY6Dlo7JUle3ah5mm5hRm9iYz+re026nO8/4Piy33B0s5Ks40FnotJk9/BW9Bu
+XvAuMC6C/Pq8tBcKSOWIm8Wba96wyrQD8Nr0kLhlZPdcTK3ofmZemde4wj7I0BOd
+re7kRXuJVfeKH2JShBKzwkCX44ofR5GmdFrS+LFjKBC4swm4VndAoiaYecb+3yXu
+PuWgf9RhD1FLPD+M2uFwdNjCaKH5wQzpoeJ/u1U8dgbuak7MkogwTZq9TwtImoS1
+mKPV+3PBV2HdKFZ1E66HjucMUQkQdYhMvI35ezzUIkgfKtzra7tEscszcTJGr61K
+8YzodDqs5xoic4DSMPclQsciOzsSrZYuxsN2B6ogtzVJV+mSSeh2FnIxZyuWfoqj
+x5RWIr9qS34BIbIjMt/kmkRtWVtd9QCgHJvGeJeNkP+byKq0rxFROV7Z+2et1VsR
+nTKaG73VululycslaVNVJ1zgyjbLiGH7HrfQy+4W+9OmTN6SpdTi3/UGVN4unUu0
+kzCqgc7dGtxRcw1PcOnlthYhGXmy5okLdWTK1au8CcEYof/UVKGFPP0UJAOyh9Ok
+twIDAQABo0IwQDAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNV
+HQ4EFgQUu//KjiOfT5nK2+JopqUVJxce2Q4wDQYJKoZIhvcNAQEMBQADggIBALZp
+8KZ3/p7uC4Gt4cCpx/k1HUCCq+YEtN/L9x0Pg/B+E02NjO7jMyLDOfxA325BS0JT
+vhaI8dI4XsRomRyYUpOM52jtG2pzegVATX9lO9ZY8c6DR2Dj/5epnGB3GFW1fgiT
+z9D2PGcDFWEJ+YF59exTpJ/JjwGLc8R3dtyDovUMSRqodt6Sm2T4syzFJ9MHwAiA
+pJiS4wGWAqoC7o87xdFtCjMwc3i5T1QWvwsHoaRc5svJXISPD+AVdyx+Jn7axEvb
+pxZ3B7DNdehyQtaVhJ2Gg/LkkM0JR9SLA3DaWsYDQvTtN6LwG1BUSw7YhN4ZKJmB
+R64JGz9I0cNv4rBgF/XuIwKl2gBbbZCr7qLpGzvpx0QnRY5rn/WkhLx3+WuXrD5R
+RaIRpsyF7gpo8j5QOHokYh4XIDdtak23CZvJ/KRY9bb7nE4Yu5UC56GtmwfuNmsk
+0jmGwZODUNKBRqhfYlcsu2xkiAhu7xNUX90txGdj08+JN7+dIPT7eoOboB6BAFDC
+5AwiWVIQ7UNWhwD4FFKnHYuTjKJNRn8nxnGbJN7k2oaLDX5rIMHAnuFl2GqjpuiF
+izoHCBy69Y9Vmhh1fuXsgWbRIXOhNUQLgD1bnF5vKheW0YMjiGZt5obicDIvUiLn
+yOd/xCxgXS/Dr55FBcOEArf9LAhST4Ldo/DUhgkC
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem
new file mode 100644
index 00000000000..f5975dc20b0
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem
@@ -0,0 +1,123 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 1e:d3:97:09:5f:d8:b4:b3:47:70:1e:aa:be:7f:45:b3
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, O = Microsoft Corporation, CN = Microsoft RSA Root Certificate Authority 2017
+ Validity
+ Not Before: Dec 18 22:51:22 2019 GMT
+ Not After : Jul 18 23:00:23 2042 GMT
+ Subject: C = US, O = Microsoft Corporation, CN = Microsoft RSA Root Certificate Authority 2017
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ca:5b:be:94:33:8c:29:95:91:16:0a:95:bd:47:
+ 62:c1:89:f3:99:36:df:46:90:c9:a5:ed:78:6a:6f:
+ 47:91:68:f8:27:67:50:33:1d:a1:a6:fb:e0:e5:43:
+ a3:84:02:57:01:5d:9c:48:40:82:53:10:bc:bf:c7:
+ 3b:68:90:b6:82:2d:e5:f4:65:d0:cc:6d:19:cc:95:
+ f9:7b:ac:4a:94:ad:0e:de:4b:43:1d:87:07:92:13:
+ 90:80:83:64:35:39:04:fc:e5:e9:6c:b3:b6:1f:50:
+ 94:38:65:50:5c:17:46:b9:b6:85:b5:1c:b5:17:e8:
+ d6:45:9d:d8:b2:26:b0:ca:c4:70:4a:ae:60:a4:dd:
+ b3:d9:ec:fc:3b:d5:57:72:bc:3f:c8:c9:b2:de:4b:
+ 6b:f8:23:6c:03:c0:05:bd:95:c7:cd:73:3b:66:80:
+ 64:e3:1a:ac:2e:f9:47:05:f2:06:b6:9b:73:f5:78:
+ 33:5b:c7:a1:fb:27:2a:a1:b4:9a:91:8c:91:d3:3a:
+ 82:3e:76:40:b4:cd:52:61:51:70:28:3f:c5:c5:5a:
+ f2:c9:8c:49:bb:14:5b:4d:c8:ff:67:4d:4c:12:96:
+ ad:f5:fe:78:a8:97:87:d7:fd:5e:20:80:dc:a1:4b:
+ 22:fb:d4:89:ad:ba:ce:47:97:47:55:7b:8f:45:c8:
+ 67:28:84:95:1c:68:30:ef:ef:49:e0:35:7b:64:e7:
+ 98:b0:94:da:4d:85:3b:3e:55:c4:28:af:57:f3:9e:
+ 13:db:46:27:9f:1e:a2:5e:44:83:a4:a5:ca:d5:13:
+ b3:4b:3f:c4:e3:c2:e6:86:61:a4:52:30:b9:7a:20:
+ 4f:6f:0f:38:53:cb:33:0c:13:2b:8f:d6:9a:bd:2a:
+ c8:2d:b1:1c:7d:4b:51:ca:47:d1:48:27:72:5d:87:
+ eb:d5:45:e6:48:65:9d:af:52:90:ba:5b:a2:18:65:
+ 57:12:9f:68:b9:d4:15:6b:94:c4:69:22:98:f4:33:
+ e0:ed:f9:51:8e:41:50:c9:34:4f:76:90:ac:fc:38:
+ c1:d8:e1:7b:b9:e3:e3:94:e1:46:69:cb:0e:0a:50:
+ 6b:13:ba:ac:0f:37:5a:b7:12:b5:90:81:1e:56:ae:
+ 57:22:86:d9:c9:d2:d1:d7:51:e3:ab:3b:c6:55:fd:
+ 1e:0e:d3:74:0a:d1:da:aa:ea:69:b8:97:28:8f:48:
+ c4:07:f8:52:43:3a:f4:ca:55:35:2c:b0:a6:6a:c0:
+ 9c:f9:f2:81:e1:12:6a:c0:45:d9:67:b3:ce:ff:23:
+ a2:89:0a:54:d4:14:b9:2a:a8:d7:ec:f9:ab:cd:25:
+ 58:32:79:8f:90:5b:98:39:c4:08:06:c1:ac:7f:0e:
+ 3d:00:a5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 09:CB:59:7F:86:B2:70:8F:1A:C3:39:E3:C0:D9:E9:BF:BB:4D:B2:23
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: sha384WithRSAEncryption
+ ac:af:3e:5d:c2:11:96:89:8e:a3:e7:92:d6:97:15:b8:13:a2:
+ a6:42:2e:02:cd:16:05:59:27:ca:20:e8:ba:b8:e8:1a:ec:4d:
+ a8:97:56:ae:65:43:b1:8f:00:9b:52:cd:55:cd:53:39:6d:62:
+ 4c:8b:0d:5b:7c:2e:44:bf:83:10:8f:f3:53:82:80:c3:4f:3a:
+ c7:6e:11:3f:e6:e3:16:91:84:fb:6d:84:7f:34:74:ad:89:a7:
+ ce:b9:d7:d7:9f:84:64:92:be:95:a1:ad:09:53:33:dd:ee:0a:
+ ea:4a:51:8e:6f:55:ab:ba:b5:94:46:ae:8c:7f:d8:a2:50:25:
+ 65:60:80:46:db:33:04:ae:6c:b5:98:74:54:25:dc:93:e4:f8:
+ e3:55:15:3d:b8:6d:c3:0a:a4:12:c1:69:85:6e:df:64:f1:53:
+ 99:e1:4a:75:20:9d:95:0f:e4:d6:dc:03:f1:59:18:e8:47:89:
+ b2:57:5a:94:b6:a9:d8:17:2b:17:49:e5:76:cb:c1:56:99:3a:
+ 37:b1:ff:69:2c:91:91:93:e1:df:4c:a3:37:76:4d:a1:9f:f8:
+ 6d:1e:1d:d3:fa:ec:fb:f4:45:1d:13:6d:cf:f7:59:e5:22:27:
+ 72:2b:86:f3:57:bb:30:ed:24:4d:dc:7d:56:bb:a3:b3:f8:34:
+ 79:89:c1:e0:f2:02:61:f7:a6:fc:0f:bb:1c:17:0b:ae:41:d9:
+ 7c:bd:27:a3:fd:2e:3a:d1:93:94:b1:73:1d:24:8b:af:5b:20:
+ 89:ad:b7:67:66:79:f5:3a:c6:a6:96:33:fe:53:92:c8:46:b1:
+ 11:91:c6:99:7f:8f:c9:d6:66:31:20:41:10:87:2d:0c:d6:c1:
+ af:34:98:ca:64:83:fb:13:57:d1:c1:f0:3c:7a:8c:a5:c1:fd:
+ 95:21:a0:71:c1:93:67:71:12:ea:8f:88:0a:69:19:64:99:23:
+ 56:fb:ac:2a:2e:70:be:66:c4:0c:84:ef:e5:8b:f3:93:01:f8:
+ 6a:90:93:67:4b:b2:68:a3:b5:62:8f:e9:3f:8c:7a:3b:5e:0f:
+ e7:8c:b8:c6:7c:ef:37:fd:74:e2:c8:4f:33:72:e1:94:39:6d:
+ bd:12:af:be:0c:4e:70:7c:1b:6f:8d:b3:32:93:73:44:16:6d:
+ e8:f4:f7:e0:95:80:8f:96:5d:38:a4:f4:ab:de:0a:30:87:93:
+ d8:4d:00:71:62:45:27:4b:3a:42:84:5b:7f:65:b7:67:34:52:
+ 2d:9c:16:6b:aa:a8:d8:7b:a3:42:4c:71:c7:0c:ca:3e:83:e4:
+ a6:ef:b7:01:30:5e:51:a3:79:f5:70:69:a6:41:44:0f:86:b0:
+ 2c:91:c6:3d:ea:ae:0f:84
+-----BEGIN CERTIFICATE-----
+MIIFqDCCA5CgAwIBAgIQHtOXCV/YtLNHcB6qvn9FszANBgkqhkiG9w0BAQwFADBl
+MQswCQYDVQQGEwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYw
+NAYDVQQDEy1NaWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+IDIwMTcwHhcNMTkxMjE4MjI1MTIyWhcNNDIwNzE4MjMwMDIzWjBlMQswCQYDVQQG
+EwJVUzEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMTYwNAYDVQQDEy1N
+aWNyb3NvZnQgUlNBIFJvb3QgQ2VydGlmaWNhdGUgQXV0aG9yaXR5IDIwMTcwggIi
+MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKW76UM4wplZEWCpW9R2LBifOZ
+Nt9GkMml7Xhqb0eRaPgnZ1AzHaGm++DlQ6OEAlcBXZxIQIJTELy/xztokLaCLeX0
+ZdDMbRnMlfl7rEqUrQ7eS0MdhweSE5CAg2Q1OQT85elss7YfUJQ4ZVBcF0a5toW1
+HLUX6NZFndiyJrDKxHBKrmCk3bPZ7Pw71VdyvD/IybLeS2v4I2wDwAW9lcfNcztm
+gGTjGqwu+UcF8ga2m3P1eDNbx6H7JyqhtJqRjJHTOoI+dkC0zVJhUXAoP8XFWvLJ
+jEm7FFtNyP9nTUwSlq31/niol4fX/V4ggNyhSyL71Imtus5Hl0dVe49FyGcohJUc
+aDDv70ngNXtk55iwlNpNhTs+VcQor1fznhPbRiefHqJeRIOkpcrVE7NLP8TjwuaG
+YaRSMLl6IE9vDzhTyzMMEyuP1pq9KsgtsRx9S1HKR9FIJ3Jdh+vVReZIZZ2vUpC6
+W6IYZVcSn2i51BVrlMRpIpj0M+Dt+VGOQVDJNE92kKz8OMHY4Xu54+OU4UZpyw4K
+UGsTuqwPN1q3ErWQgR5WrlcihtnJ0tHXUeOrO8ZV/R4O03QK0dqq6mm4lyiPSMQH
++FJDOvTKVTUssKZqwJz58oHhEmrARdlns87/I6KJClTUFLkqqNfs+avNJVgyeY+Q
+W5g5xAgGwax/Dj0ApQIDAQABo1QwUjAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUCctZf4aycI8awznjwNnpv7tNsiMwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEMBQADggIBAKyvPl3CEZaJjqPnktaXFbgToqZC
+LgLNFgVZJ8og6Lq46BrsTaiXVq5lQ7GPAJtSzVXNUzltYkyLDVt8LkS/gxCP81OC
+gMNPOsduET/m4xaRhPtthH80dK2Jp86519efhGSSvpWhrQlTM93uCupKUY5vVau6
+tZRGrox/2KJQJWVggEbbMwSubLWYdFQl3JPk+ONVFT24bcMKpBLBaYVu32TxU5nh
+SnUgnZUP5NbcA/FZGOhHibJXWpS2qdgXKxdJ5XbLwVaZOjex/2kskZGT4d9Mozd2
+TaGf+G0eHdP67Pv0RR0Tbc/3WeUiJ3IrhvNXuzDtJE3cfVa7o7P4NHmJweDyAmH3
+pvwPuxwXC65B2Xy9J6P9LjrRk5Sxcx0ki69bIImtt2dmefU6xqaWM/5TkshGsRGR
+xpl/j8nWZjEgQRCHLQzWwa80mMpkg/sTV9HB8Dx6jKXB/ZUhoHHBk2dxEuqPiApp
+GWSZI1b7rCoucL5mxAyE7+WL85MB+GqQk2dLsmijtWKP6T+MejteD+eMuMZ87zf9
+dOLITzNy4ZQ5bb0Sr74MTnB8G2+NszKTc0QWbej09+CVgI+WXTik9KveCjCHk9hN
+AHFiRSdLOkKEW39lt2c0Ui2cFmuqqNh7o0JMcccMyj6D5KbvtwEwXlGjefVwaaZB
+RA+GsCyRxj3qrg+E
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem
new file mode 100644
index 00000000000..e49674ed1fb
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem
@@ -0,0 +1,87 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:00:00:00:00:01:0f:86:26:e6:0d
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
+ Validity
+ Not Before: Dec 15 08:00:00 2006 GMT
+ Not After : Dec 15 08:00:00 2021 GMT
+ Subject: OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:a6:cf:24:0e:be:2e:6f:28:99:45:42:c4:ab:3e:
+ 21:54:9b:0b:d3:7f:84:70:fa:12:b3:cb:bf:87:5f:
+ c6:7f:86:d3:b2:30:5c:d6:fd:ad:f1:7b:dc:e5:f8:
+ 60:96:09:92:10:f5:d0:53:de:fb:7b:7e:73:88:ac:
+ 52:88:7b:4a:a6:ca:49:a6:5e:a8:a7:8c:5a:11:bc:
+ 7a:82:eb:be:8c:e9:b3:ac:96:25:07:97:4a:99:2a:
+ 07:2f:b4:1e:77:bf:8a:0f:b5:02:7c:1b:96:b8:c5:
+ b9:3a:2c:bc:d6:12:b9:eb:59:7d:e2:d0:06:86:5f:
+ 5e:49:6a:b5:39:5e:88:34:ec:bc:78:0c:08:98:84:
+ 6c:a8:cd:4b:b4:a0:7d:0c:79:4d:f0:b8:2d:cb:21:
+ ca:d5:6c:5b:7d:e1:a0:29:84:a1:f9:d3:94:49:cb:
+ 24:62:91:20:bc:dd:0b:d5:d9:cc:f9:ea:27:0a:2b:
+ 73:91:c6:9d:1b:ac:c8:cb:e8:e0:a0:f4:2f:90:8b:
+ 4d:fb:b0:36:1b:f6:19:7a:85:e0:6d:f2:61:13:88:
+ 5c:9f:e0:93:0a:51:97:8a:5a:ce:af:ab:d5:f7:aa:
+ 09:aa:60:bd:dc:d9:5f:df:72:a9:60:13:5e:00:01:
+ c9:4a:fa:3f:a4:ea:07:03:21:02:8e:82:ca:03:c2:
+ 9b:8f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 9B:E2:07:57:67:1C:1E:C0:6A:06:DE:59:B4:9A:2D:DF:DC:19:86:2E
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.globalsign.net/root-r2.crl
+
+ X509v3 Authority Key Identifier:
+ keyid:9B:E2:07:57:67:1C:1E:C0:6A:06:DE:59:B4:9A:2D:DF:DC:19:86:2E
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 99:81:53:87:1c:68:97:86:91:ec:e0:4a:b8:44:0b:ab:81:ac:
+ 27:4f:d6:c1:b8:1c:43:78:b3:0c:9a:fc:ea:2c:3c:6e:61:1b:
+ 4d:4b:29:f5:9f:05:1d:26:c1:b8:e9:83:00:62:45:b6:a9:08:
+ 93:b9:a9:33:4b:18:9a:c2:f8:87:88:4e:db:dd:71:34:1a:c1:
+ 54:da:46:3f:e0:d3:2a:ab:6d:54:22:f5:3a:62:cd:20:6f:ba:
+ 29:89:d7:dd:91:ee:d3:5c:a2:3e:a1:5b:41:f5:df:e5:64:43:
+ 2d:e9:d5:39:ab:d2:a2:df:b7:8b:d0:c0:80:19:1c:45:c0:2d:
+ 8c:e8:f8:2d:a4:74:56:49:c5:05:b5:4f:15:de:6e:44:78:39:
+ 87:a8:7e:bb:f3:79:18:91:bb:f4:6f:9d:c1:f0:8c:35:8c:5d:
+ 01:fb:c3:6d:b9:ef:44:6d:79:46:31:7e:0a:fe:a9:82:c1:ff:
+ ef:ab:6e:20:c4:50:c9:5f:9d:4d:9b:17:8c:0c:e5:01:c9:a0:
+ 41:6a:73:53:fa:a5:50:b4:6e:25:0f:fb:4c:18:f4:fd:52:d9:
+ 8e:69:b1:e8:11:0f:de:88:d8:fb:1d:49:f7:aa:de:95:cf:20:
+ 78:c2:60:12:db:25:40:8c:6a:fc:7e:42:38:40:64:12:f7:9e:
+ 81:e1:93:2e
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
+MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
+v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
+eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
+tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
+C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
+zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
+mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
+V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
+bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
+3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
+J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
+291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
+ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
+AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem
new file mode 100644
index 00000000000..d82ffa2c6ef
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 03:3a:f1:e6:a7:11:a9:a0:bb:28:64:b1:1d:09:fa:e5
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G2
+ Validity
+ Not Before: Aug 1 12:00:00 2013 GMT
+ Not After : Jan 15 12:00:00 2038 GMT
+ Subject: C = US, O = DigiCert Inc, OU = www.digicert.com, CN = DigiCert Global Root G2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bb:37:cd:34:dc:7b:6b:c9:b2:68:90:ad:4a:75:
+ ff:46:ba:21:0a:08:8d:f5:19:54:c9:fb:88:db:f3:
+ ae:f2:3a:89:91:3c:7a:e6:ab:06:1a:6b:cf:ac:2d:
+ e8:5e:09:24:44:ba:62:9a:7e:d6:a3:a8:7e:e0:54:
+ 75:20:05:ac:50:b7:9c:63:1a:6c:30:dc:da:1f:19:
+ b1:d7:1e:de:fd:d7:e0:cb:94:83:37:ae:ec:1f:43:
+ 4e:dd:7b:2c:d2:bd:2e:a5:2f:e4:a9:b8:ad:3a:d4:
+ 99:a4:b6:25:e9:9b:6b:00:60:92:60:ff:4f:21:49:
+ 18:f7:67:90:ab:61:06:9c:8f:f2:ba:e9:b4:e9:92:
+ 32:6b:b5:f3:57:e8:5d:1b:cd:8c:1d:ab:95:04:95:
+ 49:f3:35:2d:96:e3:49:6d:dd:77:e3:fb:49:4b:b4:
+ ac:55:07:a9:8f:95:b3:b4:23:bb:4c:6d:45:f0:f6:
+ a9:b2:95:30:b4:fd:4c:55:8c:27:4a:57:14:7c:82:
+ 9d:cd:73:92:d3:16:4a:06:0c:8c:50:d1:8f:1e:09:
+ be:17:a1:e6:21:ca:fd:83:e5:10:bc:83:a5:0a:c4:
+ 67:28:f6:73:14:14:3d:46:76:c3:87:14:89:21:34:
+ 4d:af:0f:45:0c:a6:49:a1:ba:bb:9c:c5:b1:33:83:
+ 29:85
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 4E:22:54:20:18:95:E6:E3:6E:E6:0F:FA:FA:B9:12:ED:06:17:8F:39
+ Signature Algorithm: sha256WithRSAEncryption
+ 60:67:28:94:6f:0e:48:63:eb:31:dd:ea:67:18:d5:89:7d:3c:
+ c5:8b:4a:7f:e9:be:db:2b:17:df:b0:5f:73:77:2a:32:13:39:
+ 81:67:42:84:23:f2:45:67:35:ec:88:bf:f8:8f:b0:61:0c:34:
+ a4:ae:20:4c:84:c6:db:f8:35:e1:76:d9:df:a6:42:bb:c7:44:
+ 08:86:7f:36:74:24:5a:da:6c:0d:14:59:35:bd:f2:49:dd:b6:
+ 1f:c9:b3:0d:47:2a:3d:99:2f:bb:5c:bb:b5:d4:20:e1:99:5f:
+ 53:46:15:db:68:9b:f0:f3:30:d5:3e:31:e2:8d:84:9e:e3:8a:
+ da:da:96:3e:35:13:a5:5f:f0:f9:70:50:70:47:41:11:57:19:
+ 4e:c0:8f:ae:06:c4:95:13:17:2f:1b:25:9f:75:f2:b1:8e:99:
+ a1:6f:13:b1:41:71:fe:88:2a:c8:4f:10:20:55:d7:f3:14:45:
+ e5:e0:44:f4:ea:87:95:32:93:0e:fe:53:46:fa:2c:9d:ff:8b:
+ 22:b9:4b:d9:09:45:a4:de:a4:b8:9a:58:dd:1b:7d:52:9f:8e:
+ 59:43:88:81:a4:9e:26:d5:6f:ad:dd:0d:c6:37:7d:ed:03:92:
+ 1b:e5:77:5f:76:ee:3c:8d:c4:5d:56:5b:a2:d9:66:6e:b3:35:
+ 37:e5:32:b6
+-----BEGIN CERTIFICATE-----
+MIIDjjCCAnagAwIBAgIQAzrx5qcRqaC7KGSxHQn65TANBgkqhkiG9w0BAQsFADBh
+MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
+d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH
+MjAeFw0xMzA4MDExMjAwMDBaFw0zODAxMTUxMjAwMDBaMGExCzAJBgNVBAYTAlVT
+MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
+b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IEcyMIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuzfNNNx7a8myaJCtSnX/RrohCgiN9RlUyfuI
+2/Ou8jqJkTx65qsGGmvPrC3oXgkkRLpimn7Wo6h+4FR1IAWsULecYxpsMNzaHxmx
+1x7e/dfgy5SDN67sH0NO3Xss0r0upS/kqbitOtSZpLYl6ZtrAGCSYP9PIUkY92eQ
+q2EGnI/yuum06ZIya7XzV+hdG82MHauVBJVJ8zUtluNJbd134/tJS7SsVQepj5Wz
+tCO7TG1F8PapspUwtP1MVYwnSlcUfIKdzXOS0xZKBgyMUNGPHgm+F6HmIcr9g+UQ
+vIOlCsRnKPZzFBQ9RnbDhxSJITRNrw9FDKZJobq7nMWxM4MphQIDAQABo0IwQDAP
+BgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUTiJUIBiV
+5uNu5g/6+rkS7QYXjzkwDQYJKoZIhvcNAQELBQADggEBAGBnKJRvDkhj6zHd6mcY
+1Yl9PMWLSn/pvtsrF9+wX3N3KjITOYFnQoQj8kVnNeyIv/iPsGEMNKSuIEyExtv4
+NeF22d+mQrvHRAiGfzZ0JFrabA0UWTW98kndth/Jsw1HKj2ZL7tcu7XUIOGZX1NG
+Fdtom/DzMNU+MeKNhJ7jitralj41E6Vf8PlwUHBHQRFXGU7Aj64GxJUTFy8bJZ91
+8rGOmaFvE7FBcf6IKshPECBV1/MUReXgRPTqh5Uykw7+U0b6LJ3/iyK5S9kJRaTe
+pLiaWN0bfVKfjllDiIGknibVb63dDcY3fe0Dkhvld1927jyNxF1WW6LZZm6zNTfl
+MrY=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem
new file mode 100644
index 00000000000..ffdb6491637
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:00:00:00:00:01:21:58:53:08:a2
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
+ Validity
+ Not Before: Mar 18 10:00:00 2009 GMT
+ Not After : Mar 18 10:00:00 2029 GMT
+ Subject: OU = GlobalSign Root CA - R3, O = GlobalSign, CN = GlobalSign
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:cc:25:76:90:79:06:78:22:16:f5:c0:83:b6:84:
+ ca:28:9e:fd:05:76:11:c5:ad:88:72:fc:46:02:43:
+ c7:b2:8a:9d:04:5f:24:cb:2e:4b:e1:60:82:46:e1:
+ 52:ab:0c:81:47:70:6c:dd:64:d1:eb:f5:2c:a3:0f:
+ 82:3d:0c:2b:ae:97:d7:b6:14:86:10:79:bb:3b:13:
+ 80:77:8c:08:e1:49:d2:6a:62:2f:1f:5e:fa:96:68:
+ df:89:27:95:38:9f:06:d7:3e:c9:cb:26:59:0d:73:
+ de:b0:c8:e9:26:0e:83:15:c6:ef:5b:8b:d2:04:60:
+ ca:49:a6:28:f6:69:3b:f6:cb:c8:28:91:e5:9d:8a:
+ 61:57:37:ac:74:14:dc:74:e0:3a:ee:72:2f:2e:9c:
+ fb:d0:bb:bf:f5:3d:00:e1:06:33:e8:82:2b:ae:53:
+ a6:3a:16:73:8c:dd:41:0e:20:3a:c0:b4:a7:a1:e9:
+ b2:4f:90:2e:32:60:e9:57:cb:b9:04:92:68:68:e5:
+ 38:26:60:75:b2:9f:77:ff:91:14:ef:ae:20:49:fc:
+ ad:40:15:48:d1:02:31:61:19:5e:b8:97:ef:ad:77:
+ b7:64:9a:7a:bf:5f:c1:13:ef:9b:62:fb:0d:6c:e0:
+ 54:69:16:a9:03:da:6e:e9:83:93:71:76:c6:69:85:
+ 82:17
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 8F:F0:4B:7F:A8:2E:45:24:AE:4D:50:FA:63:9A:8B:DE:E2:DD:1B:BC
+ Signature Algorithm: sha256WithRSAEncryption
+ 4b:40:db:c0:50:aa:fe:c8:0c:ef:f7:96:54:45:49:bb:96:00:
+ 09:41:ac:b3:13:86:86:28:07:33:ca:6b:e6:74:b9:ba:00:2d:
+ ae:a4:0a:d3:f5:f1:f1:0f:8a:bf:73:67:4a:83:c7:44:7b:78:
+ e0:af:6e:6c:6f:03:29:8e:33:39:45:c3:8e:e4:b9:57:6c:aa:
+ fc:12:96:ec:53:c6:2d:e4:24:6c:b9:94:63:fb:dc:53:68:67:
+ 56:3e:83:b8:cf:35:21:c3:c9:68:fe:ce:da:c2:53:aa:cc:90:
+ 8a:e9:f0:5d:46:8c:95:dd:7a:58:28:1a:2f:1d:de:cd:00:37:
+ 41:8f:ed:44:6d:d7:53:28:97:7e:f3:67:04:1e:15:d7:8a:96:
+ b4:d3:de:4c:27:a4:4c:1b:73:73:76:f4:17:99:c2:1f:7a:0e:
+ e3:2d:08:ad:0a:1c:2c:ff:3c:ab:55:0e:0f:91:7e:36:eb:c3:
+ 57:49:be:e1:2e:2d:7c:60:8b:c3:41:51:13:23:9d:ce:f7:32:
+ 6b:94:01:a8:99:e7:2c:33:1f:3a:3b:25:d2:86:40:ce:3b:2c:
+ 86:78:c9:61:2f:14:ba:ee:db:55:6f:df:84:ee:05:09:4d:bd:
+ 28:d8:72:ce:d3:62:50:65:1e:eb:92:97:83:31:d9:b3:b5:ca:
+ 47:58:3f:5f
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
+A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
+Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
+MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
+A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
+RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
+gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
+KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
+QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
+XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
+DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
+LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
+RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
+jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
+6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
+mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
+Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
+WD9f
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem
new file mode 100644
index 00000000000..bb65cebb580
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem
@@ -0,0 +1,91 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 50:94:6c:ec:18:ea:d5:9c:4d:d5:97:ef:75:8f:a0:ad
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, OU = www.xrampsecurity.com, O = XRamp Security Services Inc, CN = XRamp Global Certification Authority
+ Validity
+ Not Before: Nov 1 17:14:04 2004 GMT
+ Not After : Jan 1 05:37:19 2035 GMT
+ Subject: C = US, OU = www.xrampsecurity.com, O = XRamp Security Services Inc, CN = XRamp Global Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:98:24:1e:bd:15:b4:ba:df:c7:8c:a5:27:b6:38:
+ 0b:69:f3:b6:4e:a8:2c:2e:21:1d:5c:44:df:21:5d:
+ 7e:23:74:fe:5e:7e:b4:4a:b7:a6:ad:1f:ae:e0:06:
+ 16:e2:9b:5b:d9:67:74:6b:5d:80:8f:29:9d:86:1b:
+ d9:9c:0d:98:6d:76:10:28:58:e4:65:b0:7f:4a:98:
+ 79:9f:e0:c3:31:7e:80:2b:b5:8c:c0:40:3b:11:86:
+ d0:cb:a2:86:36:60:a4:d5:30:82:6d:d9:6e:d0:0f:
+ 12:04:33:97:5f:4f:61:5a:f0:e4:f9:91:ab:e7:1d:
+ 3b:bc:e8:cf:f4:6b:2d:34:7c:e2:48:61:1c:8e:f3:
+ 61:44:cc:6f:a0:4a:a9:94:b0:4d:da:e7:a9:34:7a:
+ 72:38:a8:41:cc:3c:94:11:7d:eb:c8:a6:8c:b7:86:
+ cb:ca:33:3b:d9:3d:37:8b:fb:7a:3e:86:2c:e7:73:
+ d7:0a:57:ac:64:9b:19:eb:f4:0f:04:08:8a:ac:03:
+ 17:19:64:f4:5a:25:22:8d:34:2c:b2:f6:68:1d:12:
+ 6d:d3:8a:1e:14:da:c4:8f:a6:e2:23:85:d5:7a:0d:
+ bd:6a:e0:e9:ec:ec:17:bb:42:1b:67:aa:25:ed:45:
+ 83:21:fc:c1:c9:7c:d5:62:3e:fa:f2:c5:2d:d3:fd:
+ d4:65
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ 1.3.6.1.4.1.311.20.2:
+ ...C.A
+ X509v3 Key Usage:
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ C6:4F:A2:3D:06:63:84:09:9C:CE:62:E4:04:AC:8D:5C:B5:E9:B6:1B
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.xrampsecurity.com/XGCA.crl
+
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: sha1WithRSAEncryption
+ 91:15:39:03:01:1b:67:fb:4a:1c:f9:0a:60:5b:a1:da:4d:97:
+ 62:f9:24:53:27:d7:82:64:4e:90:2e:c3:49:1b:2b:9a:dc:fc:
+ a8:78:67:35:f1:1d:f0:11:bd:b7:48:e3:10:f6:0d:df:3f:d2:
+ c9:b6:aa:55:a4:48:ba:02:db:de:59:2e:15:5b:3b:9d:16:7d:
+ 47:d7:37:ea:5f:4d:76:12:36:bb:1f:d7:a1:81:04:46:20:a3:
+ 2c:6d:a9:9e:01:7e:3f:29:ce:00:93:df:fd:c9:92:73:89:89:
+ 64:9e:e7:2b:e4:1c:91:2c:d2:b9:ce:7d:ce:6f:31:99:d3:e6:
+ be:d2:1e:90:f0:09:14:79:5c:23:ab:4d:d2:da:21:1f:4d:99:
+ 79:9d:e1:cf:27:9f:10:9b:1c:88:0d:b0:8a:64:41:31:b8:0e:
+ 6c:90:24:a4:9b:5c:71:8f:ba:bb:7e:1c:1b:db:6a:80:0f:21:
+ bc:e9:db:a6:b7:40:f4:b2:8b:a9:b1:e4:ef:9a:1a:d0:3d:69:
+ 99:ee:a8:28:a3:e1:3c:b3:f0:b2:11:9c:cf:7c:40:e6:dd:e7:
+ 43:7d:a2:d8:3a:b5:a9:8d:f2:34:99:c4:d4:10:e1:06:fd:09:
+ 84:10:3b:ee:c4:4c:f4:ec:27:7c:42:c2:74:7c:82:8a:09:c9:
+ b4:03:25:bc
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
+gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
+MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
+UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
+NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
+dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
+dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
+38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
+KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
+DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
+qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
+JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
+PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
+BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
+jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
+eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
+vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
+IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
+i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
+O+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem
new file mode 100644
index 00000000000..f26226e5296
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem
@@ -0,0 +1,85 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ da:9b:ec:71:f3:03:b0:19
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor RootCert CA-1
+ Validity
+ Not Before: Feb 4 12:32:16 2016 GMT
+ Not After : Dec 31 17:23:16 2029 GMT
+ Subject: C = PA, ST = Panama, L = Panama City, O = TrustCor Systems S. de R.L., OU = TrustCor Certificate Authority, CN = TrustCor RootCert CA-1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bf:8e:b7:95:e2:c2:26:12:6b:33:19:c7:40:58:
+ 0a:ab:59:aa:8d:00:a3:fc:80:c7:50:7b:8e:d4:20:
+ 26:ba:32:12:d8:23:54:49:25:10:22:98:9d:46:d2:
+ c1:c9:9e:4e:1b:2e:2c:0e:38:f3:1a:25:68:1c:a6:
+ 5a:05:e6:1e:8b:48:bf:98:96:74:3e:69:ca:e9:b5:
+ 78:a5:06:bc:d5:00:5e:09:0a:f2:27:7a:52:fc:2d:
+ d5:b1:ea:b4:89:61:24:f3:1a:13:db:a9:cf:52:ed:
+ 0c:24:ba:b9:9e:ec:7e:00:74:fa:93:ad:6c:29:92:
+ ae:51:b4:bb:d3:57:bf:b3:f3:a8:8d:9c:f4:24:4b:
+ 2a:d6:99:9e:f4:9e:fe:c0:7e:42:3a:e7:0b:95:53:
+ da:b7:68:0e:90:4c:fb:70:3f:8f:4a:2c:94:f3:26:
+ dd:63:69:a9:94:d8:10:4e:c5:47:08:90:99:1b:17:
+ 4d:b9:6c:6e:ef:60:95:11:8e:21:80:b5:bd:a0:73:
+ d8:d0:b2:77:c4:45:ea:5a:26:fb:66:76:76:f8:06:
+ 1f:61:6d:0f:55:c5:83:b7:10:56:72:06:07:a5:f3:
+ b1:1a:03:05:64:0e:9d:5a:8a:d6:86:70:1b:24:de:
+ fe:28:8a:2b:d0:6a:b0:fc:7a:a2:dc:b2:79:0e:8b:
+ 65:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ EE:6B:49:3C:7A:3F:0D:E3:B1:09:B7:8A:C8:AB:19:9F:73:33:50:E7
+ X509v3 Authority Key Identifier:
+ keyid:EE:6B:49:3C:7A:3F:0D:E3:B1:09:B7:8A:C8:AB:19:9F:73:33:50:E7
+
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 25:18:d4:91:8f:13:ee:8f:1e:1d:11:53:da:2d:44:29:19:a0:
+ 1e:6b:31:9e:4d:0e:9e:ad:3d:5c:41:6f:95:2b:24:a1:79:98:
+ 3a:38:36:fb:bb:66:9e:48:ff:90:90:ef:3d:d4:b8:9b:b4:87:
+ 75:3f:20:9b:ce:72:cf:a1:55:c1:4d:64:a2:19:06:a1:07:33:
+ 0c:0b:29:e5:f1:ea:ab:a3:ec:b5:0a:74:90:c7:7d:72:f2:d7:
+ 5c:9f:91:ef:91:8b:b7:dc:ed:66:a2:cf:8e:66:3b:bc:9f:3a:
+ 02:e0:27:dd:16:98:c0:95:d4:0a:a4:e4:81:9a:75:94:35:9c:
+ 90:5f:88:37:06:ad:59:95:0a:b0:d1:67:d3:19:ca:89:e7:32:
+ 5a:36:1c:3e:82:a8:5a:93:be:c6:d0:64:91:b6:cf:d9:b6:18:
+ cf:db:7e:d2:65:a3:a6:c4:8e:17:31:c1:fb:7e:76:db:d3:85:
+ e3:58:b2:77:7a:76:3b:6c:2f:50:1c:e7:db:f6:67:79:1f:f5:
+ 82:95:9a:07:a7:14:af:8f:dc:28:21:67:09:d2:d6:4d:5a:1c:
+ 19:1c:8e:77:5c:c3:94:24:3d:32:6b:4b:7e:d4:78:94:83:be:
+ 37:4d:ce:5f:c7:1e:4e:3c:e0:89:33:95:0b:0f:a5:32:d6:3c:
+ 5a:79:2c:19
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIJANqb7HHzA7AZMA0GCSqGSIb3DQEBCwUAMIGkMQswCQYD
+VQQGEwJQQTEPMA0GA1UECAwGUGFuYW1hMRQwEgYDVQQHDAtQYW5hbWEgQ2l0eTEk
+MCIGA1UECgwbVHJ1c3RDb3IgU3lzdGVtcyBTLiBkZSBSLkwuMScwJQYDVQQLDB5U
+cnVzdENvciBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkxHzAdBgNVBAMMFlRydXN0Q29y
+IFJvb3RDZXJ0IENBLTEwHhcNMTYwMjA0MTIzMjE2WhcNMjkxMjMxMTcyMzE2WjCB
+pDELMAkGA1UEBhMCUEExDzANBgNVBAgMBlBhbmFtYTEUMBIGA1UEBwwLUGFuYW1h
+IENpdHkxJDAiBgNVBAoMG1RydXN0Q29yIFN5c3RlbXMgUy4gZGUgUi5MLjEnMCUG
+A1UECwweVHJ1c3RDb3IgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MR8wHQYDVQQDDBZU
+cnVzdENvciBSb290Q2VydCBDQS0xMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAv463leLCJhJrMxnHQFgKq1mqjQCj/IDHUHuO1CAmujIS2CNUSSUQIpid
+RtLByZ5OGy4sDjjzGiVoHKZaBeYei0i/mJZ0PmnK6bV4pQa81QBeCQryJ3pS/C3V
+seq0iWEk8xoT26nPUu0MJLq5nux+AHT6k61sKZKuUbS701e/s/OojZz0JEsq1pme
+9J7+wH5COucLlVPat2gOkEz7cD+PSiyU8ybdY2mplNgQTsVHCJCZGxdNuWxu72CV
+EY4hgLW9oHPY0LJ3xEXqWib7ZnZ2+AYfYW0PVcWDtxBWcgYHpfOxGgMFZA6dWorW
+hnAbJN7+KIor0Gqw/Hqi3LJ5DotlDwIDAQABo2MwYTAdBgNVHQ4EFgQU7mtJPHo/
+DeOxCbeKyKsZn3MzUOcwHwYDVR0jBBgwFoAU7mtJPHo/DeOxCbeKyKsZn3MzUOcw
+DwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQAD
+ggEBACUY1JGPE+6PHh0RU9otRCkZoB5rMZ5NDp6tPVxBb5UrJKF5mDo4Nvu7Zp5I
+/5CQ7z3UuJu0h3U/IJvOcs+hVcFNZKIZBqEHMwwLKeXx6quj7LUKdJDHfXLy11yf
+ke+Ri7fc7Waiz45mO7yfOgLgJ90WmMCV1Aqk5IGadZQ1nJBfiDcGrVmVCrDRZ9MZ
+yonnMlo2HD6CqFqTvsbQZJG2z9m2GM/bftJlo6bEjhcxwft+dtvTheNYsnd6djts
+L1Ac59v2Z3kf9YKVmgenFK+P3CghZwnS1k1aHBkcjndcw5QkPTJrS37UeJSDvjdN
+zl/HHk484IkzlQsPpTLWPFp5LBk=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem
new file mode 100644
index 00000000000..90752467d03
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 4f:d2:2b:8f:f5:64:c8:33:9e:4f:34:58:66:23:70:60
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = CN, O = UniTrust, CN = UCA Extended Validation Root
+ Validity
+ Not Before: Mar 13 00:00:00 2015 GMT
+ Not After : Dec 31 00:00:00 2038 GMT
+ Subject: C = CN, O = UniTrust, CN = UCA Extended Validation Root
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a9:09:07:28:13:02:b0:99:e0:64:aa:1e:43:16:
+ 7a:73:b1:91:a0:75:3e:a8:fa:e3:38:00:7a:ec:89:
+ 6a:20:0f:8b:c5:b0:9b:33:03:5a:86:c6:58:86:d5:
+ c1:85:bb:4f:c6:9c:40:4d:ca:be:ee:69:96:b8:ad:
+ 81:30:9a:7c:92:05:eb:05:2b:9a:48:d0:b8:76:3e:
+ 96:c8:20:bb:d2:b0:f1:8f:d8:ac:45:46:ff:aa:67:
+ 60:b4:77:7e:6a:1f:3c:1a:52:7a:04:3d:07:3c:85:
+ 0d:84:d0:1f:76:0a:f7:6a:14:df:72:e3:34:7c:57:
+ 4e:56:01:3e:79:f1:aa:29:3b:6c:fa:f8:8f:6d:4d:
+ c8:35:df:ae:eb:dc:24:ee:79:45:a7:85:b6:05:88:
+ de:88:5d:25:7c:97:64:67:09:d9:bf:5a:15:05:86:
+ f3:09:1e:ec:58:32:33:11:f3:77:64:b0:76:1f:e4:
+ 10:35:17:1b:f2:0e:b1:6c:a4:2a:a3:73:fc:09:1f:
+ 1e:32:19:53:11:e7:d9:b3:2c:2e:76:2e:a1:a3:de:
+ 7e:6a:88:09:e8:f2:07:8a:f8:b2:cd:10:e7:e2:73:
+ 40:93:bb:08:d1:3f:e1:fc:0b:94:b3:25:ef:7c:a6:
+ d7:d1:af:9f:ff:96:9a:f5:91:7b:98:0b:77:d4:7e:
+ e8:07:d2:62:b5:95:39:e3:f3:f1:6d:0f:0e:65:84:
+ 8a:63:54:c5:80:b6:e0:9e:4b:7d:47:26:a7:01:08:
+ 5d:d1:88:9e:d7:c3:32:44:fa:82:4a:0a:68:54:7f:
+ 38:53:03:cc:a4:00:33:64:51:59:0b:a3:82:91:7a:
+ 5e:ec:16:c2:f3:2a:e6:62:da:2a:db:59:62:10:25:
+ 4a:2a:81:0b:47:07:43:06:70:87:d2:fa:93:11:29:
+ 7a:48:4d:eb:94:c7:70:4d:af:67:d5:51:b1:80:20:
+ 01:01:b4:7a:08:a6:90:7f:4e:e0:ef:07:41:87:af:
+ 6a:a5:5e:8b:fb:cf:50:b2:9a:54:af:c3:89:ba:58:
+ 2d:f5:30:98:b1:36:72:39:7e:49:04:fd:29:a7:4c:
+ 79:e4:05:57:db:94:b9:16:53:8d:46:b3:1d:95:61:
+ 57:56:7f:af:f0:16:5b:61:58:6f:36:50:11:0b:d8:
+ ac:2b:95:16:1a:0e:1f:08:cd:36:34:65:10:62:66:
+ d5:80:5f:14:20:5f:2d:0c:a0:78:0a:68:d6:2c:d7:
+ e9:6f:2b:d2:4a:05:93:fc:9e:6f:6b:67:ff:88:f1:
+ 4e:a5:69:4a:52:37:05:ea:c6:16:8d:d2:c4:99:d1:
+ 82:2b:3b:ba:35:75:f7:51:51:58:f3:c8:07:dd:e4:
+ b4:03:7f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ D9:74:3A:E4:30:3D:0D:F7:12:DC:7E:5A:05:9F:1E:34:9A:F7:E1:14
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 36:8d:97:cc:42:15:64:29:37:9b:26:2c:d6:fb:ae:15:69:2c:
+ 6b:1a:1a:f7:5f:b6:f9:07:4c:59:ea:f3:c9:c8:b9:ae:cc:ba:
+ 2e:7a:dc:c0:f5:b0:2d:c0:3b:af:9f:70:05:11:6a:9f:25:4f:
+ 01:29:70:e3:e5:0c:e1:ea:5a:7c:dc:49:bb:c1:1e:2a:81:f5:
+ 16:4b:72:91:c8:a2:31:b9:aa:da:fc:9d:1f:f3:5d:40:02:13:
+ fc:4e:1c:06:ca:b3:14:90:54:17:19:12:1a:f1:1f:d7:0c:69:
+ 5a:f6:71:78:f4:94:7d:91:0b:8e:ec:90:54:8e:bc:6f:a1:4c:
+ ab:fc:74:64:fd:71:9a:f8:41:07:a1:cd:91:e4:3c:9a:e0:9b:
+ 32:39:73:ab:2a:d5:69:c8:78:91:26:31:7d:e2:c7:30:f1:fc:
+ 14:78:77:12:0e:13:f4:dd:16:94:bf:4b:67:7b:70:53:85:ca:
+ b0:bb:f3:38:4d:2c:90:39:c0:0d:c2:5d:6b:e9:e2:e5:d5:88:
+ 8d:d6:2c:bf:ab:1b:be:b5:28:87:12:17:74:6e:fc:7d:fc:8f:
+ d0:87:26:b0:1b:fb:b9:6c:ab:e2:9e:3d:15:c1:3b:2e:67:02:
+ 58:91:9f:ef:f8:42:1f:2c:b7:68:f5:75:ad:cf:b5:f6:ff:11:
+ 7d:c2:f0:24:a5:ad:d3:fa:a0:3c:a9:fa:5d:dc:a5:a0:ef:44:
+ a4:be:d6:e8:e5:e4:13:96:17:7b:06:3e:32:ed:c7:b7:42:bc:
+ 76:a3:d8:65:38:2b:38:35:51:21:0e:0e:6f:2e:34:13:40:e1:
+ 2b:67:0c:6d:4a:41:30:18:23:5a:32:55:99:c9:17:e0:3c:de:
+ f6:ec:79:ad:2b:58:19:a2:ad:2c:22:1a:95:8e:be:96:90:5d:
+ 42:57:c4:f9:14:03:35:2b:1c:2d:51:57:08:a7:3a:de:3f:e4:
+ c8:b4:03:73:c2:c1:26:80:bb:0b:42:1f:ad:0d:af:26:72:da:
+ cc:be:b3:a3:83:58:0d:82:c5:1f:46:51:e3:9c:18:cc:8d:9b:
+ 8d:ec:49:eb:75:50:d5:8c:28:59:ca:74:34:da:8c:0b:21:ab:
+ 1e:ea:1b:e5:c7:fd:15:3e:c0:17:aa:fb:23:6e:26:46:cb:fa:
+ f9:b1:72:6b:69:cf:22:84:0b:62:0f:ac:d9:19:00:94:a2:76:
+ 3c:d4:2d:9a:ed:04:9e:2d:06:62:10:37:52:1c:85:72:1b:27:
+ e5:cc:c6:31:ec:37:ec:63:59:9b:0b:1d:76:cc:7e:32:9a:88:
+ 95:08:36:52:bb:de:76:5f:76:49:49:ad:7f:bd:65:20:b2:c9:
+ c1:2b:76:18:76:9f:56:b1
+-----BEGIN CERTIFICATE-----
+MIIFWjCCA0KgAwIBAgIQT9Irj/VkyDOeTzRYZiNwYDANBgkqhkiG9w0BAQsFADBH
+MQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNVBAMMHFVDQSBF
+eHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwHhcNMTUwMzEzMDAwMDAwWhcNMzgxMjMx
+MDAwMDAwWjBHMQswCQYDVQQGEwJDTjERMA8GA1UECgwIVW5pVHJ1c3QxJTAjBgNV
+BAMMHFVDQSBFeHRlbmRlZCBWYWxpZGF0aW9uIFJvb3QwggIiMA0GCSqGSIb3DQEB
+AQUAA4ICDwAwggIKAoICAQCpCQcoEwKwmeBkqh5DFnpzsZGgdT6o+uM4AHrsiWog
+D4vFsJszA1qGxliG1cGFu0/GnEBNyr7uaZa4rYEwmnySBesFK5pI0Lh2PpbIILvS
+sPGP2KxFRv+qZ2C0d35qHzwaUnoEPQc8hQ2E0B92CvdqFN9y4zR8V05WAT558aop
+O2z6+I9tTcg1367r3CTueUWnhbYFiN6IXSV8l2RnCdm/WhUFhvMJHuxYMjMR83dk
+sHYf5BA1FxvyDrFspCqjc/wJHx4yGVMR59mzLC52LqGj3n5qiAno8geK+LLNEOfi
+c0CTuwjRP+H8C5SzJe98ptfRr5//lpr1kXuYC3fUfugH0mK1lTnj8/FtDw5lhIpj
+VMWAtuCeS31HJqcBCF3RiJ7XwzJE+oJKCmhUfzhTA8ykADNkUVkLo4KRel7sFsLz
+KuZi2irbWWIQJUoqgQtHB0MGcIfS+pMRKXpITeuUx3BNr2fVUbGAIAEBtHoIppB/
+TuDvB0GHr2qlXov7z1CymlSvw4m6WC31MJixNnI5fkkE/SmnTHnkBVfblLkWU41G
+sx2VYVdWf6/wFlthWG82UBEL2KwrlRYaDh8IzTY0ZRBiZtWAXxQgXy0MoHgKaNYs
+1+lvK9JKBZP8nm9rZ/+I8U6laUpSNwXqxhaN0sSZ0YIrO7o1dfdRUVjzyAfd5LQD
+fwIDAQABo0IwQDAdBgNVHQ4EFgQU2XQ65DA9DfcS3H5aBZ8eNJr34RQwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAYYwDQYJKoZIhvcNAQELBQADggIBADaN
+l8xCFWQpN5smLNb7rhVpLGsaGvdftvkHTFnq88nIua7Mui563MD1sC3AO6+fcAUR
+ap8lTwEpcOPlDOHqWnzcSbvBHiqB9RZLcpHIojG5qtr8nR/zXUACE/xOHAbKsxSQ
+VBcZEhrxH9cMaVr2cXj0lH2RC47skFSOvG+hTKv8dGT9cZr4QQehzZHkPJrgmzI5
+c6sq1WnIeJEmMX3ixzDx/BR4dxIOE/TdFpS/S2d7cFOFyrC78zhNLJA5wA3CXWvp
+4uXViI3WLL+rG761KIcSF3Ru/H38j9CHJrAb+7lsq+KePRXBOy5nAliRn+/4Qh8s
+t2j1da3Ptfb/EX3C8CSlrdP6oDyp+l3cpaDvRKS+1ujl5BOWF3sGPjLtx7dCvHaj
+2GU4Kzg1USEODm8uNBNA4StnDG1KQTAYI1oyVZnJF+A83vbsea0rWBmirSwiGpWO
+vpaQXUJXxPkUAzUrHC1RVwinOt4/5Mi0A3PCwSaAuwtCH60NryZy2sy+s6ODWA2C
+xR9GUeOcGMyNm43sSet1UNWMKFnKdDTajAshqx7qG+XH/RU+wBeq+yNuJkbL+vmx
+cmtpzyKEC2IPrNkZAJSidjzULZrtBJ4tBmIQN1IchXIbJ+XMxjHsN+xjWZsLHXbM
+fjKaiJUINlK73nZfdklJrX+9ZSCyycErdhh2n1ax
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem
new file mode 100644
index 00000000000..f9bc3c9860f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem
@@ -0,0 +1,139 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ ca:e9:1b:89:f1:55:03:0d:a3:e6:41:6d:c4:e3:a6:e1
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = FR, O = Dhimyotis, OU = 0002 48146308100036, CN = Certigna Root CA
+ Validity
+ Not Before: Oct 1 08:32:27 2013 GMT
+ Not After : Oct 1 08:32:27 2033 GMT
+ Subject: C = FR, O = Dhimyotis, OU = 0002 48146308100036, CN = Certigna Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:cd:18:39:65:1a:59:b1:ea:64:16:0e:8c:94:24:
+ 95:7c:83:d3:c5:39:26:dc:0c:ef:16:57:8d:d7:d8:
+ ac:a3:42:7f:82:ca:ed:cd:5b:db:0e:b7:2d:ed:45:
+ 08:17:b2:d9:b3:cb:d6:17:52:72:28:db:8e:4e:9e:
+ 8a:b6:0b:f9:9e:84:9a:4d:76:de:22:29:5c:d2:b3:
+ d2:06:3e:30:39:a9:74:a3:92:56:1c:a1:6f:4c:0a:
+ 20:6d:9f:23:7a:b4:c6:da:2c:e4:1d:2c:dc:b3:28:
+ d0:13:f2:4c:4e:02:49:a1:54:40:9e:e6:e5:05:a0:
+ 2d:84:c8:ff:98:6c:d0:eb:8a:1a:84:08:1e:b7:68:
+ 23:ee:23:d5:70:ce:6d:51:69:10:ee:a1:7a:c2:d1:
+ 22:31:c2:82:85:d2:f2:55:76:50:7c:25:7a:c9:84:
+ 5c:0b:ac:dd:42:4e:2b:e7:82:a2:24:89:cb:90:b2:
+ d0:ee:23:ba:66:4c:bb:62:a4:f9:53:5a:64:7b:7c:
+ 98:fa:a3:48:9e:0f:95:ae:a7:18:f4:6a:ec:2e:03:
+ 45:af:f0:74:f8:2a:cd:7a:5d:d1:be:44:26:32:29:
+ f1:f1:f5:6c:cc:7e:02:21:0b:9f:6f:a4:3f:be:9d:
+ 53:e2:cf:7d:a9:2c:7c:58:1a:97:e1:3d:37:37:18:
+ 66:28:d2:40:c5:51:8a:8c:c3:2d:ce:53:88:24:58:
+ 64:30:16:c5:aa:e0:d6:0a:a6:40:df:78:f6:f5:04:
+ 7c:69:13:84:bc:d1:d1:a7:06:cf:01:f7:68:c0:a8:
+ 57:bb:3a:61:ad:04:8c:93:e3:ad:fc:f0:db:44:6d:
+ 59:dc:49:59:ae:ac:9a:99:36:30:41:7b:76:33:22:
+ 87:a3:c2:92:86:6e:f9:70:ee:ae:87:87:95:1b:c4:
+ 7a:bd:31:f3:d4:d2:e5:99:ff:be:48:ec:75:f5:78:
+ 16:1d:a6:70:c1:7f:3c:1b:a1:92:fb:cf:c8:3c:d6:
+ c5:93:0a:8f:f5:55:3a:76:95:ce:59:98:8a:09:95:
+ 77:32:9a:83:ba:2c:04:3a:97:bd:d4:2f:be:d7:6c:
+ 9b:a2:ca:7d:6d:26:c9:55:d5:cf:c3:79:52:08:09:
+ 99:07:24:2d:64:25:6b:a6:21:69:9b:6a:dd:74:4d:
+ 6b:97:7a:41:bd:ab:17:f9:90:17:48:8f:36:f9:2d:
+ d5:c5:db:ee:aa:85:45:41:fa:cd:3a:45:b1:68:e6:
+ 36:4c:9b:90:57:ec:23:b9:87:08:c2:c4:09:f1:97:
+ 86:2a:28:4d:e2:74:c0:da:c4:8c:db:df:e2:a1:17:
+ 59:ce:24:59:74:31:da:7f:fd:30:6d:d9:dc:e1:6a:
+ e1:fc:5f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 18:87:56:E0:6E:77:EE:24:35:3C:4E:73:9A:1F:D6:E1:E2:79:7E:2B
+ X509v3 Authority Key Identifier:
+ keyid:18:87:56:E0:6E:77:EE:24:35:3C:4E:73:9A:1F:D6:E1:E2:79:7E:2B
+
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: https://wwww.certigna.fr/autorites/
+
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.certigna.fr/certignarootca.crl
+
+ Full Name:
+ URI:http://crl.dhimyotis.com/certignarootca.crl
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 94:b8:9e:4f:f0:e3:95:08:22:e7:cd:68:41:f7:1c:55:d5:7c:
+ 00:e2:2d:3a:89:5d:68:38:2f:51:22:0b:4a:8d:cb:e9:bb:5d:
+ 3e:bb:5c:3d:b1:28:fe:e4:53:55:13:cf:a1:90:1b:02:1d:5f:
+ 66:46:09:33:28:e1:0d:24:97:70:d3:10:1f:ea:64:57:96:bb:
+ 5d:da:e7:c4:8c:4f:4c:64:46:1d:5c:87:e3:59:de:42:d1:9b:
+ a8:7e:a6:89:dd:8f:1c:c9:30:82:ed:3b:9c:cd:c0:e9:19:e0:
+ 6a:d8:02:75:37:ab:f7:34:28:28:91:f2:04:0a:4f:35:e3:60:
+ 26:01:fa:d0:11:8c:f9:11:6a:ee:af:3d:c3:50:d3:8f:5f:33:
+ 79:3c:86:a8:73:45:90:8c:20:b6:72:73:17:23:be:07:65:e5:
+ 78:92:0d:ba:01:c0:eb:8c:1c:66:bf:ac:86:77:01:94:0d:9c:
+ e6:e9:39:8d:1f:a6:51:8c:99:0c:39:77:e1:b4:9b:fa:1c:67:
+ 57:6f:6a:6a:8e:a9:2b:4c:57:79:7a:57:22:cf:cd:5f:63:46:
+ 8d:5c:59:3a:86:f8:32:47:62:a3:67:0d:18:91:dc:fb:a6:6b:
+ f5:48:61:73:23:59:8e:02:a7:bc:44:ea:f4:49:9d:f1:54:58:
+ f9:60:af:da:18:a4:2f:28:45:dc:7a:a0:88:86:5d:f3:3b:e7:
+ ff:29:35:80:fc:64:43:94:e6:e3:1c:6f:be:ad:0e:2a:63:99:
+ 2b:c9:7e:85:f6:71:e8:06:03:95:fe:de:8f:48:1c:5a:d4:92:
+ e8:2b:ee:e7:31:db:ba:04:6a:87:98:e7:c5:5f:ef:7d:a7:22:
+ f7:01:d8:4d:f9:89:d0:0e:9a:05:59:a4:9e:98:d9:6f:2b:ca:
+ 70:be:64:c2:55:a3:f4:e9:af:c3:92:29:dc:88:16:24:99:3c:
+ 8d:26:98:b6:5b:b7:cc:ce:b7:37:07:fd:26:d9:98:85:24:ff:
+ 59:23:03:9a:ed:9d:9d:a8:e4:5e:38:ce:d7:52:0d:6f:d2:3f:
+ 6d:b1:05:6b:49:ce:8a:91:46:73:f4:f6:2f:f0:a8:73:77:0e:
+ 65:ac:a1:8d:66:52:69:7e:4b:68:0c:c7:1e:37:27:83:a5:8c:
+ c7:02:e4:14:cd:49:01:b0:73:b3:fd:c6:90:3a:6f:d2:6c:ed:
+ 3b:ee:ec:91:be:a2:43:5d:8b:00:4a:66:25:44:70:de:40:0f:
+ f8:7c:15:f7:a2:ce:3c:d7:5e:13:8c:81:17:18:17:d1:bd:f1:
+ 77:10:3a:d4:65:39:c1:27:ac:57:2c:25:54:ff:a2:da:4f:8a:
+ 61:39:5e:ae:3d:4a:8c:bd
+-----BEGIN CERTIFICATE-----
+MIIGWzCCBEOgAwIBAgIRAMrpG4nxVQMNo+ZBbcTjpuEwDQYJKoZIhvcNAQELBQAw
+WjELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczEcMBoGA1UECwwTMDAw
+MiA0ODE0NjMwODEwMDAzNjEZMBcGA1UEAwwQQ2VydGlnbmEgUm9vdCBDQTAeFw0x
+MzEwMDEwODMyMjdaFw0zMzEwMDEwODMyMjdaMFoxCzAJBgNVBAYTAkZSMRIwEAYD
+VQQKDAlEaGlteW90aXMxHDAaBgNVBAsMEzAwMDIgNDgxNDYzMDgxMDAwMzYxGTAX
+BgNVBAMMEENlcnRpZ25hIFJvb3QgQ0EwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDNGDllGlmx6mQWDoyUJJV8g9PFOSbcDO8WV43X2KyjQn+Cyu3NW9sO
+ty3tRQgXstmzy9YXUnIo245Onoq2C/mehJpNdt4iKVzSs9IGPjA5qXSjklYcoW9M
+CiBtnyN6tMbaLOQdLNyzKNAT8kxOAkmhVECe5uUFoC2EyP+YbNDrihqECB63aCPu
+I9Vwzm1RaRDuoXrC0SIxwoKF0vJVdlB8JXrJhFwLrN1CTivngqIkicuQstDuI7pm
+TLtipPlTWmR7fJj6o0ieD5Wupxj0auwuA0Wv8HT4Ks16XdG+RCYyKfHx9WzMfgIh
+C59vpD++nVPiz32pLHxYGpfhPTc3GGYo0kDFUYqMwy3OU4gkWGQwFsWq4NYKpkDf
+ePb1BHxpE4S80dGnBs8B92jAqFe7OmGtBIyT46388NtEbVncSVmurJqZNjBBe3Yz
+IoejwpKGbvlw7q6Hh5UbxHq9MfPU0uWZ/75I7HX1eBYdpnDBfzwboZL7z8g81sWT
+Co/1VTp2lc5ZmIoJlXcymoO6LAQ6l73UL77XbJuiyn1tJslV1c/DeVIICZkHJC1k
+JWumIWmbat10TWuXekG9qxf5kBdIjzb5LdXF2+6qhUVB+s06RbFo5jZMm5BX7CO5
+hwjCxAnxl4YqKE3idMDaxIzb3+KhF1nOJFl0Mdp//TBt2dzhauH8XwIDAQABo4IB
+GjCCARYwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYE
+FBiHVuBud+4kNTxOc5of1uHieX4rMB8GA1UdIwQYMBaAFBiHVuBud+4kNTxOc5of
+1uHieX4rMEQGA1UdIAQ9MDswOQYEVR0gADAxMC8GCCsGAQUFBwIBFiNodHRwczov
+L3d3d3cuY2VydGlnbmEuZnIvYXV0b3JpdGVzLzBtBgNVHR8EZjBkMC+gLaArhilo
+dHRwOi8vY3JsLmNlcnRpZ25hLmZyL2NlcnRpZ25hcm9vdGNhLmNybDAxoC+gLYYr
+aHR0cDovL2NybC5kaGlteW90aXMuY29tL2NlcnRpZ25hcm9vdGNhLmNybDANBgkq
+hkiG9w0BAQsFAAOCAgEAlLieT/DjlQgi581oQfccVdV8AOItOoldaDgvUSILSo3L
+6btdPrtcPbEo/uRTVRPPoZAbAh1fZkYJMyjhDSSXcNMQH+pkV5a7XdrnxIxPTGRG
+HVyH41neQtGbqH6mid2PHMkwgu07nM3A6RngatgCdTer9zQoKJHyBApPNeNgJgH6
+0BGM+RFq7q89w1DTj18zeTyGqHNFkIwgtnJzFyO+B2XleJINugHA64wcZr+shncB
+lA2c5uk5jR+mUYyZDDl34bSb+hxnV29qao6pK0xXeXpXIs/NX2NGjVxZOob4Mkdi
+o2cNGJHc+6Zr9UhhcyNZjgKnvETq9Emd8VRY+WCv2hikLyhF3HqgiIZd8zvn/yk1
+gPxkQ5Tm4xxvvq0OKmOZK8l+hfZx6AYDlf7ej0gcWtSS6Cvu5zHbugRqh5jnxV/v
+faci9wHYTfmJ0A6aBVmknpjZbyvKcL5kwlWj9Omvw5Ip3IgWJJk8jSaYtlu3zM63
+Nwf9JtmYhST/WSMDmu2dnajkXjjO11INb9I/bbEFa0nOipFGc/T2L/Coc3cOZayh
+jWZSaX5LaAzHHjcng6WMxwLkFM1JAbBzs/3GkDpv0mztO+7skb6iQ12LAEpmJURw
+3kAP+HwV96LOPNdeE4yBFxgX0b3xdxA61GU5wSesVywlVP+i2k+KYTlerj1KjL0=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem
new file mode 100644
index 00000000000..53a44ff5763
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem
@@ -0,0 +1,89 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
+ Validity
+ Not Before: Jan 1 00:00:00 2004 GMT
+ Not After : Dec 31 23:59:59 2028 GMT
+ Subject: C = GB, ST = Greater Manchester, L = Salford, O = Comodo CA Limited, CN = AAA Certificate Services
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:be:40:9d:f4:6e:e1:ea:76:87:1c:4d:45:44:8e:
+ be:46:c8:83:06:9d:c1:2a:fe:18:1f:8e:e4:02:fa:
+ f3:ab:5d:50:8a:16:31:0b:9a:06:d0:c5:70:22:cd:
+ 49:2d:54:63:cc:b6:6e:68:46:0b:53:ea:cb:4c:24:
+ c0:bc:72:4e:ea:f1:15:ae:f4:54:9a:12:0a:c3:7a:
+ b2:33:60:e2:da:89:55:f3:22:58:f3:de:dc:cf:ef:
+ 83:86:a2:8c:94:4f:9f:68:f2:98:90:46:84:27:c7:
+ 76:bf:e3:cc:35:2c:8b:5e:07:64:65:82:c0:48:b0:
+ a8:91:f9:61:9f:76:20:50:a8:91:c7:66:b5:eb:78:
+ 62:03:56:f0:8a:1a:13:ea:31:a3:1e:a0:99:fd:38:
+ f6:f6:27:32:58:6f:07:f5:6b:b8:fb:14:2b:af:b7:
+ aa:cc:d6:63:5f:73:8c:da:05:99:a8:38:a8:cb:17:
+ 78:36:51:ac:e9:9e:f4:78:3a:8d:cf:0f:d9:42:e2:
+ 98:0c:ab:2f:9f:0e:01:de:ef:9f:99:49:f1:2d:df:
+ ac:74:4d:1b:98:b5:47:c5:e5:29:d1:f9:90:18:c7:
+ 62:9c:be:83:c7:26:7b:3e:8a:25:c7:c0:dd:9d:e6:
+ 35:68:10:20:9d:8f:d8:de:d2:c3:84:9c:0d:5e:e8:
+ 2f:c9
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A0:11:0A:23:3E:96:F1:07:EC:E2:AF:29:EF:82:A5:7F:D0:30:A4:B4
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.comodoca.com/AAACertificateServices.crl
+
+ Full Name:
+ URI:http://crl.comodo.net/AAACertificateServices.crl
+
+ Signature Algorithm: sha1WithRSAEncryption
+ 08:56:fc:02:f0:9b:e8:ff:a4:fa:d6:7b:c6:44:80:ce:4f:c4:
+ c5:f6:00:58:cc:a6:b6:bc:14:49:68:04:76:e8:e6:ee:5d:ec:
+ 02:0f:60:d6:8d:50:18:4f:26:4e:01:e3:e6:b0:a5:ee:bf:bc:
+ 74:54:41:bf:fd:fc:12:b8:c7:4f:5a:f4:89:60:05:7f:60:b7:
+ 05:4a:f3:f6:f1:c2:bf:c4:b9:74:86:b6:2d:7d:6b:cc:d2:f3:
+ 46:dd:2f:c6:e0:6a:c3:c3:34:03:2c:7d:96:dd:5a:c2:0e:a7:
+ 0a:99:c1:05:8b:ab:0c:2f:f3:5c:3a:cf:6c:37:55:09:87:de:
+ 53:40:6c:58:ef:fc:b6:ab:65:6e:04:f6:1b:dc:3c:e0:5a:15:
+ c6:9e:d9:f1:59:48:30:21:65:03:6c:ec:e9:21:73:ec:9b:03:
+ a1:e0:37:ad:a0:15:18:8f:fa:ba:02:ce:a7:2c:a9:10:13:2c:
+ d4:e5:08:26:ab:22:97:60:f8:90:5e:74:d4:a2:9a:53:bd:f2:
+ a9:68:e0:a2:6e:c2:d7:6c:b1:a3:0f:9e:bf:eb:68:e7:56:f2:
+ ae:f2:e3:2b:38:3a:09:81:b5:6b:85:d7:be:2d:ed:3f:1a:b7:
+ b2:63:e2:f5:62:2c:82:d4:6a:00:41:50:f1:39:83:9f:95:e9:
+ 36:96:98:6e
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
+MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
+GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
+YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
+MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
+BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
+GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
+BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
+3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
+YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
+rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
+ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
+oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
+QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
+b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
+AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
+GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
+G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
+l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
+smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem
new file mode 100644
index 00000000000..472ad20488a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem
@@ -0,0 +1,124 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ d9:b5:43:7f:af:a9:39:0f:00:00:00:00:55:65:ad:58
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2015 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - G4
+ Validity
+ Not Before: May 27 11:11:16 2015 GMT
+ Not After : Dec 27 11:41:16 2037 GMT
+ Subject: C = US, O = "Entrust, Inc.", OU = See www.entrust.net/legal-terms, OU = "(c) 2015 Entrust, Inc. - for authorized use only", CN = Entrust Root Certification Authority - G4
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:b1:ec:2c:42:ee:e2:d1:30:ff:a5:92:47:e2:2d:
+ c3:ba:64:97:6d:ca:f7:0d:b5:59:c1:b3:cb:a8:68:
+ 19:d8:af:84:6d:30:70:5d:7e:f3:2e:d2:53:99:e1:
+ fe:1f:5e:d9:48:af:5d:13:8d:db:ff:63:33:4d:d3:
+ 00:02:bc:c4:f8:d1:06:08:94:79:58:8a:15:de:29:
+ b3:fd:fd:c4:4f:e8:aa:e2:a0:3b:79:cd:bf:6b:43:
+ 32:dd:d9:74:10:b9:f7:f4:68:d4:bb:d0:87:d5:aa:
+ 4b:8a:2a:6f:2a:04:b5:b2:a6:c7:a0:7a:e6:48:ab:
+ d2:d1:59:cc:d6:7e:23:e6:97:6c:f0:42:e5:dc:51:
+ 4b:15:41:ed:49:4a:c9:de:10:97:d6:76:c1:ef:a5:
+ b5:36:14:97:35:d8:78:22:35:52:ef:43:bd:db:27:
+ db:61:56:82:34:dc:cb:88:60:0c:0b:5a:e5:2c:01:
+ c6:54:af:d7:aa:c1:10:7b:d2:05:5a:b8:40:9e:86:
+ a7:c3:90:86:02:56:52:09:7a:9c:d2:27:82:53:4a:
+ 65:52:6a:f5:3c:e7:a8:f2:9c:af:8b:bd:d3:0e:d4:
+ d4:5e:6e:87:9e:6a:3d:45:1d:d1:5d:1b:f4:e9:0a:
+ ac:60:99:fb:89:b4:ff:98:2c:cf:7c:1d:e9:02:aa:
+ 04:9a:1e:b8:dc:88:6e:25:b3:6c:66:f7:3c:90:f3:
+ 57:c1:b3:2f:f5:6d:f2:fb:ca:a1:f8:29:9d:46:8b:
+ b3:6a:f6:e6:67:07:be:2c:67:0a:2a:1f:5a:b2:3e:
+ 57:c4:d3:21:21:63:65:52:91:1b:b1:99:8e:79:7e:
+ e6:eb:8d:00:d9:5a:aa:ea:73:e8:a4:82:02:47:96:
+ fe:5b:8e:54:61:a3:eb:2f:4b:30:b0:8b:23:75:72:
+ 7c:21:3c:c8:f6:f1:74:d4:1c:7b:a3:05:55:ee:bb:
+ 4d:3b:32:be:9a:77:66:9e:ac:69:90:22:07:1f:61:
+ 3a:96:be:e5:9a:4f:cc:05:3c:28:59:d3:c1:0c:54:
+ a8:59:61:bd:c8:72:4c:e8:dc:9f:87:7f:bd:9c:48:
+ 36:5e:95:a3:0e:b9:38:24:55:fc:75:66:eb:02:e3:
+ 08:34:29:4a:c6:e3:2b:2f:33:a0:da:a3:86:a5:12:
+ 97:fd:80:2b:da:14:42:e3:92:bd:3e:f2:5d:5e:67:
+ 74:2e:1c:88:47:29:34:5f:e2:32:a8:9c:25:37:8c:
+ ba:98:00:97:8b:49:96:1e:fd:25:8a:ac:dc:da:d8:
+ 5d:74:6e:66:b0:ff:44:df:a1:18:c6:be:48:2f:37:
+ 94:78:f8:95:4a:3f:7f:13:5e:5d:59:fd:74:86:43:
+ 63:73:49
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ 9F:38:C4:56:23:C3:39:E8:A0:71:6C:E8:54:4C:E4:E8:3A:B1:BF:67
+ Signature Algorithm: sha256WithRSAEncryption
+ 12:e5:42:a6:7b:8b:0f:0c:e4:46:a5:b6:60:40:87:8c:25:7e:
+ ad:b8:68:2e:5b:c6:40:76:3c:03:f8:c9:59:f4:f3:ab:62:ce:
+ 10:8d:b4:5a:64:8c:68:c0:b0:72:43:34:d2:1b:0b:f6:2c:53:
+ d2:ca:90:4b:86:66:fc:aa:83:22:f4:8b:1a:6f:26:48:ac:76:
+ 77:08:bf:c5:98:5c:f4:26:89:9e:7b:c3:b9:64:32:01:7f:d3:
+ c3:dd:58:6d:ec:b1:ab:84:55:74:77:84:04:27:52:6b:86:4c:
+ ce:dd:b9:65:ff:d6:c6:5e:9f:9a:10:99:4b:75:6a:fe:6a:e9:
+ 97:20:e4:e4:76:7a:c6:d0:24:aa:90:cd:20:90:ba:47:64:fb:
+ 7f:07:b3:53:78:b5:0a:62:f2:73:43:ce:41:2b:81:6a:2e:85:
+ 16:94:53:d4:6b:5f:72:22:ab:51:2d:42:d5:00:9c:99:bf:de:
+ bb:94:3b:57:fd:9a:f5:86:cb:56:3b:5b:88:01:e5:7c:28:4b:
+ 03:f9:49:83:7c:b2:7f:7c:e3:ed:8e:a1:7f:60:53:8e:55:9d:
+ 50:34:12:0f:b7:97:7b:6c:87:4a:44:e7:f5:6d:ec:80:37:f0:
+ 58:19:6e:4a:68:76:f0:1f:92:e4:ea:b5:92:d3:61:51:10:0b:
+ ad:a7:d9:5f:c7:5f:dc:1f:a3:5c:8c:a1:7e:9b:b7:9e:d3:56:
+ 6f:66:5e:07:96:20:ed:0b:74:fb:66:4e:8b:11:15:e9:81:49:
+ 7e:6f:b0:d4:50:7f:22:d7:5f:65:02:0d:a6:f4:85:1e:d8:ae:
+ 06:4b:4a:a7:d2:31:66:c2:f8:ce:e5:08:a6:a4:02:96:44:68:
+ 57:c4:d5:33:cf:19:2f:14:c4:94:1c:7b:a4:d9:f0:9f:0e:b1:
+ 80:e2:d1:9e:11:64:a9:88:11:3a:76:82:e5:62:c2:80:d8:a4:
+ 83:ed:93:ef:7c:2f:90:b0:32:4c:96:15:68:48:52:d4:99:08:
+ c0:24:e8:1c:e3:b3:a5:21:0e:92:c0:90:1f:cf:20:5f:ca:3b:
+ 38:c7:b7:6d:3a:f3:e6:44:b8:0e:31:6b:88:8e:70:eb:9c:17:
+ 52:a8:41:94:2e:87:b6:e7:a6:12:c5:75:df:5b:c0:0a:6e:7b:
+ a4:e4:5e:86:f9:36:94:df:77:c3:e9:0d:c0:39:f1:79:bb:46:
+ 8e:ab:43:59:27:b7:20:bb:23:e9:56:40:21:ec:31:3d:65:aa:
+ 43:f2:3d:df:70:44:e1:ba:4d:26:10:3b:98:9f:f3:c8:8e:1b:
+ 38:56:21:6a:51:93:d3:91:ca:46:da:89:b7:3d:53:83:2c:08:
+ 1f:8b:8f:53:dd:ff:ac:1f
+-----BEGIN CERTIFICATE-----
+MIIGSzCCBDOgAwIBAgIRANm1Q3+vqTkPAAAAAFVlrVgwDQYJKoZIhvcNAQELBQAw
+gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL
+Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg
+MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw
+BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0
+MB4XDTE1MDUyNzExMTExNloXDTM3MTIyNzExNDExNlowgb4xCzAJBgNVBAYTAlVT
+MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1
+c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNSBFbnRydXN0LCBJ
+bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAwBgNVBAMTKUVudHJ1c3Qg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAsewsQu7i0TD/pZJH4i3DumSXbcr3DbVZwbPLqGgZ
+2K+EbTBwXX7zLtJTmeH+H17ZSK9dE43b/2MzTdMAArzE+NEGCJR5WIoV3imz/f3E
+T+iq4qA7ec2/a0My3dl0ELn39GjUu9CH1apLiipvKgS1sqbHoHrmSKvS0VnM1n4j
+5pds8ELl3FFLFUHtSUrJ3hCX1nbB76W1NhSXNdh4IjVS70O92yfbYVaCNNzLiGAM
+C1rlLAHGVK/XqsEQe9IFWrhAnoanw5CGAlZSCXqc0ieCU0plUmr1POeo8pyvi73T
+DtTUXm6Hnmo9RR3RXRv06QqsYJn7ibT/mCzPfB3pAqoEmh643IhuJbNsZvc8kPNX
+wbMv9W3y+8qh+CmdRouzavbmZwe+LGcKKh9asj5XxNMhIWNlUpEbsZmOeX7m640A
+2Vqq6nPopIICR5b+W45UYaPrL0swsIsjdXJ8ITzI9vF01Bx7owVV7rtNOzK+mndm
+nqxpkCIHH2E6lr7lmk/MBTwoWdPBDFSoWWG9yHJM6Nyfh3+9nEg2XpWjDrk4JFX8
+dWbrAuMINClKxuMrLzOg2qOGpRKX/YAr2hRC45K9PvJdXmd0LhyIRyk0X+IyqJwl
+N4y6mACXi0mWHv0liqzc2thddG5msP9E36EYxr5ILzeUePiVSj9/E15dWf10hkNj
+c0kCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFJ84xFYjwznooHFs6FRM5Og6sb9nMA0GCSqGSIb3DQEBCwUAA4ICAQAS
+5UKme4sPDORGpbZgQIeMJX6tuGguW8ZAdjwD+MlZ9POrYs4QjbRaZIxowLByQzTS
+Gwv2LFPSypBLhmb8qoMi9IsabyZIrHZ3CL/FmFz0Jomee8O5ZDIBf9PD3Vht7LGr
+hFV0d4QEJ1JrhkzO3bll/9bGXp+aEJlLdWr+aumXIOTkdnrG0CSqkM0gkLpHZPt/
+B7NTeLUKYvJzQ85BK4FqLoUWlFPUa19yIqtRLULVAJyZv967lDtX/Zr1hstWO1uI
+AeV8KEsD+UmDfLJ/fOPtjqF/YFOOVZ1QNBIPt5d7bIdKROf1beyAN/BYGW5KaHbw
+H5Lk6rWS02FREAutp9lfx1/cH6NcjKF+m7ee01ZvZl4HliDtC3T7Zk6LERXpgUl+
+b7DUUH8i119lAg2m9IUe2K4GS0qn0jFmwvjO5QimpAKWRGhXxNUzzxkvFMSUHHuk
+2fCfDrGA4tGeEWSpiBE6doLlYsKA2KSD7ZPvfC+QsDJMlhVoSFLUmQjAJOgc47Ol
+IQ6SwJAfzyBfyjs4x7dtOvPmRLgOMWuIjnDrnBdSqEGULoe256YSxXXfW8AKbnuk
+5F6G+TaU33fD6Q3AOfF5u0aOq0NZJ7cguyPpVkAh7DE9ZapD8j3fcEThuk0mEDuY
+n/PIjhs4ViFqUZPTkcpG2om3PVODLAgfi49T3f+sHw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem
new file mode 100644
index 00000000000..b521c2817da
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem
@@ -0,0 +1,118 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 95:be:16:a0:f7:2e:46:f1:7b:39:82:72:fa:8b:cd:96
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: O = TeliaSonera, CN = TeliaSonera Root CA v1
+ Validity
+ Not Before: Oct 18 12:00:50 2007 GMT
+ Not After : Oct 18 12:00:50 2032 GMT
+ Subject: O = TeliaSonera, CN = TeliaSonera Root CA v1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:c2:be:eb:27:f0:21:a3:f3:69:26:55:7e:9d:c5:
+ 55:16:91:5c:fd:ef:21:bf:53:80:7a:2d:d2:91:8c:
+ 63:31:f0:ec:24:f0:c3:a5:d2:72:7c:10:6d:f4:37:
+ b7:e5:e6:7c:79:ea:8c:b5:82:8b:ae:48:b6:ac:00:
+ dc:65:75:ec:2a:4d:5f:c1:87:f5:20:65:2b:81:a8:
+ 47:3e:89:23:95:30:16:90:7f:e8:57:07:48:e7:19:
+ ae:bf:45:67:b1:37:1b:06:2a:fe:de:f9:ac:7d:83:
+ fb:5e:ba:e4:8f:97:67:be:4b:8e:8d:64:07:57:38:
+ 55:69:34:36:3d:13:48:ef:4f:e2:d3:66:1e:a4:cf:
+ 1a:b7:5e:36:33:d4:b4:06:bd:18:01:fd:77:84:50:
+ 00:45:f5:8c:5d:e8:23:bc:7e:fe:35:e1:ed:50:7b:
+ a9:30:8d:19:d3:09:8e:68:67:5d:bf:3c:97:18:53:
+ bb:29:62:c5:ca:5e:72:c1:c7:96:d4:db:2d:a0:b4:
+ 1f:69:03:ec:ea:e2:50:f1:0c:3c:f0:ac:f3:53:2d:
+ f0:1c:f5:ed:6c:39:39:73:80:16:c8:52:b0:23:cd:
+ e0:3e:dc:dd:3c:47:a0:bb:35:8a:e2:98:68:8b:be:
+ e5:bf:72:ee:d2:fa:a5:ed:12:ed:fc:98:18:a9:26:
+ 76:dc:28:4b:10:20:1c:d3:7f:16:77:2d:ed:6f:80:
+ f7:49:bb:53:05:bb:5d:68:c7:d4:c8:75:16:3f:89:
+ 5a:8b:f7:17:47:d4:4c:f1:d2:89:79:3e:4d:3d:98:
+ a8:61:de:3a:1e:d2:f8:5e:03:e0:c1:c9:1c:8c:d3:
+ 8d:4d:d3:95:36:b3:37:5f:63:63:9b:33:14:f0:2d:
+ 26:6b:53:7c:89:8c:32:c2:6e:ec:3d:21:00:39:c9:
+ a1:68:e2:50:83:2e:b0:3a:2b:f3:36:a0:ac:2f:e4:
+ 6f:61:c2:51:09:39:3e:8b:53:b9:bb:67:da:dc:53:
+ b9:76:59:36:9d:43:e5:20:e0:3d:32:60:85:22:51:
+ b7:c7:33:bb:dd:15:2f:a4:78:a6:07:7b:81:46:36:
+ 04:86:dd:79:35:c7:95:2c:3b:b0:a3:17:35:e5:73:
+ 1f:b4:5c:59:ef:da:ea:10:65:7b:7a:d0:7f:9f:b3:
+ b4:2a:37:3b:70:8b:9b:5b:b9:2b:b7:ec:b2:51:12:
+ 97:53:29:5a:d4:f0:12:10:dc:4f:02:bb:12:92:2f:
+ 62:d4:3f:69:43:7c:0d:d6:fc:58:75:01:88:9d:58:
+ 16:4b:de:ba:90:ff:47:01:89:06:6a:f6:5f:b2:90:
+ 6a:b3:02:a6:02:88:bf:b3:47:7e:2a:d9:d5:fa:68:
+ 78:35:4d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ F0:8F:59:38:00:B3:F5:8F:9A:96:0C:D5:EB:FA:7B:AA:17:E8:13:12
+ Signature Algorithm: sha1WithRSAEncryption
+ be:e4:5c:62:4e:24:f4:0c:08:ff:f0:d3:0c:68:e4:93:49:22:
+ 3f:44:27:6f:bb:6d:de:83:66:ce:a8:cc:0d:fc:f5:9a:06:e5:
+ 77:14:91:eb:9d:41:7b:99:2a:84:e5:ff:fc:21:c1:5d:f0:e4:
+ 1f:57:b7:75:a9:a1:5f:02:26:ff:d7:c7:f7:4e:de:4f:f8:f7:
+ 1c:46:c0:7a:4f:40:2c:22:35:f0:19:b1:d0:6b:67:2c:b0:a8:
+ e0:c0:40:37:35:f6:84:5c:5c:e3:af:42:78:fe:a7:c9:0d:50:
+ ea:0d:84:76:f6:51:ef:83:53:c6:7a:ff:0e:56:49:2e:8f:7a:
+ d6:0c:e6:27:54:e3:4d:0a:60:72:62:cd:91:07:d6:a5:bf:c8:
+ 99:6b:ed:c4:19:e6:ab:4c:11:38:c5:6f:31:e2:6e:49:c8:3f:
+ 76:80:26:03:26:29:e0:36:f6:f6:20:53:e3:17:70:34:17:9d:
+ 63:68:1e:6b:ec:c3:4d:86:b8:13:30:2f:5d:46:0d:47:43:d5:
+ 1b:aa:59:0e:b9:5c:8d:06:48:ad:74:87:5f:c7:fc:31:54:41:
+ 13:e2:c7:21:0e:9e:e0:1e:0d:e1:c0:7b:43:85:90:c5:8a:58:
+ c6:65:0a:78:57:f2:c6:23:0f:01:d9:20:4b:de:0f:fb:92:85:
+ 75:2a:5c:73:8d:6d:7b:25:91:ca:ee:45:ae:06:4b:00:cc:d3:
+ b1:59:50:da:3a:88:3b:29:43:46:5e:97:2b:54:ce:53:6f:8d:
+ 4a:e7:96:fa:bf:71:0e:42:8b:7c:fd:28:a0:d0:48:ca:da:c4:
+ 81:4c:bb:a2:73:93:26:c8:eb:0c:d6:26:88:b6:c0:24:cf:bb:
+ bd:5b:eb:75:7d:e9:08:8e:86:33:2c:79:77:09:69:a5:89:fc:
+ b3:70:90:87:76:8f:d3:22:bb:42:ce:bd:73:0b:20:26:2a:d0:
+ 9b:3d:70:1e:24:6c:cd:87:76:a9:17:96:b7:cf:0d:92:fb:8e:
+ 18:a9:98:49:d1:9e:fe:60:44:72:21:b9:19:ed:c2:f5:31:f1:
+ 39:48:88:90:24:75:54:16:ad:ce:f4:f8:69:14:64:39:fb:a3:
+ b8:ba:70:40:c7:27:1c:bf:c4:56:53:fa:63:65:d0:f3:1c:0e:
+ 16:f5:6b:86:58:4d:18:d4:e4:0d:8e:a5:9d:5b:91:dc:76:24:
+ 50:3f:c6:2a:fb:d9:b7:9c:b5:d6:e6:d0:d9:e8:19:8b:15:71:
+ 48:ad:b7:ea:d8:59:88:d4:90:bf:16:b3:d9:e9:ac:59:61:54:
+ c8:1c:ba:ca:c1:ca:e1:b9:20:4c:8f:3a:93:89:a5:a0:cc:bf:
+ d3:f6:75:a4:75:96:6d:56
+-----BEGIN CERTIFICATE-----
+MIIFODCCAyCgAwIBAgIRAJW+FqD3LkbxezmCcvqLzZYwDQYJKoZIhvcNAQEFBQAw
+NzEUMBIGA1UECgwLVGVsaWFTb25lcmExHzAdBgNVBAMMFlRlbGlhU29uZXJhIFJv
+b3QgQ0EgdjEwHhcNMDcxMDE4MTIwMDUwWhcNMzIxMDE4MTIwMDUwWjA3MRQwEgYD
+VQQKDAtUZWxpYVNvbmVyYTEfMB0GA1UEAwwWVGVsaWFTb25lcmEgUm9vdCBDQSB2
+MTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMK+6yfwIaPzaSZVfp3F
+VRaRXP3vIb9TgHot0pGMYzHw7CTww6XScnwQbfQ3t+XmfHnqjLWCi65ItqwA3GV1
+7CpNX8GH9SBlK4GoRz6JI5UwFpB/6FcHSOcZrr9FZ7E3GwYq/t75rH2D+1665I+X
+Z75Ljo1kB1c4VWk0Nj0TSO9P4tNmHqTPGrdeNjPUtAa9GAH9d4RQAEX1jF3oI7x+
+/jXh7VB7qTCNGdMJjmhnXb88lxhTuylixcpecsHHltTbLaC0H2kD7OriUPEMPPCs
+81Mt8Bz17Ww5OXOAFshSsCPN4D7c3TxHoLs1iuKYaIu+5b9y7tL6pe0S7fyYGKkm
+dtwoSxAgHNN/Fnct7W+A90m7UwW7XWjH1Mh1Fj+JWov3F0fUTPHSiXk+TT2YqGHe
+Oh7S+F4D4MHJHIzTjU3TlTazN19jY5szFPAtJmtTfImMMsJu7D0hADnJoWjiUIMu
+sDor8zagrC/kb2HCUQk5PotTubtn2txTuXZZNp1D5SDgPTJghSJRt8czu90VL6R4
+pgd7gUY2BIbdeTXHlSw7sKMXNeVzH7RcWe/a6hBle3rQf5+ztCo3O3CLm1u5K7fs
+slESl1MpWtTwEhDcTwK7EpIvYtQ/aUN8Ddb8WHUBiJ1YFkveupD/RwGJBmr2X7KQ
+arMCpgKIv7NHfirZ1fpoeDVNAgMBAAGjPzA9MA8GA1UdEwEB/wQFMAMBAf8wCwYD
+VR0PBAQDAgEGMB0GA1UdDgQWBBTwj1k4ALP1j5qWDNXr+nuqF+gTEjANBgkqhkiG
+9w0BAQUFAAOCAgEAvuRcYk4k9AwI//DTDGjkk0kiP0Qnb7tt3oNmzqjMDfz1mgbl
+dxSR651Be5kqhOX//CHBXfDkH1e3damhXwIm/9fH907eT/j3HEbAek9ALCI18Bmx
+0GtnLLCo4MBANzX2hFxc469CeP6nyQ1Q6g2EdvZR74NTxnr/DlZJLo961gzmJ1Tj
+TQpgcmLNkQfWpb/ImWvtxBnmq0wROMVvMeJuScg/doAmAyYp4Db29iBT4xdwNBed
+Y2gea+zDTYa4EzAvXUYNR0PVG6pZDrlcjQZIrXSHX8f8MVRBE+LHIQ6e4B4N4cB7
+Q4WQxYpYxmUKeFfyxiMPAdkgS94P+5KFdSpcc41teyWRyu5FrgZLAMzTsVlQ2jqI
+OylDRl6XK1TOU2+NSueW+r9xDkKLfP0ooNBIytrEgUy7onOTJsjrDNYmiLbAJM+7
+vVvrdX3pCI6GMyx5dwlppYn8s3CQh3aP0yK7Qs69cwsgJirQmz1wHiRszYd2qReW
+t88NkvuOGKmYSdGe/mBEciG5Ge3C9THxOUiIkCR1VBatzvT4aRRkOfujuLpwQMcn
+HL/EVlP6Y2XQ8xwOFvVrhlhNGNTkDY6lnVuR3HYkUD/GKvvZt5y11ubQ2egZixVx
+SK236thZiNSQvxaz2emsWWFUyBy6ysHK4bkgTI86k4mloMy/0/Z1pHWWbVY=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem
new file mode 100644
index 00000000000..0548e2eba85
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem
@@ -0,0 +1,119 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 92:b8:88:db:b0:8a:c1:63
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = SK, L = Bratislava, O = Disig a.s., CN = CA Disig Root R2
+ Validity
+ Not Before: Jul 19 09:15:30 2012 GMT
+ Not After : Jul 19 09:15:30 2042 GMT
+ Subject: C = SK, L = Bratislava, O = Disig a.s., CN = CA Disig Root R2
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a2:a3:c4:00:09:d6:85:5d:2d:6d:14:f6:c2:c3:
+ 73:9e:35:c2:71:55:7e:81:fb:ab:46:50:e0:c1:7c:
+ 49:78:e6:ab:79:58:3c:da:ff:7c:1c:9f:d8:97:02:
+ 78:3e:6b:41:04:e9:41:bd:be:03:2c:45:f6:2f:64:
+ d4:ab:5d:a3:47:3d:64:9b:e9:68:9a:c6:cc:1b:3f:
+ ba:be:b2:8b:34:02:2e:98:55:19:fc:8c:6f:aa:5f:
+ da:4c:ce:4d:03:21:a3:d8:d2:34:93:56:96:cb:4c:
+ 0c:00:16:3c:5f:1a:cd:c8:c7:6c:a6:ad:d3:31:a7:
+ bc:e8:e5:e1:66:d6:d2:fb:03:b4:41:65:c9:10:ae:
+ 0e:05:63:c6:80:6a:69:30:fd:d2:ee:90:ef:0d:27:
+ df:9f:95:73:f4:e1:25:da:6c:16:de:41:38:34:ea:
+ 8b:fc:d1:e8:04:14:61:2d:41:7e:ac:c7:77:4e:cb:
+ 51:54:fb:5e:92:18:1b:04:5a:68:c6:c9:c4:fa:b7:
+ 13:a0:98:b7:11:2b:b7:d6:57:cc:7c:9e:17:d1:cb:
+ 25:fe:86:4e:24:2e:56:0c:78:4d:9e:01:12:a6:2b:
+ a7:01:65:6e:7c:62:1d:84:84:df:ea:c0:6b:b5:a5:
+ 2a:95:83:c3:53:11:0c:73:1d:0b:b2:46:90:d1:42:
+ 3a:ce:40:6e:95:ad:ff:c6:94:ad:6e:97:84:8e:7d:
+ 6f:9e:8a:80:0d:49:6d:73:e2:7b:92:1e:c3:f3:c1:
+ f3:eb:2e:05:6f:d9:1b:cf:37:76:04:c8:b4:5a:e4:
+ 17:a7:cb:dd:76:1f:d0:19:76:e8:2c:05:b3:d6:9c:
+ 34:d8:96:dc:61:87:91:05:e4:44:08:33:c1:da:b9:
+ 08:65:d4:ae:b2:36:0d:eb:ba:38:ba:0c:e5:9b:9e:
+ eb:8d:66:dd:99:cf:d6:89:41:f6:04:92:8a:29:29:
+ 6d:6b:3a:1c:e7:75:7d:02:71:0e:f3:c0:e7:bd:cb:
+ 19:dd:9d:60:b2:c2:66:60:b6:b1:04:ee:c9:e6:86:
+ b9:9a:66:40:a8:e7:11:ed:81:45:03:8b:f6:67:59:
+ e8:c1:06:11:bd:dd:cf:80:02:4f:65:40:78:5c:47:
+ 50:c8:9b:e6:1f:81:7b:e4:44:a8:5b:85:9a:e2:de:
+ 5a:d5:c7:f9:3a:44:66:4b:e4:32:54:7c:e4:6c:9c:
+ b3:0e:3d:17:a2:b2:34:12:d6:7e:b2:a8:49:bb:d1:
+ 7a:28:40:be:a2:16:1f:df:e4:37:1f:11:73:fb:90:
+ 0a:65:43:a2:0d:7c:f8:06:01:55:33:7d:b0:0d:b8:
+ f4:f5:ae:a5:42:57:7c:36:11:8c:7b:5e:c4:03:9d:
+ 8c:79:9d
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B5:99:F8:AF:B0:94:F5:E3:20:D6:0A:AD:CE:4E:56:A4:2E:6E:42:ED
+ Signature Algorithm: sha256WithRSAEncryption
+ 26:06:5e:70:e7:65:33:c8:82:6e:d9:9c:17:3a:1b:7a:66:b2:
+ 01:f6:78:3b:69:5e:2f:ea:ff:4e:f9:28:c3:98:2a:61:4c:b4:
+ 24:12:8a:7d:6d:11:14:f7:9c:b5:ca:e6:bc:9e:27:8e:4c:19:
+ c8:a9:bd:7a:c0:d7:36:0e:6d:85:72:6e:a8:c6:a2:6d:f6:fa:
+ 73:63:7f:bc:6e:79:08:1c:9d:8a:9f:1a:8a:53:a6:d8:bb:d9:
+ 35:55:b1:11:c5:a9:03:b3:56:3b:b9:84:93:22:5e:7e:c1:f6:
+ 12:52:8b:ea:2c:67:bc:fe:36:4c:f5:b8:cf:d1:b3:49:92:3b:
+ d3:29:0e:99:1b:96:f7:61:b8:3b:c4:2b:b6:78:6c:b4:23:6f:
+ f0:fd:d3:b2:5e:75:1f:99:95:a8:ac:f6:da:e1:c5:31:7b:fb:
+ d1:46:b3:d2:bc:67:b4:62:54:ba:09:f7:63:b0:93:a2:9a:f9:
+ e9:52:2e:8b:60:12:ab:fc:f5:60:56:ef:10:5c:8b:c4:1a:42:
+ dc:83:5b:64:0e:cb:b5:bc:d6:4f:c1:7c:3c:6e:8d:13:6d:fb:
+ 7b:eb:30:d0:dc:4d:af:c5:d5:b6:a5:4c:5b:71:c9:e8:31:be:
+ e8:38:06:48:a1:1a:e2:ea:d2:de:12:39:58:1a:ff:80:0e:82:
+ 75:e6:b7:c9:07:6c:0e:ef:ff:38:f1:98:71:c4:b7:7f:0e:15:
+ d0:25:69:bd:22:9d:2b:ed:05:f6:46:47:ac:ed:c0:f0:d4:3b:
+ e2:ec:ee:96:5b:90:13:4e:1e:56:3a:eb:b0:ef:96:bb:96:23:
+ 11:ba:f2:43:86:74:64:95:c8:28:75:df:1d:35:ba:d2:37:83:
+ 38:53:38:36:3b:cf:6c:e9:f9:6b:0e:d0:fb:04:e8:4f:77:d7:
+ 65:01:78:86:0c:7a:3e:21:62:f1:7f:63:71:0c:c9:9f:44:db:
+ a8:27:a2:75:be:6e:81:3e:d7:c0:eb:1b:98:0f:70:5c:34:b2:
+ 8a:cc:c0:85:18:eb:6e:7a:b3:f7:5a:a1:07:bf:a9:42:92:f3:
+ 60:22:97:e4:14:a1:07:9b:4e:76:c0:8e:7d:fd:a4:25:c7:47:
+ ed:ff:1f:73:ac:cc:c3:a5:e9:6f:0a:8e:9b:65:c2:50:85:b5:
+ a3:a0:53:12:cc:55:87:61:f3:81:ae:10:46:61:bd:44:21:b8:
+ c2:3d:74:cf:7e:24:35:fa:1c:07:0e:9b:3d:22:ca:ef:31:2f:
+ 8c:ac:12:bd:ef:40:28:fc:29:67:9f:b2:13:4f:66:24:c4:53:
+ 19:e9:1e:29:15:ef:e6:6d:b0:7f:2d:67:fd:f3:6c:1b:75:46:
+ a3:e5:4a:17:e9:a4:d7:0b
+-----BEGIN CERTIFICATE-----
+MIIFaTCCA1GgAwIBAgIJAJK4iNuwisFjMA0GCSqGSIb3DQEBCwUAMFIxCzAJBgNV
+BAYTAlNLMRMwEQYDVQQHEwpCcmF0aXNsYXZhMRMwEQYDVQQKEwpEaXNpZyBhLnMu
+MRkwFwYDVQQDExBDQSBEaXNpZyBSb290IFIyMB4XDTEyMDcxOTA5MTUzMFoXDTQy
+MDcxOTA5MTUzMFowUjELMAkGA1UEBhMCU0sxEzARBgNVBAcTCkJyYXRpc2xhdmEx
+EzARBgNVBAoTCkRpc2lnIGEucy4xGTAXBgNVBAMTEENBIERpc2lnIFJvb3QgUjIw
+ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCio8QACdaFXS1tFPbCw3Oe
+NcJxVX6B+6tGUODBfEl45qt5WDza/3wcn9iXAng+a0EE6UG9vgMsRfYvZNSrXaNH
+PWSb6WiaxswbP7q+sos0Ai6YVRn8jG+qX9pMzk0DIaPY0jSTVpbLTAwAFjxfGs3I
+x2ymrdMxp7zo5eFm1tL7A7RBZckQrg4FY8aAamkw/dLukO8NJ9+flXP04SXabBbe
+QTg06ov80egEFGEtQX6sx3dOy1FU+16SGBsEWmjGycT6txOgmLcRK7fWV8x8nhfR
+yyX+hk4kLlYMeE2eARKmK6cBZW58Yh2EhN/qwGu1pSqVg8NTEQxzHQuyRpDRQjrO
+QG6Vrf/GlK1ul4SOfW+eioANSW1z4nuSHsPzwfPrLgVv2RvPN3YEyLRa5Beny912
+H9AZdugsBbPWnDTYltxhh5EF5EQIM8HauQhl1K6yNg3ruji6DOWbnuuNZt2Zz9aJ
+QfYEkoopKW1rOhzndX0CcQ7zwOe9yxndnWCywmZgtrEE7snmhrmaZkCo5xHtgUUD
+i/ZnWejBBhG93c+AAk9lQHhcR1DIm+YfgXvkRKhbhZri3lrVx/k6RGZL5DJUfORs
+nLMOPReisjQS1n6yqEm70XooQL6iFh/f5DcfEXP7kAplQ6INfPgGAVUzfbANuPT1
+rqVCV3w2EYx7XsQDnYx5nQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUtZn4r7CU9eMg1gqtzk5WpC5uQu0wDQYJKoZI
+hvcNAQELBQADggIBACYGXnDnZTPIgm7ZnBc6G3pmsgH2eDtpXi/q/075KMOYKmFM
+tCQSin1tERT3nLXK5ryeJ45MGcipvXrA1zYObYVybqjGom32+nNjf7xueQgcnYqf
+GopTpti72TVVsRHFqQOzVju5hJMiXn7B9hJSi+osZ7z+Nkz1uM/Rs0mSO9MpDpkb
+lvdhuDvEK7Z4bLQjb/D907JedR+Zlais9trhxTF7+9FGs9K8Z7RiVLoJ92Owk6Ka
++elSLotgEqv89WBW7xBci8QaQtyDW2QOy7W81k/BfDxujRNt+3vrMNDcTa/F1bal
+TFtxyegxvug4BkihGuLq0t4SOVga/4AOgnXmt8kHbA7v/zjxmHHEt38OFdAlab0i
+nSvtBfZGR6ztwPDUO+Ls7pZbkBNOHlY667DvlruWIxG68kOGdGSVyCh13x01utI3
+gzhTODY7z2zp+WsO0PsE6E9312UBeIYMej4hYvF/Y3EMyZ9E26gnonW+boE+18Dr
+G5gPcFw0sorMwIUY6256s/daoQe/qUKS82Ail+QUoQebTnbAjn39pCXHR+3/H3Os
+zMOl6W8KjptlwlCFtaOgUxLMVYdh84GuEEZhvUQhuMI9dM9+JDX6HAcOmz0iyu8x
+L4ysEr3vQCj8KWefshNPZiTEUxnpHikV7+ZtsH8tZ/3zbBt1RqPlShfppNcL
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem
new file mode 100644
index 00000000000..10390b2675f
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem
@@ -0,0 +1,51 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 06:6c:9f:d7:c1:bb:10:4c:29:43:e5:71:7b:7b:2c:c8:1a:c1:0e
+ Signature Algorithm: ecdsa-with-SHA384
+ Issuer: C = US, O = Amazon, CN = Amazon Root CA 4
+ Validity
+ Not Before: May 26 00:00:00 2015 GMT
+ Not After : May 26 00:00:00 2040 GMT
+ Subject: C = US, O = Amazon, CN = Amazon Root CA 4
+ Subject Public Key Info:
+ Public Key Algorithm: id-ecPublicKey
+ Public-Key: (384 bit)
+ pub:
+ 04:d2:ab:8a:37:4f:a3:53:0d:fe:c1:8a:7b:4b:a8:
+ 7b:46:4b:63:b0:62:f6:2d:1b:db:08:71:21:d2:00:
+ e8:63:bd:9a:27:fb:f0:39:6e:5d:ea:3d:a5:c9:81:
+ aa:a3:5b:20:98:45:5d:16:db:fd:e8:10:6d:e3:9c:
+ e0:e3:bd:5f:84:62:f3:70:64:33:a0:cb:24:2f:70:
+ ba:88:a1:2a:a0:75:f8:81:ae:62:06:c4:81:db:39:
+ 6e:29:b0:1e:fa:2e:5c
+ ASN1 OID: secp384r1
+ NIST CURVE: P-384
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ D3:EC:C7:3A:65:6E:CC:E1:DA:76:9A:56:FB:9C:F3:86:6D:57:E5:81
+ Signature Algorithm: ecdsa-with-SHA384
+ 30:65:02:30:3a:8b:21:f1:bd:7e:11:ad:d0:ef:58:96:2f:d6:
+ eb:9d:7e:90:8d:2b:cf:66:55:c3:2c:e3:28:a9:70:0a:47:0e:
+ f0:37:59:12:ff:2d:99:94:28:4e:2a:4f:35:4d:33:5a:02:31:
+ 00:ea:75:00:4e:3b:c4:3a:94:12:91:c9:58:46:9d:21:13:72:
+ a7:88:9c:8a:e4:4c:4a:db:96:d4:ac:8b:6b:6b:49:12:53:33:
+ ad:d7:e4:be:24:fc:b5:0a:76:d4:a5:bc:10
+-----BEGIN CERTIFICATE-----
+MIIB8jCCAXigAwIBAgITBmyf18G7EEwpQ+Vxe3ssyBrBDjAKBggqhkjOPQQDAzA5
+MQswCQYDVQQGEwJVUzEPMA0GA1UEChMGQW1hem9uMRkwFwYDVQQDExBBbWF6b24g
+Um9vdCBDQSA0MB4XDTE1MDUyNjAwMDAwMFoXDTQwMDUyNjAwMDAwMFowOTELMAkG
+A1UEBhMCVVMxDzANBgNVBAoTBkFtYXpvbjEZMBcGA1UEAxMQQW1hem9uIFJvb3Qg
+Q0EgNDB2MBAGByqGSM49AgEGBSuBBAAiA2IABNKrijdPo1MN/sGKe0uoe0ZLY7Bi
+9i0b2whxIdIA6GO9mif78DluXeo9pcmBqqNbIJhFXRbb/egQbeOc4OO9X4Ri83Bk
+M6DLJC9wuoihKqB1+IGuYgbEgds5bimwHvouXKNCMEAwDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFNPsxzplbszh2naaVvuc84ZtV+WB
+MAoGCCqGSM49BAMDA2gAMGUCMDqLIfG9fhGt0O9Yli/W651+kI0rz2ZVwyzjKKlw
+CkcO8DdZEv8tmZQoTipPNU0zWgIxAOp1AE47xDqUEpHJWEadIRNyp4iciuRMStuW
+1KyLa2tJElMzrdfkviT8tQp21KW8EA==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem
new file mode 100644
index 00000000000..d41f9a76719
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem
@@ -0,0 +1,86 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ fe:dc:e3:01:0f:c9:48:ff
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = FR, O = Dhimyotis, CN = Certigna
+ Validity
+ Not Before: Jun 29 15:13:05 2007 GMT
+ Not After : Jun 29 15:13:05 2027 GMT
+ Subject: C = FR, O = Dhimyotis, CN = Certigna
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:c8:68:f1:c9:d6:d6:b3:34:75:26:82:1e:ec:b4:
+ be:ea:5c:e1:26:ed:11:47:61:e1:a2:7c:16:78:40:
+ 21:e4:60:9e:5a:c8:63:e1:c4:b1:96:92:ff:18:6d:
+ 69:23:e1:2b:62:f7:dd:e2:36:2f:91:07:b9:48:cf:
+ 0e:ec:79:b6:2c:e7:34:4b:70:08:25:a3:3c:87:1b:
+ 19:f2:81:07:0f:38:90:19:d3:11:fe:86:b4:f2:d1:
+ 5e:1e:1e:96:cd:80:6c:ce:3b:31:93:b6:f2:a0:d0:
+ a9:95:12:7d:a5:9a:cc:6b:c8:84:56:8a:33:a9:e7:
+ 22:15:53:16:f0:cc:17:ec:57:5f:e9:a2:0a:98:09:
+ de:e3:5f:9c:6f:dc:48:e3:85:0b:15:5a:a6:ba:9f:
+ ac:48:e3:09:b2:f7:f4:32:de:5e:34:be:1c:78:5d:
+ 42:5b:ce:0e:22:8f:4d:90:d7:7d:32:18:b3:0b:2c:
+ 6a:bf:8e:3f:14:11:89:20:0e:77:14:b5:3d:94:08:
+ 87:f7:25:1e:d5:b2:60:00:ec:6f:2a:28:25:6e:2a:
+ 3e:18:63:17:25:3f:3e:44:20:16:f6:26:c8:25:ae:
+ 05:4a:b4:e7:63:2c:f3:8c:16:53:7e:5c:fb:11:1a:
+ 08:c1:46:62:9f:22:b8:f1:c2:8d:69:dc:fa:3a:58:
+ 06:df
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11
+ X509v3 Authority Key Identifier:
+ keyid:1A:ED:FE:41:39:90:B4:24:59:BE:01:F2:52:D5:45:F6:5A:39:DC:11
+ DirName:/C=FR/O=Dhimyotis/CN=Certigna
+ serial:FE:DC:E3:01:0F:C9:48:FF
+
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Netscape Cert Type:
+ SSL CA, S/MIME CA, Object Signing CA
+ Signature Algorithm: sha1WithRSAEncryption
+ 85:03:1e:92:71:f6:42:af:e1:a3:61:9e:eb:f3:c0:0f:f2:a5:
+ d4:da:95:e6:d6:be:68:36:3d:7e:6e:1f:4c:8a:ef:d1:0f:21:
+ 6d:5e:a5:52:63:ce:12:f8:ef:2a:da:6f:eb:37:fe:13:02:c7:
+ cb:3b:3e:22:6b:da:61:2e:7f:d4:72:3d:dd:30:e1:1e:4c:40:
+ 19:8c:0f:d7:9c:d1:83:30:7b:98:59:dc:7d:c6:b9:0c:29:4c:
+ a1:33:a2:eb:67:3a:65:84:d3:96:e2:ed:76:45:70:8f:b5:2b:
+ de:f9:23:d6:49:6e:3c:14:b5:c6:9f:35:1e:50:d0:c1:8f:6a:
+ 70:44:02:62:cb:ae:1d:68:41:a7:aa:57:e8:53:aa:07:d2:06:
+ f6:d5:14:06:0b:91:03:75:2c:6c:72:b5:61:95:9a:0d:8b:b9:
+ 0d:e7:f5:df:54:cd:de:e6:d8:d6:09:08:97:63:e5:c1:2e:b0:
+ b7:44:26:c0:26:c0:af:55:30:9e:3b:d5:36:2a:19:04:f4:5c:
+ 1e:ff:cf:2c:b7:ff:d0:fd:87:40:11:d5:11:23:bb:48:c0:21:
+ a9:a4:28:2d:fd:15:f8:b0:4e:2b:f4:30:5b:21:fc:11:91:34:
+ be:41:ef:7b:9d:97:75:ff:97:95:c0:96:58:2f:ea:bb:46:d7:
+ bb:e4:d9:2e
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
+BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
+DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
+BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
+QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
+gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
+zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
+130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
+JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
+DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
+ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
+AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
+AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
+9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
+bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
+fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
+HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
+t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem
new file mode 100644
index 00000000000..55a57c81fad
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem
@@ -0,0 +1,76 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 0 (0x0)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = JP, O = SECOM Trust.net, OU = Security Communication RootCA1
+ Validity
+ Not Before: Sep 30 04:20:49 2003 GMT
+ Not After : Sep 30 04:20:49 2023 GMT
+ Subject: C = JP, O = SECOM Trust.net, OU = Security Communication RootCA1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b3:b3:fe:7f:d3:6d:b1:ef:16:7c:57:a5:0c:6d:
+ 76:8a:2f:4b:bf:64:fb:4c:ee:8a:f0:f3:29:7c:f5:
+ ff:ee:2a:e0:e9:e9:ba:5b:64:22:9a:9a:6f:2c:3a:
+ 26:69:51:05:99:26:dc:d5:1c:6a:71:c6:9a:7d:1e:
+ 9d:dd:7c:6c:c6:8c:67:67:4a:3e:f8:71:b0:19:27:
+ a9:09:0c:a6:95:bf:4b:8c:0c:fa:55:98:3b:d8:e8:
+ 22:a1:4b:71:38:79:ac:97:92:69:b3:89:7e:ea:21:
+ 68:06:98:14:96:87:d2:61:36:bc:6d:27:56:9e:57:
+ ee:c0:c0:56:fd:32:cf:a4:d9:8e:c2:23:d7:8d:a8:
+ f3:d8:25:ac:97:e4:70:38:f4:b6:3a:b4:9d:3b:97:
+ 26:43:a3:a1:bc:49:59:72:4c:23:30:87:01:58:f6:
+ 4e:be:1c:68:56:66:af:cd:41:5d:c8:b3:4d:2a:55:
+ 46:ab:1f:da:1e:e2:40:3d:db:cd:7d:b9:92:80:9c:
+ 37:dd:0c:96:64:9d:dc:22:f7:64:8b:df:61:de:15:
+ 94:52:15:a0:7d:52:c9:4b:a8:21:c9:c6:b1:ed:cb:
+ c3:95:60:d1:0f:f0:ab:70:f8:df:cb:4d:7e:ec:d6:
+ fa:ab:d9:bd:7f:54:f2:a5:e9:79:fa:d9:d6:76:24:
+ 28:73
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A0:73:49:99:68:DC:85:5B:65:E3:9B:28:2F:57:9F:BD:33:BC:07:48
+ X509v3 Key Usage:
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha1WithRSAEncryption
+ 68:40:a9:a8:bb:e4:4f:5d:79:b3:05:b5:17:b3:60:13:eb:c6:
+ 92:5d:e0:d1:d3:6a:fe:fb:be:9b:6d:bf:c7:05:6d:59:20:c4:
+ 1c:f0:b7:da:84:58:02:63:fa:48:16:ef:4f:a5:0b:f7:4a:98:
+ f2:3f:9e:1b:ad:47:6b:63:ce:08:47:eb:52:3f:78:9c:af:4d:
+ ae:f8:d5:4f:cf:9a:98:2a:10:41:39:52:c4:dd:d9:9b:0e:ef:
+ 93:01:ae:b2:2e:ca:68:42:24:42:6c:b0:b3:3a:3e:cd:e9:da:
+ 48:c4:15:cb:e9:f9:07:0f:92:50:49:8a:dd:31:97:5f:c9:e9:
+ 37:aa:3b:59:65:97:94:32:c9:b3:9f:3e:3a:62:58:c5:49:ad:
+ 62:0e:71:a5:32:aa:2f:c6:89:76:43:40:13:13:67:3d:a2:54:
+ 25:10:cb:f1:3a:f2:d9:fa:db:49:56:bb:a6:fe:a7:41:35:c3:
+ e0:88:61:c9:88:c7:df:36:10:22:98:59:ea:b0:4a:fb:56:16:
+ 73:6e:ac:4d:f7:22:a1:4f:ad:1d:7a:2d:45:27:e5:30:c1:5e:
+ f2:da:13:cb:25:42:51:95:47:03:8c:6c:21:cc:74:42:ed:53:
+ ff:33:8b:8f:0f:57:01:16:2f:cf:a6:ee:c9:70:22:14:bd:fd:
+ be:6c:0b:03
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
+MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
+dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
+WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
+VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
+9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
+DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
+Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
+QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
+xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
+A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
+AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
+kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
+Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
+Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
+JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
+RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem
new file mode 100644
index 00000000000..903e945a7e6
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem
@@ -0,0 +1,122 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 01:fd:6d:30:fc:a3:ca:51:a8:1b:bc:64:0e:35:03:2d
+ Signature Algorithm: sha384WithRSAEncryption
+ Issuer: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
+ Validity
+ Not Before: Feb 1 00:00:00 2010 GMT
+ Not After : Jan 18 23:59:59 2038 GMT
+ Subject: C = US, ST = New Jersey, L = Jersey City, O = The USERTRUST Network, CN = USERTrust RSA Certification Authority
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:80:12:65:17:36:0e:c3:db:08:b3:d0:ac:57:0d:
+ 76:ed:cd:27:d3:4c:ad:50:83:61:e2:aa:20:4d:09:
+ 2d:64:09:dc:ce:89:9f:cc:3d:a9:ec:f6:cf:c1:dc:
+ f1:d3:b1:d6:7b:37:28:11:2b:47:da:39:c6:bc:3a:
+ 19:b4:5f:a6:bd:7d:9d:a3:63:42:b6:76:f2:a9:3b:
+ 2b:91:f8:e2:6f:d0:ec:16:20:90:09:3e:e2:e8:74:
+ c9:18:b4:91:d4:62:64:db:7f:a3:06:f1:88:18:6a:
+ 90:22:3c:bc:fe:13:f0:87:14:7b:f6:e4:1f:8e:d4:
+ e4:51:c6:11:67:46:08:51:cb:86:14:54:3f:bc:33:
+ fe:7e:6c:9c:ff:16:9d:18:bd:51:8e:35:a6:a7:66:
+ c8:72:67:db:21:66:b1:d4:9b:78:03:c0:50:3a:e8:
+ cc:f0:dc:bc:9e:4c:fe:af:05:96:35:1f:57:5a:b7:
+ ff:ce:f9:3d:b7:2c:b6:f6:54:dd:c8:e7:12:3a:4d:
+ ae:4c:8a:b7:5c:9a:b4:b7:20:3d:ca:7f:22:34:ae:
+ 7e:3b:68:66:01:44:e7:01:4e:46:53:9b:33:60:f7:
+ 94:be:53:37:90:73:43:f3:32:c3:53:ef:db:aa:fe:
+ 74:4e:69:c7:6b:8c:60:93:de:c4:c7:0c:df:e1:32:
+ ae:cc:93:3b:51:78:95:67:8b:ee:3d:56:fe:0c:d0:
+ 69:0f:1b:0f:f3:25:26:6b:33:6d:f7:6e:47:fa:73:
+ 43:e5:7e:0e:a5:66:b1:29:7c:32:84:63:55:89:c4:
+ 0d:c1:93:54:30:19:13:ac:d3:7d:37:a7:eb:5d:3a:
+ 6c:35:5c:db:41:d7:12:da:a9:49:0b:df:d8:80:8a:
+ 09:93:62:8e:b5:66:cf:25:88:cd:84:b8:b1:3f:a4:
+ 39:0f:d9:02:9e:eb:12:4c:95:7c:f3:6b:05:a9:5e:
+ 16:83:cc:b8:67:e2:e8:13:9d:cc:5b:82:d3:4c:b3:
+ ed:5b:ff:de:e5:73:ac:23:3b:2d:00:bf:35:55:74:
+ 09:49:d8:49:58:1a:7f:92:36:e6:51:92:0e:f3:26:
+ 7d:1c:4d:17:bc:c9:ec:43:26:d0:bf:41:5f:40:a9:
+ 44:44:f4:99:e7:57:87:9e:50:1f:57:54:a8:3e:fd:
+ 74:63:2f:b1:50:65:09:e6:58:42:2e:43:1a:4c:b4:
+ f0:25:47:59:fa:04:1e:93:d4:26:46:4a:50:81:b2:
+ de:be:78:b7:fc:67:15:e1:c9:57:84:1e:0f:63:d6:
+ e9:62:ba:d6:5f:55:2e:ea:5c:c6:28:08:04:25:39:
+ b8:0e:2b:a9:f2:4c:97:1c:07:3f:0d:52:f5:ed:ef:
+ 2f:82:0f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ 53:79:BF:5A:AA:2B:4A:CF:54:80:E1:D8:9B:C0:9D:F2:B2:03:66:CB
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ Signature Algorithm: sha384WithRSAEncryption
+ 5c:d4:7c:0d:cf:f7:01:7d:41:99:65:0c:73:c5:52:9f:cb:f8:
+ cf:99:06:7f:1b:da:43:15:9f:9e:02:55:57:96:14:f1:52:3c:
+ 27:87:94:28:ed:1f:3a:01:37:a2:76:fc:53:50:c0:84:9b:c6:
+ 6b:4e:ba:8c:21:4f:a2:8e:55:62:91:f3:69:15:d8:bc:88:e3:
+ c4:aa:0b:fd:ef:a8:e9:4b:55:2a:06:20:6d:55:78:29:19:ee:
+ 5f:30:5c:4b:24:11:55:ff:24:9a:6e:5e:2a:2b:ee:0b:4d:9f:
+ 7f:f7:01:38:94:14:95:43:07:09:fb:60:a9:ee:1c:ab:12:8c:
+ a0:9a:5e:a7:98:6a:59:6d:8b:3f:08:fb:c8:d1:45:af:18:15:
+ 64:90:12:0f:73:28:2e:c5:e2:24:4e:fc:58:ec:f0:f4:45:fe:
+ 22:b3:eb:2f:8e:d2:d9:45:61:05:c1:97:6f:a8:76:72:8f:8b:
+ 8c:36:af:bf:0d:05:ce:71:8d:e6:a6:6f:1f:6c:a6:71:62:c5:
+ d8:d0:83:72:0c:f1:67:11:89:0c:9c:13:4c:72:34:df:bc:d5:
+ 71:df:aa:71:dd:e1:b9:6c:8c:3c:12:5d:65:da:bd:57:12:b6:
+ 43:6b:ff:e5:de:4d:66:11:51:cf:99:ae:ec:17:b6:e8:71:91:
+ 8c:de:49:fe:dd:35:71:a2:15:27:94:1c:cf:61:e3:26:bb:6f:
+ a3:67:25:21:5d:e6:dd:1d:0b:2e:68:1b:3b:82:af:ec:83:67:
+ 85:d4:98:51:74:b1:b9:99:80:89:ff:7f:78:19:5c:79:4a:60:
+ 2e:92:40:ae:4c:37:2a:2c:c9:c7:62:c8:0e:5d:f7:36:5b:ca:
+ e0:25:25:01:b4:dd:1a:07:9c:77:00:3f:d0:dc:d5:ec:3d:d4:
+ fa:bb:3f:cc:85:d6:6f:7f:a9:2d:df:b9:02:f7:f5:97:9a:b5:
+ 35:da:c3:67:b0:87:4a:a9:28:9e:23:8e:ff:5c:27:6b:e1:b0:
+ 4f:f3:07:ee:00:2e:d4:59:87:cb:52:41:95:ea:f4:47:d7:ee:
+ 64:41:55:7c:8d:59:02:95:dd:62:9d:c2:b9:ee:5a:28:74:84:
+ a5:9b:b7:90:c7:0c:07:df:f5:89:36:74:32:d6:28:c1:b0:b0:
+ 0b:e0:9c:4c:c3:1c:d6:fc:e3:69:b5:47:46:81:2f:a2:82:ab:
+ d3:63:44:70:c4:8d:ff:2d:33:ba:ad:8f:7b:b5:70:88:ae:3e:
+ 19:cf:40:28:d8:fc:c8:90:bb:5d:99:22:f5:52:e6:58:c5:1f:
+ 88:31:43:ee:88:1d:d7:c6:8e:3c:43:6a:1d:a7:18:de:7d:3d:
+ 16:f1:62:f9:ca:90:a8:fd
+-----BEGIN CERTIFICATE-----
+MIIF3jCCA8agAwIBAgIQAf1tMPyjylGoG7xkDjUDLTANBgkqhkiG9w0BAQwFADCB
+iDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0pl
+cnNleSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNV
+BAMTJVVTRVJUcnVzdCBSU0EgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMTAw
+MjAxMDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBiDELMAkGA1UEBhMCVVMxEzARBgNV
+BAgTCk5ldyBKZXJzZXkxFDASBgNVBAcTC0plcnNleSBDaXR5MR4wHAYDVQQKExVU
+aGUgVVNFUlRSVVNUIE5ldHdvcmsxLjAsBgNVBAMTJVVTRVJUcnVzdCBSU0EgQ2Vy
+dGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIK
+AoICAQCAEmUXNg7D2wiz0KxXDXbtzSfTTK1Qg2HiqiBNCS1kCdzOiZ/MPans9s/B
+3PHTsdZ7NygRK0faOca8Ohm0X6a9fZ2jY0K2dvKpOyuR+OJv0OwWIJAJPuLodMkY
+tJHUYmTbf6MG8YgYapAiPLz+E/CHFHv25B+O1ORRxhFnRghRy4YUVD+8M/5+bJz/
+Fp0YvVGONaanZshyZ9shZrHUm3gDwFA66Mzw3LyeTP6vBZY1H1dat//O+T23LLb2
+VN3I5xI6Ta5MirdcmrS3ID3KfyI0rn47aGYBROcBTkZTmzNg95S+UzeQc0PzMsNT
+79uq/nROacdrjGCT3sTHDN/hMq7MkztReJVni+49Vv4M0GkPGw/zJSZrM233bkf6
+c0Plfg6lZrEpfDKEY1WJxA3Bk1QwGROs0303p+tdOmw1XNtB1xLaqUkL39iAigmT
+Yo61Zs8liM2EuLE/pDkP2QKe6xJMlXzzawWpXhaDzLhn4ugTncxbgtNMs+1b/97l
+c6wjOy0AvzVVdAlJ2ElYGn+SNuZRkg7zJn0cTRe8yexDJtC/QV9AqURE9JnnV4ee
+UB9XVKg+/XRjL7FQZQnmWEIuQxpMtPAlR1n6BB6T1CZGSlCBst6+eLf8ZxXhyVeE
+Hg9j1uliutZfVS7qXMYoCAQlObgOK6nyTJccBz8NUvXt7y+CDwIDAQABo0IwQDAd
+BgNVHQ4EFgQUU3m/WqorSs9UgOHYm8Cd8rIDZsswDgYDVR0PAQH/BAQDAgEGMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEMBQADggIBAFzUfA3P9wF9QZllDHPF
+Up/L+M+ZBn8b2kMVn54CVVeWFPFSPCeHlCjtHzoBN6J2/FNQwISbxmtOuowhT6KO
+VWKR82kV2LyI48SqC/3vqOlLVSoGIG1VeCkZ7l8wXEskEVX/JJpuXior7gtNn3/3
+ATiUFJVDBwn7YKnuHKsSjKCaXqeYalltiz8I+8jRRa8YFWSQEg9zKC7F4iRO/Fjs
+8PRF/iKz6y+O0tlFYQXBl2+odnKPi4w2r78NBc5xjeambx9spnFixdjQg3IM8WcR
+iQycE0xyNN+81XHfqnHd4blsjDwSXWXavVcStkNr/+XeTWYRUc+ZruwXtuhxkYze
+Sf7dNXGiFSeUHM9h4ya7b6NnJSFd5t0dCy5oGzuCr+yDZ4XUmFF0sbmZgIn/f3gZ
+XHlKYC6SQK5MNyosycdiyA5d9zZbyuAlJQG03RoHnHcAP9Dc1ew91Pq7P8yF1m9/
+qS3fuQL39ZeatTXaw2ewh0qpKJ4jjv9cJ2vhsE/zB+4ALtRZh8tSQZXq9EfX7mRB
+VXyNWQKV3WKdwrnuWih0hKWbt5DHDAff9Yk2dDLWKMGwsAvgnEzDHNb842m1R0aB
+L6KCq9NjRHDEjf8tM7qtj3u1cIiuPhnPQCjY/MiQu12ZIvVS5ljFH4gxQ+6IHdfG
+jjxDah2nGN59PRbxYvnKkKj9
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem
new file mode 100644
index 00000000000..31c0f6f281d
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem
@@ -0,0 +1,76 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 35210227249154 (0x200605167002)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = RO, O = certSIGN, OU = certSIGN ROOT CA
+ Validity
+ Not Before: Jul 4 17:20:04 2006 GMT
+ Not After : Jul 4 17:20:04 2031 GMT
+ Subject: C = RO, O = certSIGN, OU = certSIGN ROOT CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:b7:33:b9:7e:c8:25:4a:8e:b5:db:b4:28:1b:aa:
+ 57:90:e8:d1:22:d3:64:ba:d3:93:e8:d4:ac:86:61:
+ 40:6a:60:57:68:54:84:4d:bc:6a:54:02:05:ff:df:
+ 9b:9a:2a:ae:5d:07:8f:4a:c3:28:7f:ef:fb:2b:fa:
+ 79:f1:c7:ad:f0:10:53:24:90:8b:66:c9:a8:88:ab:
+ af:5a:a3:00:e9:be:ba:46:ee:5b:73:7b:2c:17:82:
+ 81:5e:62:2c:a1:02:65:b3:bd:c5:2b:00:7e:c4:fc:
+ 03:33:57:0d:ed:e2:fa:ce:5d:45:d6:38:cd:35:b6:
+ b2:c1:d0:9c:81:4a:aa:e4:b2:01:5c:1d:8f:5f:99:
+ c4:b1:ad:db:88:21:eb:90:08:82:80:f3:30:a3:43:
+ e6:90:82:ae:55:28:49:ed:5b:d7:a9:10:38:0e:fe:
+ 8f:4c:5b:9b:46:ea:41:f5:b0:08:74:c3:d0:88:33:
+ b6:7c:d7:74:df:dc:84:d1:43:0e:75:39:a1:25:40:
+ 28:ea:78:cb:0e:2c:2e:39:9d:8c:8b:6e:16:1c:2f:
+ 26:82:10:e2:e3:65:94:0a:04:c0:5e:f7:5d:5b:f8:
+ 10:e2:d0:ba:7a:4b:fb:de:37:00:00:1a:5b:28:e3:
+ d2:9c:73:3e:32:87:98:a1:c9:51:2f:d7:de:ac:33:
+ b3:4f
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ E0:8C:9B:DB:25:49:B3:F1:7C:86:D6:B2:42:87:0B:D0:6B:A0:D9:E4
+ Signature Algorithm: sha1WithRSAEncryption
+ 3e:d2:1c:89:2e:35:fc:f8:75:dd:e6:7f:65:88:f4:72:4c:c9:
+ 2c:d7:32:4e:f3:dd:19:79:47:bd:8e:3b:5b:93:0f:50:49:24:
+ 13:6b:14:06:72:ef:09:d3:a1:a1:e3:40:84:c9:e7:18:32:74:
+ 3c:48:6e:0f:9f:4b:d4:f7:1e:d3:93:86:64:54:97:63:72:50:
+ d5:55:cf:fa:20:93:02:a2:9b:c3:23:93:4e:16:55:76:a0:70:
+ 79:6d:cd:21:1f:cf:2f:2d:bc:19:e3:88:31:f8:59:1a:81:09:
+ c8:97:a6:74:c7:60:c4:5b:cc:57:8e:b2:75:fd:1b:02:09:db:
+ 59:6f:72:93:69:f7:31:41:d6:88:38:bf:87:b2:bd:16:79:f9:
+ aa:e4:be:88:25:dd:61:27:23:1c:b5:31:07:04:36:b4:1a:90:
+ bd:a0:74:71:50:89:6d:bc:14:e3:0f:86:ae:f1:ab:3e:c7:a0:
+ 09:cc:a3:48:d1:e0:db:64:e7:92:b5:cf:af:72:43:70:8b:f9:
+ c3:84:3c:13:aa:7e:92:9b:57:53:93:fa:70:c2:91:0e:31:f9:
+ 9b:67:5d:e9:96:38:5e:5f:b3:73:4e:88:15:67:de:9e:76:10:
+ 62:20:be:55:69:95:43:00:39:4d:f6:ee:b0:5a:4e:49:44:54:
+ 58:5f:42:83
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
+AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
+QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
+MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
+0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
+UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
+RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
+OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
+JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
+AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
+BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
+LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
+MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
+44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
+Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
+i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
+9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem
new file mode 100644
index 00000000000..37494312757
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem
@@ -0,0 +1,124 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 5d:93:8d:30:67:36:c8:06:1d:1a:c7:54:84:69:07
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = ES, O = FNMT-RCM, OU = AC RAIZ FNMT-RCM
+ Validity
+ Not Before: Oct 29 15:59:56 2008 GMT
+ Not After : Jan 1 00:00:00 2030 GMT
+ Subject: C = ES, O = FNMT-RCM, OU = AC RAIZ FNMT-RCM
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:ba:71:80:7a:4c:86:6e:7f:c8:13:6d:c0:c6:7d:
+ 1c:00:97:8f:2c:0c:23:bb:10:9a:40:a9:1a:b7:87:
+ 88:f8:9b:56:6a:fb:e6:7b:8e:8b:92:8e:a7:25:5d:
+ 59:11:db:36:2e:b7:51:17:1f:a9:08:1f:04:17:24:
+ 58:aa:37:4a:18:df:e5:39:d4:57:fd:d7:c1:2c:91:
+ 01:91:e2:22:d4:03:c0:58:fc:77:47:ec:8f:3e:74:
+ 43:ba:ac:34:8d:4d:38:76:67:8e:b0:c8:6f:30:33:
+ 58:71:5c:b4:f5:6b:6e:d4:01:50:b8:13:7e:6c:4a:
+ a3:49:d1:20:19:ee:bc:c0:29:18:65:a7:de:fe:ef:
+ dd:0a:90:21:e7:1a:67:92:42:10:98:5f:4f:30:bc:
+ 3e:1c:45:b4:10:d7:68:40:14:c0:40:fa:e7:77:17:
+ 7a:e6:0b:8f:65:5b:3c:d9:9a:52:db:b5:bd:9e:46:
+ cf:3d:eb:91:05:02:c0:96:b2:76:4c:4d:10:96:3b:
+ 92:fa:9c:7f:0f:99:df:be:23:35:45:1e:02:5c:fe:
+ b5:a8:9b:99:25:da:5e:f3:22:c3:39:f5:e4:2a:2e:
+ d3:c6:1f:c4:6c:aa:c5:1c:6a:01:05:4a:2f:d2:c5:
+ c1:a8:34:26:5d:66:a5:d2:02:21:f9:18:b7:06:f5:
+ 4e:99:6f:a8:ab:4c:51:e8:cf:50:18:c5:77:c8:39:
+ 09:2c:49:92:32:99:a8:bb:17:17:79:b0:5a:c5:e6:
+ a3:c4:59:65:47:35:83:5e:a9:e8:35:0b:99:bb:e4:
+ cd:20:c6:9b:4a:06:39:b5:68:fc:22:ba:ee:55:8c:
+ 2b:4e:ea:f3:b1:e3:fc:b6:99:9a:d5:42:fa:71:4d:
+ 08:cf:87:1e:6a:71:7d:f9:d3:b4:e9:a5:71:81:7b:
+ c2:4e:47:96:a5:f6:76:85:a3:28:8f:e9:80:6e:81:
+ 53:a5:6d:5f:b8:48:f9:c2:f9:36:a6:2e:49:ff:b8:
+ 96:c2:8c:07:b3:9b:88:58:fc:eb:1b:1c:de:2d:70:
+ e2:97:92:30:a1:89:e3:bc:55:a8:27:d6:4b:ed:90:
+ ad:8b:fa:63:25:59:2d:a8:35:dd:ca:97:33:bc:e5:
+ cd:c7:9d:d1:ec:ef:5e:0e:4a:90:06:26:63:ad:b9:
+ d9:35:2d:07:ba:76:65:2c:ac:57:8f:7d:f4:07:94:
+ d7:81:02:96:5d:a3:07:49:d5:7a:d0:57:f9:1b:e7:
+ 53:46:75:aa:b0:79:42:cb:68:71:08:e9:60:bd:39:
+ 69:ce:f4:af:c3:56:40:c7:ad:52:a2:09:e4:6f:86:
+ 47:8a:1f:eb:28:27:5d:83:20:af:04:c9:6c:56:9a:
+ 8b:46:f5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ F7:7D:C5:FD:C4:E8:9A:1B:77:64:A7:F5:1D:A0:CC:BF:87:60:9A:6D
+ X509v3 Certificate Policies:
+ Policy: X509v3 Any Policy
+ CPS: http://www.cert.fnmt.es/dpcs/
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 07:90:4a:df:f3:23:4e:f0:c3:9c:51:65:9b:9c:22:a2:8a:0c:
+ 85:f3:73:29:6b:4d:fe:01:e2:a9:0c:63:01:bf:04:67:a5:9d:
+ 98:5f:fd:01:13:fa:ec:9a:62:e9:86:fe:b6:62:d2:6e:4c:94:
+ fb:c0:75:45:7c:65:0c:f8:b2:37:cf:ac:0f:cf:8d:6f:f9:19:
+ f7:8f:ec:1e:f2:70:9e:f0:ca:b8:ef:b7:ff:76:37:76:5b:f6:
+ 6e:88:f3:af:62:32:22:93:0d:3a:6a:8e:14:66:0c:2d:53:74:
+ 57:65:1e:d5:b2:dd:23:81:3b:a5:66:23:27:67:09:8f:e1:77:
+ aa:43:cd:65:51:08:ed:51:58:fe:e6:39:f9:cb:47:84:a4:15:
+ f1:76:bb:a4:ee:a4:3b:c4:5f:ef:b2:33:96:11:18:b7:c9:65:
+ be:18:e1:a3:a4:dc:fa:18:f9:d3:bc:13:9b:39:7a:34:ba:d3:
+ 41:fb:fa:32:8a:2a:b7:2b:86:0b:69:83:38:be:cd:8a:2e:0b:
+ 70:ad:8d:26:92:ee:1e:f5:01:2b:0a:d9:d6:97:9b:6e:e0:a8:
+ 19:1c:3a:21:8b:0c:1e:40:ad:03:e7:dd:66:7e:f5:b9:20:0d:
+ 03:e8:96:f9:82:45:d4:39:e0:a0:00:5d:d7:98:e6:7d:9e:67:
+ 73:c3:9a:2a:f7:ab:8b:a1:3a:14:ef:34:bc:52:0e:89:98:9a:
+ 04:40:84:1d:7e:45:69:93:57:ce:eb:ce:f8:50:7c:4f:1c:6e:
+ 04:43:9b:f9:d6:3b:23:18:e9:ea:8e:d1:4d:46:8d:f1:3b:e4:
+ 6a:ca:ba:fb:23:b7:9b:fa:99:01:29:5a:58:5a:2d:e3:f9:d4:
+ 6d:0e:26:ad:c1:6e:34:bc:32:f8:0c:05:fa:65:a3:db:3b:37:
+ 83:22:e9:d6:dc:72:33:fd:5d:f2:20:bd:76:3c:23:da:28:f7:
+ f9:1b:eb:59:64:d5:dc:5f:72:7e:20:fc:cd:89:b5:90:67:4d:
+ 62:7a:3f:4e:ad:1d:c3:39:fe:7a:f4:28:16:df:41:f6:48:80:
+ 05:d7:0f:51:79:ac:10:ab:d4:ec:03:66:e6:6a:b0:ba:31:92:
+ 42:40:6a:be:3a:d3:72:e1:6a:37:55:bc:ac:1d:95:b7:69:61:
+ f2:43:91:74:e6:a0:d3:0a:24:46:a1:08:af:d6:da:45:19:96:
+ d4:53:1d:5b:84:79:f0:c0:f7:47:ef:8b:8f:c5:06:ae:9d:4c:
+ 62:9d:ff:46:04:f8:d3:c9:b6:10:25:40:75:fe:16:aa:c9:4a:
+ 60:86:2f:ba:ef:30:77:e4:54:e2:b8:84:99:58:80:aa:13:8b:
+ 51:3a:4f:48:f6:8b:b6:b3
+-----BEGIN CERTIFICATE-----
+MIIFgzCCA2ugAwIBAgIPXZONMGc2yAYdGsdUhGkHMA0GCSqGSIb3DQEBCwUAMDsx
+CzAJBgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJ
+WiBGTk1ULVJDTTAeFw0wODEwMjkxNTU5NTZaFw0zMDAxMDEwMDAwMDBaMDsxCzAJ
+BgNVBAYTAkVTMREwDwYDVQQKDAhGTk1ULVJDTTEZMBcGA1UECwwQQUMgUkFJWiBG
+Tk1ULVJDTTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALpxgHpMhm5/
+yBNtwMZ9HACXjywMI7sQmkCpGreHiPibVmr75nuOi5KOpyVdWRHbNi63URcfqQgf
+BBckWKo3Shjf5TnUV/3XwSyRAZHiItQDwFj8d0fsjz50Q7qsNI1NOHZnjrDIbzAz
+WHFctPVrbtQBULgTfmxKo0nRIBnuvMApGGWn3v7v3QqQIecaZ5JCEJhfTzC8PhxF
+tBDXaEAUwED653cXeuYLj2VbPNmaUtu1vZ5Gzz3rkQUCwJaydkxNEJY7kvqcfw+Z
+374jNUUeAlz+taibmSXaXvMiwzn15Cou08YfxGyqxRxqAQVKL9LFwag0Jl1mpdIC
+IfkYtwb1TplvqKtMUejPUBjFd8g5CSxJkjKZqLsXF3mwWsXmo8RZZUc1g16p6DUL
+mbvkzSDGm0oGObVo/CK67lWMK07q87Hj/LaZmtVC+nFNCM+HHmpxffnTtOmlcYF7
+wk5HlqX2doWjKI/pgG6BU6VtX7hI+cL5NqYuSf+4lsKMB7ObiFj86xsc3i1w4peS
+MKGJ47xVqCfWS+2QrYv6YyVZLag13cqXM7zlzced0ezvXg5KkAYmY6252TUtB7p2
+ZSysV4999AeU14ECll2jB0nVetBX+RvnU0Z1qrB5QstocQjpYL05ac70r8NWQMet
+UqIJ5G+GR4of6ygnXYMgrwTJbFaai0b1AgMBAAGjgYMwgYAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFPd9xf3E6Jobd2Sn9R2gzL+H
+YJptMD4GA1UdIAQ3MDUwMwYEVR0gADArMCkGCCsGAQUFBwIBFh1odHRwOi8vd3d3
+LmNlcnQuZm5tdC5lcy9kcGNzLzANBgkqhkiG9w0BAQsFAAOCAgEAB5BK3/MjTvDD
+nFFlm5wioooMhfNzKWtN/gHiqQxjAb8EZ6WdmF/9ARP67Jpi6Yb+tmLSbkyU+8B1
+RXxlDPiyN8+sD8+Nb/kZ94/sHvJwnvDKuO+3/3Y3dlv2bojzr2IyIpMNOmqOFGYM
+LVN0V2Ue1bLdI4E7pWYjJ2cJj+F3qkPNZVEI7VFY/uY5+ctHhKQV8Xa7pO6kO8Rf
+77IzlhEYt8llvhjho6Tc+hj507wTmzl6NLrTQfv6MooqtyuGC2mDOL7Nii4LcK2N
+JpLuHvUBKwrZ1pebbuCoGRw6IYsMHkCtA+fdZn71uSANA+iW+YJF1DngoABd15jm
+fZ5nc8OaKveri6E6FO80vFIOiZiaBECEHX5FaZNXzuvO+FB8TxxuBEOb+dY7Ixjp
+6o7RTUaN8Tvkasq6+yO3m/qZASlaWFot4/nUbQ4mrcFuNLwy+AwF+mWj2zs3gyLp
+1txyM/1d8iC9djwj2ij3+RvrWWTV3F9yfiD8zYm1kGdNYno/Tq0dwzn+evQoFt9B
+9kiABdcPUXmsEKvU7ANm5mqwujGSQkBqvjrTcuFqN1W8rB2Vt2lh8kORdOag0wok
+RqEIr9baRRmW1FMdW4R58MD3R++Lj8UGrp1MYp3/RgT408m2ECVAdf4WqslKYIYv
+uu8wd+RU4riEmViAqhOLUTpPSPaLtrM=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem
new file mode 100644
index 00000000000..f22a033e534
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem
@@ -0,0 +1,78 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 04:00:00:00:00:01:15:4b:5a:c3:94
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
+ Validity
+ Not Before: Sep 1 12:00:00 1998 GMT
+ Not After : Jan 28 12:00:00 2028 GMT
+ Subject: C = BE, O = GlobalSign nv-sa, OU = Root CA, CN = GlobalSign Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:da:0e:e6:99:8d:ce:a3:e3:4f:8a:7e:fb:f1:8b:
+ 83:25:6b:ea:48:1f:f1:2a:b0:b9:95:11:04:bd:f0:
+ 63:d1:e2:67:66:cf:1c:dd:cf:1b:48:2b:ee:8d:89:
+ 8e:9a:af:29:80:65:ab:e9:c7:2d:12:cb:ab:1c:4c:
+ 70:07:a1:3d:0a:30:cd:15:8d:4f:f8:dd:d4:8c:50:
+ 15:1c:ef:50:ee:c4:2e:f7:fc:e9:52:f2:91:7d:e0:
+ 6d:d5:35:30:8e:5e:43:73:f2:41:e9:d5:6a:e3:b2:
+ 89:3a:56:39:38:6f:06:3c:88:69:5b:2a:4d:c5:a7:
+ 54:b8:6c:89:cc:9b:f9:3c:ca:e5:fd:89:f5:12:3c:
+ 92:78:96:d6:dc:74:6e:93:44:61:d1:8d:c7:46:b2:
+ 75:0e:86:e8:19:8a:d5:6d:6c:d5:78:16:95:a2:e9:
+ c8:0a:38:eb:f2:24:13:4f:73:54:93:13:85:3a:1b:
+ bc:1e:34:b5:8b:05:8c:b9:77:8b:b1:db:1f:20:91:
+ ab:09:53:6e:90:ce:7b:37:74:b9:70:47:91:22:51:
+ 63:16:79:ae:b1:ae:41:26:08:c8:19:2b:d1:46:aa:
+ 48:d6:64:2a:d7:83:34:ff:2c:2a:c1:6c:19:43:4a:
+ 07:85:e7:d3:7c:f6:21:68:ef:ea:f2:52:9f:7f:93:
+ 90:cf
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 60:7B:66:1A:45:0D:97:CA:89:50:2F:7D:04:CD:34:A8:FF:FC:FD:4B
+ Signature Algorithm: sha1WithRSAEncryption
+ d6:73:e7:7c:4f:76:d0:8d:bf:ec:ba:a2:be:34:c5:28:32:b5:
+ 7c:fc:6c:9c:2c:2b:bd:09:9e:53:bf:6b:5e:aa:11:48:b6:e5:
+ 08:a3:b3:ca:3d:61:4d:d3:46:09:b3:3e:c3:a0:e3:63:55:1b:
+ f2:ba:ef:ad:39:e1:43:b9:38:a3:e6:2f:8a:26:3b:ef:a0:50:
+ 56:f9:c6:0a:fd:38:cd:c4:0b:70:51:94:97:98:04:df:c3:5f:
+ 94:d5:15:c9:14:41:9c:c4:5d:75:64:15:0d:ff:55:30:ec:86:
+ 8f:ff:0d:ef:2c:b9:63:46:f6:aa:fc:df:bc:69:fd:2e:12:48:
+ 64:9a:e0:95:f0:a6:ef:29:8f:01:b1:15:b5:0c:1d:a5:fe:69:
+ 2c:69:24:78:1e:b3:a7:1c:71:62:ee:ca:c8:97:ac:17:5d:8a:
+ c2:f8:47:86:6e:2a:c4:56:31:95:d0:67:89:85:2b:f9:6c:a6:
+ 5d:46:9d:0c:aa:82:e4:99:51:dd:70:b7:db:56:3d:61:e4:6a:
+ e1:5c:d6:f6:fe:3d:de:41:cc:07:ae:63:52:bf:53:53:f4:2b:
+ e9:c7:fd:b6:f7:82:5f:85:d2:41:18:db:81:b3:04:1c:c5:1f:
+ a4:80:6f:15:20:c9:de:0c:88:0a:1d:d6:66:55:e2:fc:48:c9:
+ 29:26:69:e0
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
+A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
+b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
+MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
+YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
+aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
+jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
+xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
+1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
+snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
+U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
+9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
+BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
+AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
+yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
+38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
+AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
+DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
+HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem
new file mode 100644
index 00000000000..28fe0553a8a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem
@@ -0,0 +1,118 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 2 (0x2)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = NO, O = Buypass AS-983163327, CN = Buypass Class 3 Root CA
+ Validity
+ Not Before: Oct 26 08:28:58 2010 GMT
+ Not After : Oct 26 08:28:58 2040 GMT
+ Subject: C = NO, O = Buypass AS-983163327, CN = Buypass Class 3 Root CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (4096 bit)
+ Modulus:
+ 00:a5:da:0a:95:16:50:e3:95:f2:5e:9d:76:31:06:
+ 32:7a:9b:f1:10:76:b8:00:9a:b5:52:36:cd:24:47:
+ b0:9f:18:64:bc:9a:f6:fa:d5:79:d8:90:62:4c:22:
+ 2f:de:38:3d:d6:e0:a8:e9:1c:2c:db:78:11:e9:8e:
+ 68:51:15:72:c7:f3:33:87:e4:a0:5d:0b:5c:e0:57:
+ 07:2a:30:f5:cd:c4:37:77:28:4d:18:91:e6:bf:d5:
+ 52:fd:71:2d:70:3e:e7:c6:c4:8a:e3:f0:28:0b:f4:
+ 76:98:a1:8b:87:55:b2:3a:13:fc:b7:3e:27:37:8e:
+ 22:e3:a8:4f:2a:ef:60:bb:3d:b7:39:c3:0e:01:47:
+ 99:5d:12:4f:db:43:fa:57:a1:ed:f9:9d:be:11:47:
+ 26:5b:13:98:ab:5d:16:8a:b0:37:1c:57:9d:45:ff:
+ 88:96:36:bf:bb:ca:07:7b:6f:87:63:d7:d0:32:6a:
+ d6:5d:6c:0c:f1:b3:6e:39:e2:6b:31:2e:39:00:27:
+ 14:de:38:c0:ec:19:66:86:12:e8:9d:72:16:13:64:
+ 52:c7:a9:37:1c:fd:82:30:ed:84:18:1d:f4:ae:5c:
+ ff:70:13:00:eb:b1:f5:33:7a:4b:d6:55:f8:05:8d:
+ 4b:69:b0:f5:b3:28:36:5c:14:c4:51:73:4d:6b:0b:
+ f1:34:07:db:17:39:d7:dc:28:7b:6b:f5:9f:f3:2e:
+ c1:4f:17:2a:10:f3:cc:ca:e8:eb:fd:6b:ab:2e:9a:
+ 9f:2d:82:6e:04:d4:52:01:93:2d:3d:86:fc:7e:fc:
+ df:ef:42:1d:a6:6b:ef:b9:20:c6:f7:bd:a0:a7:95:
+ fd:a7:e6:89:24:d8:cc:8c:34:6c:e2:23:2f:d9:12:
+ 1a:21:b9:55:91:6f:0b:91:79:19:0c:ad:40:88:0b:
+ 70:e2:7a:d2:0e:d8:68:48:bb:82:13:39:10:58:e9:
+ d8:2a:07:c6:12:db:58:db:d2:3b:55:10:47:05:15:
+ 67:62:7e:18:63:a6:46:3f:09:0e:54:32:5e:bf:0d:
+ 62:7a:27:ef:80:e8:db:d9:4b:06:5a:37:5a:25:d0:
+ 08:12:77:d4:6f:09:50:97:3d:c8:1d:c3:df:8c:45:
+ 30:56:c6:d3:64:ab:66:f3:c0:5e:96:9c:c3:c4:ef:
+ c3:7c:6b:8b:3a:79:7f:b3:49:cf:3d:e2:89:9f:a0:
+ 30:4b:85:b9:9c:94:24:79:8f:7d:6b:a9:45:68:0f:
+ 2b:d0:f1:da:1c:cb:69:b8:ca:49:62:6d:c8:d0:63:
+ 62:dd:60:0f:58:aa:8f:a1:bc:05:a5:66:a2:cf:1b:
+ 76:b2:84:64:b1:4c:39:52:c0:30:ba:f0:8c:4b:02:
+ b0:b6:b7
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 47:B8:CD:FF:E5:6F:EE:F8:B2:EC:2F:4E:0E:F9:25:B0:8E:3C:6B:C3
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 00:20:23:41:35:04:90:c2:40:62:60:ef:e2:35:4c:d7:3f:ac:
+ e2:34:90:b8:a1:6f:76:fa:16:16:a4:48:37:2c:e9:90:c2:f2:
+ 3c:f8:0a:9f:d8:81:e5:bb:5b:da:25:2c:a4:a7:55:71:24:32:
+ f6:c8:0b:f2:bc:6a:f8:93:ac:b2:07:c2:5f:9f:db:cc:c8:8a:
+ aa:be:6a:6f:e1:49:10:cc:31:d7:80:bb:bb:c8:d8:a2:0e:64:
+ 57:ea:a2:f5:c2:a9:31:15:d2:20:6a:ec:fc:22:01:28:cf:86:
+ b8:80:1e:a9:cc:11:a5:3c:f2:16:b3:47:9d:fc:d2:80:21:c4:
+ cb:d0:47:70:41:a1:ca:83:19:08:2c:6d:f2:5d:77:9c:8a:14:
+ 13:d4:36:1c:92:f0:e5:06:37:dc:a6:e6:90:9b:38:8f:5c:6b:
+ 1b:46:86:43:42:5f:3e:01:07:53:54:5d:65:7d:f7:8a:73:a1:
+ 9a:54:5a:1f:29:43:14:27:c2:85:0f:b5:88:7b:1a:3b:94:b7:
+ 1d:60:a7:b5:9c:e7:29:69:57:5a:9b:93:7a:43:30:1b:03:d7:
+ 62:c8:40:a6:aa:fc:64:e4:4a:d7:91:53:01:a8:20:88:6e:9c:
+ 5f:44:b9:cb:60:81:34:ec:6f:d3:7d:da:48:5f:eb:b4:90:bc:
+ 2d:a9:1c:0b:ac:1c:d5:a2:68:20:80:04:d6:fc:b1:8f:2f:bb:
+ 4a:31:0d:4a:86:1c:eb:e2:36:29:26:f5:da:d8:c4:f2:75:61:
+ cf:7e:ae:76:63:4a:7a:40:65:93:87:f8:1e:80:8c:86:e5:86:
+ d6:8f:0e:fc:53:2c:60:e8:16:61:1a:a2:3e:43:7b:cd:39:60:
+ 54:6a:f5:f2:89:26:01:68:83:48:a2:33:e8:c9:04:91:b2:11:
+ 34:11:3e:ea:d0:43:19:1f:03:93:90:0c:ff:51:3d:57:f4:41:
+ 6e:e1:cb:a0:be:eb:c9:63:cd:6d:cc:e4:f8:36:aa:68:9d:ed:
+ bd:5d:97:70:44:0d:b6:0e:35:dc:e1:0c:5d:bb:a0:51:94:cb:
+ 7e:16:eb:11:2f:a3:92:45:c8:4c:71:d9:bc:c9:99:52:57:46:
+ 2f:50:cf:bd:35:69:f4:3d:15:ce:06:a5:2c:0f:3e:f6:81:ba:
+ 94:bb:c3:bb:bf:65:78:d2:86:79:ff:49:3b:1a:83:0c:f0:de:
+ 78:ec:c8:f2:4d:4c:1a:de:82:29:f8:c1:5a:da:ed:ee:e6:27:
+ 5e:e8:45:d0:9d:1c:51:a8:68:ab:44:e3:d0:8b:6a:e3:f8:3b:
+ bb:dc:4d:d7:64:f2:51:be:e6:aa:ab:5a:e9:31:ee:06:bc:73:
+ bf:13:62:0a:9f:c7:b9:97
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEd
+MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3Mg
+Q2xhc3MgMyBSb290IENBMB4XDTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFow
+TjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MSAw
+HgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIwDQYJKoZIhvcNAQEB
+BQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRHsJ8Y
+ZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3E
+N3coTRiR5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9
+tznDDgFHmV0ST9tD+leh7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX
+0DJq1l1sDPGzbjniazEuOQAnFN44wOwZZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c
+/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH2xc519woe2v1n/MuwU8X
+KhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV/afmiSTY
+zIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvS
+O1UQRwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D
+34xFMFbG02SrZvPAXpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgP
+K9Dx2hzLabjKSWJtyNBjYt1gD1iqj6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3
+AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFEe4zf/lb+74suwv
+Tg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsFAAOCAgEAACAj
+QTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXS
+IGrs/CIBKM+GuIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2
+HJLw5QY33KbmkJs4j1xrG0aGQ0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsa
+O5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8ZORK15FTAaggiG6cX0S5y2CBNOxv
+033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2KSb12tjE8nVhz36u
+dmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz6MkE
+kbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg41
+3OEMXbugUZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvD
+u79leNKGef9JOxqDDPDeeOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq
+4/g7u9xN12TyUb7mqqta6THuBrxzvxNiCp/HuZc=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem
new file mode 100644
index 00000000000..a881da301ec
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem
@@ -0,0 +1,89 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 623604 (0x983f4)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 EV 2009
+ Validity
+ Not Before: Nov 5 08:50:46 2009 GMT
+ Not After : Nov 5 08:50:46 2029 GMT
+ Subject: C = DE, O = D-Trust GmbH, CN = D-TRUST Root Class 3 CA 2 EV 2009
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:99:f1:84:34:70:ba:2f:b7:30:a0:8e:bd:7c:04:
+ cf:be:62:bc:99:fd:82:97:d2:7a:0a:67:96:38:09:
+ f6:10:4e:95:22:73:99:8d:da:15:2d:e7:05:fc:19:
+ 73:22:b7:8e:98:00:bc:3c:3d:ac:a1:6c:fb:d6:79:
+ 25:4b:ad:f0:cc:64:da:88:3e:29:b8:0f:09:d3:34:
+ dd:33:f5:62:d1:e1:cd:19:e9:ee:18:4f:4c:58:ae:
+ e2:1e:d6:0c:5b:15:5a:d8:3a:b8:c4:18:64:1e:e3:
+ 33:b2:b5:89:77:4e:0c:bf:d9:94:6b:13:97:6f:12:
+ a3:fe:99:a9:04:cc:15:ec:60:68:36:ed:08:7b:b7:
+ f5:bf:93:ed:66:31:83:8c:c6:71:34:87:4e:17:ea:
+ af:8b:91:8d:1c:56:41:ae:22:37:5e:37:f2:1d:d9:
+ d1:2d:0d:2f:69:51:a7:be:66:a6:8a:3a:2a:bd:c7:
+ 1a:b1:e1:14:f0:be:3a:1d:b9:cf:5b:b1:6a:fe:b4:
+ b1:46:20:a2:fb:1e:3b:70:ef:93:98:7d:8c:73:96:
+ f2:c5:ef:85:70:ad:29:26:fc:1e:04:3e:1c:a0:d8:
+ 0f:cb:52:83:62:7c:ee:8b:53:95:90:a9:57:a2:ea:
+ 61:05:d8:f9:4d:c4:27:fa:6e:ad:ed:f9:d7:51:f7:
+ 6b:a5
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ D3:94:8A:4C:62:13:2A:19:2E:CC:AF:72:8A:7D:36:D7:9A:1C:DC:67
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:ldap://directory.d-trust.net/CN=D-TRUST%20Root%20Class%203%20CA%202%20EV%202009,O=D-Trust%20GmbH,C=DE?certificaterevocationlist
+
+ Full Name:
+ URI:http://www.d-trust.net/crl/d-trust_root_class_3_ca_2_ev_2009.crl
+
+ Signature Algorithm: sha256WithRSAEncryption
+ 34:ed:7b:5a:3c:a4:94:88:ef:1a:11:75:07:2f:b3:fe:3c:fa:
+ 1e:51:26:eb:87:f6:29:de:e0:f1:d4:c6:24:09:e9:c1:cf:55:
+ 1b:b4:30:d9:ce:1a:fe:06:51:a6:15:a4:2d:ef:b2:4b:bf:20:
+ 28:25:49:d1:a6:36:77:34:e8:64:df:52:b1:11:c7:73:7a:cd:
+ 39:9e:c2:ad:8c:71:21:f2:5a:6b:af:df:3c:4e:55:af:b2:84:
+ 65:14:89:b9:77:cb:2a:31:be:cf:a3:6d:cf:6f:48:94:32:46:
+ 6f:e7:71:8c:a0:a6:84:19:37:07:f2:03:45:09:2b:86:75:7c:
+ df:5f:69:57:00:db:6e:d8:a6:72:22:4b:50:d4:75:98:56:df:
+ b7:18:ff:43:43:50:ae:7a:44:7b:f0:79:51:d7:43:3d:a7:d3:
+ 81:d3:f0:c9:4f:b9:da:c6:97:86:d0:82:c3:e4:42:6d:fe:b0:
+ e2:64:4e:0e:26:e7:40:34:26:b5:08:89:d7:08:63:63:38:27:
+ 75:1e:33:ea:6e:a8:dd:9f:99:4f:74:4d:81:89:80:4b:dd:9a:
+ 97:29:5c:2f:be:81:41:b9:8c:ff:ea:7d:60:06:9e:cd:d7:3d:
+ d3:2e:a3:15:bc:a8:e6:26:e5:6f:c3:dc:b8:03:21:ea:9f:16:
+ f1:2c:54:b5
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIDCYP0MA0GCSqGSIb3DQEBCwUAMFAxCzAJBgNVBAYTAkRF
+MRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNVBAMMIUQtVFJVU1QgUm9vdCBD
+bGFzcyAzIENBIDIgRVYgMjAwOTAeFw0wOTExMDUwODUwNDZaFw0yOTExMDUwODUw
+NDZaMFAxCzAJBgNVBAYTAkRFMRUwEwYDVQQKDAxELVRydXN0IEdtYkgxKjAoBgNV
+BAMMIUQtVFJVU1QgUm9vdCBDbGFzcyAzIENBIDIgRVYgMjAwOTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAJnxhDRwui+3MKCOvXwEz75ivJn9gpfSegpn
+ljgJ9hBOlSJzmY3aFS3nBfwZcyK3jpgAvDw9rKFs+9Z5JUut8Mxk2og+KbgPCdM0
+3TP1YtHhzRnp7hhPTFiu4h7WDFsVWtg6uMQYZB7jM7K1iXdODL/ZlGsTl28So/6Z
+qQTMFexgaDbtCHu39b+T7WYxg4zGcTSHThfqr4uRjRxWQa4iN1438h3Z0S0NL2lR
+p75mpoo6Kr3HGrHhFPC+Oh25z1uxav60sUYgovseO3Dvk5h9jHOW8sXvhXCtKSb8
+HgQ+HKDYD8tSg2J87otTlZCpV6LqYQXY+U3EJ/pure3511H3a6UCAwEAAaOCASQw
+ggEgMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNOUikxiEyoZLsyvcop9Ntea
+HNxnMA4GA1UdDwEB/wQEAwIBBjCB3QYDVR0fBIHVMIHSMIGHoIGEoIGBhn9sZGFw
+Oi8vZGlyZWN0b3J5LmQtdHJ1c3QubmV0L0NOPUQtVFJVU1QlMjBSb290JTIwQ2xh
+c3MlMjAzJTIwQ0ElMjAyJTIwRVYlMjAyMDA5LE89RC1UcnVzdCUyMEdtYkgsQz1E
+RT9jZXJ0aWZpY2F0ZXJldm9jYXRpb25saXN0MEagRKBChkBodHRwOi8vd3d3LmQt
+dHJ1c3QubmV0L2NybC9kLXRydXN0X3Jvb3RfY2xhc3NfM19jYV8yX2V2XzIwMDku
+Y3JsMA0GCSqGSIb3DQEBCwUAA4IBAQA07XtaPKSUiO8aEXUHL7P+PPoeUSbrh/Yp
+3uDx1MYkCenBz1UbtDDZzhr+BlGmFaQt77JLvyAoJUnRpjZ3NOhk31KxEcdzes05
+nsKtjHEh8lprr988TlWvsoRlFIm5d8sqMb7Po23Pb0iUMkZv53GMoKaEGTcH8gNF
+CSuGdXzfX2lXANtu2KZyIktQ1HWYVt+3GP9DQ1CuekR78HlR10M9p9OB0/DJT7na
+xpeG0ILD5EJt/rDiZE4OJudANCa1CInXCGNjOCd1HjPqbqjdn5lPdE2BiYBL3ZqX
+KVwvvoFBuYz/6n1gBp7N1z3TLqMVvKjmJuVvw9y4AyHqnxbxLFS1
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem
new file mode 100644
index 00000000000..4cc18e8245a
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem
@@ -0,0 +1,88 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number:
+ 0c:f0:8e:5c:08:16:a5:ad:42:7f:f0:eb:27:18:59:d0
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = US, O = SecureTrust Corporation, CN = SecureTrust CA
+ Validity
+ Not Before: Nov 7 19:31:18 2006 GMT
+ Not After : Dec 31 19:40:55 2029 GMT
+ Subject: C = US, O = SecureTrust Corporation, CN = SecureTrust CA
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ab:a4:81:e5:95:cd:f5:f6:14:8e:c2:4f:ca:d4:
+ e2:78:95:58:9c:41:e1:0d:99:40:24:17:39:91:33:
+ 66:e9:be:e1:83:af:62:5c:89:d1:fc:24:5b:61:b3:
+ e0:11:11:41:1c:1d:6e:f0:b8:bb:f8:de:a7:81:ba:
+ a6:48:c6:9f:1d:bd:be:8e:a9:41:3e:b8:94:ed:29:
+ 1a:d4:8e:d2:03:1d:03:ef:6d:0d:67:1c:57:d7:06:
+ ad:ca:c8:f5:fe:0e:af:66:25:48:04:96:0b:5d:a3:
+ ba:16:c3:08:4f:d1:46:f8:14:5c:f2:c8:5e:01:99:
+ 6d:fd:88:cc:86:a8:c1:6f:31:42:6c:52:3e:68:cb:
+ f3:19:34:df:bb:87:18:56:80:26:c4:d0:dc:c0:6f:
+ df:de:a0:c2:91:16:a0:64:11:4b:44:bc:1e:f6:e7:
+ fa:63:de:66:ac:76:a4:71:a3:ec:36:94:68:7a:77:
+ a4:b1:e7:0e:2f:81:7a:e2:b5:72:86:ef:a2:6b:8b:
+ f0:0f:db:d3:59:3f:ba:72:bc:44:24:9c:e3:73:b3:
+ f7:af:57:2f:42:26:9d:a9:74:ba:00:52:f2:4b:cd:
+ 53:7c:47:0b:36:85:0e:66:a9:08:97:16:34:57:c1:
+ 66:f7:80:e3:ed:70:54:c7:93:e0:2e:28:15:59:87:
+ ba:bb
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ 1.3.6.1.4.1.311.20.2:
+ ...C.A
+ X509v3 Key Usage:
+ Digital Signature, Certificate Sign, CRL Sign
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Subject Key Identifier:
+ 42:32:B6:16:FA:04:FD:FE:5D:4B:7A:C3:FD:F7:4C:40:1D:5A:43:AF
+ X509v3 CRL Distribution Points:
+
+ Full Name:
+ URI:http://crl.securetrust.com/STCA.crl
+
+ 1.3.6.1.4.1.311.21.1:
+ ...
+ Signature Algorithm: sha1WithRSAEncryption
+ 30:ed:4f:4a:e1:58:3a:52:72:5b:b5:a6:a3:65:18:a6:bb:51:
+ 3b:77:e9:9d:ea:d3:9f:5c:e0:45:65:7b:0d:ca:5b:e2:70:50:
+ b2:94:05:14:ae:49:c7:8d:41:07:12:73:94:7e:0c:23:21:fd:
+ bc:10:7f:60:10:5a:72:f5:98:0e:ac:ec:b9:7f:dd:7a:6f:5d:
+ d3:1c:f4:ff:88:05:69:42:a9:05:71:c8:b7:ac:26:e8:2e:b4:
+ 8c:6a:ff:71:dc:b8:b1:df:99:bc:7c:21:54:2b:e4:58:a2:bb:
+ 57:29:ae:9e:a9:a3:19:26:0f:99:2e:08:b0:ef:fd:69:cf:99:
+ 1a:09:8d:e3:a7:9f:2b:c9:36:34:7b:24:b3:78:4c:95:17:a4:
+ 06:26:1e:b6:64:52:36:5f:60:67:d9:9c:c5:05:74:0b:e7:67:
+ 23:d2:08:fc:88:e9:ae:8b:7f:e1:30:f4:37:7e:fd:c6:32:da:
+ 2d:9e:44:30:30:6c:ee:07:de:d2:34:fc:d2:ff:40:f6:4b:f4:
+ 66:46:06:54:a6:f2:32:0a:63:26:30:6b:9b:d1:dc:8b:47:ba:
+ e1:b9:d5:62:d0:a2:a0:f4:67:05:78:29:63:1a:6f:04:d6:f8:
+ c6:4c:a3:9a:b1:37:b4:8d:e5:28:4b:1d:9e:2c:c2:b8:68:bc:
+ ed:02:ee:31
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
+MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
+FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
+MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
+cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
+AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
+Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
+0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
+wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
+7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
+8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
+BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
+/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
+JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
+NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
+6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
+3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
+D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
+CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem
new file mode 100644
index 00000000000..759f2b97247
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem
@@ -0,0 +1,83 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 6643877497813316402 (0x5c33cb622c5fb332)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: CN = Atos TrustedRoot 2011, O = Atos, C = DE
+ Validity
+ Not Before: Jul 7 14:58:30 2011 GMT
+ Not After : Dec 31 23:59:59 2030 GMT
+ Subject: CN = Atos TrustedRoot 2011, O = Atos, C = DE
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:95:85:3b:97:6f:2a:3b:2e:3b:cf:a6:f3:29:35:
+ be:cf:18:ac:3e:aa:d9:f8:4d:a0:3e:1a:47:b9:bc:
+ 9a:df:f2:fe:cc:3e:47:e8:7a:96:c2:24:8e:35:f4:
+ a9:0c:fc:82:fd:6d:c1:72:62:27:bd:ea:6b:eb:e7:
+ 8a:cc:54:3e:90:50:cf:80:d4:95:fb:e8:b5:82:d4:
+ 14:c5:b6:a9:55:25:57:db:b1:50:f6:b0:60:64:59:
+ 7a:69:cf:03:b7:6f:0d:be:ca:3e:6f:74:72:ea:aa:
+ 30:2a:73:62:be:49:91:61:c8:11:fe:0e:03:2a:f7:
+ 6a:20:dc:02:15:0d:5e:15:6a:fc:e3:82:c1:b5:c5:
+ 9d:64:09:6c:a3:59:98:07:27:c7:1b:96:2b:61:74:
+ 71:6c:43:f1:f7:35:89:10:e0:9e:ec:55:a1:37:22:
+ a2:87:04:05:2c:47:7d:b4:1c:b9:62:29:66:28:ca:
+ b7:e1:93:f5:a4:94:03:99:b9:70:85:b5:e6:48:ea:
+ 8d:50:fc:d9:de:cc:6f:07:0e:dd:0b:72:9d:80:30:
+ 16:07:95:3f:28:0e:fd:c5:75:4f:53:d6:74:9a:b4:
+ 24:2e:8e:02:91:cf:76:c5:9b:1e:55:74:9c:78:21:
+ b1:f0:2d:f1:0b:9f:c2:d5:96:18:1f:f0:54:22:7a:
+ 8c:07
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Subject Key Identifier:
+ A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Authority Key Identifier:
+ keyid:A7:A5:06:B1:2C:A6:09:60:EE:D1:97:E9:70:AE:BC:3B:19:6C:DB:21
+
+ X509v3 Certificate Policies:
+ Policy: 1.3.6.1.4.1.6189.3.4.1.1
+
+ X509v3 Key Usage: critical
+ Digital Signature, Certificate Sign, CRL Sign
+ Signature Algorithm: sha256WithRSAEncryption
+ 26:77:34:db:94:48:86:2a:41:9d:2c:3e:06:90:60:c4:8c:ac:
+ 0b:54:b8:1f:b9:7b:d3:07:39:e4:fa:3e:7b:b2:3d:4e:ed:9f:
+ 23:bd:97:f3:6b:5c:ef:ee:fd:40:a6:df:a1:93:a1:0a:86:ac:
+ ef:20:d0:79:01:bd:78:f7:19:d8:24:31:34:04:01:a6:ba:15:
+ 9a:c3:27:dc:d8:4f:0f:cc:18:63:ff:99:0f:0e:91:6b:75:16:
+ e1:21:fc:d8:26:c7:47:b7:a6:cf:58:72:71:7e:ba:e1:4d:95:
+ 47:3b:c9:af:6d:a1:b4:c1:ec:89:f6:b4:0f:38:b5:e2:64:dc:
+ 25:cf:a6:db:eb:9a:5c:99:a1:c5:08:de:fd:e6:da:d5:d6:5a:
+ 45:0c:c4:b7:c2:b5:14:ef:b4:11:ff:0e:15:b5:f5:f5:db:c6:
+ bd:eb:5a:a7:f0:56:22:a9:3c:65:54:c6:15:a8:bd:86:9e:cd:
+ 83:96:68:7a:71:81:89:e1:0b:e1:ea:11:1b:68:08:cc:69:9e:
+ ec:9e:41:9e:44:32:26:7a:e2:87:0a:71:3d:eb:e4:5a:a4:d2:
+ db:c5:cd:c6:de:60:7f:b9:f3:4f:44:92:ef:2a:b7:18:3e:a7:
+ 19:d9:0b:7d:b1:37:41:42:b0:ba:60:1d:f2:fe:09:11:b0:f0:
+ 87:7b:a7:9d
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIIXDPLYixfszIwDQYJKoZIhvcNAQELBQAwPDEeMBwGA1UE
+AwwVQXRvcyBUcnVzdGVkUm9vdCAyMDExMQ0wCwYDVQQKDARBdG9zMQswCQYDVQQG
+EwJERTAeFw0xMTA3MDcxNDU4MzBaFw0zMDEyMzEyMzU5NTlaMDwxHjAcBgNVBAMM
+FUF0b3MgVHJ1c3RlZFJvb3QgMjAxMTENMAsGA1UECgwEQXRvczELMAkGA1UEBhMC
+REUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCVhTuXbyo7LjvPpvMp
+Nb7PGKw+qtn4TaA+Gke5vJrf8v7MPkfoepbCJI419KkM/IL9bcFyYie96mvr54rM
+VD6QUM+A1JX76LWC1BTFtqlVJVfbsVD2sGBkWXppzwO3bw2+yj5vdHLqqjAqc2K+
+SZFhyBH+DgMq92og3AIVDV4VavzjgsG1xZ1kCWyjWZgHJ8cblithdHFsQ/H3NYkQ
+4J7sVaE3IqKHBAUsR320HLliKWYoyrfhk/WklAOZuXCFteZI6o1Q/NnezG8HDt0L
+cp2AMBYHlT8oDv3FdU9T1nSatCQujgKRz3bFmx5VdJx4IbHwLfELn8LVlhgf8FQi
+eowHAgMBAAGjfTB7MB0GA1UdDgQWBBSnpQaxLKYJYO7Rl+lwrrw7GWzbITAPBgNV
+HRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKelBrEspglg7tGX6XCuvDsZbNshMBgG
+A1UdIAQRMA8wDQYLKwYBBAGwLQMEAQEwDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3
+DQEBCwUAA4IBAQAmdzTblEiGKkGdLD4GkGDEjKwLVLgfuXvTBznk+j57sj1O7Z8j
+vZfza1zv7v1Apt+hk6EKhqzvINB5Ab149xnYJDE0BAGmuhWawyfc2E8PzBhj/5kP
+DpFrdRbhIfzYJsdHt6bPWHJxfrrhTZVHO8mvbaG0weyJ9rQPOLXiZNwlz6bb65pc
+maHFCN795trV1lpFDMS3wrUU77QR/w4VtfX128a961qn8FYiqTxlVMYVqL2Gns2D
+lmh6cYGJ4Qvh6hEbaAjMaZ7snkGeRDImeuKHCnE96+RapNLbxc3G3mB/ufNPRJLv
+KrcYPqcZ2Qt9sTdBQrC6YB3y/gkRsPCHe6ed
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem
new file mode 100644
index 00000000000..73716b0ba61
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem
@@ -0,0 +1,74 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1000 (0x3e8)
+ Signature Algorithm: sha1WithRSAEncryption
+ Issuer: C = HK, O = Hongkong Post, CN = Hongkong Post Root CA 1
+ Validity
+ Not Before: May 15 05:13:14 2003 GMT
+ Not After : May 15 04:52:29 2023 GMT
+ Subject: C = HK, O = Hongkong Post, CN = Hongkong Post Root CA 1
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:ac:ff:38:b6:e9:66:02:49:e3:a2:b4:e1:90:f9:
+ 40:8f:79:f9:e2:bd:79:fe:02:bd:ee:24:92:1d:22:
+ f6:da:85:72:69:fe:d7:3f:09:d4:dd:91:b5:02:9c:
+ d0:8d:5a:e1:55:c3:50:86:b9:29:26:c2:e3:d9:a0:
+ f1:69:03:28:20:80:45:22:2d:56:a7:3b:54:95:56:
+ 22:59:1f:28:df:1f:20:3d:6d:a2:36:be:23:a0:b1:
+ 6e:b5:b1:27:3f:39:53:09:ea:ab:6a:e8:74:b2:c2:
+ 65:5c:8e:bf:7c:c3:78:84:cd:9e:16:fc:f5:2e:4f:
+ 20:2a:08:9f:77:f3:c5:1e:c4:9a:52:66:1e:48:5e:
+ e3:10:06:8f:22:98:e1:65:8e:1b:5d:23:66:3b:b8:
+ a5:32:51:c8:86:aa:a1:a9:9e:7f:76:94:c2:a6:6c:
+ b7:41:f0:d5:c8:06:38:e6:d4:0c:e2:f3:3b:4c:6d:
+ 50:8c:c4:83:27:c1:13:84:59:3d:9e:75:74:b6:d8:
+ 02:5e:3a:90:7a:c0:42:36:72:ec:6a:4d:dc:ef:c4:
+ 00:df:13:18:57:5f:26:78:c8:d6:0a:79:77:bf:f7:
+ af:b7:76:b9:a5:0b:84:17:5d:10:ea:6f:e1:ab:95:
+ 11:5f:6d:3c:a3:5c:4d:83:5b:f2:b3:19:8a:80:8b:
+ 0b:87
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE, pathlen:3
+ X509v3 Key Usage: critical
+ Digital Signature, Non Repudiation, Certificate Sign, CRL Sign
+ Signature Algorithm: sha1WithRSAEncryption
+ 0e:46:d5:3c:ae:e2:87:d9:5e:81:8b:02:98:41:08:8c:4c:bc:
+ da:db:ee:27:1b:82:e7:6a:45:ec:16:8b:4f:85:a0:f3:b2:70:
+ bd:5a:96:ba:ca:6e:6d:ee:46:8b:6e:e7:2a:2e:96:b3:19:33:
+ eb:b4:9f:a8:b2:37:ee:98:a8:97:b6:2e:b6:67:27:d4:a6:49:
+ fd:1c:93:65:76:9e:42:2f:dc:22:6c:9a:4f:f2:5a:15:39:b1:
+ 71:d7:2b:51:e8:6d:1c:98:c0:d9:2a:f4:a1:82:7b:d5:c9:41:
+ a2:23:01:74:38:55:8b:0f:b9:2e:67:a2:20:04:37:da:9c:0b:
+ d3:17:21:e0:8f:97:79:34:6f:84:48:02:20:33:1b:e6:34:44:
+ 9f:91:70:f4:80:5e:84:43:c2:29:d2:6c:12:14:e4:61:8d:ac:
+ 10:90:9e:84:50:bb:f0:96:6f:45:9f:8a:f3:ca:6c:4f:fa:11:
+ 3a:15:15:46:c3:cd:1f:83:5b:2d:41:12:ed:50:67:41:13:3d:
+ 21:ab:94:8a:aa:4e:7c:c1:b1:fb:a7:d6:b5:27:2f:97:ab:6e:
+ e0:1d:e2:d1:1c:2c:1f:44:e2:fc:be:91:a1:9c:fb:d6:29:53:
+ 73:86:9f:53:d8:43:0e:5d:d6:63:82:71:1d:80:74:ca:f6:e2:
+ 02:6b:d9:5a
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
+FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
+Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
+A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
+b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
+jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
+PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
+ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
+nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
+q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
+MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
+mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
+7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
+oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
+EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
+fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
+AmvZWg==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/certs/fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem b/chromium/net/data/ssl/chrome_root_store/store/certs/fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem
new file mode 100644
index 00000000000..15faebac3de
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/certs/fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem
@@ -0,0 +1,79 @@
+Certificate:
+ Data:
+ Version: 3 (0x2)
+ Serial Number: 1 (0x1)
+ Signature Algorithm: sha256WithRSAEncryption
+ Issuer: C = DE, O = T-Systems Enterprise Services GmbH, OU = T-Systems Trust Center, CN = T-TeleSec GlobalRoot Class 3
+ Validity
+ Not Before: Oct 1 10:29:56 2008 GMT
+ Not After : Oct 1 23:59:59 2033 GMT
+ Subject: C = DE, O = T-Systems Enterprise Services GmbH, OU = T-Systems Trust Center, CN = T-TeleSec GlobalRoot Class 3
+ Subject Public Key Info:
+ Public Key Algorithm: rsaEncryption
+ RSA Public-Key: (2048 bit)
+ Modulus:
+ 00:bd:75:93:f0:62:22:6f:24:ae:e0:7a:76:ac:7d:
+ bd:d9:24:d5:b8:b7:fc:cd:f0:42:e0:eb:78:88:56:
+ 5e:9b:9a:54:1d:4d:0c:8a:f6:d3:cf:70:f4:52:b5:
+ d8:93:04:e3:46:86:71:41:4a:2b:f0:2a:2c:55:03:
+ d6:48:c3:e0:39:38:ed:f2:5c:3c:3f:44:bc:93:3d:
+ 61:ab:4e:cd:0d:be:f0:20:27:58:0e:44:7f:04:1a:
+ 87:a5:d7:96:14:36:90:d0:49:7b:a1:75:fb:1a:6b:
+ 73:b1:f8:ce:a9:09:2c:f2:53:d5:c3:14:44:b8:86:
+ a5:f6:8b:2b:39:da:a3:33:54:d9:fa:72:1a:f7:22:
+ 15:1c:88:91:6b:7f:66:e5:c3:6a:80:b0:24:f3:df:
+ 86:45:88:fd:19:7f:75:87:1f:1f:b1:1b:0a:73:24:
+ 5b:b9:65:e0:2c:54:c8:60:d3:66:17:3f:e1:cc:54:
+ 33:73:91:02:3a:a6:7f:7b:76:39:a2:1f:96:b6:38:
+ ae:b5:c8:93:74:1d:9e:b9:b4:e5:60:9d:2f:56:d1:
+ e0:eb:5e:5b:4c:12:70:0c:6c:44:20:ab:11:d8:f4:
+ 19:f6:d2:9c:52:37:e7:fa:b6:c2:31:3b:4a:d4:14:
+ 99:ad:c7:1a:f5:5d:5f:fa:07:b8:7c:0d:1f:d6:83:
+ 1e:b3
+ Exponent: 65537 (0x10001)
+ X509v3 extensions:
+ X509v3 Basic Constraints: critical
+ CA:TRUE
+ X509v3 Key Usage: critical
+ Certificate Sign, CRL Sign
+ X509v3 Subject Key Identifier:
+ B5:03:F7:76:3B:61:82:6A:12:AA:18:53:EB:03:21:94:BF:FE:CE:CA
+ Signature Algorithm: sha256WithRSAEncryption
+ 56:3d:ef:94:d5:bd:da:73:b2:58:be:ae:90:ad:98:27:97:fe:
+ 01:b1:b0:52:00:b8:4d:e4:1b:21:74:1b:7e:c0:ee:5e:69:2a:
+ 25:af:5c:d6:1d:da:d2:79:c9:f3:97:29:e0:86:87:de:04:59:
+ 0f:f1:59:d4:64:85:4b:99:af:25:04:1e:c9:46:a9:97:de:82:
+ b2:1b:70:9f:9c:f6:af:71:31:dd:7b:05:a5:2c:d3:b9:ca:47:
+ f6:ca:f2:f6:e7:ad:b9:48:3f:bc:16:b7:c1:6d:f4:ea:09:af:
+ ec:f3:b5:e7:05:9e:a6:1e:8a:53:51:d6:93:81:cc:74:93:f6:
+ b9:da:a6:25:05:74:79:5a:7e:40:3e:82:4b:26:11:30:6e:e1:
+ 3f:41:c7:47:00:35:d5:f5:d3:f7:54:3e:81:3d:da:49:6a:9a:
+ b3:ef:10:3d:e6:eb:6f:d1:c8:22:47:cb:cc:cf:01:31:92:d9:
+ 18:e3:22:be:09:1e:1a:3e:5a:b2:e4:6b:0c:54:7a:7d:43:4e:
+ b8:89:a5:7b:d7:a2:3d:96:86:cc:f2:26:34:2d:6a:92:9d:9a:
+ 1a:d0:30:e2:5d:4e:04:b0:5f:8b:20:7e:77:c1:3d:95:82:d1:
+ 46:9a:3b:3c:78:b8:6f:a1:d0:0d:64:a2:78:1e:29:4e:93:c3:
+ a4:54:14:5b
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUx
+KzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAd
+BgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNl
+YyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgxMDAxMTAyOTU2WhcNMzMxMDAxMjM1
+OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lzdGVtcyBFbnRlcnBy
+aXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBDZW50
+ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN
+8ELg63iIVl6bmlQdTQyK9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/
+RLyTPWGrTs0NvvAgJ1gORH8EGoel15YUNpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4
+hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZFiP0Zf3WHHx+xGwpzJFu5
+ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W0eDrXltM
+EnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGj
+QjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1
+A/d2O2GCahKqGFPrAyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOy
+WL6ukK2YJ5f+AbGwUgC4TeQbIXQbfsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ
+1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzTucpH9sry9uetuUg/vBa3wW30
+6gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7hP0HHRwA11fXT
+91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4p
+TpPDpFQUWw==
+-----END CERTIFICATE-----
diff --git a/chromium/net/data/ssl/chrome_root_store/store/root_store.textproto b/chromium/net/data/ssl/chrome_root_store/store/root_store.textproto
new file mode 100644
index 00000000000..4c810437d53
--- /dev/null
+++ b/chromium/net/data/ssl/chrome_root_store/store/root_store.textproto
@@ -0,0 +1,620 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# When adding a trust anchor, name the PEM based on the SHA-256 fingerprint of
+# the certificate. Also make sure to add the PEM file to the inputs section of
+# BUILD.gn.
+#
+# TODO(https://crbug.com/1216547): set up presubmit check to ensure consistency
+# between BUILD.gn and this file.
+
+# Actalis Authentication Root CA
+trust_anchors {
+ filename: "55926084ec963a64b96e2abe01ce0ba86a64fbfebcc7aab5afc155b37fd76066.pem"
+}
+
+# Amazon Root CA 3
+trust_anchors {
+ filename: "18ce6cfe7bf14e60b2e347b8dfe868cb31d02ebb3ada271569f50343b46db3a4.pem"
+}
+
+# Amazon Root CA 2
+trust_anchors {
+ filename: "1ba5b2aa8c65401a82960118f80bec4f62304d83cec4713a19c39c011ea46db4.pem"
+}
+
+# Starfield Services Root Certificate Authority - G2
+trust_anchors {
+ filename: "568d6905a2c88708a4b3025190edcfedb1974a606a13c6e5290fcb2ae63edab5.pem"
+}
+
+# Amazon Root CA 1
+trust_anchors {
+ filename: "8ecde6884f3d87b1125ba31ac3fcb13d7016de7f57cc904fe1cb97c6ae98196e.pem"
+}
+
+# Amazon Root CA 4
+trust_anchors {
+ filename: "e35d28419ed02025cfa69038cd623962458da5c695fbdea3c22b0bfb25897092.pem"
+}
+
+# Certum Trusted Network CA
+trust_anchors {
+ filename: "5c58468d55f58e497e743982d2b50010b6d165374acf83a7d4a32db768c4408e.pem"
+}
+
+# Certum Trusted Network CA 2
+trust_anchors {
+ filename: "b676f2eddae8775cd36cb0f63cd1d4603961f49e6265ba013a2f0307b6d0b804.pem"
+}
+
+# Atos TrustedRoot 2011
+trust_anchors {
+ filename: "f356bea244b7a91eb35d53ca9ad7864ace018e2d35d5f8f96ddf68a6f41aa474.pem"
+}
+
+# Autoridad de Certificacion Firmaprofesional CIF A62634068
+trust_anchors {
+ filename: "04048028bf1f2864d48f9ad4d83294366a828856553f3b14303f90147f5d40ef.pem"
+}
+
+# Buypass Class 2 Root CA
+trust_anchors {
+ filename: "9a114025197c5bb95d94e63d55cd43790847b646b23cdf11ada4a00eff15fb48.pem"
+}
+
+# Buypass Class 3 Root CA
+trust_anchors {
+ filename: "edf7ebbca27a2a384d387b7d4010c666e2edb4843e4c29b4ae1d5b9332e6b24d.pem"
+}
+
+# certSIGN Root CA G2
+trust_anchors {
+ filename: "657cfe2fa73faa38462571f332a2363a46fce7020951710702cdfbb6eeda3305.pem"
+}
+
+# certSIGN ROOT CA
+trust_anchors {
+ filename: "eaa962c4fa4a6bafebe415196d351ccd888d4f53f3fa8ae6d7c466a94e6042bb.pem"
+}
+
+# CFCA EV ROOT
+trust_anchors {
+ filename: "5cc3d78e4e1d5e45547a04e6873e64f90cf9536d1ccc2ef800f355c4c5fd70fd.pem"
+}
+
+# Chunghwa Telecom Co., Ltd. - ePKI Root Certification Authority
+trust_anchors {
+ filename: "c0a6f4dc63a24bfdcf54ef2a6a082a0a72de35803e2ff5ff527ae5d87206dfd5.pem"
+}
+
+# SecureSign RootCA11
+trust_anchors {
+ filename: "bf0feefb9e3a581ad5f9e9db7589985743d261085c4d314f6f5d7259aa421612.pem"
+}
+
+# D-TRUST Root Class 3 CA 2 2009
+trust_anchors {
+ filename: "49e7a442acf0ea6287050054b52564b650e4f49e42e348d6aa38e039e957b1c1.pem"
+}
+
+# D-TRUST Root Class 3 CA 2 EV 2009
+trust_anchors {
+ filename: "eec5496b988ce98625b934092eec2908bed0b0f316c2d4730c84eaf1f3d34881.pem"
+}
+
+# T-TeleSec GlobalRoot Class 2
+trust_anchors {
+ filename: "91e2f5788d5810eba7ba58737de1548a8ecacd014598bc0b143e041b17052552.pem"
+}
+
+# T-TeleSec GlobalRoot Class 3
+trust_anchors {
+ filename: "fd73dad31c644ff1b43bef0ccdda96710b9cd9875eca7e31707af3e96d522bbd.pem"
+}
+
+# Certigna Root CA
+trust_anchors {
+ filename: "d48d3d23eedb50a459e55197601c27774b9d7b18c94d5a059511a10250b93168.pem"
+}
+
+# Certigna
+trust_anchors {
+ filename: "e3b6a2db2ed7ce48842f7ac53241c7b71d54144bfb40c11f3f1d0b42f5eea12d.pem"
+}
+
+# Baltimore CyberTrust Root
+trust_anchors {
+ filename: "16af57a9f676b0ab126095aa5ebadef22ab31119d644ac95cd4b93dbf3f26aeb.pem"
+}
+
+# DigiCert Global Root G3
+trust_anchors {
+ filename: "31ad6648f8104138c738f39ea4320133393e3a18cc02296ef97c2ac9ef6731d0.pem"
+}
+
+# DigiCert Assured ID Root CA
+trust_anchors {
+ filename: "3e9099b5015e8f486c00bcea9d111ee721faba355a89bcf1df69561e3dc6325c.pem"
+}
+
+# DigiCert Global Root CA
+trust_anchors {
+ filename: "4348a0e9444c78cb265e058d5e8944b4d84f9662bd26db257f8934a443c70161.pem"
+}
+
+# DigiCert Trusted Root G4
+trust_anchors {
+ filename: "552f7bdcf1a7af9e6ce672017f4f12abf77240c78e761ac203d1d9d20ac89988.pem"
+}
+
+# DigiCert High Assurance EV Root CA
+trust_anchors {
+ filename: "7431e5f4c3c1ce4690774f0b61e05440883ba9a01ed00ba6abd7806ed3b118cf.pem"
+}
+
+# DigiCert Assured ID Root G2
+trust_anchors {
+ filename: "7d05ebb682339f8c9451ee094eebfefa7953a114edb2f44949452fab7d2fc185.pem"
+}
+
+# DigiCert Assured ID Root G3
+trust_anchors {
+ filename: "7e37cb8b4c47090cab36551ba6f45db840680fba166a952db100717f43053fc2.pem"
+}
+
+# Cybertrust Global Root
+trust_anchors {
+ filename: "960adf0063e96356750c2965dd0a0867da0b9cbd6e77714aeafb2349ab393da3.pem"
+}
+
+# DigiCert Global Root G2
+trust_anchors {
+ filename: "cb3ccbb76031e5e0138f8dd39a23f9de47ffc35e43c1144cea27d46a5ab1cb5f.pem"
+}
+
+# CA Disig Root R2
+trust_anchors {
+ filename: "e23d4a036d7b70e9f595b1422079d2b91edfbb1fb651a0633eaa8a9dc5f80703.pem"
+}
+
+# E-Tugra Certification Authority
+trust_anchors {
+ filename: "b0bfd52bb0d7d9bd92bf5d4dc13da255c02c542f378365ea893911f55e55f23c.pem"
+}
+
+# emSign Root CA - C1
+trust_anchors {
+ filename: "125609aa301da0a249b97a8239cb6a34216f44dcac9f3954b14292f2e8c8608f.pem"
+}
+
+# emSign Root CA - G1
+trust_anchors {
+ filename: "40f6af0346a99aa1cd1d555a4e9cce62c7f9634603ee406615833dc8c8d00367.pem"
+}
+
+# emSign ECC Root CA - G3
+trust_anchors {
+ filename: "86a1ecba089c4a8d3bbe2734c612ba341d813e043cf9e8a862cd5c57a36bbe6b.pem"
+}
+
+# emSign ECC Root CA - C3
+trust_anchors {
+ filename: "bc4d809b15189d78db3e1d8cf4f9726a795da1643ca5f1358e1ddb0edc0d7eb3.pem"
+}
+
+# Entrust Root Certification Authority - EC1
+trust_anchors {
+ filename: "02ed0eb28c14da45165c566791700d6451d7fb56f0b2ab1d3b8eb070e56edff5.pem"
+}
+
+# AffirmTrust Commercial
+trust_anchors {
+ filename: "0376ab1d54c5f9803ce4b2e201a0ee7eef7b57b636e8a93c9b8d4860c96f5fa7.pem"
+}
+
+# AffirmTrust Networking
+trust_anchors {
+ filename: "0a81ec5a929777f145904af38d5d509f66b5e2c58fcdb531058b0e17f3f0b41b.pem"
+}
+
+# Entrust Root Certification Authority - G2
+trust_anchors {
+ filename: "43df5774b03e7fef5fe40d931a7bedf1bb2e6b42738c4e6d3841103d3aa7f339.pem"
+}
+
+# Entrust.net Certification Authority (2048)
+trust_anchors {
+ filename: "6dc47172e01cbcb0bf62580d895fe2b8ac9ad4f873801e0c10b9c837d21eb177.pem"
+}
+
+# AffirmTrust Premium
+trust_anchors {
+ filename: "70a73f7f376b60074248904534b11482d5bf0e698ecc498df52577ebf2e93b9a.pem"
+}
+
+# Entrust Root Certification Authority
+trust_anchors {
+ filename: "73c176434f1bc6d5adf45b0e76e727287c8de57616c1e6e6141a2b2cbc7d8e4c.pem"
+}
+
+# AffirmTrust Premium ECC
+trust_anchors {
+ filename: "bd71fdf6da97e4cf62d1647add2581b07d79adf8397eb4ecba9c5e8488821423.pem"
+}
+
+# Entrust Root Certification Authority - G4
+trust_anchors {
+ filename: "db3517d1f6732a2d5ab97c533ec70779ee3270a62fb4ac4238372460e6f01e88.pem"
+}
+
+# GDCA TrustAUTH R5 ROOT
+trust_anchors {
+ filename: "bfff8fd04433487d6a8aa60c1a29767a9fc2bbb05e420f713a13b992891d3893.pem"
+}
+
+# GlobalSign
+trust_anchors {
+ filename: "179fbc148a3dd00fd24ea13458cc43bfa7f59c8182d783a513f6ebec100c8924.pem"
+}
+
+# GlobalSign
+trust_anchors {
+ filename: "2cabeafe37d06ca22aba7391c0033d25982952c453647349763a3ab5ad6ccf69.pem"
+}
+
+# GlobalSign
+trust_anchors {
+ filename: "cbb522d7b7f127ad6a0113865bdf1cd4102e7d0759af635a7cf4720dc963c53b.pem"
+}
+
+# GlobalSign Root CA
+trust_anchors {
+ filename: "ebd41040e4bb3ec742c9e381d31ef2a41a48b6685c96e7cef3c1df6cd4331c99.pem"
+}
+
+# Starfield Class 2 CA
+trust_anchors {
+ filename: "1465fa205397b876faa6f0a9958e5590e40fcc7faa4fb7c2c8677521fb5fb658.pem"
+}
+
+# Starfield Root Certificate Authority - G2
+trust_anchors {
+ filename: "2ce1cb0bf9d2f9e102993fbe215152c3b2dd0cabde1c68e5319b839154dbb7f5.pem"
+}
+
+# Go Daddy Root Certificate Authority - G2
+trust_anchors {
+ filename: "45140b3247eb9cc8c5b4f0d7b53091f73292089e6e5a63e2749dd3aca9198eda.pem"
+}
+
+# Go Daddy Class 2 CA
+trust_anchors {
+ filename: "c3846bf24b9e93ca64274c0ec67c1ecc5e024ffcacd2d74019350e81fe546ae4.pem"
+}
+
+# GTS Root R3
+trust_anchors {
+ filename: "15d5b8774619ea7d54ce1ca6d0b0c403e037a917f131e8a04e1e6b7a71babce5.pem"
+}
+
+# GTS Root R1
+trust_anchors {
+ filename: "2a575471e31340bc21581cbd2cf13e158463203ece94bcf9d3cc196bf09a5472.pem"
+}
+
+# GTS Root R4
+trust_anchors {
+ filename: "71cca5391f9e794b04802530b363e121da8a3043bb26662fea4dca7fc951a4bd.pem"
+}
+
+# GlobalSign
+trust_anchors {
+ filename: "bec94911c2955676db6c0a550986d76e3ba005667c442c9762b4fbb773de228c.pem"
+}
+
+# GTS Root R2
+trust_anchors {
+ filename: "c45d7bb08e6d67e62e4235110b564e5f78fd92ef058c840aea4e6455d7585c60.pem"
+}
+
+# GlobalSign
+trust_anchors {
+ filename: "ca42dd41745fd0b81eb902362cf9d8bf719da1bd1b1efc946f5b4c99f42c1b9e.pem"
+}
+
+# Hongkong Post Root CA 3
+trust_anchors {
+ filename: "5a2fc03f0c83b090bbfa40604b0988446c7636183df9846e17101a447fb8efd6.pem"
+}
+
+# Hongkong Post Root CA 1
+trust_anchors {
+ filename: "f9e67d336c51002ac054c632022d66dda2e7e3fff10ad061ed31d8bbb410cfb2.pem"
+}
+
+# ACCVRAIZ1
+trust_anchors {
+ filename: "9a6ec012e1a7da9dbe34194d478ad7c0db1822fb071df12981496ed104384113.pem"
+}
+
+# FNMT-RCM - SHA256
+trust_anchors {
+ filename: "ebc5570c29018c4d67b1aa127baf12f703b4611ebc17b7dab5573894179b93fa.pem"
+}
+
+# Staat der Nederlanden Root CA - G3
+trust_anchors {
+ filename: "3c4fb0b95ab8b30032f432b86f535fe172c185d0fd39865837cf36187fa6f428.pem"
+}
+
+# Staat der Nederlanden EV Root CA
+trust_anchors {
+ filename: "4d2491414cfe956746ec4cefa6cf6f72e28a1329432f9d8a907ac4cb5dadc15a.pem"
+}
+
+# TUBITAK Kamu SM SSL Kok Sertifikasi - Surum 1
+trust_anchors {
+ filename: "46edc3689046d53a453fb3104ab80dcaec658b2660ea1629dd7e867990648716.pem"
+}
+
+# Hellenic Academic and Research Institutions ECC RootCA 2015
+trust_anchors {
+ filename: "44b545aa8a25e65a73ca15dc27fc36d24c1cb9953a066539b11582dc487b4833.pem"
+}
+
+# Hellenic Academic and Research Institutions RootCA 2015
+trust_anchors {
+ filename: "a040929a02ce53b4acf4f2ffc6981ce4496f755e6d45fe0b2a692bcd52523f36.pem"
+}
+
+# Hellenic Academic and Research Institutions RootCA 2011
+trust_anchors {
+ filename: "bc104f15a48be709dca542a7e1d4b9df6f054527e802eaa92d595444258afe71.pem"
+}
+
+# DST Root CA X3
+trust_anchors {
+ filename: "0687260331a72403d909f105e69bcf0d32e1bd2493ffc6d9206d11bcd6770739.pem"
+}
+
+# IdenTrust Public Sector Root CA 1
+trust_anchors {
+ filename: "30d0895a9a448a262091635522d1f52010b5867acae12c78ef958fd4f4389f2f.pem"
+}
+
+# IdenTrust Commercial Root CA 1
+trust_anchors {
+ filename: "5d56499be4d2e08bcfcad08a3e38723d50503bde706948e42f55603019e528ae.pem"
+}
+
+# ISRG Root X1
+trust_anchors {
+ filename: "96bcec06264976f37460779acf28c5a7cfe8a3c0aae11a8ffcee05c0bddf08c6.pem"
+}
+
+# Izenpe.com
+trust_anchors {
+ filename: "2530cc8e98321502bad96f9b1fba1b099e2d299e0f4548bb914f363bc0d4531f.pem"
+}
+
+# SZAFIR ROOT CA2
+trust_anchors {
+ filename: "a1339d33281a0b56e557d3d32b1ce7f9367eb094bd5fa72a7e5004c8ded7cafe.pem"
+}
+
+# Microsec e-Szigno Root CA 2009
+trust_anchors {
+ filename: "3c5f81fea5fab82c64bfa2eaecafcde8e077fc8620a7cae537163df36edbf378.pem"
+}
+
+# e-Szigno Root CA 2017
+trust_anchors {
+ filename: "beb00b30839b9bc32c32e4447905950641f26421b15ed089198b518ae2ea1b99.pem"
+}
+
+# Microsoft ECC Root Certificate Authority 2017
+trust_anchors {
+ filename: "358df39d764af9e1b766e9c972df352ee15cfac227af6ad1d70e8e4a6edcba02.pem"
+}
+
+# Microsoft RSA Root Certificate Authority 2017
+trust_anchors {
+ filename: "c741f70f4b2a8d88bf2e71c14122ef53ef10eba0cfa5e64cfa20f418853073e0.pem"
+}
+
+# NetLock Arany (Class Gold) Főtanúsítvány
+trust_anchors {
+ filename: "6c61dac3a2def031506be036d2a6fe401994fbd13df9c8d466599274c446ec98.pem"
+}
+
+# OISTE WISeKey Global Root GB CA
+trust_anchors {
+ filename: "6b9c08e86eb0f767cfad65cd98b62149e5494a67f5845e7bd1ed019f27b86bd6.pem"
+}
+
+# OISTE WISeKey Global Root GC CA
+trust_anchors {
+ filename: "8560f91c3624daba9570b5fea0dbe36ff11a8323be9486854fb3f34a5571198d.pem"
+}
+
+# QuoVadis Root CA 3
+trust_anchors {
+ filename: "18f1fc7f205df8adddeb7fe007dd57e3af375a9c4d8d73546bf4f1fed1e18d35.pem"
+}
+
+# QuoVadis Root CA 2
+trust_anchors {
+ filename: "85a0dd7dd720adb7ff05f83d542b209dc7ff4528f7d677b18389fea5e5c49e86.pem"
+}
+
+# QuoVadis Root CA 3 G3
+trust_anchors {
+ filename: "88ef81de202eb018452e43f864725cea5fbd1fc2d9d205730709c5d8b8690f46.pem"
+}
+
+# QuoVadis Root CA 1 G3
+trust_anchors {
+ filename: "8a866fd1b276b57e578e921c65828a2bed58e9f2f288054134b7f1f4bfc9cc74.pem"
+}
+
+# QuoVadis Root CA 2 G3
+trust_anchors {
+ filename: "8fe4fb0af93a4d0d67db0bebb23e37c71bf325dcbcdd240ea04daf58b47e1840.pem"
+}
+
+# QuoVadis Root Certification Authority
+trust_anchors {
+ filename: "a45ede3bbbf09c8ae15c72efc07268d693a21c996fd51e67ca079460fd6d8873.pem"
+}
+
+# Security Communication RootCA2
+trust_anchors {
+ filename: "513b2cecb810d4cde5dd85391adfc6c2dd60d87bb736d2b521484aa47a0ebef6.pem"
+}
+
+# SECOM Trust.net - Security Communication RootCA1
+trust_anchors {
+ filename: "e75e72ed9f560eec6eb4800073a43fc3ad19195a392282017895974a99026b6c.pem"
+}
+
+# COMODO Certification Authority
+trust_anchors {
+ filename: "0c2cd63df7806fa399ede809116b575bf87989f06518f9808c860503178baf66.pem"
+}
+
+# COMODO ECC Certification Authority
+trust_anchors {
+ filename: "1793927a0614549789adce2f8f34f7f0b66d0f3ae3a3b84d21ec15dbba4fadc7.pem"
+}
+
+# USERTrust ECC Certification Authority
+trust_anchors {
+ filename: "4ff460d54b9c86dabfbcfc5712e0400d2bed3fbc4d4fbdaa86e06adcd2a9ad7a.pem"
+}
+
+# COMODO RSA Certification Authority
+trust_anchors {
+ filename: "52f0e1c4e58ec629291b60317f074671b85d7ea80d5b07273463534b32b40234.pem"
+}
+
+# AAA Certificate Services
+trust_anchors {
+ filename: "d7a7a0fb5d7e2731d771e9484ebcdef71d5f0c3e0a2948782bc83ee0ea699ef4.pem"
+}
+
+# USERTrust RSA Certification Authority
+trust_anchors {
+ filename: "e793c9b02fd8aa13e21c31228accb08119643b749c898964b1746d46c3d4cbd2.pem"
+}
+
+# Secure Global CA
+trust_anchors {
+ filename: "4200f5043ac8590ebb527d209ed1503029fbcbd41ca1b506ec27f15ade7dac69.pem"
+}
+
+# Trustwave Global ECC P384 Certification Authority
+trust_anchors {
+ filename: "55903859c8c0c3ebb8759ece4e2557225ff5758bbd38ebd48276601e1bd58097.pem"
+}
+
+# Trustwave Global ECC P256 Certification Authority
+trust_anchors {
+ filename: "945bbc825ea554f489d1fd51a73ddf2ea624ac7019a05205225c22a78ccfa8b4.pem"
+}
+
+# Trustwave Global Certification Authority
+trust_anchors {
+ filename: "97552015f5ddfc3c8788c006944555408894450084f100867086bc1a2bb58dc8.pem"
+}
+
+# XRamp Global Certification Authority
+trust_anchors {
+ filename: "cecddc905099d8dadfc5b1d209b737cbe2c18cfb2c10c0ff0bcf0d3286fc1aa2.pem"
+}
+
+# SecureTrust CA
+trust_anchors {
+ filename: "f1c1b50ae5a20dd8030ec9f6bc24823dd367b5255759b4e71b61fce9f7375d73.pem"
+}
+
+# UCA Global G2 Root
+trust_anchors {
+ filename: "9bea11c976fe014764c1be56a6f914b5a560317abd9988393382e5161aa0493c.pem"
+}
+
+# UCA Extended Validation Root
+trust_anchors {
+ filename: "d43af9b35473755c9684fc06d7d8cb70ee5c28e773fb294eb41ee71722924d24.pem"
+}
+
+# SSL.com EV Root Certification Authority ECC
+trust_anchors {
+ filename: "22a2c1f7bded704cc1e701b5f408c310880fe956b5de2a4a44f99c873a25a7c8.pem"
+}
+
+# SSL.com EV Root Certification Authority RSA R2
+trust_anchors {
+ filename: "2e7bf16cc22485a7bbe2aa8696750761b0ae39be3b2fe9d0cc6d4ef73491425c.pem"
+}
+
+# SSL.com Root Certification Authority ECC
+trust_anchors {
+ filename: "3417bb06cc6007da1b961c920b8ab4ce3fad820e4aa30b9acbc4a74ebdcebc65.pem"
+}
+
+# SSL.com Root Certification Authority RSA
+trust_anchors {
+ filename: "85666a562ee0be5ce925c1d8890a6f76a87ec16d4d7d5f29ea7419cf20123b69.pem"
+}
+
+# SwissSign Gold CA - G2
+trust_anchors {
+ filename: "62dd0be9b9f50a163ea0f8e75c053b1eca57ea55c8688f647c6881f2c8357b95.pem"
+}
+
+# SwissSign Silver CA - G2
+trust_anchors {
+ filename: "be6c4da2bbb9ba59b6f3939768374246c3c005993fa98f020d1dedbed48a81d5.pem"
+}
+
+# TWCA Global Root CA
+trust_anchors {
+ filename: "59769007f7685d0fcd50872f9f95d5755a5b2b457d81f3692b610a98672f0e1b.pem"
+}
+
+# TWCA Root Certification Authority
+trust_anchors {
+ filename: "bfd88fe1101c41ae3e801bf8be56350ee9bad1a6b9bd515edc5c6d5b8711ac44.pem"
+}
+
+# Sonera Class2 CA
+trust_anchors {
+ filename: "7908b40314c138100b518d0735807ffbfcf8518a0095337105ba386b153dd927.pem"
+}
+
+# TeliaSonera Root CA v1
+trust_anchors {
+ filename: "dd6936fe21f8f077c123a1a521c12224f72255b73e03a7260693e8a24b0fa389.pem"
+}
+
+# TrustCor RootCert CA-2
+trust_anchors {
+ filename: "0753e940378c1bd5e3836e395daea5cb839e5046f1bd0eae1951cf10fec7c965.pem"
+}
+
+# TrustCor ECA-1
+trust_anchors {
+ filename: "5a885db19c01d912c5759388938cafbbdf031ab2d48e91ee15589b42971d039c.pem"
+}
+
+# TrustCor RootCert CA-1
+trust_anchors {
+ filename: "d40e9c86cd8fe468c1776959f49ea774fa548684b6c406f3909261f4dce2575c.pem"
+}
+
+# Network Solutions Certificate Authority
+trust_anchors {
+ filename: "15f0ba00a3ac7af3ac884c072b1011a077bd77c097f40164b2f8598abd83860c.pem"
+}
diff --git a/chromium/net/der/input.cc b/chromium/net/der/input.cc
index 835651272fb..580789f4aef 100644
--- a/chromium/net/der/input.cc
+++ b/chromium/net/der/input.cc
@@ -33,6 +33,10 @@ base::StringPiece Input::AsStringPiece() const {
return base::StringPiece(reinterpret_cast<const char*>(data_), len_);
}
+base::span<const uint8_t> Input::AsSpan() const {
+ return base::make_span(data_, len_);
+}
+
bool operator==(const Input& lhs, const Input& rhs) {
if (lhs.Length() != rhs.Length())
return false;
diff --git a/chromium/net/der/input.h b/chromium/net/der/input.h
index 656ff997802..69e4f5cbc7d 100644
--- a/chromium/net/der/input.h
+++ b/chromium/net/der/input.h
@@ -11,6 +11,7 @@
#include <string>
#include "base/compiler_specific.h"
+#include "base/containers/span.h"
#include "base/strings/string_piece.h"
#include "net/base/net_export.h"
@@ -66,6 +67,11 @@ class NET_EXPORT_PRIVATE Input {
// Input.
base::StringPiece AsStringPiece() const;
+ // Returns a base::span pointing to the same data as the Input. The resulting
+ // base::span must not outlive the data that was used to construct this
+ // Input.
+ base::span<const uint8_t> AsSpan() const;
+
private:
// This constructor is deleted to prevent constructing an Input from a
// std::string r-value. Since the Input points to memory owned by another
diff --git a/chromium/net/der/input_unittest.cc b/chromium/net/der/input_unittest.cc
index c4064816059..f0a3a4a4069 100644
--- a/chromium/net/der/input_unittest.cc
+++ b/chromium/net/der/input_unittest.cc
@@ -4,7 +4,7 @@
#include "net/der/input.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/parse_values_unittest.cc b/chromium/net/der/parse_values_unittest.cc
index e677531795b..266a0715a50 100644
--- a/chromium/net/der/parse_values_unittest.cc
+++ b/chromium/net/der/parse_values_unittest.cc
@@ -6,8 +6,8 @@
#include <stdint.h>
+#include "base/cxx17_backports.h"
#include "base/macros.h"
-#include "base/stl_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/der/parser.h b/chromium/net/der/parser.h
index 7c8e24bf632..fc372e6ff32 100644
--- a/chromium/net/der/parser.h
+++ b/chromium/net/der/parser.h
@@ -97,6 +97,9 @@ class NET_EXPORT Parser {
// the Parser object.
explicit Parser(const Input& input);
+ Parser(const Parser&) = default;
+ Parser& operator=(const Parser&) = default;
+
// Returns whether there is any more data left in the input to parse. This
// does not guarantee that the data is parseable.
bool HasMore();
@@ -206,8 +209,6 @@ class NET_EXPORT Parser {
private:
CBS cbs_;
size_t advance_len_;
-
- DISALLOW_COPY(Parser);
};
} // namespace der
diff --git a/chromium/net/disk_cache/backend_unittest.cc b/chromium/net/disk_cache/backend_unittest.cc
index e2b420202c2..8bdbe5b6d54 100644
--- a/chromium/net/disk_cache/backend_unittest.cc
+++ b/chromium/net/disk_cache/backend_unittest.cc
@@ -8,13 +8,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/memory/memory_pressure_listener.h"
#include "base/metrics/field_trial.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
@@ -69,6 +69,8 @@ using testing::Field;
#if defined(OS_WIN)
#include "base/win/scoped_handle.h"
+
+#include <windows.h>
#endif
// Provide a BackendImpl object to macros from histogram_macros.h.
diff --git a/chromium/net/disk_cache/blockfile/backend_impl.cc b/chromium/net/disk_cache/blockfile/backend_impl.cc
index 05e07338fe3..665dd1f439a 100644
--- a/chromium/net/disk_cache/blockfile/backend_impl.cc
+++ b/chromium/net/disk_cache/blockfile/backend_impl.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
@@ -21,7 +22,6 @@
#include "base/metrics/histogram.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/net/disk_cache/blockfile/block_files.cc b/chromium/net/disk_cache/blockfile/block_files.cc
index e9375270c1e..9beaade906d 100644
--- a/chromium/net/disk_cache/blockfile/block_files.cc
+++ b/chromium/net/disk_cache/blockfile/block_files.cc
@@ -157,10 +157,6 @@ bool BlockHeader::UsedMapBlock(int index, int size) {
int byte_index = index / 8;
uint8_t* byte_map = reinterpret_cast<uint8_t*>(header_->allocation_map);
- uint8_t map_block = byte_map[byte_index];
-
- if (index % 8 >= 4)
- map_block >>= 4;
STRESS_DCHECK((((1 << size) - 1) << (index % 8)) < 0x100);
uint8_t to_clear = ((1 << size) - 1) << (index % 8);
diff --git a/chromium/net/disk_cache/blockfile/entry_impl.cc b/chromium/net/disk_cache/blockfile/entry_impl.cc
index 9d697a8dcba..1dc20bb8bb9 100644
--- a/chromium/net/disk_cache/blockfile/entry_impl.cc
+++ b/chromium/net/disk_cache/blockfile/entry_impl.cc
@@ -405,12 +405,12 @@ int EntryImpl::WriteSparseDataImpl(int64_t offset,
return result;
}
-int EntryImpl::GetAvailableRangeImpl(int64_t offset, int len, int64_t* start) {
+RangeResult EntryImpl::GetAvailableRangeImpl(int64_t offset, int len) {
int result = InitSparseData();
if (net::OK != result)
- return result;
+ return RangeResult(static_cast<net::Error>(result));
- return sparse_->GetAvailableRange(offset, len, start);
+ return sparse_->GetAvailableRange(offset, len);
}
void EntryImpl::CancelSparseIOImpl() {
@@ -922,16 +922,14 @@ int EntryImpl::WriteSparseData(int64_t offset,
return net::ERR_IO_PENDING;
}
-int EntryImpl::GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) {
+RangeResult EntryImpl::GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) {
if (!background_queue_.get())
- return net::ERR_UNEXPECTED;
+ return RangeResult(net::ERR_UNEXPECTED);
- background_queue_->GetAvailableRange(this, offset, len, start,
- std::move(callback));
- return net::ERR_IO_PENDING;
+ background_queue_->GetAvailableRange(this, offset, len, std::move(callback));
+ return RangeResult(net::ERR_IO_PENDING);
}
bool EntryImpl::CouldBeSparse() const {
diff --git a/chromium/net/disk_cache/blockfile/entry_impl.h b/chromium/net/disk_cache/blockfile/entry_impl.h
index 24da1f923af..e1cf14d52f6 100644
--- a/chromium/net/disk_cache/blockfile/entry_impl.h
+++ b/chromium/net/disk_cache/blockfile/entry_impl.h
@@ -71,7 +71,7 @@ class NET_EXPORT_PRIVATE EntryImpl
IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback);
- int GetAvailableRangeImpl(int64_t offset, int len, int64_t* start);
+ RangeResult GetAvailableRangeImpl(int64_t offset, int len);
void CancelSparseIOImpl();
int ReadyForSparseIOImpl(CompletionOnceCallback callback);
@@ -193,10 +193,9 @@ class NET_EXPORT_PRIVATE EntryImpl
IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
- int GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) override;
+ RangeResult GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) override;
bool CouldBeSparse() const override;
void CancelSparseIO() override;
net::Error ReadyForSparseIO(CompletionOnceCallback callback) override;
diff --git a/chromium/net/disk_cache/blockfile/histogram_macros.h b/chromium/net/disk_cache/blockfile/histogram_macros.h
index a5de85cc9da..f709e2d0ebb 100644
--- a/chromium/net/disk_cache/blockfile/histogram_macros.h
+++ b/chromium/net/disk_cache/blockfile/histogram_macros.h
@@ -104,6 +104,7 @@
break; \
case net::GENERATED_BYTE_CODE_CACHE: \
case net::GENERATED_NATIVE_CODE_CACHE: \
+ case net::GENERATED_WEBUI_BYTE_CODE_CACHE: \
break; \
} \
}
diff --git a/chromium/net/disk_cache/blockfile/in_flight_backend_io.cc b/chromium/net/disk_cache/blockfile/in_flight_backend_io.cc
index cc9bcf4457e..c1dc7656170 100644
--- a/chromium/net/disk_cache/blockfile/in_flight_backend_io.cc
+++ b/chromium/net/disk_cache/blockfile/in_flight_backend_io.cc
@@ -49,6 +49,13 @@ BackendIO::BackendIO(InFlightIO* controller,
entry_result_callback_ = std::move(callback);
}
+BackendIO::BackendIO(InFlightIO* controller,
+ BackendImpl* backend,
+ RangeResultCallback callback)
+ : BackendIO(controller, backend) {
+ range_result_callback_ = std::move(callback);
+}
+
BackendIO::BackendIO(InFlightIO* controller, BackendImpl* backend)
: BackgroundIO(controller),
backend_(backend),
@@ -61,8 +68,7 @@ BackendIO::BackendIO(InFlightIO* controller, BackendImpl* backend)
offset_(0),
buf_len_(0),
truncate_(false),
- offset64_(0),
- start_(nullptr) {
+ offset64_(0) {
start_time_ = base::TimeTicks::Now();
}
@@ -115,6 +121,10 @@ void BackendIO::RunEntryResultCallback() {
std::move(entry_result_callback_).Run(std::move(entry_result));
}
+void BackendIO::RunRangeResultCallback() {
+ std::move(range_result_callback_).Run(range_result_);
+}
+
void BackendIO::Init() {
operation_ = OP_INIT;
}
@@ -236,15 +246,11 @@ void BackendIO::WriteSparseData(EntryImpl* entry,
buf_len_ = buf_len;
}
-void BackendIO::GetAvailableRange(EntryImpl* entry,
- int64_t offset,
- int len,
- int64_t* start) {
+void BackendIO::GetAvailableRange(EntryImpl* entry, int64_t offset, int len) {
operation_ = OP_GET_RANGE;
entry_ = entry;
offset64_ = offset;
buf_len_ = len;
- start_ = start;
}
void BackendIO::CancelSparseIO(EntryImpl* entry) {
@@ -384,7 +390,8 @@ void BackendIO::ExecuteEntryOperation() {
base::BindOnce(&BackendIO::OnIOComplete, this));
break;
case OP_GET_RANGE:
- result_ = entry_->GetAvailableRangeImpl(offset64_, buf_len_, start_);
+ range_result_ = entry_->GetAvailableRangeImpl(offset64_, buf_len_);
+ result_ = range_result_.net_error;
break;
case OP_CANCEL_IO:
entry_->CancelSparseIOImpl();
@@ -581,15 +588,13 @@ void InFlightBackendIO::WriteSparseData(EntryImpl* entry,
PostOperation(FROM_HERE, operation.get());
}
-void InFlightBackendIO::GetAvailableRange(
- EntryImpl* entry,
- int64_t offset,
- int len,
- int64_t* start,
- net::CompletionOnceCallback callback) {
+void InFlightBackendIO::GetAvailableRange(EntryImpl* entry,
+ int64_t offset,
+ int len,
+ RangeResultCallback callback) {
scoped_refptr<BackendIO> operation(
new BackendIO(this, backend_, std::move(callback)));
- operation->GetAvailableRange(entry, offset, len, start);
+ operation->GetAvailableRange(entry, offset, len);
PostOperation(FROM_HERE, operation.get());
}
@@ -620,6 +625,11 @@ void InFlightBackendIO::OnOperationComplete(BackgroundIO* operation,
if (op->has_callback() && (!cancel || op->IsEntryOperation()))
op->RunCallback(op->result());
+ if (op->has_range_result_callback()) {
+ DCHECK(op->IsEntryOperation());
+ op->RunRangeResultCallback();
+ }
+
if (op->has_entry_result_callback() && !cancel) {
DCHECK(!op->IsEntryOperation());
op->RunEntryResultCallback();
diff --git a/chromium/net/disk_cache/blockfile/in_flight_backend_io.h b/chromium/net/disk_cache/blockfile/in_flight_backend_io.h
index d06436e90c4..a84a2e3e418 100644
--- a/chromium/net/disk_cache/blockfile/in_flight_backend_io.h
+++ b/chromium/net/disk_cache/blockfile/in_flight_backend_io.h
@@ -41,6 +41,10 @@ class BackendIO : public BackgroundIO {
BackendImpl* backend,
EntryResultCallback callback);
+ BackendIO(InFlightIO* controller,
+ BackendImpl* backend,
+ RangeResultCallback callback);
+
// Runs the actual operation on the background thread.
void ExecuteOperation();
@@ -62,6 +66,11 @@ class BackendIO : public BackgroundIO {
}
void RunEntryResultCallback();
+ bool has_range_result_callback() const {
+ return !range_result_callback_.is_null();
+ }
+ void RunRangeResultCallback();
+
// The operations we proxy:
void Init();
void OpenOrCreateEntry(const std::string& key);
@@ -92,10 +101,7 @@ class BackendIO : public BackgroundIO {
int64_t offset,
net::IOBuffer* buf,
int buf_len);
- void GetAvailableRange(EntryImpl* entry,
- int64_t offset,
- int len,
- int64_t* start);
+ void GetAvailableRange(EntryImpl* entry, int64_t offset, int len);
void CancelSparseIO(EntryImpl* entry);
void ReadyForSparseIO(EntryImpl* entry);
@@ -155,6 +161,10 @@ class BackendIO : public BackgroundIO {
Entry* out_entry_; // if set, already has the user's ref added.
bool out_entry_opened_;
+ // For GetAvailableRange
+ RangeResultCallback range_result_callback_;
+ RangeResult range_result_;
+
// The arguments of all the operations we proxy:
std::string key_;
base::Time initial_time_;
@@ -168,7 +178,6 @@ class BackendIO : public BackgroundIO {
int buf_len_;
bool truncate_;
int64_t offset64_;
- int64_t* start_;
base::TimeTicks start_time_;
base::OnceClosure task_;
@@ -230,8 +239,7 @@ class InFlightBackendIO : public InFlightIO {
void GetAvailableRange(EntryImpl* entry,
int64_t offset,
int len,
- int64_t* start,
- net::CompletionOnceCallback callback);
+ RangeResultCallback callback);
void CancelSparseIO(EntryImpl* entry);
void ReadyForSparseIO(EntryImpl* entry, net::CompletionOnceCallback callback);
diff --git a/chromium/net/disk_cache/blockfile/mapped_file_unittest.cc b/chromium/net/disk_cache/blockfile/mapped_file_unittest.cc
index 72bbfe6ed0f..06714a96381 100644
--- a/chromium/net/disk_cache/blockfile/mapped_file_unittest.cc
+++ b/chromium/net/disk_cache/blockfile/mapped_file_unittest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "net/disk_cache/blockfile/mapped_file.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "net/disk_cache/disk_cache_test_base.h"
#include "net/disk_cache/disk_cache_test_util.h"
diff --git a/chromium/net/disk_cache/blockfile/sparse_control.cc b/chromium/net/disk_cache/blockfile/sparse_control.cc
index a914ac0dac4..0a1fee4f72b 100644
--- a/chromium/net/disk_cache/blockfile/sparse_control.cc
+++ b/chromium/net/disk_cache/blockfile/sparse_control.cc
@@ -336,25 +336,23 @@ int SparseControl::StartIO(SparseOperation op,
return net::ERR_IO_PENDING;
}
-int SparseControl::GetAvailableRange(int64_t offset, int len, int64_t* start) {
+RangeResult SparseControl::GetAvailableRange(int64_t offset, int len) {
DCHECK(init_);
// We don't support simultaneous IO for sparse data.
if (operation_ != kNoOperation)
- return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
-
- DCHECK(start);
+ return RangeResult(net::ERR_CACHE_OPERATION_NOT_SUPPORTED);
range_found_ = false;
int result = StartIO(kGetRangeOperation, offset, nullptr, len,
CompletionOnceCallback());
- if (range_found_) {
- *start = offset_;
- return result;
- }
+ if (range_found_)
+ return RangeResult(offset_, result);
- // This is a failure. We want to return a valid start value in any case.
- *start = offset;
- return result < 0 ? result : 0; // Don't mask error codes to the caller.
+ // This is a failure. We want to return a valid start value if it's just an
+ // empty range, though.
+ if (result < 0)
+ return RangeResult(static_cast<net::Error>(result));
+ return RangeResult(offset, 0);
}
void SparseControl::CancelIO() {
@@ -720,7 +718,8 @@ void SparseControl::DoChildrenIO() {
// |finished_| to true.
if (kGetRangeOperation == operation_ && entry_->net_log().IsCapturing()) {
entry_->net_log().EndEvent(net::NetLogEventType::SPARSE_GET_RANGE, [&] {
- return CreateNetLogGetAvailableRangeResultParams(offset_, result_);
+ return CreateNetLogGetAvailableRangeResultParams(
+ RangeResult(offset_, result_));
});
}
if (finished_) {
diff --git a/chromium/net/disk_cache/blockfile/sparse_control.h b/chromium/net/disk_cache/blockfile/sparse_control.h
index dfe16b2baa6..ebd6c91e68b 100644
--- a/chromium/net/disk_cache/blockfile/sparse_control.h
+++ b/chromium/net/disk_cache/blockfile/sparse_control.h
@@ -15,6 +15,7 @@
#include "net/base/completion_once_callback.h"
#include "net/disk_cache/blockfile/bitmap.h"
#include "net/disk_cache/blockfile/disk_format.h"
+#include "net/disk_cache/disk_cache.h"
namespace net {
class IOBuffer;
@@ -23,7 +24,6 @@ class DrainableIOBuffer;
namespace disk_cache {
-class Entry;
class EntryImpl;
// This class provides support for the sparse capabilities of the disk cache.
@@ -68,7 +68,7 @@ class SparseControl {
CompletionOnceCallback callback);
// Implements Entry::GetAvailableRange().
- int GetAvailableRange(int64_t offset, int len, int64_t* start);
+ RangeResult GetAvailableRange(int64_t offset, int len);
// Cancels the current sparse operation (if any).
void CancelIO();
diff --git a/chromium/net/disk_cache/blockfile/stats.cc b/chromium/net/disk_cache/blockfile/stats.cc
index 224e1c9d06a..4d6244f404a 100644
--- a/chromium/net/disk_cache/blockfile/stats.cc
+++ b/chromium/net/disk_cache/blockfile/stats.cc
@@ -5,6 +5,7 @@
#include "net/disk_cache/blockfile/stats.h"
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
#include "base/metrics/bucket_ranges.h"
#include "base/metrics/histogram.h"
@@ -12,7 +13,6 @@
#include "base/metrics/sample_vector.h"
#include "base/metrics/statistics_recorder.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/net/disk_cache/cache_util.cc b/chromium/net/disk_cache/cache_util.cc
index 2a4c34d5670..c290381ad7a 100644
--- a/chromium/net/disk_cache/cache_util.cc
+++ b/chromium/net/disk_cache/cache_util.cc
@@ -179,17 +179,20 @@ int PreferredCacheSize(int64_t available, net::CacheType type) {
percent_relative_size) /
100;
- if (available < 0)
- return static_cast<int32_t>(scaled_default_disk_cache_size);
-
- int64_t preferred_cache_size = PreferredCacheSizeInternal(available);
-
- // If the preferred cache size is less than 20% of the available space, scale
- // for the field trial, capping the scaled value at 20% of the available
- // space.
- if (preferred_cache_size < available / 5) {
- preferred_cache_size = std::min(
- (preferred_cache_size * percent_relative_size) / 100, available / 5);
+ int64_t preferred_cache_size = scaled_default_disk_cache_size;
+
+ // If available disk space is known, use it to compute a better value for
+ // preferred_cache_size.
+ if (available >= 0) {
+ preferred_cache_size = PreferredCacheSizeInternal(available);
+
+ // If the preferred cache size is less than 20% of the available space,
+ // scale for the field trial, capping the scaled value at 20% of the
+ // available space.
+ if (preferred_cache_size < available / 5) {
+ preferred_cache_size = std::min(
+ (preferred_cache_size * percent_relative_size) / 100, available / 5);
+ }
}
// Limit cache size to somewhat less than kint32max to avoid potential
@@ -204,6 +207,9 @@ int PreferredCacheSize(int64_t available, net::CacheType type) {
// Make the size limit 50% larger in that case.
if (type == net::GENERATED_NATIVE_CODE_CACHE) {
size_limit = (size_limit / 2) * 3;
+ } else if (type == net::GENERATED_WEBUI_BYTE_CODE_CACHE) {
+ size_limit =
+ std::min(size_limit, static_cast<int64_t>(kMaxWebUICodeCacheSize));
}
DCHECK_LT(size_limit, std::numeric_limits<int32_t>::max());
diff --git a/chromium/net/disk_cache/cache_util_unittest.cc b/chromium/net/disk_cache/cache_util_unittest.cc
index 7f8df01e969..39edcbef58b 100644
--- a/chromium/net/disk_cache/cache_util_unittest.cc
+++ b/chromium/net/disk_cache/cache_util_unittest.cc
@@ -151,6 +151,15 @@ TEST_F(CacheUtilTest, PreferredCacheSize) {
EXPECT_EQ(test_case.expected_without_trial,
PreferredCacheSize(test_case.available))
<< test_case.available;
+
+ // Preferred size for WebUI code cache matches expected_without_trial but
+ // should never be more than 5 MB.
+ int expected_webui_code_cache_size =
+ std::min(5 * 1024 * 1024, test_case.expected_without_trial);
+ EXPECT_EQ(expected_webui_code_cache_size,
+ PreferredCacheSize(test_case.available,
+ net::GENERATED_WEBUI_BYTE_CODE_CACHE))
+ << test_case.available;
}
// Check that the cache size cap is 50% higher for native code caches.
@@ -189,6 +198,15 @@ TEST_F(CacheUtilTest, PreferredCacheSize) {
EXPECT_EQ(test_case.expected_without_trial,
PreferredCacheSize(test_case.available,
net::GENERATED_BYTE_CODE_CACHE));
+
+ // Preferred size for WebUI code cache is not scaled by the trial, and
+ // should never be more than 5 MB.
+ int expected_webui_code_cache_size =
+ std::min(5 * 1024 * 1024, test_case.expected_without_trial);
+ EXPECT_EQ(expected_webui_code_cache_size,
+ PreferredCacheSize(test_case.available,
+ net::GENERATED_WEBUI_BYTE_CODE_CACHE))
+ << test_case.available;
}
// Check that the cache size cap is 50% higher for native code caches but is
diff --git a/chromium/net/disk_cache/disk_cache.h b/chromium/net/disk_cache/disk_cache.h
index 579600e31f4..e15e891c39f 100644
--- a/chromium/net/disk_cache/disk_cache.h
+++ b/chromium/net/disk_cache/disk_cache.h
@@ -47,7 +47,9 @@ namespace disk_cache {
class Entry;
class Backend;
class EntryResult;
+struct RangeResult;
using EntryResultCallback = base::OnceCallback<void(EntryResult)>;
+using RangeResultCallback = base::OnceCallback<void(const RangeResult&)>;
// How to handle resetting the back-end cache from the previous session.
// See CreateCacheBackend() for its usage.
@@ -295,8 +297,10 @@ class NET_EXPORT Backend {
// This interface represents an entry in the disk cache.
class NET_EXPORT Entry {
public:
- typedef net::CompletionOnceCallback CompletionOnceCallback;
- typedef net::IOBuffer IOBuffer;
+ using CompletionOnceCallback = net::CompletionOnceCallback;
+ using IOBuffer = net::IOBuffer;
+ using RangeResultCallback = disk_cache::RangeResultCallback;
+ using RangeResult = disk_cache::RangeResult;
// Marks this cache entry for deletion.
virtual void Doom() = 0;
@@ -413,17 +417,11 @@ class NET_EXPORT Entry {
// Returns information about the currently stored portion of a sparse entry.
// |offset| and |len| describe a particular range that should be scanned to
- // find out if it is stored or not. |start| will contain the offset of the
- // first byte that is stored within this range, and the return value is the
- // minimum number of consecutive stored bytes. Note that it is possible that
- // this entry has stored more than the returned value. This method returns a
- // net error code whenever the request cannot be completed successfully. If
- // this method returns ERR_IO_PENDING, the |callback| will be invoked when the
- // operation completes, and |start| must remain valid until that point.
- virtual int GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) = 0;
+ // find out if it is stored or not. Please see the documentation of
+ // RangeResult for more details.
+ virtual RangeResult GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) = 0;
// Returns true if this entry could be a sparse entry or false otherwise. This
// is a quick test that may return true even if the entry is not really
@@ -522,6 +520,44 @@ class NET_EXPORT EntryResult {
ScopedEntryPtr entry_;
};
+// Represents a result of GetAvailableRange.
+struct NET_EXPORT RangeResult {
+ RangeResult() = default;
+ explicit RangeResult(net::Error error) : net_error(error) {}
+
+ RangeResult(int64_t start, int available_len)
+ : net_error(net::OK), start(start), available_len(available_len) {}
+
+ // This is net::OK if operation succeeded, and `start` and `available_len`
+ // were set appropriately (potentially with 0 for `available_len`).
+ //
+ // In return value of GetAvailableRange(), net::ERR_IO_PENDING means that the
+ // result will be provided asynchronously via the callback. This can not occur
+ // in the value passed to the callback itself.
+ //
+ // In case the operation failed, this will be the error code.
+ net::Error net_error = net::ERR_FAILED;
+
+ // First byte within the range passed to GetAvailableRange that's available
+ // in the cache entry.
+ //
+ // Valid iff net_error is net::OK.
+ int64_t start = -1;
+
+ // Number of consecutive bytes stored within the requested range starting from
+ // `start` that can be read at once. This may be zero.
+ //
+ // Valid iff net_error is net::OK.
+ int available_len = 0;
+};
+
+// The maximum size of cache that can be created for type
+// GENERATED_WEBUI_BYTE_CODE_CACHE. There are only a handful of commonly
+// accessed WebUI pages, which can each cache 0.5 - 1.5 MB of code. There is no
+// point in having a very large WebUI code cache, even if lots of disk space is
+// available.
+constexpr int kMaxWebUICodeCacheSize = 5 * 1024 * 1024;
+
} // namespace disk_cache
#endif // NET_DISK_CACHE_DISK_CACHE_H_
diff --git a/chromium/net/disk_cache/disk_cache_fuzzer.cc b/chromium/net/disk_cache/disk_cache_fuzzer.cc
index ee4c1036e08..b2618c8b0dd 100644
--- a/chromium/net/disk_cache/disk_cache_fuzzer.cc
+++ b/chromium/net/disk_cache/disk_cache_fuzzer.cc
@@ -985,22 +985,15 @@ void DiskCacheLPMFuzzer::RunCommands(
uint32_t offset = gar.offset() % kMaxEntrySize;
uint32_t len = gar.len() % kMaxEntrySize;
bool async = gar.async();
- auto start = base::MakeRefCounted<base::RefCountedData<int64_t>>();
- // Raw pointer will stay alive until the end of this command for sure,
- // as we hold a reference to the object.
- int64_t* start_tmp = &start->data;
auto result_checker = base::BindRepeating(
- [](net::CompletionOnceCallback callback,
- scoped_refptr<base::RefCountedData<int64_t>> start,
- uint32_t offset, uint32_t len, int rv) {
- std::move(callback).Run(rv);
+ [](net::CompletionOnceCallback callback, uint32_t offset,
+ uint32_t len, const disk_cache::RangeResult& result) {
+ std::move(callback).Run(result.net_error);
- if (rv <= 0)
+ if (result.net_error <= 0)
return;
- int64_t* start_tmp = &start->data;
-
// Make sure that the result is contained in what was
// requested. It doesn't have to be the same even if there was
// an exact corresponding write, since representation of ranges
@@ -1010,41 +1003,45 @@ void DiskCacheLPMFuzzer::RunCommands(
net::Interval<uint32_t> requested(offset, offset + len);
uint32_t range_start, range_end;
- base::CheckedNumeric<uint64_t> range_start64(*start_tmp);
+ base::CheckedNumeric<uint64_t> range_start64(result.start);
CHECK(range_start64.AssignIfValid(&range_start));
- base::CheckedNumeric<uint64_t> range_end64 = range_start + rv;
+ base::CheckedNumeric<uint64_t> range_end64 =
+ range_start + result.available_len;
CHECK(range_end64.AssignIfValid(&range_end));
net::Interval<uint32_t> gotten(range_start, range_end);
CHECK(requested.Contains(gotten));
},
- GetIOCallback(IOType::GetAvailableRange), start, offset, len);
+ GetIOCallback(IOType::GetAvailableRange), offset, len);
- net::TestCompletionCallback tcb;
- net::CompletionOnceCallback cb =
+ TestRangeResultCompletionCallback tcb;
+ disk_cache::RangeResultCallback cb =
!async ? tcb.callback() : result_checker;
MAYBE_PRINT << "GetAvailableRange(\"" << entry->GetKey() << "\", "
<< offset << ", " << len << ")" << std::flush;
- int rv =
- entry->GetAvailableRange(offset, len, start_tmp, std::move(cb));
+ disk_cache::RangeResult result =
+ entry->GetAvailableRange(offset, len, std::move(cb));
- if (rv != net::ERR_IO_PENDING) {
+ if (result.net_error != net::ERR_IO_PENDING) {
// Run the checker callback ourselves.
- result_checker.Run(rv);
+ result_checker.Run(result);
} else if (!async) {
// In this case the callback will be run by the backend, so we don't
// need to do it manually.
- rv = tcb.GetResult(rv);
+ result = tcb.GetResult(result);
}
// Finally, take care of printing.
- if (async && rv == net::ERR_IO_PENDING) {
+ if (async && result.net_error == net::ERR_IO_PENDING) {
MAYBE_PRINT << " = net::ERR_IO_PENDING (async)" << std::endl;
} else {
- MAYBE_PRINT << " = " << rv << ", *start = " << *start_tmp;
- if (rv < 0) {
- MAYBE_PRINT << ", error to string: " << net::ErrorToShortString(rv)
+ MAYBE_PRINT << " = " << result.net_error
+ << ", start = " << result.start
+ << ", available_len = " << result.available_len;
+ if (result.net_error < 0) {
+ MAYBE_PRINT << ", error to string: "
+ << net::ErrorToShortString(result.net_error)
<< std::endl;
} else {
MAYBE_PRINT << std::endl;
diff --git a/chromium/net/disk_cache/disk_cache_test_base.cc b/chromium/net/disk_cache/disk_cache_test_base.cc
index ae5b73dd6f3..f7467ecb9a9 100644
--- a/chromium/net/disk_cache/disk_cache_test_base.cc
+++ b/chromium/net/disk_cache/disk_cache_test_base.cc
@@ -302,9 +302,15 @@ int DiskCacheTestWithCache::GetAvailableRange(disk_cache::Entry* entry,
int64_t offset,
int len,
int64_t* start) {
- net::TestCompletionCallback cb;
- int rv = entry->GetAvailableRange(offset, len, start, cb.callback());
- return cb.GetResult(rv);
+ TestRangeResultCompletionCallback cb;
+ disk_cache::RangeResult result =
+ cb.GetResult(entry->GetAvailableRange(offset, len, cb.callback()));
+
+ if (result.net_error == net::OK) {
+ *start = result.start;
+ return result.available_len;
+ }
+ return result.net_error;
}
void DiskCacheTestWithCache::TrimForTest(bool empty) {
diff --git a/chromium/net/disk_cache/disk_cache_test_base.h b/chromium/net/disk_cache/disk_cache_test_base.h
index f7b5395ba8b..0b305801367 100644
--- a/chromium/net/disk_cache/disk_cache_test_base.h
+++ b/chromium/net/disk_cache/disk_cache_test_base.h
@@ -168,6 +168,7 @@ class DiskCacheTestWithCache : public DiskCacheTest {
int64_t offset,
net::IOBuffer* buf,
int len);
+ // TODO(morlovich): Port all the tests using this to RangeResult.
int GetAvailableRange(disk_cache::Entry* entry,
int64_t offset,
int len,
diff --git a/chromium/net/disk_cache/disk_cache_test_util.cc b/chromium/net/disk_cache/disk_cache_test_util.cc
index 959fa88b54e..d18d917e7fe 100644
--- a/chromium/net/disk_cache/disk_cache_test_util.cc
+++ b/chromium/net/disk_cache/disk_cache_test_util.cc
@@ -92,6 +92,22 @@ TestEntryResultCompletionCallback::callback() {
base::Unretained(this));
}
+TestRangeResultCompletionCallback::TestRangeResultCompletionCallback() =
+ default;
+
+TestRangeResultCompletionCallback::~TestRangeResultCompletionCallback() =
+ default;
+
+disk_cache::RangeResultCallback TestRangeResultCompletionCallback::callback() {
+ return base::BindOnce(&TestRangeResultCompletionCallback::HelpSetResult,
+ base::Unretained(this));
+}
+
+void TestRangeResultCompletionCallback::HelpSetResult(
+ const disk_cache::RangeResult& result) {
+ SetResult(result);
+}
+
// -----------------------------------------------------------------------
MessageLoopHelper::MessageLoopHelper()
diff --git a/chromium/net/disk_cache/disk_cache_test_util.h b/chromium/net/disk_cache/disk_cache_test_util.h
index 24c7573462b..f7e2fa70570 100644
--- a/chromium/net/disk_cache/disk_cache_test_util.h
+++ b/chromium/net/disk_cache/disk_cache_test_util.h
@@ -62,6 +62,29 @@ class TestEntryResultCompletionCallback
DISALLOW_COPY_AND_ASSIGN(TestEntryResultCompletionCallback);
};
+// Like net::TestCompletionCallback, but for RangeResultCallback.
+struct RangeResultIsPendingHelper {
+ bool operator()(const disk_cache::RangeResult& result) const {
+ return result.net_error == net::ERR_IO_PENDING;
+ }
+};
+
+class TestRangeResultCompletionCallback
+ : public net::internal::TestCompletionCallbackTemplate<
+ disk_cache::RangeResult,
+ RangeResultIsPendingHelper> {
+ public:
+ TestRangeResultCompletionCallback();
+ ~TestRangeResultCompletionCallback() override;
+
+ disk_cache::RangeResultCallback callback();
+
+ private:
+ // Reference -> Value adapter --- disk_cache wants reference for callback,
+ // base class wants a value.
+ void HelpSetResult(const disk_cache::RangeResult& result);
+};
+
// -----------------------------------------------------------------------
// Simple helper to deal with the message loop on a test.
diff --git a/chromium/net/disk_cache/entry_unittest.cc b/chromium/net/disk_cache/entry_unittest.cc
index 28cf481541f..369a68843c8 100644
--- a/chromium/net/disk_cache/entry_unittest.cc
+++ b/chromium/net/disk_cache/entry_unittest.cc
@@ -17,6 +17,7 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
+#include "build/build_config.h"
#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -45,6 +46,7 @@ using net::test::IsOk;
using base::Time;
using disk_cache::EntryResult;
using disk_cache::EntryResultCallback;
+using disk_cache::RangeResult;
using disk_cache::ScopedEntryPtr;
// Tests that can run with different types of caches.
@@ -1734,57 +1736,66 @@ void DiskCacheEntryTest::GetAvailableRangeTest() {
EXPECT_EQ(kSize, WriteSparseData(entry, 0x20F4400, buf.get(), kSize));
// We stop at the first empty block.
- int64_t start;
- net::TestCompletionCallback cb;
- int rv = entry->GetAvailableRange(
- 0x20F0000, kSize * 2, &start, cb.callback());
- EXPECT_EQ(kSize, cb.GetResult(rv));
- EXPECT_EQ(0x20F0000, start);
-
- start = 0;
- rv = entry->GetAvailableRange(0, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
- rv = entry->GetAvailableRange(
- 0x20F0000 - kSize, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
- rv = entry->GetAvailableRange(0, 0x2100000, &start, cb.callback());
- EXPECT_EQ(kSize, cb.GetResult(rv));
- EXPECT_EQ(0x20F0000, start);
+ TestRangeResultCompletionCallback cb;
+ RangeResult result = cb.GetResult(
+ entry->GetAvailableRange(0x20F0000, kSize * 2, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSize, result.available_len);
+ EXPECT_EQ(0x20F0000, result.start);
+
+ result = cb.GetResult(entry->GetAvailableRange(0, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
+
+ result = cb.GetResult(
+ entry->GetAvailableRange(0x20F0000 - kSize, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
+
+ result = cb.GetResult(entry->GetAvailableRange(0, 0x2100000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSize, result.available_len);
+ EXPECT_EQ(0x20F0000, result.start);
// We should be able to Read based on the results of GetAvailableRange.
- start = -1;
- rv = entry->GetAvailableRange(0x2100000, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
- rv = entry->ReadSparseData(start, buf.get(), kSize, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
-
- start = 0;
- rv = entry->GetAvailableRange(0x20F2000, kSize, &start, cb.callback());
- EXPECT_EQ(0x2000, cb.GetResult(rv));
- EXPECT_EQ(0x20F2000, start);
- EXPECT_EQ(0x2000, ReadSparseData(entry, start, buf.get(), kSize));
+ net::TestCompletionCallback read_cb;
+ result =
+ cb.GetResult(entry->GetAvailableRange(0x2100000, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
+ int rv =
+ entry->ReadSparseData(result.start, buf.get(), kSize, read_cb.callback());
+ EXPECT_EQ(0, read_cb.GetResult(rv));
+
+ result =
+ cb.GetResult(entry->GetAvailableRange(0x20F2000, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0x2000, result.available_len);
+ EXPECT_EQ(0x20F2000, result.start);
+ EXPECT_EQ(0x2000, ReadSparseData(entry, result.start, buf.get(), kSize));
// Make sure that we respect the |len| argument.
- start = 0;
- rv = entry->GetAvailableRange(
- 0x20F0001 - kSize, kSize, &start, cb.callback());
- EXPECT_EQ(1, cb.GetResult(rv));
- EXPECT_EQ(0x20F0000, start);
+ result = cb.GetResult(
+ entry->GetAvailableRange(0x20F0001 - kSize, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1, result.available_len);
+ EXPECT_EQ(0x20F0000, result.start);
// Use very small ranges. Write at offset 50.
const int kTinyLen = 10;
EXPECT_EQ(kTinyLen, WriteSparseData(entry, 50, buf.get(), kTinyLen));
- start = -1;
- rv = entry->GetAvailableRange(kTinyLen * 2, kTinyLen, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
- EXPECT_EQ(kTinyLen * 2, start);
+ result = cb.GetResult(
+ entry->GetAvailableRange(kTinyLen * 2, kTinyLen, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
+ EXPECT_EQ(kTinyLen * 2, result.start);
// Get a huge range with maximum boundary
- start = -1;
- rv = entry->GetAvailableRange(0x2100000, std::numeric_limits<int32_t>::max(),
- &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
+ result = cb.GetResult(entry->GetAvailableRange(
+ 0x2100000, std::numeric_limits<int32_t>::max(), cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
entry->Close();
}
@@ -1831,24 +1842,27 @@ TEST_F(DiskCacheEntryTest, GetAvailableRangeBlockFileDiscontinuous) {
// Try to query a range starting from that block 0.
// The cache tracks: [0, 612) [1024, 3072).
// The request is for: [812, 2059) so response should be [1024, 2059), which
- // has lenth = 1035. Previously this return a negative number for rv.
- int64_t start = -1;
- net::TestCompletionCallback cb;
- int rv = entry->GetAvailableRange(812, 1247, &start, cb.callback());
- EXPECT_EQ(1035, cb.GetResult(rv));
- EXPECT_EQ(1024, start);
+ // has length = 1035. Previously this return a negative number for rv.
+ TestRangeResultCompletionCallback cb;
+ RangeResult result =
+ cb.GetResult(entry->GetAvailableRange(812, 1247, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1035, result.available_len);
+ EXPECT_EQ(1024, result.start);
// Now query [512, 1536). This matches both [512, 612) and [1024, 1536),
// so this should return [512, 612).
- rv = entry->GetAvailableRange(512, 1024, &start, cb.callback());
- EXPECT_EQ(100, cb.GetResult(rv));
- EXPECT_EQ(512, start);
+ result = cb.GetResult(entry->GetAvailableRange(512, 1024, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(100, result.available_len);
+ EXPECT_EQ(512, result.start);
// Now query next portion, [612, 1636). This now just should produce
// [1024, 1636)
- rv = entry->GetAvailableRange(612, 1024, &start, cb.callback());
- EXPECT_EQ(612, cb.GetResult(rv));
- EXPECT_EQ(1024, start);
+ result = cb.GetResult(entry->GetAvailableRange(612, 1024, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(612, result.available_len);
+ EXPECT_EQ(1024, result.start);
// Do a continuous small write, this one at [3072, 3684).
// This means the cache tracks [1024, 3072) via bitmaps and [3072, 3684)
@@ -1857,9 +1871,10 @@ TEST_F(DiskCacheEntryTest, GetAvailableRangeBlockFileDiscontinuous) {
buf_small.get(), kSmallSize));
// Query [2048, 4096). Should get [2048, 3684)
- rv = entry->GetAvailableRange(2048, 2048, &start, cb.callback());
- EXPECT_EQ(1636, cb.GetResult(rv));
- EXPECT_EQ(2048, start);
+ result = cb.GetResult(entry->GetAvailableRange(2048, 2048, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1636, result.available_len);
+ EXPECT_EQ(2048, result.start);
// Now write at [4096, 4708). Since only one sub-kb thing is tracked, this
// now tracks [1024, 3072) via bitmaps and [4096, 4708) as the last write.
@@ -1867,22 +1882,26 @@ TEST_F(DiskCacheEntryTest, GetAvailableRangeBlockFileDiscontinuous) {
buf_small.get(), kSmallSize));
// Query [2048, 4096). Should get [2048, 3072)
- rv = entry->GetAvailableRange(2048, 2048, &start, cb.callback());
- EXPECT_EQ(1024, cb.GetResult(rv));
- EXPECT_EQ(2048, start);
+ result = cb.GetResult(entry->GetAvailableRange(2048, 2048, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1024, result.available_len);
+ EXPECT_EQ(2048, result.start);
// Query 2K more after that: [3072, 5120). Should get [4096, 4708)
- rv = entry->GetAvailableRange(3072, 2048, &start, cb.callback());
- EXPECT_EQ(612, cb.GetResult(rv));
- EXPECT_EQ(4096, start);
+ result = cb.GetResult(entry->GetAvailableRange(3072, 2048, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(612, result.available_len);
+ EXPECT_EQ(4096, result.start);
// Also double-check that offsets within later children are correctly
// computed.
EXPECT_EQ(kSmallSize, WriteSparseData(entry, /* offset = */ 0x200400,
buf_small.get(), kSmallSize));
- rv = entry->GetAvailableRange(0x100000, 0x200000, &start, cb.callback());
- EXPECT_EQ(kSmallSize, cb.GetResult(rv));
- EXPECT_EQ(0x200400, start);
+ result =
+ cb.GetResult(entry->GetAvailableRange(0x100000, 0x200000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSmallSize, result.available_len);
+ EXPECT_EQ(0x200400, result.start);
entry->Close();
}
@@ -1908,42 +1927,46 @@ TEST_F(DiskCacheEntryTest, SparseWriteDropped) {
int offset = 1024 - 500;
int rv = 0;
net::TestCompletionCallback cb;
- int64_t start;
+ TestRangeResultCompletionCallback range_cb;
+ RangeResult result;
for (int i = 0; i < 5; i++) {
// Check result of last GetAvailableRange.
- EXPECT_EQ(0, rv);
+ EXPECT_EQ(0, result.available_len);
rv = entry->WriteSparseData(offset, buf_1.get(), kSize, cb.callback());
EXPECT_EQ(kSize, cb.GetResult(rv));
- rv = entry->GetAvailableRange(offset - 100, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
+ result = range_cb.GetResult(
+ entry->GetAvailableRange(offset - 100, kSize, range_cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
- rv = entry->GetAvailableRange(offset, kSize, &start, cb.callback());
- rv = cb.GetResult(rv);
- if (!rv) {
+ result = range_cb.GetResult(
+ entry->GetAvailableRange(offset, kSize, range_cb.callback()));
+ if (!result.available_len) {
rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
EXPECT_EQ(0, cb.GetResult(rv));
- rv = 0;
}
offset += 1024 * i + 100;
}
// The last write started 100 bytes below a bundary, so there should be 80
// bytes after the boundary.
- EXPECT_EQ(80, rv);
- EXPECT_EQ(1024 * 7, start);
- rv = entry->ReadSparseData(start, buf_2.get(), kSize, cb.callback());
+ EXPECT_EQ(80, result.available_len);
+ EXPECT_EQ(1024 * 7, result.start);
+ rv = entry->ReadSparseData(result.start, buf_2.get(), kSize, cb.callback());
EXPECT_EQ(80, cb.GetResult(rv));
EXPECT_EQ(0, memcmp(buf_1.get()->data() + 100, buf_2.get()->data(), 80));
// And even that part is dropped when another write changes the offset.
- offset = start;
+ offset = result.start;
rv = entry->WriteSparseData(0, buf_1.get(), kSize, cb.callback());
EXPECT_EQ(kSize, cb.GetResult(rv));
- rv = entry->GetAvailableRange(offset, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
+ result = range_cb.GetResult(
+ entry->GetAvailableRange(offset, kSize, range_cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
entry->Close();
}
@@ -1963,16 +1986,19 @@ TEST_F(DiskCacheEntryTest, SparseSquentialWriteNotDropped) {
// Any starting offset is fine as long as it is 1024-bytes aligned.
int rv = 0;
+ RangeResult result;
net::TestCompletionCallback cb;
- int64_t start;
+ TestRangeResultCompletionCallback range_cb;
int64_t offset = 1024 * 11;
for (; offset < 20000; offset += kSize) {
rv = entry->WriteSparseData(offset, buf_1.get(), kSize, cb.callback());
EXPECT_EQ(kSize, cb.GetResult(rv));
- rv = entry->GetAvailableRange(offset, kSize, &start, cb.callback());
- EXPECT_EQ(kSize, cb.GetResult(rv));
- EXPECT_EQ(offset, start);
+ result = range_cb.GetResult(
+ entry->GetAvailableRange(offset, kSize, range_cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSize, result.available_len);
+ EXPECT_EQ(offset, result.start);
rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
EXPECT_EQ(kSize, cb.GetResult(rv));
@@ -1985,9 +2011,11 @@ TEST_F(DiskCacheEntryTest, SparseSquentialWriteNotDropped) {
// Verify again the last write made.
ASSERT_THAT(OpenEntry(key, &entry), IsOk());
offset -= kSize;
- rv = entry->GetAvailableRange(offset, kSize, &start, cb.callback());
- EXPECT_EQ(kSize, cb.GetResult(rv));
- EXPECT_EQ(offset, start);
+ result = range_cb.GetResult(
+ entry->GetAvailableRange(offset, kSize, range_cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSize, result.available_len);
+ EXPECT_EQ(offset, result.start);
rv = entry->ReadSparseData(offset, buf_2.get(), kSize, cb.callback());
EXPECT_EQ(kSize, cb.GetResult(rv));
@@ -2100,40 +2128,46 @@ TEST_F(DiskCacheEntryTest, MemoryOnlyMisalignedGetAvailableRange) {
EXPECT_EQ(8192, entry->WriteSparseData(50000, buf.get(), 8192,
net::CompletionOnceCallback()));
- int64_t start;
- net::TestCompletionCallback cb;
+ TestRangeResultCompletionCallback cb;
// Test that we stop at a discontinuous child at the second block.
- int rv = entry->GetAvailableRange(0, 10000, &start, cb.callback());
- EXPECT_EQ(1024, cb.GetResult(rv));
- EXPECT_EQ(0, start);
+ RangeResult result =
+ cb.GetResult(entry->GetAvailableRange(0, 10000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1024, result.available_len);
+ EXPECT_EQ(0, result.start);
// Test that number of bytes is reported correctly when we start from the
// middle of a filled region.
- rv = entry->GetAvailableRange(512, 10000, &start, cb.callback());
- EXPECT_EQ(512, cb.GetResult(rv));
- EXPECT_EQ(512, start);
+ result = cb.GetResult(entry->GetAvailableRange(512, 10000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(512, result.available_len);
+ EXPECT_EQ(512, result.start);
// Test that we found bytes in the child of next block.
- rv = entry->GetAvailableRange(1024, 10000, &start, cb.callback());
- EXPECT_EQ(1024, cb.GetResult(rv));
- EXPECT_EQ(5120, start);
+ result = cb.GetResult(entry->GetAvailableRange(1024, 10000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1024, result.available_len);
+ EXPECT_EQ(5120, result.start);
// Test that the desired length is respected. It starts within a filled
// region.
- rv = entry->GetAvailableRange(5500, 512, &start, cb.callback());
- EXPECT_EQ(512, cb.GetResult(rv));
- EXPECT_EQ(5500, start);
+ result = cb.GetResult(entry->GetAvailableRange(5500, 512, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(512, result.available_len);
+ EXPECT_EQ(5500, result.start);
// Test that the desired length is respected. It starts before a filled
// region.
- rv = entry->GetAvailableRange(5000, 620, &start, cb.callback());
- EXPECT_EQ(500, cb.GetResult(rv));
- EXPECT_EQ(5120, start);
+ result = cb.GetResult(entry->GetAvailableRange(5000, 620, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(500, result.available_len);
+ EXPECT_EQ(5120, result.start);
// Test that multiple blocks are scanned.
- rv = entry->GetAvailableRange(40000, 20000, &start, cb.callback());
- EXPECT_EQ(8192, cb.GetResult(rv));
- EXPECT_EQ(50000, start);
+ result = cb.GetResult(entry->GetAvailableRange(40000, 20000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(8192, result.available_len);
+ EXPECT_EQ(50000, result.start);
entry->Close();
}
@@ -2338,53 +2372,64 @@ void DiskCacheEntryTest::PartialSparseEntry() {
EXPECT_EQ(500, ReadSparseData(entry, kSize, buf2.get(), kSize));
EXPECT_EQ(0, ReadSparseData(entry, 99, buf2.get(), kSize));
- int rv;
- int64_t start;
- net::TestCompletionCallback cb;
+ TestRangeResultCompletionCallback cb;
+ RangeResult result;
if (memory_only_ || simple_cache_mode_) {
- rv = entry->GetAvailableRange(0, 600, &start, cb.callback());
- EXPECT_EQ(100, cb.GetResult(rv));
- EXPECT_EQ(500, start);
+ result = cb.GetResult(entry->GetAvailableRange(0, 600, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(100, result.available_len);
+ EXPECT_EQ(500, result.start);
} else {
- rv = entry->GetAvailableRange(0, 2048, &start, cb.callback());
- EXPECT_EQ(1024, cb.GetResult(rv));
- EXPECT_EQ(1024, start);
+ result = cb.GetResult(entry->GetAvailableRange(0, 2048, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1024, result.available_len);
+ EXPECT_EQ(1024, result.start);
}
- rv = entry->GetAvailableRange(kSize, kSize, &start, cb.callback());
- EXPECT_EQ(500, cb.GetResult(rv));
- EXPECT_EQ(kSize, start);
- rv = entry->GetAvailableRange(20 * 1024, 10000, &start, cb.callback());
+ result = cb.GetResult(entry->GetAvailableRange(kSize, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(500, result.available_len);
+ EXPECT_EQ(kSize, result.start);
+ result =
+ cb.GetResult(entry->GetAvailableRange(20 * 1024, 10000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
if (memory_only_ || simple_cache_mode_)
- EXPECT_EQ(3616, cb.GetResult(rv));
+ EXPECT_EQ(3616, result.available_len);
else
- EXPECT_EQ(3072, cb.GetResult(rv));
+ EXPECT_EQ(3072, result.available_len);
- EXPECT_EQ(20 * 1024, start);
+ EXPECT_EQ(20 * 1024, result.start);
// 1. Query before a filled 1KB block.
// 2. Query within a filled 1KB block.
// 3. Query beyond a filled 1KB block.
if (memory_only_ || simple_cache_mode_) {
- rv = entry->GetAvailableRange(19400, kSize, &start, cb.callback());
- EXPECT_EQ(3496, cb.GetResult(rv));
- EXPECT_EQ(20000, start);
+ result =
+ cb.GetResult(entry->GetAvailableRange(19400, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(3496, result.available_len);
+ EXPECT_EQ(20000, result.start);
} else {
- rv = entry->GetAvailableRange(19400, kSize, &start, cb.callback());
- EXPECT_EQ(3016, cb.GetResult(rv));
- EXPECT_EQ(20480, start);
+ result =
+ cb.GetResult(entry->GetAvailableRange(19400, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(3016, result.available_len);
+ EXPECT_EQ(20480, result.start);
}
- rv = entry->GetAvailableRange(3073, kSize, &start, cb.callback());
- EXPECT_EQ(1523, cb.GetResult(rv));
- EXPECT_EQ(3073, start);
- rv = entry->GetAvailableRange(4600, kSize, &start, cb.callback());
- EXPECT_EQ(0, cb.GetResult(rv));
- EXPECT_EQ(4600, start);
+ result = cb.GetResult(entry->GetAvailableRange(3073, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(1523, result.available_len);
+ EXPECT_EQ(3073, result.start);
+ result = cb.GetResult(entry->GetAvailableRange(4600, kSize, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
+ EXPECT_EQ(4600, result.start);
// Now make another write and verify that there is no hole in between.
EXPECT_EQ(kSize, WriteSparseData(entry, 500 + kSize, buf1.get(), kSize));
- rv = entry->GetAvailableRange(1024, 10000, &start, cb.callback());
- EXPECT_EQ(7 * 1024 + 500, cb.GetResult(rv));
- EXPECT_EQ(1024, start);
+ result = cb.GetResult(entry->GetAvailableRange(1024, 10000, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(7 * 1024 + 500, result.available_len);
+ EXPECT_EQ(1024, result.start);
EXPECT_EQ(kSize, ReadSparseData(entry, kSize, buf2.get(), kSize));
EXPECT_EQ(0, memcmp(buf2->data(), buf1->data() + kSize - 500, 500));
EXPECT_EQ(0, memcmp(buf2->data() + 500, buf1->data(), kSize - 500));
@@ -2483,17 +2528,17 @@ void DiskCacheEntryTest::SparseClipEnd(int64_t max_index,
EXPECT_EQ(0, memcmp(buf->data(), read_buf->data(), kSize));
}
- int64_t out_start = 0;
- net::TestCompletionCallback cb;
- rv = entry->GetAvailableRange(kOffset - kSize, kSize * 3, &out_start,
- cb.callback());
- rv = cb.GetResult(rv);
+ TestRangeResultCompletionCallback cb;
+ RangeResult result = cb.GetResult(
+ entry->GetAvailableRange(kOffset - kSize, kSize * 3, cb.callback()));
if (expect_unsupported) {
// GetAvailableRange just returns nothing found, not an error.
- EXPECT_EQ(rv, 0);
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(result.available_len, 0);
} else {
- EXPECT_EQ(kSize, rv);
- EXPECT_EQ(kOffset, out_start);
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(kSize, result.available_len);
+ EXPECT_EQ(kOffset, result.start);
}
entry->Close();
@@ -2534,11 +2579,11 @@ TEST_F(DiskCacheEntryTest, SparseClipEnd2) {
EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED, rv);
// GetAvailableRange just returns nothing.
- net::TestCompletionCallback cb;
- int64_t out_start = 0;
- rv = entry->GetAvailableRange(kLimit, kSize * 3, &out_start, cb.callback());
- rv = cb.GetResult(rv);
- EXPECT_EQ(rv, 0);
+ TestRangeResultCompletionCallback cb;
+ RangeResult result =
+ cb.GetResult(entry->GetAvailableRange(kLimit, kSize * 3, cb.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
entry->Close();
}
@@ -2620,14 +2665,14 @@ TEST_F(DiskCacheEntryTest, CancelSparseIO) {
CacheTestFillBuffer(buf->data(), kSize, false);
// This will open and write two "real" entries.
- net::TestCompletionCallback cb1, cb2, cb3, cb4, cb5;
+ net::TestCompletionCallback cb1, cb2, cb3, cb4;
int rv = entry->WriteSparseData(
1024 * 1024 - 4096, buf.get(), kSize, cb1.callback());
EXPECT_THAT(rv, IsError(net::ERR_IO_PENDING));
- int64_t offset = 0;
- rv = entry->GetAvailableRange(offset, kSize, &offset, cb5.callback());
- rv = cb5.GetResult(rv);
+ TestRangeResultCompletionCallback cb5;
+ RangeResult result =
+ cb5.GetResult(entry->GetAvailableRange(0, kSize, cb5.callback()));
if (!cb1.have_result()) {
// We may or may not have finished writing to the entry. If we have not,
// we cannot start another operation at this time.
@@ -2646,10 +2691,10 @@ TEST_F(DiskCacheEntryTest, CancelSparseIO) {
if (!cb1.have_result()) {
EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED,
- entry->ReadSparseData(offset, buf.get(), kSize,
+ entry->ReadSparseData(result.start, buf.get(), kSize,
net::CompletionOnceCallback()));
EXPECT_EQ(net::ERR_CACHE_OPERATION_NOT_SUPPORTED,
- entry->WriteSparseData(offset, buf.get(), kSize,
+ entry->WriteSparseData(result.start, buf.get(), kSize,
net::CompletionOnceCallback()));
}
@@ -2661,8 +2706,10 @@ TEST_F(DiskCacheEntryTest, CancelSparseIO) {
EXPECT_THAT(cb3.WaitForResult(), IsOk());
EXPECT_THAT(cb4.WaitForResult(), IsOk());
- rv = entry->GetAvailableRange(offset, kSize, &offset, cb5.callback());
- EXPECT_EQ(0, cb5.GetResult(rv));
+ result = cb5.GetResult(
+ entry->GetAvailableRange(result.start, kSize, cb5.callback()));
+ EXPECT_EQ(net::OK, result.net_error);
+ EXPECT_EQ(0, result.available_len);
entry->Close();
}
@@ -5041,9 +5088,11 @@ TEST_F(DiskCacheEntryTest, SimpleCacheSparseErrorHandling) {
// Similarly for other ops.
EXPECT_EQ(net::ERR_FAILED, WriteSparseData(entry, 0, buffer.get(), kSize));
net::TestCompletionCallback cb;
- int64_t start;
- int rv = entry->GetAvailableRange(0, 1024, &start, cb.callback());
- EXPECT_EQ(net::ERR_FAILED, cb.GetResult(rv));
+
+ TestRangeResultCompletionCallback range_cb;
+ RangeResult result = range_cb.GetResult(
+ entry->GetAvailableRange(0, 1024, range_cb.callback()));
+ EXPECT_EQ(net::ERR_FAILED, result.net_error);
entry->Close();
disk_cache::FlushCacheThreadForTesting();
@@ -5743,10 +5792,6 @@ TEST_F(DiskCacheSimplePrefetchTest, NoFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_NONE, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 0);
}
TEST_F(DiskCacheSimplePrefetchTest, NoFullSmallSpeculative) {
@@ -5759,10 +5804,6 @@ TEST_F(DiskCacheSimplePrefetchTest, NoFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 1);
}
TEST_F(DiskCacheSimplePrefetchTest, NoFullLargeSpeculative) {
@@ -5777,10 +5818,6 @@ TEST_F(DiskCacheSimplePrefetchTest, NoFullLargeSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_FULL, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 0);
}
TEST_F(DiskCacheSimplePrefetchTest, SmallFullNoSpeculative) {
@@ -5793,10 +5830,6 @@ TEST_F(DiskCacheSimplePrefetchTest, SmallFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_NONE, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 0);
}
TEST_F(DiskCacheSimplePrefetchTest, LargeFullNoSpeculative) {
@@ -5809,10 +5842,6 @@ TEST_F(DiskCacheSimplePrefetchTest, LargeFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_FULL, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 0);
}
TEST_F(DiskCacheSimplePrefetchTest, SmallFullSmallSpeculative) {
@@ -5825,10 +5854,6 @@ TEST_F(DiskCacheSimplePrefetchTest, SmallFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 1);
}
TEST_F(DiskCacheSimplePrefetchTest, LargeFullSmallSpeculative) {
@@ -5842,10 +5867,6 @@ TEST_F(DiskCacheSimplePrefetchTest, LargeFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.Http.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_FULL, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.Http.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount(
- "SimpleCache.Http.EntryTrailerPrefetchDelta", 0);
}
class DiskCacheSimpleAppCachePrefetchTest : public DiskCacheSimplePrefetchTest {
@@ -5864,10 +5885,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectUniqueSample(
- "SimpleCache.App.EntryTrailerPrefetchDelta", 0, 1);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullSmallSpeculative) {
@@ -5880,10 +5897,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectUniqueSample(
- "SimpleCache.App.EntryTrailerPrefetchDelta", 0, 1);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullLargeSpeculative) {
@@ -5899,10 +5912,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, NoFullLargeSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectUniqueSample(
- "SimpleCache.App.EntryTrailerPrefetchDelta", 0, 1);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullNoSpeculative) {
@@ -5915,10 +5924,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectUniqueSample(
- "SimpleCache.App.EntryTrailerPrefetchDelta", 0, 1);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullNoSpeculative) {
@@ -5932,10 +5937,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullNoSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_FULL, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchDelta",
- 0);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullSmallSpeculative) {
@@ -5948,10 +5949,6 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, SmallFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_TRAILER, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchDelta",
- 1);
}
TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullSmallSpeculative) {
@@ -5965,8 +5962,4 @@ TEST_F(DiskCacheSimpleAppCachePrefetchTest, LargeFullSmallSpeculative) {
histogram_tester.ExpectUniqueSample("SimpleCache.App.SyncOpenPrefetchMode",
disk_cache::OPEN_PREFETCH_FULL, 1);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchSize",
- 0);
- histogram_tester.ExpectTotalCount("SimpleCache.App.EntryTrailerPrefetchDelta",
- 0);
}
diff --git a/chromium/net/disk_cache/memory/mem_entry_impl.cc b/chromium/net/disk_cache/memory/mem_entry_impl.cc
index 3a5eac74b3c..3e17d532872 100644
--- a/chromium/net/disk_cache/memory/mem_entry_impl.cc
+++ b/chromium/net/disk_cache/memory/mem_entry_impl.cc
@@ -252,18 +252,17 @@ int MemEntryImpl::WriteSparseData(int64_t offset,
return result;
}
-int MemEntryImpl::GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) {
+RangeResult MemEntryImpl::GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) {
if (net_log_.IsCapturing()) {
NetLogSparseOperation(net_log_, net::NetLogEventType::SPARSE_GET_RANGE,
net::NetLogEventPhase::BEGIN, offset, len);
}
- int result = InternalGetAvailableRange(offset, len, start);
+ RangeResult result = InternalGetAvailableRange(offset, len);
if (net_log_.IsCapturing()) {
net_log_.EndEvent(net::NetLogEventType::SPARSE_GET_RANGE, [&] {
- return CreateNetLogGetAvailableRangeResultParams(*start, result);
+ return CreateNetLogGetAvailableRangeResultParams(result);
});
}
return result;
@@ -541,17 +540,14 @@ int MemEntryImpl::InternalWriteSparseData(int64_t offset,
return io_buf->BytesConsumed();
}
-int MemEntryImpl::InternalGetAvailableRange(int64_t offset,
- int len,
- int64_t* start) {
+RangeResult MemEntryImpl::InternalGetAvailableRange(int64_t offset, int len) {
DCHECK_EQ(PARENT_ENTRY, type());
- DCHECK(start);
if (!InitSparseInfo())
- return net::ERR_CACHE_OPERATION_NOT_SUPPORTED;
+ return RangeResult(net::ERR_CACHE_OPERATION_NOT_SUPPORTED);
- if (offset < 0 || len < 0 || !start)
- return net::ERR_INVALID_ARGUMENT;
+ if (offset < 0 || len < 0)
+ return RangeResult(net::ERR_INVALID_ARGUMENT);
// Truncate |len| to make sure that |offset + len| does not overflow.
// This is OK since one can't write that far anyway.
@@ -584,12 +580,11 @@ int MemEntryImpl::InternalGetAvailableRange(int64_t offset,
found.SpanningUnion(relevant_in_next_child);
}
- *start = found.min();
- return found.Length();
+
+ return RangeResult(found.min(), found.Length());
}
- *start = offset;
- return 0;
+ return RangeResult(offset, 0);
}
bool MemEntryImpl::InitSparseInfo() {
diff --git a/chromium/net/disk_cache/memory/mem_entry_impl.h b/chromium/net/disk_cache/memory/mem_entry_impl.h
index be4934c02e3..9b71e03acda 100644
--- a/chromium/net/disk_cache/memory/mem_entry_impl.h
+++ b/chromium/net/disk_cache/memory/mem_entry_impl.h
@@ -126,10 +126,9 @@ class NET_EXPORT_PRIVATE MemEntryImpl final
IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
- int GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) override;
+ RangeResult GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) override;
bool CouldBeSparse() const override;
void CancelSparseIO() override {}
net::Error ReadyForSparseIO(CompletionOnceCallback callback) override;
@@ -156,7 +155,7 @@ class NET_EXPORT_PRIVATE MemEntryImpl final
bool truncate);
int InternalReadSparseData(int64_t offset, IOBuffer* buf, int buf_len);
int InternalWriteSparseData(int64_t offset, IOBuffer* buf, int buf_len);
- int InternalGetAvailableRange(int64_t offset, int len, int64_t* start);
+ RangeResult InternalGetAvailableRange(int64_t offset, int len);
// Initializes the children map and sparse info. This method is only called
// on a parent entry.
diff --git a/chromium/net/disk_cache/net_log_parameters.cc b/chromium/net/disk_cache/net_log_parameters.cc
index 67afd8b1c26..89c1245a3fb 100644
--- a/chromium/net/disk_cache/net_log_parameters.cc
+++ b/chromium/net/disk_cache/net_log_parameters.cc
@@ -107,14 +107,14 @@ void NetLogSparseReadWrite(const net::NetLogWithSource& net_log,
});
}
-base::Value CreateNetLogGetAvailableRangeResultParams(int64_t start,
- int result) {
+base::Value CreateNetLogGetAvailableRangeResultParams(
+ disk_cache::RangeResult result) {
base::Value dict(base::Value::Type::DICTIONARY);
- if (result > 0) {
- dict.SetIntKey("length", result);
- dict.SetKey("start", net::NetLogNumberValue(start));
+ if (result.net_error == net::OK) {
+ dict.SetIntKey("length", result.available_len);
+ dict.SetKey("start", net::NetLogNumberValue(result.start));
} else {
- dict.SetIntKey("net_error", result);
+ dict.SetIntKey("net_error", result.net_error);
}
return dict;
}
diff --git a/chromium/net/disk_cache/net_log_parameters.h b/chromium/net/disk_cache/net_log_parameters.h
index bbfa44668c5..605b7f4b262 100644
--- a/chromium/net/disk_cache/net_log_parameters.h
+++ b/chromium/net/disk_cache/net_log_parameters.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "net/disk_cache/disk_cache.h"
#include "net/log/net_log_with_source.h"
namespace net {
@@ -63,8 +64,8 @@ void NetLogSparseReadWrite(const net::NetLogWithSource& net_log,
int child_len);
// Creates NetLog parameters for when a call to GetAvailableRange returns.
-base::Value CreateNetLogGetAvailableRangeResultParams(int64_t start,
- int result);
+base::Value CreateNetLogGetAvailableRangeResultParams(
+ const disk_cache::RangeResult result);
} // namespace disk_cache
diff --git a/chromium/net/disk_cache/simple/simple_backend_impl.cc b/chromium/net/disk_cache/simple/simple_backend_impl.cc
index 75ef8401680..d79a9cacd4a 100644
--- a/chromium/net/disk_cache/simple/simple_backend_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_backend_impl.cc
@@ -174,6 +174,14 @@ void RecordIndexLoad(net::CacheType cache_type,
}
}
+SimpleEntryImpl::OperationsMode CacheTypeToOperationsMode(net::CacheType type) {
+ return (type == net::DISK_CACHE || type == net::GENERATED_BYTE_CODE_CACHE ||
+ type == net::GENERATED_NATIVE_CODE_CACHE ||
+ type == net::GENERATED_WEBUI_BYTE_CODE_CACHE)
+ ? SimpleEntryImpl::OPTIMISTIC_OPERATIONS
+ : SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS;
+}
+
} // namespace
const base::Feature SimpleBackendImpl::kPrioritizedSimpleCacheTasks{
@@ -228,11 +236,7 @@ SimpleBackendImpl::SimpleBackendImpl(
{base::MayBlock(), base::TaskPriority::USER_BLOCKING,
base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
orig_max_size_(max_bytes),
- entry_operations_mode_((cache_type == net::DISK_CACHE ||
- cache_type == net::GENERATED_BYTE_CODE_CACHE ||
- cache_type == net::GENERATED_NATIVE_CODE_CACHE)
- ? SimpleEntryImpl::OPTIMISTIC_OPERATIONS
- : SimpleEntryImpl::NON_OPTIMISTIC_OPERATIONS),
+ entry_operations_mode_(CacheTypeToOperationsMode(cache_type)),
post_doom_waiting_(
base::MakeRefCounted<SimplePostDoomWaiterTable>(cache_type)),
net_log_(net_log) {
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.cc b/chromium/net/disk_cache/simple/simple_entry_impl.cc
index 39346f7d486..69db7cfaccc 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.cc
@@ -14,9 +14,9 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -163,9 +163,6 @@ SimpleEntryImpl::SimpleEntryImpl(
static_assert(std::extent<decltype(data_size_)>() ==
std::extent<decltype(have_written_)>(),
"arrays should be the same size");
- static_assert(std::extent<decltype(data_size_)>() ==
- std::extent<decltype(crc_check_state_)>(),
- "arrays should be the same size");
ResetEntry();
NetLogSimpleEntryConstruction(net_log_,
net::NetLogEventType::SIMPLE_CACHE_ENTRY,
@@ -566,13 +563,12 @@ int SimpleEntryImpl::WriteSparseData(int64_t offset,
return net::ERR_IO_PENDING;
}
-int SimpleEntryImpl::GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) {
+RangeResult SimpleEntryImpl::GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (offset < 0 || len < 0)
- return net::ERR_INVALID_ARGUMENT;
+ return RangeResult(net::ERR_INVALID_ARGUMENT);
// Truncate |len| to make sure that |offset + len| does not overflow.
// This is OK since one can't write that far anyway.
@@ -582,8 +578,8 @@ int SimpleEntryImpl::GetAvailableRange(int64_t offset,
ScopedOperationRunner operation_runner(this);
pending_operations_.push(SimpleEntryOperation::GetAvailableRangeOperation(
- this, offset, len, start, std::move(callback)));
- return net::ERR_IO_PENDING;
+ this, offset, len, std::move(callback)));
+ return RangeResult(net::ERR_IO_PENDING);
}
bool SimpleEntryImpl::CouldBeSparse() const {
@@ -671,9 +667,6 @@ void SimpleEntryImpl::ResetEntry() {
std::memset(crc32s_, 0, sizeof(crc32s_));
std::memset(have_written_, 0, sizeof(have_written_));
std::memset(data_size_, 0, sizeof(data_size_));
- for (size_t i = 0; i < base::size(crc_check_state_); ++i) {
- crc_check_state_[i] = CRC_CHECK_NEVER_READ_AT_ALL;
- }
}
void SimpleEntryImpl::ReturnEntryToCaller() {
@@ -766,8 +759,7 @@ void SimpleEntryImpl::RunNextOperationIfNeeded() {
break;
case SimpleEntryOperation::TYPE_GET_AVAILABLE_RANGE:
GetAvailableRangeInternal(operation.sparse_offset(), operation.length(),
- operation.out_start(),
- operation.ReleaseCallback());
+ operation.ReleaseRangeResultCalback());
break;
case SimpleEntryOperation::TYPE_DOOM:
DoomEntryInternal(operation.ReleaseCallback());
@@ -991,14 +983,6 @@ void SimpleEntryImpl::CloseInternal() {
synchronous_entry_ = nullptr;
prioritized_task_runner_->PostTaskAndReply(
FROM_HERE, std::move(task), std::move(reply), entry_priority_);
-
- for (int i = 0; i < kSimpleEntryStreamCount; ++i) {
- if (!have_written_[i]) {
- SIMPLE_CACHE_UMA(ENUMERATION,
- "CheckCRCResult", cache_type_,
- crc_check_state_[i], CRC_CHECK_MAX);
- }
- }
} else {
CloseOperationComplete(std::move(results));
}
@@ -1308,18 +1292,17 @@ void SimpleEntryImpl::WriteSparseDataInternal(
std::move(reply), entry_priority_);
}
-void SimpleEntryImpl::GetAvailableRangeInternal(
- int64_t sparse_offset,
- int len,
- int64_t* out_start,
- net::CompletionOnceCallback callback) {
+void SimpleEntryImpl::GetAvailableRangeInternal(int64_t sparse_offset,
+ int len,
+ RangeResultCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
ScopedOperationRunner operation_runner(this);
if (state_ == STATE_FAILURE || state_ == STATE_UNINITIALIZED) {
if (!callback.is_null()) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(std::move(callback), net::ERR_FAILED));
+ FROM_HERE,
+ base::BindOnce(std::move(callback), RangeResult(net::ERR_FAILED)));
}
// |this| may be destroyed after return here.
return;
@@ -1328,12 +1311,11 @@ void SimpleEntryImpl::GetAvailableRangeInternal(
DCHECK_EQ(STATE_READY, state_);
state_ = STATE_IO_PENDING;
- std::unique_ptr<int> result(new int());
- OnceClosure task =
- base::BindOnce(&SimpleSynchronousEntry::GetAvailableRange,
- base::Unretained(synchronous_entry_),
- SimpleSynchronousEntry::SparseRequest(sparse_offset, len),
- out_start, result.get());
+ auto result = std::make_unique<RangeResult>();
+ OnceClosure task = base::BindOnce(
+ &SimpleSynchronousEntry::GetAvailableRange,
+ base::Unretained(synchronous_entry_),
+ SimpleSynchronousEntry::SparseRequest(sparse_offset, len), result.get());
OnceClosure reply =
base::BindOnce(&SimpleEntryImpl::GetAvailableRangeOperationComplete, this,
std::move(callback), std::move(result));
@@ -1456,7 +1438,6 @@ void SimpleEntryImpl::CreationOperationComplete(
stream_1_prefetch_data_ = prefetched.data;
// The crc was read in SimpleSynchronousEntry.
- crc_check_state_[stream] = CRC_CHECK_DONE;
crc32s_[stream] = prefetched.stream_crc32;
crc32s_end_offset_[stream] = in_results->entry_stat.data_size(stream);
}
@@ -1494,8 +1475,7 @@ void SimpleEntryImpl::CreationOperationComplete(
}
}
-void SimpleEntryImpl::EntryOperationComplete(
- net::CompletionOnceCallback completion_callback,
+void SimpleEntryImpl::UpdateStateAfterOperationComplete(
const SimpleEntryStat& entry_stat,
int result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
@@ -1508,7 +1488,13 @@ void SimpleEntryImpl::EntryOperationComplete(
state_ = STATE_READY;
UpdateDataFromEntryStat(entry_stat);
}
+}
+void SimpleEntryImpl::EntryOperationComplete(
+ net::CompletionOnceCallback completion_callback,
+ const SimpleEntryStat& entry_stat,
+ int result) {
+ UpdateStateAfterOperationComplete(entry_stat, result);
if (!completion_callback.is_null()) {
base::SequencedTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(completion_callback), result));
@@ -1528,29 +1514,16 @@ void SimpleEntryImpl::ReadOperationComplete(
DCHECK(read_result);
int result = read_result->result;
- if (result > 0 &&
- crc_check_state_[stream_index] == CRC_CHECK_NEVER_READ_AT_ALL) {
- crc_check_state_[stream_index] = CRC_CHECK_NEVER_READ_TO_END;
- }
-
if (read_result->crc_updated) {
if (result > 0) {
DCHECK_EQ(crc32s_end_offset_[stream_index], offset);
crc32s_end_offset_[stream_index] += result;
crc32s_[stream_index] = read_result->updated_crc32;
}
-
- if (read_result->crc_performed_verify)
- crc_check_state_[stream_index] = CRC_CHECK_DONE;
}
if (result < 0) {
crc32s_end_offset_[stream_index] = 0;
- } else {
- if (crc_check_state_[stream_index] == CRC_CHECK_NEVER_READ_TO_END &&
- offset + result == GetDataSize(stream_index)) {
- crc_check_state_[stream_index] = CRC_CHECK_NOT_DONE;
- }
}
if (net_log_.IsCapturing()) {
@@ -1623,15 +1596,20 @@ void SimpleEntryImpl::WriteSparseOperationComplete(
}
void SimpleEntryImpl::GetAvailableRangeOperationComplete(
- net::CompletionOnceCallback completion_callback,
- std::unique_ptr<int> result) {
+ RangeResultCallback completion_callback,
+ std::unique_ptr<RangeResult> result) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(synchronous_entry_);
DCHECK(result);
SimpleEntryStat entry_stat(last_used_, last_modified_, data_size_,
sparse_data_size_);
- EntryOperationComplete(std::move(completion_callback), entry_stat, *result);
+ UpdateStateAfterOperationComplete(entry_stat, result->net_error);
+ if (!completion_callback.is_null()) {
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(completion_callback), *result));
+ }
+ RunNextOperationIfNeeded();
}
void SimpleEntryImpl::DoomOperationComplete(
diff --git a/chromium/net/disk_cache/simple/simple_entry_impl.h b/chromium/net/disk_cache/simple/simple_entry_impl.h
index 2d66478bddd..9a133e659ee 100644
--- a/chromium/net/disk_cache/simple/simple_entry_impl.h
+++ b/chromium/net/disk_cache/simple/simple_entry_impl.h
@@ -134,10 +134,9 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
net::IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
- int GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) override;
+ RangeResult GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) override;
bool CouldBeSparse() const override;
void CancelSparseIO() override;
net::Error ReadyForSparseIO(CompletionOnceCallback callback) override;
@@ -184,15 +183,6 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
DOOM_COMPLETED,
};
- // Used in histograms, please only add entries at the end.
- enum CheckCrcResult {
- CRC_CHECK_NEVER_READ_TO_END = 0,
- CRC_CHECK_NOT_DONE = 1,
- CRC_CHECK_DONE = 2,
- CRC_CHECK_NEVER_READ_AT_ALL = 3,
- CRC_CHECK_MAX = 4,
- };
-
~SimpleEntryImpl() override;
// Must be used to invoke a client-provided completion callback for an
@@ -272,8 +262,7 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
void GetAvailableRangeInternal(int64_t sparse_offset,
int len,
- int64_t* out_start,
- CompletionOnceCallback callback);
+ RangeResultCallback callback);
void DoomEntryInternal(CompletionOnceCallback callback);
@@ -294,6 +283,11 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
void CloseOperationComplete(
std::unique_ptr<SimpleEntryCloseResults> in_results);
+ // Internal utility method used by other completion methods.
+ // Updaties state and dooms on errors.
+ void UpdateStateAfterOperationComplete(const SimpleEntryStat& entry_stat,
+ int result);
+
// Internal utility method used by other completion methods. Calls
// |completion_callback| after updating state and dooming on errors.
void EntryOperationComplete(CompletionOnceCallback completion_callback,
@@ -328,8 +322,8 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
std::unique_ptr<int> result);
void GetAvailableRangeOperationComplete(
- CompletionOnceCallback completion_callback,
- std::unique_ptr<int> result);
+ RangeResultCallback completion_callback,
+ std::unique_ptr<RangeResult> result);
// Called after an asynchronous doom completes.
void DoomOperationComplete(CompletionOnceCallback callback,
@@ -417,10 +411,6 @@ class NET_EXPORT_PRIVATE SimpleEntryImpl : public Entry,
// contains stream |index|.
bool have_written_[kSimpleEntryStreamCount];
- // Reflects how much CRC checking has been done with the entry. This state is
- // reported on closing each entry stream.
- CheckCrcResult crc_check_state_[kSimpleEntryStreamCount];
-
// The |synchronous_entry_| is the worker thread object that performs IO on
// entries. It's owned by this SimpleEntryImpl whenever |executing_operation_|
// is false (i.e. when an operation is not pending on the worker pool). When
diff --git a/chromium/net/disk_cache/simple/simple_entry_operation.cc b/chromium/net/disk_cache/simple/simple_entry_operation.cc
index ebe9cada319..b58f57309b5 100644
--- a/chromium/net/disk_cache/simple/simple_entry_operation.cc
+++ b/chromium/net/disk_cache/simple/simple_entry_operation.cc
@@ -23,7 +23,7 @@ SimpleEntryOperation SimpleEntryOperation::OpenOperation(
EntryResultState result_state,
EntryResultCallback callback) {
SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0,
- nullptr, TYPE_OPEN, INDEX_NOEXIST, 0, false, false);
+ TYPE_OPEN, INDEX_NOEXIST, 0, false, false);
op.entry_callback_ = std::move(callback);
op.entry_result_state_ = result_state;
return op;
@@ -35,7 +35,7 @@ SimpleEntryOperation SimpleEntryOperation::CreateOperation(
EntryResultState result_state,
EntryResultCallback callback) {
SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0,
- nullptr, TYPE_CREATE, INDEX_NOEXIST, 0, false, false);
+ TYPE_CREATE, INDEX_NOEXIST, 0, false, false);
op.entry_callback_ = std::move(callback);
op.entry_result_state_ = result_state;
return op;
@@ -48,8 +48,7 @@ SimpleEntryOperation SimpleEntryOperation::OpenOrCreateOperation(
EntryResultState result_state,
EntryResultCallback callback) {
SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0, 0, 0,
- nullptr, TYPE_OPEN_OR_CREATE, index_state, 0, false,
- false);
+ TYPE_OPEN_OR_CREATE, index_state, 0, false, false);
op.entry_callback_ = std::move(callback);
op.entry_result_state_ = result_state;
return op;
@@ -59,8 +58,7 @@ SimpleEntryOperation SimpleEntryOperation::OpenOrCreateOperation(
SimpleEntryOperation SimpleEntryOperation::CloseOperation(
SimpleEntryImpl* entry) {
return SimpleEntryOperation(entry, nullptr, CompletionOnceCallback(), 0, 0, 0,
- nullptr, TYPE_CLOSE, INDEX_NOEXIST, 0, false,
- false);
+ TYPE_CLOSE, INDEX_NOEXIST, 0, false, false);
}
// static
@@ -72,8 +70,8 @@ SimpleEntryOperation SimpleEntryOperation::ReadOperation(
net::IOBuffer* buf,
CompletionOnceCallback callback) {
return SimpleEntryOperation(entry, buf, std::move(callback), offset, 0,
- length, nullptr, TYPE_READ, INDEX_NOEXIST, index,
- false, false);
+ length, TYPE_READ, INDEX_NOEXIST, index, false,
+ false);
}
// static
@@ -87,7 +85,7 @@ SimpleEntryOperation SimpleEntryOperation::WriteOperation(
bool optimistic,
CompletionOnceCallback callback) {
return SimpleEntryOperation(entry, buf, std::move(callback), offset, 0,
- length, nullptr, TYPE_WRITE, INDEX_NOEXIST, index,
+ length, TYPE_WRITE, INDEX_NOEXIST, index,
truncate, optimistic);
}
@@ -99,8 +97,8 @@ SimpleEntryOperation SimpleEntryOperation::ReadSparseOperation(
net::IOBuffer* buf,
CompletionOnceCallback callback) {
return SimpleEntryOperation(entry, buf, std::move(callback), 0, sparse_offset,
- length, nullptr, TYPE_READ_SPARSE, INDEX_NOEXIST,
- 0, false, false);
+ length, TYPE_READ_SPARSE, INDEX_NOEXIST, 0, false,
+ false);
}
// static
@@ -111,8 +109,8 @@ SimpleEntryOperation SimpleEntryOperation::WriteSparseOperation(
net::IOBuffer* buf,
CompletionOnceCallback callback) {
return SimpleEntryOperation(entry, buf, std::move(callback), 0, sparse_offset,
- length, nullptr, TYPE_WRITE_SPARSE, INDEX_NOEXIST,
- 0, false, false);
+ length, TYPE_WRITE_SPARSE, INDEX_NOEXIST, 0,
+ false, false);
}
// static
@@ -120,11 +118,12 @@ SimpleEntryOperation SimpleEntryOperation::GetAvailableRangeOperation(
SimpleEntryImpl* entry,
int64_t sparse_offset,
int length,
- int64_t* out_start,
- CompletionOnceCallback callback) {
- return SimpleEntryOperation(
- entry, nullptr, std::move(callback), 0, sparse_offset, length, out_start,
- TYPE_GET_AVAILABLE_RANGE, INDEX_NOEXIST, 0, false, false);
+ RangeResultCallback callback) {
+ SimpleEntryOperation op(entry, nullptr, CompletionOnceCallback(), 0,
+ sparse_offset, length, TYPE_GET_AVAILABLE_RANGE,
+ INDEX_NOEXIST, 0, false, false);
+ op.range_callback_ = std::move(callback);
+ return op;
}
// static
@@ -135,14 +134,13 @@ SimpleEntryOperation SimpleEntryOperation::DoomOperation(
const int offset = 0;
const int64_t sparse_offset = 0;
const int length = 0;
- int64_t* const out_start = nullptr;
const OpenEntryIndexEnum index_state = INDEX_NOEXIST;
const int index = 0;
const bool truncate = false;
const bool optimistic = false;
return SimpleEntryOperation(entry, buf, std::move(callback), offset,
- sparse_offset, length, out_start, TYPE_DOOM,
- index_state, index, truncate, optimistic);
+ sparse_offset, length, TYPE_DOOM, index_state,
+ index, truncate, optimistic);
}
SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
@@ -151,7 +149,6 @@ SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
int offset,
int64_t sparse_offset,
int length,
- int64_t* out_start,
EntryOperationType type,
OpenEntryIndexEnum index_state,
int index,
@@ -163,7 +160,6 @@ SimpleEntryOperation::SimpleEntryOperation(SimpleEntryImpl* entry,
offset_(offset),
sparse_offset_(sparse_offset),
length_(length),
- out_start_(out_start),
type_(type),
index_state_(index_state),
index_(index),
diff --git a/chromium/net/disk_cache/simple/simple_entry_operation.h b/chromium/net/disk_cache/simple/simple_entry_operation.h
index c5989449f8c..a7f4d529c45 100644
--- a/chromium/net/disk_cache/simple/simple_entry_operation.h
+++ b/chromium/net/disk_cache/simple/simple_entry_operation.h
@@ -92,8 +92,7 @@ class SimpleEntryOperation {
SimpleEntryImpl* entry,
int64_t sparse_offset,
int length,
- int64_t* out_start,
- CompletionOnceCallback callback);
+ RangeResultCallback callback);
static SimpleEntryOperation DoomOperation(SimpleEntryImpl* entry,
CompletionOnceCallback callback);
@@ -104,6 +103,9 @@ class SimpleEntryOperation {
EntryResultCallback ReleaseEntryResultCallback() {
return std::move(entry_callback_);
}
+ RangeResultCallback ReleaseRangeResultCalback() {
+ return std::move(range_callback_);
+ }
EntryResultState entry_result_state() { return entry_result_state_; }
@@ -112,7 +114,6 @@ class SimpleEntryOperation {
int offset() const { return offset_; }
int64_t sparse_offset() const { return sparse_offset_; }
int length() const { return length_; }
- int64_t* out_start() { return out_start_; }
net::IOBuffer* buf() { return buf_.get(); }
bool truncate() const { return truncate_; }
bool optimistic() const { return optimistic_; }
@@ -124,7 +125,6 @@ class SimpleEntryOperation {
int offset,
int64_t sparse_offset,
int length,
- int64_t* out_start,
EntryOperationType type,
OpenEntryIndexEnum index_state,
int index,
@@ -146,7 +146,7 @@ class SimpleEntryOperation {
const int length_;
// Used in get available range operations.
- int64_t* const out_start_;
+ RangeResultCallback range_callback_;
const EntryOperationType type_;
// Used in the "open or create" operation.
diff --git a/chromium/net/disk_cache/simple/simple_histogram_macros.h b/chromium/net/disk_cache/simple/simple_histogram_macros.h
index d7d36f38d2d..192907ff41f 100644
--- a/chromium/net/disk_cache/simple/simple_histogram_macros.h
+++ b/chromium/net/disk_cache/simple/simple_histogram_macros.h
@@ -13,33 +13,41 @@
// media), while making it easy to report histograms and have all names
// precomputed.
-#define SIMPLE_CACHE_THUNK(uma_type, args) UMA_HISTOGRAM_##uma_type args
+#define SIMPLE_CACHE_THUNK(uma_prefix, uma_type, args) \
+ uma_prefix##_HISTOGRAM_##uma_type args
// TODO(pasko): add histograms for shader cache as soon as it becomes possible
// for a user to get shader cache with the |SimpleBackendImpl| without altering
// any flags.
-#define SIMPLE_CACHE_UMA(uma_type, uma_name, cache_type, ...) \
- do { \
- switch (cache_type) { \
- case net::DISK_CACHE: \
- SIMPLE_CACHE_THUNK(uma_type, \
- ("SimpleCache.Http." uma_name, ##__VA_ARGS__)); \
- break; \
- case net::APP_CACHE: \
- SIMPLE_CACHE_THUNK(uma_type, \
- ("SimpleCache.App." uma_name, ##__VA_ARGS__)); \
- break; \
- case net::GENERATED_BYTE_CODE_CACHE: \
- SIMPLE_CACHE_THUNK(uma_type, \
- ("SimpleCache.Code." uma_name, ##__VA_ARGS__)); \
- break; \
- case net::GENERATED_NATIVE_CODE_CACHE: \
- case net::SHADER_CACHE: \
- break; \
- default: \
- NOTREACHED(); \
- break; \
- } \
+#define SIMPLE_CACHE_HISTO(uma_prefix, uma_type, uma_name, cache_type, ...) \
+ do { \
+ switch (cache_type) { \
+ case net::DISK_CACHE: \
+ SIMPLE_CACHE_THUNK(uma_prefix, uma_type, \
+ ("SimpleCache.Http." uma_name, ##__VA_ARGS__)); \
+ break; \
+ case net::APP_CACHE: \
+ SIMPLE_CACHE_THUNK(uma_prefix, uma_type, \
+ ("SimpleCache.App." uma_name, ##__VA_ARGS__)); \
+ break; \
+ case net::GENERATED_BYTE_CODE_CACHE: \
+ SIMPLE_CACHE_THUNK(uma_prefix, uma_type, \
+ ("SimpleCache.Code." uma_name, ##__VA_ARGS__)); \
+ break; \
+ case net::GENERATED_NATIVE_CODE_CACHE: \
+ case net::GENERATED_WEBUI_BYTE_CODE_CACHE: \
+ case net::SHADER_CACHE: \
+ break; \
+ default: \
+ NOTREACHED(); \
+ break; \
+ } \
} while (0)
+#define SIMPLE_CACHE_UMA(uma_type, uma_name, cache_type, ...) \
+ SIMPLE_CACHE_HISTO(UMA, uma_type, uma_name, cache_type, ##__VA_ARGS__)
+
+#define SIMPLE_CACHE_LOCAL(uma_type, uma_name, cache_type, ...) \
+ SIMPLE_CACHE_HISTO(LOCAL, uma_type, uma_name, cache_type, ##__VA_ARGS__)
+
#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_HISTOGRAM_MACROS_H_
diff --git a/chromium/net/disk_cache/simple/simple_index.cc b/chromium/net/disk_cache/simple/simple_index.cc
index 55abd97d0d2..03485ed16c6 100644
--- a/chromium/net/disk_cache/simple/simple_index.cc
+++ b/chromium/net/disk_cache/simple/simple_index.cc
@@ -410,14 +410,10 @@ void SimpleIndex::StartEvictionIfNeeded() {
// Take all live key hashes from the index and sort them by time.
eviction_in_progress_ = true;
eviction_start_time_ = base::TimeTicks::Now();
- SIMPLE_CACHE_UMA(
- MEMORY_KB, "Eviction.CacheSizeOnStart2", cache_type_,
- static_cast<base::HistogramBase::Sample>(cache_size_ / kBytesInKb));
- SIMPLE_CACHE_UMA(
- MEMORY_KB, "Eviction.MaxCacheSizeOnStart2", cache_type_,
- static_cast<base::HistogramBase::Sample>(max_size_ / kBytesInKb));
- bool use_size_heuristic = (cache_type_ != net::GENERATED_BYTE_CODE_CACHE);
+ bool use_size_heuristic =
+ (cache_type_ != net::GENERATED_BYTE_CODE_CACHE &&
+ cache_type_ != net::GENERATED_WEBUI_BYTE_CODE_CACHE);
// Flatten for sorting.
std::vector<std::pair<uint64_t, const EntrySet::value_type*>> entries;
@@ -453,10 +449,6 @@ void SimpleIndex::StartEvictionIfNeeded() {
SIMPLE_CACHE_UMA(TIMES,
"Eviction.TimeToSelectEntries", cache_type_,
base::TimeTicks::Now() - eviction_start_time_);
- SIMPLE_CACHE_UMA(
- MEMORY_KB, "Eviction.SizeOfEvicted2", cache_type_,
- static_cast<base::HistogramBase::Sample>(
- evicted_so_far_size / kBytesInKb));
delegate_->DoomEntries(
&entry_hashes, base::BindOnce(&SimpleIndex::EvictionDone, AsWeakPtr()));
@@ -505,13 +497,9 @@ void SimpleIndex::EvictionDone(int result) {
// Ignore the result of eviction. We did our best.
eviction_in_progress_ = false;
- SIMPLE_CACHE_UMA(BOOLEAN, "Eviction.Result", cache_type_, result == net::OK);
SIMPLE_CACHE_UMA(TIMES,
"Eviction.TimeToDone", cache_type_,
base::TimeTicks::Now() - eviction_start_time_);
- SIMPLE_CACHE_UMA(
- MEMORY_KB, "Eviction.SizeWhenDone2", cache_type_,
- static_cast<base::HistogramBase::Sample>(cache_size_ / kBytesInKb));
}
// static
@@ -602,11 +590,6 @@ void SimpleIndex::MergeInitializingSet(
SIMPLE_CACHE_UMA(
MEMORY_KB, "MaxCacheSizeOnInit", cache_type_,
static_cast<base::HistogramBase::Sample>(max_size_ / kBytesInKb));
- if (max_size_ > 0) {
- SIMPLE_CACHE_UMA(PERCENTAGE, "PercentFullOnInit", cache_type_,
- static_cast<base::HistogramBase::Sample>(
- (cache_size_ * 100) / max_size_));
- }
// Run all callbacks waiting for the index to come up.
for (auto it = to_run_when_initialized_.begin(),
@@ -641,10 +624,6 @@ void SimpleIndex::WriteToDisk(IndexWriteToDiskReason reason) {
// Cancel any pending writes since we are about to write to disk now.
write_to_disk_timer_.AbandonAndStop();
- SIMPLE_CACHE_UMA(CUSTOM_COUNTS,
- "IndexNumEntriesOnWrite", cache_type_,
- entries_set_.size(), 0, 100000, 50);
-
base::OnceClosure after_write;
if (cleanup_tracker_) {
// Make anyone synchronizing with our cleanup wait for the index to be
diff --git a/chromium/net/disk_cache/simple/simple_index_file.cc b/chromium/net/disk_cache/simple/simple_index_file.cc
index 8427ca1bb04..8f00888888e 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file.cc
@@ -15,6 +15,7 @@
#include "base/pickle.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
#include "net/disk_cache/simple/simple_entry_format.h"
#include "net/disk_cache/simple/simple_histogram_macros.h"
#include "net/disk_cache/simple/simple_index.h"
@@ -67,18 +68,6 @@ void UmaRecordIndexInitMethod(SimpleIndex::IndexInitMethod method,
SimpleIndex::INITIALIZE_METHOD_MAX);
}
-void UmaRecordIndexWriteReason(SimpleIndex::IndexWriteToDiskReason reason,
- net::CacheType cache_type) {
- SIMPLE_CACHE_UMA(ENUMERATION, "IndexWriteReason", cache_type, reason,
- SimpleIndex::INDEX_WRITE_REASON_MAX);
-}
-
-void UmaRecordIndexWriteReasonAtLoad(SimpleIndex::IndexWriteToDiskReason reason,
- net::CacheType cache_type) {
- SIMPLE_CACHE_UMA(ENUMERATION, "IndexWriteReasonAtLoad", cache_type, reason,
- SimpleIndex::INDEX_WRITE_REASON_MAX);
-}
-
void UmaRecordStaleIndexQuality(int missed_entry_count,
int extra_entry_count,
net::CacheType cache_type) {
@@ -372,7 +361,6 @@ void SimpleIndexFile::WriteToDisk(net::CacheType cache_type,
const SimpleIndex::EntrySet& entry_set,
uint64_t cache_size,
base::OnceClosure callback) {
- UmaRecordIndexWriteReason(reason, cache_type_);
IndexMetadata index_metadata(reason, entry_set.size(), cache_size);
std::unique_ptr<base::Pickle> pickle =
Serialize(cache_type, index_metadata, entry_set);
@@ -405,11 +393,6 @@ void SimpleIndexFile::SyncLoadIndexEntries(
UmaRecordIndexFileState(INDEX_STATE_CORRUPT, cache_type);
} else {
if (cache_last_modified <= last_cache_seen_by_index) {
- if (out_result->index_write_reason !=
- SimpleIndex::INDEX_WRITE_REASON_MAX) {
- UmaRecordIndexWriteReasonAtLoad(out_result->index_write_reason,
- cache_type);
- }
base::Time latest_dir_mtime;
simple_util::GetMTime(cache_directory, &latest_dir_mtime);
if (LegacyIsIndexFileStale(latest_dir_mtime, index_file_path)) {
diff --git a/chromium/net/disk_cache/simple/simple_index_file.h b/chromium/net/disk_cache/simple/simple_index_file.h
index 0e768f98656..b397469d189 100644
--- a/chromium/net/disk_cache/simple/simple_index_file.h
+++ b/chromium/net/disk_cache/simple/simple_index_file.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/files/file_path.h"
@@ -205,7 +204,6 @@ class NET_EXPORT_PRIVATE SimpleIndexFile {
DISALLOW_COPY_AND_ASSIGN(SimpleIndexFile);
};
-
} // namespace disk_cache
#endif // NET_DISK_CACHE_SIMPLE_SIMPLE_INDEX_FILE_H_
diff --git a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
index a162ca7e564..a01f096e617 100644
--- a/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
+++ b/chromium/net/disk_cache/simple/simple_index_file_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/files/file.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -15,7 +16,6 @@
#include "base/pickle.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
index 7b82043f6cf..8cb0cabc838 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.cc
@@ -17,6 +17,7 @@
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
+#include "base/metrics/histogram_macros_local.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_piece.h"
#include "base/timer/elapsed_timer.h"
@@ -40,24 +41,23 @@ namespace {
void RecordSyncOpenResult(net::CacheType cache_type, OpenEntryResult result) {
DCHECK_LT(result, OPEN_ENTRY_MAX);
- SIMPLE_CACHE_UMA(ENUMERATION,
- "SyncOpenResult", cache_type, result, OPEN_ENTRY_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncOpenResult", cache_type, result,
+ OPEN_ENTRY_MAX);
}
void RecordWriteResult(net::CacheType cache_type, SyncWriteResult result) {
- SIMPLE_CACHE_UMA(ENUMERATION, "SyncWriteResult", cache_type, result,
- SYNC_WRITE_RESULT_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncWriteResult", cache_type, result,
+ SYNC_WRITE_RESULT_MAX);
}
void RecordCheckEOFResult(net::CacheType cache_type, CheckEOFResult result) {
- SIMPLE_CACHE_UMA(ENUMERATION,
- "SyncCheckEOFResult", cache_type,
- result, CHECK_EOF_RESULT_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncCheckEOFResult", cache_type, result,
+ CHECK_EOF_RESULT_MAX);
}
void RecordCloseResult(net::CacheType cache_type, CloseResult result) {
- SIMPLE_CACHE_UMA(ENUMERATION,
- "SyncCloseResult", cache_type, result, CLOSE_RESULT_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncCloseResult", cache_type, result,
+ CLOSE_RESULT_MAX);
}
void RecordOpenPrefetchMode(net::CacheType cache_type, OpenPrefetchMode mode) {
@@ -66,7 +66,7 @@ void RecordOpenPrefetchMode(net::CacheType cache_type, OpenPrefetchMode mode) {
}
void RecordDiskCreateLatency(net::CacheType cache_type, base::TimeDelta delay) {
- SIMPLE_CACHE_UMA(TIMES, "DiskCreateLatency", cache_type, delay);
+ SIMPLE_CACHE_LOCAL(TIMES, "DiskCreateLatency", cache_type, delay);
}
bool CanOmitEmptyFile(int file_index) {
@@ -540,16 +540,12 @@ void SimpleSynchronousEntry::ReadData(const ReadRequest& in_entry_op,
if (in_entry_op.request_verify_crc &&
in_entry_op.offset + bytes_read ==
entry_stat->data_size(in_entry_op.index)) {
- out_result->crc_performed_verify = true;
int checksum_result =
CheckEOFRecord(file.get(), in_entry_op.index, *entry_stat,
out_result->updated_crc32);
if (checksum_result < 0) {
- out_result->crc_verify_ok = false;
out_result->result = checksum_result;
return;
- } else {
- out_result->crc_verify_ok = true;
}
}
}
@@ -875,8 +871,7 @@ void SimpleSynchronousEntry::WriteSparseData(const SparseRequest& in_entry_op,
}
void SimpleSynchronousEntry::GetAvailableRange(const SparseRequest& in_entry_op,
- int64_t* out_start,
- int* out_result) {
+ RangeResult* out_result) {
DCHECK(initialized_);
int64_t offset = in_entry_op.sparse_offset;
int len = in_entry_op.buf_len;
@@ -907,8 +902,8 @@ void SimpleSynchronousEntry::GetAvailableRange(const SparseRequest& in_entry_op,
}
int64_t len_from_start = len - (start - offset);
- *out_start = start;
- *out_result = static_cast<int>(std::min(avail_so_far, len_from_start));
+ *out_result = RangeResult(
+ start, static_cast<int>(std::min(avail_so_far, len_from_start)));
}
int SimpleSynchronousEntry::CheckEOFRecord(base::File* file,
@@ -1166,9 +1161,8 @@ bool SimpleSynchronousEntry::OpenFiles(SimpleEntryStat* out_entry_stat) {
if (!MaybeOpenFile(i, &error)) {
RecordSyncOpenResult(cache_type_, OPEN_ENTRY_PLATFORM_FILE_ERROR);
- SIMPLE_CACHE_UMA(ENUMERATION,
- "SyncOpenPlatformFileError", cache_type_,
- -error, -base::File::FILE_ERROR_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncOpenPlatformFileError", cache_type_,
+ -error, -base::File::FILE_ERROR_MAX);
while (--i >= 0)
CloseFile(i);
return false;
@@ -1221,9 +1215,8 @@ bool SimpleSynchronousEntry::CreateFiles(SimpleEntryStat* out_entry_stat) {
for (int i = 0; i < kSimpleEntryNormalFileCount; ++i) {
base::File::Error error;
if (!MaybeCreateFile(i, FILE_NOT_REQUIRED, &error)) {
- SIMPLE_CACHE_UMA(ENUMERATION,
- "SyncCreatePlatformFileError", cache_type_,
- -error, -base::File::FILE_ERROR_MAX);
+ SIMPLE_CACHE_LOCAL(ENUMERATION, "SyncCreatePlatformFileError",
+ cache_type_, -error, -base::File::FILE_ERROR_MAX);
while (--i >= 0)
CloseFile(i);
return false;
@@ -1496,8 +1489,6 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1(
size_t offset = file_size - length;
if (!prefetch_data.PrefetchFromFile(&file, offset, length))
return net::ERR_FAILED;
- SIMPLE_CACHE_UMA(COUNTS_100000, "EntryTrailerPrefetchSize", cache_type_,
- trailer_prefetch_size);
} else {
// Do no prefetching.
RecordOpenPrefetchMode(cache_type_, prefetch_mode);
@@ -1547,13 +1538,6 @@ int SimpleSynchronousEntry::ReadAndValidateStream0AndMaybe1(
computed_trailer_prefetch_size_ =
prefetch_data.GetDesiredTrailerPrefetchSize();
- // If we performed a trailer prefetch, record how accurate the prefetch was
- // compared to the ideal value.
- if (prefetch_mode == OPEN_PREFETCH_TRAILER) {
- SIMPLE_CACHE_UMA(COUNTS_100000, "EntryTrailerPrefetchDelta", cache_type_,
- (trailer_prefetch_size - computed_trailer_prefetch_size_));
- }
-
// If prefetch buffer is available, and we have sha256(key) (so we don't need
// to look at the header), extract out stream 1 info as well.
int stream_1_offset = out_entry_stat->GetOffsetInFile(
diff --git a/chromium/net/disk_cache/simple/simple_synchronous_entry.h b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
index 9e1536b1b42..120c67499e2 100644
--- a/chromium/net/disk_cache/simple/simple_synchronous_entry.h
+++ b/chromium/net/disk_cache/simple/simple_synchronous_entry.h
@@ -46,6 +46,7 @@ NET_EXPORT_PRIVATE extern const char
NET_EXPORT_PRIVATE int GetSimpleCachePrefetchSize();
class SimpleSynchronousEntry;
+struct RangeResult;
// This class handles the passing of data about the entry between
// SimpleEntryImplementation and SimpleSynchronousEntry and the computation of
@@ -142,15 +143,10 @@ class SimpleSynchronousEntry {
};
struct ReadResult {
- ReadResult()
- : crc_updated(false),
- crc_performed_verify(false),
- crc_verify_ok(false) {}
+ ReadResult() : crc_updated(false) {}
int result;
uint32_t updated_crc32; // only relevant if crc_updated set
bool crc_updated;
- bool crc_performed_verify; // only relevant if crc_updated set
- bool crc_verify_ok; // only relevant if crc_updated set
};
struct WriteRequest {
@@ -269,8 +265,7 @@ class SimpleSynchronousEntry {
SimpleEntryStat* out_entry_stat,
int* out_result);
void GetAvailableRange(const SparseRequest& in_entry_op,
- int64_t* out_start,
- int* out_result);
+ RangeResult* out_result);
// Close all streams, and add write EOF records to streams indicated by the
// CRCRecord entries in |crc32s_to_write|.
diff --git a/chromium/net/dns/BUILD.gn b/chromium/net/dns/BUILD.gn
index c398d8ac69b..1895dfb6654 100644
--- a/chromium/net/dns/BUILD.gn
+++ b/chromium/net/dns/BUILD.gn
@@ -198,6 +198,7 @@ source_set("host_resolver") {
"//chrome/test:unit_tests",
"//components/grpc_support/test:unit_tests",
"//content/shell:content_shell_lib",
+ "//content/test:*",
# Stand-alone tools.
"//google_apis/gcm:mcs_probe",
@@ -207,17 +208,12 @@ source_set("host_resolver") {
"//components/cronet/*",
"//net/*",
"//services/network/*",
-
- # The proxy resolution service uses its own host cache and HostResolver Mojo
- # wrapper.
- "//services/proxy_resolver/*",
]
sources = [
"dns_config.h",
"host_cache.h",
"host_resolver.h",
- "host_resolver_source.h",
"mapped_host_resolver.h",
]
public = []
@@ -294,7 +290,7 @@ source_set("dns_client") {
# TODO(crbug.com/874662): Remove once migrated to network service.
"//chrome/browser",
- # chrome/browser/chromeos/smb_client/discovery/mdns_host_locator.cc
+ # chrome/browser/ash/smb_client/discovery/mdns_host_locator.cc
# Result parsing for results read through MdnsClient.
# TODO(crbug.com/902531): Remove once migrated to network service.
"//chrome/browser/chromeos",
@@ -353,8 +349,8 @@ source_set("mdns_client") {
# TODO(crbug.com/874662): Remove once discovery client migrated.
"//chrome/tools/service_discovery_sniffer",
- # chrome/browser/chromeos/smb_client/discovery/mdns_host_locator.h
- # chrome/browser/chromeos/smb_client/discovery/mdns_host_locator.cc
+ # chrome/browser/ash/smb_client/discovery/mdns_host_locator.h
+ # chrome/browser/ash/smb_client/discovery/mdns_host_locator.cc
# Makes MDNS queries using MDnsClient.
# TODO(crbug.com/902531): Remove once migrated to network service.
"//chrome/browser/chromeos",
diff --git a/chromium/net/dns/address_info_test_util.h b/chromium/net/dns/address_info_test_util.h
index 59715ad5854..72e36eeef40 100644
--- a/chromium/net/dns/address_info_test_util.h
+++ b/chromium/net/dns/address_info_test_util.h
@@ -14,10 +14,10 @@ namespace test {
struct IpAndPort {
struct Ip {
- int a;
- int b;
- int c;
- int d;
+ uint8_t a;
+ uint8_t b;
+ uint8_t c;
+ uint8_t d;
};
Ip ip;
int port;
diff --git a/chromium/net/dns/address_sorter_posix.cc b/chromium/net/dns/address_sorter_posix.cc
index e0443455a67..8a6c75113bb 100644
--- a/chromium/net/dns/address_sorter_posix.cc
+++ b/chromium/net/dns/address_sorter_posix.cc
@@ -21,8 +21,8 @@
#include <algorithm>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source.h"
#include "net/socket/client_socket_factory.h"
diff --git a/chromium/net/dns/context_host_resolver.cc b/chromium/net/dns/context_host_resolver.cc
index 915bc744d15..9c9c1736b6c 100644
--- a/chromium/net/dns/context_host_resolver.cc
+++ b/chromium/net/dns/context_host_resolver.cc
@@ -16,11 +16,15 @@
#include "net/base/network_isolation_key.h"
#include "net/dns/dns_config.h"
#include "net/dns/host_cache.h"
+#include "net/dns/host_resolver.h"
#include "net/dns/host_resolver_manager.h"
#include "net/dns/host_resolver_proc.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/resolve_context.h"
+#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -172,9 +176,8 @@ class ContextHostResolver::WrappedResolveHostRequest
const absl::optional<HostCache::EntryStaleness>& GetStaleInfo()
const override {
if (!inner_request_) {
- static const base::NoDestructor<absl::optional<HostCache::EntryStaleness>>
- nullopt_result;
- return *nullopt_result;
+ static const absl::optional<HostCache::EntryStaleness> nullopt_result;
+ return nullopt_result;
}
return inner_request_->GetStaleInfo();
@@ -293,6 +296,29 @@ void ContextHostResolver::OnShutdown() {
std::unique_ptr<HostResolver::ResolveHostRequest>
ContextHostResolver::CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource source_net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ std::unique_ptr<HostResolverManager::CancellableResolveHostRequest>
+ inner_request;
+ if (!shutting_down_) {
+ inner_request = manager_->CreateRequest(
+ std::move(host), std::move(network_isolation_key),
+ std::move(source_net_log), std::move(optional_parameters),
+ resolve_context_.get(), resolve_context_->host_cache());
+ }
+
+ auto request = std::make_unique<WrappedResolveHostRequest>(
+ std::move(inner_request), this, shutting_down_);
+ handed_out_requests_.insert(request.get());
+ return request;
+}
+
+std::unique_ptr<HostResolver::ResolveHostRequest>
+ContextHostResolver::CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& source_net_log,
diff --git a/chromium/net/dns/context_host_resolver.h b/chromium/net/dns/context_host_resolver.h
index 5faba8daedb..eed4048bd60 100644
--- a/chromium/net/dns/context_host_resolver.h
+++ b/chromium/net/dns/context_host_resolver.h
@@ -12,7 +12,11 @@
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "net/base/net_export.h"
+#include "net/base/network_isolation_key.h"
#include "net/dns/host_resolver.h"
+#include "net/log/net_log_with_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace base {
class TickClock;
@@ -45,6 +49,11 @@ class NET_EXPORT ContextHostResolver : public HostResolver {
// HostResolver methods:
void OnShutdown() override;
std::unique_ptr<ResolveHostRequest> CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) override;
+ std::unique_ptr<ResolveHostRequest> CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& net_log,
diff --git a/chromium/net/dns/context_host_resolver_unittest.cc b/chromium/net/dns/context_host_resolver_unittest.cc
index c4a51e56a9e..141eae8c636 100644
--- a/chromium/net/dns/context_host_resolver_unittest.cc
+++ b/chromium/net/dns/context_host_resolver_unittest.cc
@@ -4,6 +4,7 @@
#include "net/dns/context_host_resolver.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -17,16 +18,18 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/schemeful_site.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/dns_config.h"
#include "net/dns/dns_test_util.h"
#include "net/dns/dns_util.h"
#include "net/dns/host_cache.h"
+#include "net/dns/host_resolver.h"
#include "net/dns/host_resolver_manager.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/dns_protocol.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/resolve_context.h"
#include "net/log/net_log_with_source.h"
@@ -37,6 +40,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -123,6 +127,59 @@ TEST_F(ContextHostResolverTest, Resolve) {
testing::ElementsAre(kEndpoint));
}
+TEST_F(ContextHostResolverTest, ResolveWithScheme) {
+ URLRequestContext context;
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back("example.com", dns_protocol::kTypeA, false /* secure */,
+ MockDnsClientRule::Result(BuildTestDnsAddressResponse(
+ "example.com", kEndpoint.address())),
+ false /* delay */, &context);
+ rules.emplace_back("example.com", dns_protocol::kTypeAAAA, false /* secure */,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ false /* delay */, &context);
+ SetMockDnsRules(std::move(rules));
+
+ auto resolve_context =
+ std::make_unique<ResolveContext>(&context, false /* enable_caching */);
+ auto resolver = std::make_unique<ContextHostResolver>(
+ manager_.get(), std::move(resolve_context));
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, "example.com", 100),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+ EXPECT_THAT(callback.GetResult(rv), test::IsOk());
+ EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
+ EXPECT_THAT(request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(kEndpoint));
+}
+
+TEST_F(ContextHostResolverTest, ResolveWithSchemeAndIpLiteral) {
+ URLRequestContext context;
+
+ IPAddress expected_address;
+ ASSERT_TRUE(expected_address.AssignFromIPLiteral("1234::5678"));
+
+ auto resolve_context =
+ std::make_unique<ResolveContext>(&context, false /* enable_caching */);
+ auto resolver = std::make_unique<ContextHostResolver>(
+ manager_.get(), std::move(resolve_context));
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, "[1234::5678]", 100),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+ EXPECT_THAT(callback.GetResult(rv), test::IsOk());
+ EXPECT_THAT(request->GetResolveErrorInfo().error, test::IsError(net::OK));
+ EXPECT_THAT(request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(expected_address, 100)));
+}
+
// Test that destroying a request silently cancels that request.
TEST_F(ContextHostResolverTest, DestroyRequest) {
// Set up delayed results for "example.com".
diff --git a/chromium/net/dns/dns_config_service_linux_unittest.cc b/chromium/net/dns/dns_config_service_linux_unittest.cc
index de79588bf15..9dce7811b57 100644
--- a/chromium/net/dns/dns_config_service_linux_unittest.cc
+++ b/chromium/net/dns/dns_config_service_linux_unittest.cc
@@ -14,10 +14,10 @@
#include "base/bind.h"
#include "base/cancelable_callback.h"
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
diff --git a/chromium/net/dns/dns_config_service_posix_unittest.cc b/chromium/net/dns/dns_config_service_posix_unittest.cc
index 003032d902e..d164b6b45c2 100644
--- a/chromium/net/dns/dns_config_service_posix_unittest.cc
+++ b/chromium/net/dns/dns_config_service_posix_unittest.cc
@@ -7,10 +7,10 @@
#include <memory>
#include "base/cancelable_callback.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
-#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
diff --git a/chromium/net/dns/dns_hosts_unittest.cc b/chromium/net/dns/dns_hosts_unittest.cc
index 65b0df26d09..e559ddc72fd 100644
--- a/chromium/net/dns/dns_hosts_unittest.cc
+++ b/chromium/net/dns/dns_hosts_unittest.cc
@@ -4,7 +4,7 @@
#include "net/dns/dns_hosts.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/ip_address.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/dns/dns_query_unittest.cc b/chromium/net/dns/dns_query_unittest.cc
index 8862558e2e8..a0f0e1f4683 100644
--- a/chromium/net/dns/dns_query_unittest.cc
+++ b/chromium/net/dns/dns_query_unittest.cc
@@ -8,8 +8,8 @@
#include <string>
#include <tuple>
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
-#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/dns/dns_util.h"
#include "net/dns/public/dns_protocol.h"
diff --git a/chromium/net/dns/dns_response.cc b/chromium/net/dns/dns_response.cc
index 2706bbe88af..3f6a47609ee 100644
--- a/chromium/net/dns/dns_response.cc
+++ b/chromium/net/dns/dns_response.cc
@@ -371,6 +371,17 @@ DnsResponse::DnsResponse(const void* data, size_t length, size_t answer_offset)
memcpy(io_buffer_->data(), data, length);
}
+// static
+DnsResponse DnsResponse::CreateEmptyNoDataResponse(uint16_t id,
+ bool is_authoritative,
+ base::StringPiece qname,
+ uint16_t qtype) {
+ return DnsResponse(id, is_authoritative,
+ /*answers=*/{},
+ /*authority_records=*/{},
+ /*additional_records=*/{}, DnsQuery(id, qname, qtype));
+}
+
DnsResponse::DnsResponse(DnsResponse&& other) = default;
DnsResponse& DnsResponse::operator=(DnsResponse&& other) = default;
diff --git a/chromium/net/dns/dns_response.h b/chromium/net/dns/dns_response.h
index 2640c7e3c68..4c512bedf4e 100644
--- a/chromium/net/dns/dns_response.h
+++ b/chromium/net/dns/dns_response.h
@@ -148,6 +148,11 @@ class NET_EXPORT_PRIVATE DnsResponse {
// Constructs a response from |data|. Used for testing purposes only!
DnsResponse(const void* data, size_t length, size_t answer_offset);
+ static DnsResponse CreateEmptyNoDataResponse(uint16_t id,
+ bool is_authoritative,
+ base::StringPiece qname,
+ uint16_t qtype);
+
// Move-only.
DnsResponse(DnsResponse&& other);
DnsResponse& operator=(DnsResponse&& other);
diff --git a/chromium/net/dns/dns_response_result_extractor.cc b/chromium/net/dns/dns_response_result_extractor.cc
index 5aea3c8c0ab..8e82202880e 100644
--- a/chromium/net/dns/dns_response_result_extractor.cc
+++ b/chromium/net/dns/dns_response_result_extractor.cc
@@ -450,20 +450,10 @@ ExtractionError ExtractIntegrityResults(const DnsResponse& response,
response, dns_protocol::kExperimentalTypeIntegrity, &records,
&response_ttl, nullptr /* out_aliases */);
- // If the response couldn't be parsed, assume no INTEGRITY records, and
- // pretend success. This is a temporary hack to keep errors with INTEGRITY
- // (which is only used for experiments) from affecting non-experimental
- // results, e.g. due to a parse error being treated as fatal for the whole
- // HostResolver request.
- //
- // TODO(crbug.com/1138620): Cleanup handling of fatal vs non-fatal errors and
- // the organization responsibility for handling them so that this extractor
- // can more sensibly return honest results rather than lying to try to be
- // helpful to HostResolverManager.
if (extraction_error != ExtractionError::kOk) {
- *out_results =
- DnsResponseResultExtractor::CreateEmptyResult(DnsQueryType::INTEGRITY);
- return ExtractionError::kOk;
+ *out_results = HostCache::Entry(ERR_DNS_MALFORMED_RESPONSE,
+ HostCache::Entry::SOURCE_DNS);
+ return extraction_error;
}
// Condense results into a list of booleans. We do not cache the results,
@@ -474,21 +464,17 @@ ExtractionError ExtractIntegrityResults(const DnsResponse& response,
condensed_results.push_back(rdata.IsIntact());
}
- // As another temporary hack for the experimental nature of INTEGRITY, always
- // claim no results, even on success. This will let it merge with address
- // results since an address request should be considered successful overall
- // only with A/AAAA results, not INTEGRITY results.
- //
- // TODO(crbug.com/1138620): Remove and handle the merging more intelligently
- // in HostResolverManager.
- *out_results =
- HostCache::Entry(ERR_NAME_NOT_RESOLVED, std::move(condensed_results),
- HostCache::Entry::SOURCE_DNS, response_ttl);
+ *out_results = HostCache::Entry(
+ condensed_results.empty() ? ERR_NAME_NOT_RESOLVED : OK,
+ std::move(condensed_results), HostCache::Entry::SOURCE_DNS, response_ttl);
DCHECK_EQ(extraction_error, ExtractionError::kOk);
return extraction_error;
}
+// TODO(crbug.com/1203426): Remove `malformed_record_is_fatal` and make it
+// always fatal once HTTPS queries are no longer done for pure experimental use.
ExtractionError ExtractHttpsResults(const DnsResponse& response,
+ bool malformed_record_is_fatal,
HostCache::Entry* out_results) {
DCHECK(out_results);
@@ -498,40 +484,28 @@ ExtractionError ExtractHttpsResults(const DnsResponse& response,
ExtractResponseRecords(response, dns_protocol::kTypeHttps, &records,
&response_ttl, nullptr /* out_aliases */);
- // If the response couldn't be parsed, assume no HTTPS records, and pretend
- // success. This is a temporary hack to keep errors with HTTPS (which is
- // currently only used for experiments) from affecting non-experimental
- // results, e.g. due to a parse error being treated as fatal for the whole
- // HostResolver request.
- //
- // TODO(crbug.com/1138620): Cleanup handling of fatal vs non-fatal errors and
- // the organization responsibility for handling them so that this extractor
- // can more sensibly return honest results rather than lying to try to be
- // helpful to HostResolverManager.
if (extraction_error != ExtractionError::kOk) {
- *out_results =
- DnsResponseResultExtractor::CreateEmptyResult(DnsQueryType::HTTPS);
- return ExtractionError::kOk;
+ *out_results = HostCache::Entry(ERR_DNS_MALFORMED_RESPONSE,
+ HostCache::Entry::SOURCE_DNS);
+ return extraction_error;
}
- // Condense results into a list of booleans. We do not cache the results,
- // but this enables us to write some unit tests.
+ // Record experimental result bools for each record.
std::vector<bool> condensed_results;
for (const auto& record : records) {
const HttpsRecordRdata& rdata = *record->rdata<HttpsRecordRdata>();
+ if (rdata.IsMalformed() && malformed_record_is_fatal) {
+ *out_results = HostCache::Entry(ERR_DNS_MALFORMED_RESPONSE,
+ HostCache::Entry::SOURCE_DNS);
+ return ExtractionError::kMalformedRecord;
+ }
condensed_results.push_back(!rdata.IsMalformed());
}
- // As another temporary hack for experimental usage of HTTPS, always claim no
- // results, even on success. This will let it merge with address results
- // since an address request should be considered successful overall only with
- // A/AAAA results, not HTTPS results.
- //
- // TODO(crbug.com/1138620): Remove and handle the merging more intelligently
- // in HostResolverManager.
- *out_results =
- HostCache::Entry(ERR_NAME_NOT_RESOLVED, std::move(condensed_results),
- HostCache::Entry::SOURCE_DNS, response_ttl);
+ // TODO(crbug.com/1225776): Output a non-experimental result representation.
+ *out_results = HostCache::Entry(records.empty() ? ERR_NAME_NOT_RESOLVED : OK,
+ std::move(condensed_results),
+ HostCache::Entry::SOURCE_DNS, response_ttl);
DCHECK_EQ(extraction_error, ExtractionError::kOk);
return extraction_error;
}
@@ -570,7 +544,11 @@ DnsResponseResultExtractor::ExtractDnsResults(
case DnsQueryType::INTEGRITY:
return ExtractIntegrityResults(*response_, out_results);
case DnsQueryType::HTTPS:
- return ExtractHttpsResults(*response_, out_results);
+ return ExtractHttpsResults(*response_, /*malformed_record_is_fatal=*/true,
+ out_results);
+ case DnsQueryType::HTTPS_EXPERIMENTAL:
+ return ExtractHttpsResults(
+ *response_, /*malformed_record_is_fatal=*/false, out_results);
}
}
@@ -578,7 +556,8 @@ DnsResponseResultExtractor::ExtractDnsResults(
HostCache::Entry DnsResponseResultExtractor::CreateEmptyResult(
DnsQueryType query_type) {
if (query_type != DnsQueryType::INTEGRITY &&
- query_type != DnsQueryType::HTTPS) {
+ query_type != DnsQueryType::HTTPS &&
+ query_type != DnsQueryType::HTTPS_EXPERIMENTAL) {
// Currently only used for INTEGRITY/HTTPS.
NOTIMPLEMENTED();
return HostCache::Entry(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
diff --git a/chromium/net/dns/dns_response_result_extractor.h b/chromium/net/dns/dns_response_result_extractor.h
index 039847e3b68..9ff53325277 100644
--- a/chromium/net/dns/dns_response_result_extractor.h
+++ b/chromium/net/dns/dns_response_result_extractor.h
@@ -52,12 +52,6 @@ class NET_EXPORT_PRIVATE DnsResponseResultExtractor {
// May have the side effect of recording metrics about DnsResponses as they
// are parsed, so while not an absolute requirement, any given DnsResponse
// should only be used and extracted from at most once.
- //
- // Note that for INTEGRITY or HTTPS, this will ignore errors and pretend it
- // successfully parsed a no-result response.
- // TODO(crbug.com/1138620): Cleanup this "helpfulness" and let
- // HostResolverManager handle whether or not errors should be fatal due to
- // experimentation.
ExtractionError ExtractDnsResults(DnsQueryType query_type,
HostCache::Entry* out_results) const;
diff --git a/chromium/net/dns/dns_response_result_extractor_unittest.cc b/chromium/net/dns/dns_response_result_extractor_unittest.cc
index 86306844594..c411950d145 100644
--- a/chromium/net/dns/dns_response_result_extractor_unittest.cc
+++ b/chromium/net/dns/dns_response_result_extractor_unittest.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
@@ -45,6 +46,7 @@ TEST(DnsResponseResultExtractorTest, ExtractsSingleARecord) {
EXPECT_EQ(results.addresses().value().GetCanonicalName(), kName);
EXPECT_THAT(results.addresses().value().dns_aliases(),
testing::ElementsAre(kName));
+ EXPECT_TRUE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, ExtractsSingleAAAARecord) {
@@ -124,11 +126,14 @@ TEST(DnsResponseResultExtractorTest, ExtractsARecordsWithCname) {
}
TEST(DnsResponseResultExtractorTest, ExtractsNxdomainAResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromHours(2);
+
DnsResponse response = BuildTestDnsResponse(
- "address.test", dns_protocol::kTypeA, {} /* answers */,
- {BuildTestDnsRecord("address.test", dns_protocol::kTypeSOA,
- "fake rdata")} /* authority */,
- {} /* additional */, dns_protocol::kRcodeNOERROR);
+ "address.test", dns_protocol::kTypeA, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("address.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -140,11 +145,19 @@ TEST(DnsResponseResultExtractorTest, ExtractsNxdomainAResponses) {
EXPECT_TRUE(results.addresses().value().empty());
EXPECT_EQ(results.addresses().value().GetCanonicalName(), "");
EXPECT_TRUE(results.addresses().value().dns_aliases().empty());
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNodataAResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromMinutes(15);
+
DnsResponse response = BuildTestDnsResponse(
- "address.test", dns_protocol::kTypeA, {} /* answers */);
+ "address.test", dns_protocol::kTypeA, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("address.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -156,6 +169,9 @@ TEST(DnsResponseResultExtractorTest, ExtractsNodataAResponses) {
EXPECT_TRUE(results.addresses().value().empty());
EXPECT_EQ(results.addresses().value().GetCanonicalName(), "");
EXPECT_TRUE(results.addresses().value().dns_aliases().empty());
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, RejectsMalformedARecord) {
@@ -170,6 +186,7 @@ TEST(DnsResponseResultExtractorTest, RejectsMalformedARecord) {
DnsResponseResultExtractor::ExtractionError::kMalformedRecord);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, RejectsWrongNameARecord) {
@@ -182,6 +199,7 @@ TEST(DnsResponseResultExtractorTest, RejectsWrongNameARecord) {
DnsResponseResultExtractor::ExtractionError::kNameMismatch);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeRecordsInAResponse) {
@@ -199,16 +217,19 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeRecordsInAResponse) {
EXPECT_TRUE(results.addresses().value().empty());
EXPECT_EQ(results.addresses().value().GetCanonicalName(), "");
EXPECT_TRUE(results.addresses().value().dns_aliases().empty());
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeRecordsMixedWithARecords) {
constexpr char kName[] = "address.test";
const IPAddress kExpected(8, 8, 8, 8);
+ constexpr auto kTtl = base::TimeDelta::FromDays(3);
- DnsResponse response = BuildTestDnsResponse(
- kName, dns_protocol::kTypeA,
- {BuildTestTextRecord(kName, {"foo"} /* text_strings */),
- BuildTestAddressRecord(kName, kExpected)});
+ DnsResponse response =
+ BuildTestDnsResponse(kName, dns_protocol::kTypeA,
+ {BuildTestTextRecord(kName, /*text_strings=*/{"foo"},
+ base::TimeDelta::FromHours(2)),
+ BuildTestAddressRecord(kName, kExpected, kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -223,6 +244,9 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeRecordsMixedWithARecords) {
EXPECT_EQ(results.addresses().value().GetCanonicalName(), kName);
EXPECT_THAT(results.addresses().value().dns_aliases(),
testing::ElementsAre(kName));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsMinATtl) {
@@ -278,11 +302,14 @@ TEST(DnsResponseResultExtractorTest, ExtractsTxtResponses) {
}
TEST(DnsResponseResultExtractorTest, ExtractsNxdomainTxtResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromDays(4);
+
DnsResponse response = BuildTestDnsResponse(
- "name.test", dns_protocol::kTypeTXT, {} /* answers */,
- {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA,
- "fake rdata")} /* authority */,
- {} /* additional */, dns_protocol::kRcodeNOERROR);
+ "name.test", dns_protocol::kTypeTXT, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -291,11 +318,19 @@ TEST(DnsResponseResultExtractorTest, ExtractsNxdomainTxtResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.text_records(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNodataTxtResponses) {
- DnsResponse response =
- BuildTestDnsTextResponse("name.test", {} /* text_records */);
+ constexpr auto kTtl = base::TimeDelta::FromMinutes(42);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "name.test", dns_protocol::kTypeTXT,
+ /*answers=*/{}, /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -304,6 +339,9 @@ TEST(DnsResponseResultExtractorTest, ExtractsNodataTxtResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.text_records(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, RejectsMalformedTxtRecord) {
@@ -318,6 +356,7 @@ TEST(DnsResponseResultExtractorTest, RejectsMalformedTxtRecord) {
DnsResponseResultExtractor::ExtractionError::kMalformedRecord);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, RejectsWrongNameTxtRecord) {
@@ -330,6 +369,7 @@ TEST(DnsResponseResultExtractorTest, RejectsWrongNameTxtRecord) {
DnsResponseResultExtractor::ExtractionError::kNameMismatch);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeTxtResponses) {
@@ -344,6 +384,7 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeTxtResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.text_records(), testing::Optional(testing::IsEmpty()));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, ExtractsMinTxtTtl) {
@@ -383,11 +424,14 @@ TEST(DnsResponseResultExtractorTest, ExtractsPtrResponses) {
}
TEST(DnsResponseResultExtractorTest, ExtractsNxdomainPtrResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromHours(5);
+
DnsResponse response = BuildTestDnsResponse(
- "name.test", dns_protocol::kTypePTR, {} /* answers */,
- {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA,
- "fake rdata")} /* authority */,
- {} /* additional */, dns_protocol::kRcodeNOERROR);
+ "name.test", dns_protocol::kTypePTR, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -396,11 +440,19 @@ TEST(DnsResponseResultExtractorTest, ExtractsNxdomainPtrResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNodataPtrResponses) {
- DnsResponse response =
- BuildTestDnsPointerResponse("name.test", {} /* pointer_names */);
+ constexpr auto kTtl = base::TimeDelta::FromMinutes(50);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "name.test", dns_protocol::kTypePTR, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -409,6 +461,9 @@ TEST(DnsResponseResultExtractorTest, ExtractsNodataPtrResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, RejectsMalformedPtrRecord) {
@@ -423,6 +478,7 @@ TEST(DnsResponseResultExtractorTest, RejectsMalformedPtrRecord) {
DnsResponseResultExtractor::ExtractionError::kMalformedRecord);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, RejectsWrongNamePtrRecord) {
@@ -435,6 +491,7 @@ TEST(DnsResponseResultExtractorTest, RejectsWrongNamePtrRecord) {
DnsResponseResultExtractor::ExtractionError::kNameMismatch);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypePtrResponses) {
@@ -449,6 +506,7 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypePtrResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, ExtractsSrvResponses) {
@@ -509,11 +567,14 @@ TEST(DnsResponseResultExtractorTest, ExtractsZeroWeightSrvResponses) {
}
TEST(DnsResponseResultExtractorTest, ExtractsNxdomainSrvResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromDays(7);
+
DnsResponse response = BuildTestDnsResponse(
- "name.test", dns_protocol::kTypeSRV, {} /* answers */,
- {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA,
- "fake rdata")} /* authority */,
- {} /* additional */, dns_protocol::kRcodeNOERROR);
+ "name.test", dns_protocol::kTypeSRV, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -522,11 +583,19 @@ TEST(DnsResponseResultExtractorTest, ExtractsNxdomainSrvResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNodataSrvResponses) {
- DnsResponse response =
- BuildTestDnsServiceResponse("name.test", {} /* service_records */);
+ constexpr auto kTtl = base::TimeDelta::FromHours(12);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "name.test", dns_protocol::kTypeSRV, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -535,6 +604,9 @@ TEST(DnsResponseResultExtractorTest, ExtractsNodataSrvResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, RejectsMalformedSrvRecord) {
@@ -549,6 +621,7 @@ TEST(DnsResponseResultExtractorTest, RejectsMalformedSrvRecord) {
DnsResponseResultExtractor::ExtractionError::kMalformedRecord);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, RejectsWrongNameSrvRecord) {
@@ -562,6 +635,7 @@ TEST(DnsResponseResultExtractorTest, RejectsWrongNameSrvRecord) {
DnsResponseResultExtractor::ExtractionError::kNameMismatch);
EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeSrvResponses) {
@@ -576,31 +650,189 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeSrvResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.hostnames(), testing::Optional(testing::IsEmpty()));
+ EXPECT_FALSE(results.has_ttl());
+}
+
+TEST(DnsResponseResultExtractorTest, ExtractsExperimentalHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromMinutes(31);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps,
+ {BuildTestHttpsAliasRecord("https.test", "alias.test", kTtl)});
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ EXPECT_THAT(results.error(), test::IsOk());
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::ElementsAre(true)));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
+}
+
+TEST(DnsResponseResultExtractorTest,
+ ExtractsNxdomainExperimentalHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromHours(8);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("https.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
+}
+
+TEST(DnsResponseResultExtractorTest, ExtractsNodataExperimentalHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromDays(3);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("https.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
+}
+
+TEST(DnsResponseResultExtractorTest,
+ RecognizesMalformedExperimentalHttpsRecord) {
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps,
+ {BuildTestDnsRecord("https.test", dns_protocol::kTypeHttps,
+ "malformed rdata")} /* answers */);
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ // HTTPS_EXPERIMENTAL continues on finding malformed records to allow metrics
+ // to be recorded about them.
+ EXPECT_THAT(results.error(), test::IsOk());
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::ElementsAre(false)));
+}
+
+TEST(DnsResponseResultExtractorTest, RejectsWrongNameExperimentalHttpsRecord) {
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps,
+ {BuildTestHttpsAliasRecord("different.test", "alias.test")});
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kNameMismatch);
+
+ EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
+}
+
+TEST(DnsResponseResultExtractorTest,
+ IgnoresWrongTypeExperimentalHttpsResponses) {
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps,
+ {BuildTestAddressRecord("https.test", IPAddress(1, 2, 3, 4))});
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::IsEmpty()));
+ EXPECT_FALSE(results.has_ttl());
+}
+
+TEST(DnsResponseResultExtractorTest,
+ IgnoresAdditionalExperimentalHttpsRecords) {
+ constexpr auto kTtl = base::TimeDelta::FromDays(3);
+
+ DnsResponse response = BuildTestDnsResponse(
+ "https.test", dns_protocol::kTypeHttps,
+ /*answers=*/{BuildTestHttpsAliasRecord("https.test", "alias.test", kTtl)},
+ /*authority=*/{},
+ /*additional=*/
+ {BuildTestHttpsServiceRecord("https.test", 3u, "service1.test", {},
+ base::TimeDelta::FromMinutes(44)),
+ BuildTestHttpsServiceRecord("https.test", 2u, "service2.test", {},
+ base::TimeDelta::FromMinutes(30))});
+ DnsResponseResultExtractor extractor(&response);
+
+ HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
+ EXPECT_EQ(
+ extractor.ExtractDnsResults(DnsQueryType::HTTPS_EXPERIMENTAL, &results),
+ DnsResponseResultExtractor::ExtractionError::kOk);
+
+ EXPECT_THAT(results.error(), test::IsOk());
+ EXPECT_THAT(results.experimental_results(),
+ testing::Optional(testing::ElementsAre(true)));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromHours(12);
+
DnsResponse response = BuildTestDnsResponse(
"https.test", dns_protocol::kTypeHttps,
- {BuildTestHttpsAliasRecord("https.test", "alias.test")});
+ /*answers=*/
+ {BuildTestHttpsAliasRecord("https.test", "alias.test", kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
EXPECT_EQ(extractor.ExtractDnsResults(DnsQueryType::HTTPS, &results),
DnsResponseResultExtractor::ExtractionError::kOk);
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
-
+ EXPECT_THAT(results.error(), test::IsOk());
EXPECT_THAT(results.experimental_results(),
testing::Optional(testing::ElementsAre(true)));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNxdomainHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromMinutes(45);
+
DnsResponse response = BuildTestDnsResponse(
- "https.test", dns_protocol::kTypeHttps, {} /* answers */,
- {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA,
- "fake rdata")} /* authority */,
- {} /* additional */, dns_protocol::kRcodeNOERROR);
+ "https.test", dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)},
+ /*additional=*/{}, dns_protocol::kRcodeNXDOMAIN);
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -610,11 +842,19 @@ TEST(DnsResponseResultExtractorTest, ExtractsNxdomainHttpsResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.experimental_results(),
testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, ExtractsNodataHttpsResponses) {
+ constexpr auto kTtl = base::TimeDelta::FromHours(36);
+
DnsResponse response = BuildTestDnsResponse(
- "https.test", dns_protocol::kTypeHttps, {} /* answers */);
+ "https.test", dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/
+ {BuildTestDnsRecord("name.test", dns_protocol::kTypeSOA, "fake rdata",
+ kTtl)});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
@@ -624,9 +864,12 @@ TEST(DnsResponseResultExtractorTest, ExtractsNodataHttpsResponses) {
EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_THAT(results.experimental_results(),
testing::Optional(testing::IsEmpty()));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
-TEST(DnsResponseResultExtractorTest, RecognizesMalformedHttpsRecord) {
+TEST(DnsResponseResultExtractorTest, RejectsMalformedHttpsRecord) {
DnsResponse response = BuildTestDnsResponse(
"https.test", dns_protocol::kTypeHttps,
{BuildTestDnsRecord("https.test", dns_protocol::kTypeHttps,
@@ -635,14 +878,13 @@ TEST(DnsResponseResultExtractorTest, RecognizesMalformedHttpsRecord) {
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
EXPECT_EQ(extractor.ExtractDnsResults(DnsQueryType::HTTPS, &results),
- DnsResponseResultExtractor::ExtractionError::kOk);
+ DnsResponseResultExtractor::ExtractionError::kMalformedRecord);
- EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
- EXPECT_THAT(results.experimental_results(),
- testing::Optional(testing::ElementsAre(false)));
+ EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
-TEST(DnsResponseResultExtractorTest, IgnoresWrongNameHttpsRecord) {
+TEST(DnsResponseResultExtractorTest, RejectsWrongNameHttpsRecord) {
DnsResponse response = BuildTestDnsResponse(
"https.test", dns_protocol::kTypeHttps,
{BuildTestHttpsAliasRecord("different.test", "alias.test")});
@@ -650,15 +892,10 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongNameHttpsRecord) {
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
EXPECT_EQ(extractor.ExtractDnsResults(DnsQueryType::HTTPS, &results),
- DnsResponseResultExtractor::ExtractionError::kOk);
-
- EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
+ DnsResponseResultExtractor::ExtractionError::kNameMismatch);
- HostCache::Entry default_results =
- DnsResponseResultExtractor::CreateEmptyResult(DnsQueryType::HTTPS);
- EXPECT_EQ(results.error(), default_results.error());
- EXPECT_EQ(results.experimental_results(),
- default_results.experimental_results());
+ EXPECT_THAT(results.error(), test::IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(results.has_ttl());
}
TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeHttpsResponses) {
@@ -677,24 +914,29 @@ TEST(DnsResponseResultExtractorTest, IgnoresWrongTypeHttpsResponses) {
}
TEST(DnsResponseResultExtractorTest, IgnoresAdditionalHttpsRecords) {
+ constexpr auto kTtl = base::TimeDelta::FromDays(5);
+
DnsResponse response = BuildTestDnsResponse(
"https.test", dns_protocol::kTypeHttps,
- {BuildTestHttpsAliasRecord("https.test", "alias.test")} /* answers */,
- {} /* authority */,
- {BuildTestHttpsServiceRecord("https.test", 3u, "service1.test", {}),
- BuildTestHttpsServiceRecord("https.test", 2u, "service2.test",
- {})} /* additional */);
+ /*answers=*/{BuildTestHttpsAliasRecord("https.test", "alias.test", kTtl)},
+ /*authority=*/{},
+ /*additional=*/
+ {BuildTestHttpsServiceRecord("https.test", 3u, "service1.test", {},
+ base::TimeDelta::FromMinutes(30)),
+ BuildTestHttpsServiceRecord("https.test", 2u, "service2.test", {},
+ base::TimeDelta::FromMinutes(45))});
DnsResponseResultExtractor extractor(&response);
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
EXPECT_EQ(extractor.ExtractDnsResults(DnsQueryType::HTTPS, &results),
DnsResponseResultExtractor::ExtractionError::kOk);
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(results.error(), test::IsError(ERR_NAME_NOT_RESOLVED));
-
+ EXPECT_THAT(results.error(), test::IsOk());
EXPECT_THAT(results.experimental_results(),
testing::Optional(testing::ElementsAre(true)));
+
+ ASSERT_TRUE(results.has_ttl());
+ EXPECT_EQ(results.ttl(), kTtl);
}
TEST(DnsResponseResultExtractorTest, IgnoresUnsolicitedHttpsRecords) {
diff --git a/chromium/net/dns/dns_response_unittest.cc b/chromium/net/dns/dns_response_unittest.cc
index bb30e0ddc88..74be2439273 100644
--- a/chromium/net/dns/dns_response_unittest.cc
+++ b/chromium/net/dns/dns_response_unittest.cc
@@ -11,7 +11,6 @@
#include "base/big_endian.h"
#include "base/check.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "net/base/io_buffer.h"
@@ -1226,7 +1225,7 @@ TEST(DnsResponseTest, ParserLimitedToBufferSize) {
}
TEST(DnsResponseWriteTest, SingleARecordAnswer) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x00, // number of questions
@@ -1254,14 +1253,15 @@ TEST(DnsResponseWriteTest, SingleARecordAnswer) {
{} /* additional records */, absl::nullopt);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, SingleARecordAnswerWithFinalDotInName) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x00, // number of questions
@@ -1289,14 +1289,15 @@ TEST(DnsResponseWriteTest, SingleARecordAnswerWithFinalDotInName) {
{} /* additional records */, absl::nullopt);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x01, // number of questions
@@ -1336,7 +1337,8 @@ TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) {
query);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
@@ -1344,7 +1346,7 @@ TEST(DnsResponseWriteTest, SingleARecordAnswerWithQuestion) {
TEST(DnsResponseWriteTest,
SingleAnswerWithQuestionConstructedFromSizeInflatedQuery) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x01, // number of questions
@@ -1400,14 +1402,15 @@ TEST(DnsResponseWriteTest,
query);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x00, // number of questions
@@ -1437,7 +1440,8 @@ TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) {
absl::nullopt);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
@@ -1445,7 +1449,7 @@ TEST(DnsResponseWriteTest, SingleQuadARecordAnswer) {
TEST(DnsResponseWriteTest,
SingleARecordAnswerWithQuestionAndNsecAdditionalRecord) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x01, // number of questions
@@ -1500,14 +1504,15 @@ TEST(DnsResponseWriteTest,
{} /* authority_records */, additional_records, query);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, TwoAnswersWithAAndQuadARecords) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x34, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x00, // number of questions
@@ -1552,14 +1557,15 @@ TEST(DnsResponseWriteTest, TwoAnswersWithAAndQuadARecords) {
absl::nullopt);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, AnswerWithAuthorityRecord) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x35, // ID
0x84, 0x00, // flags, response with authoritative answer
0x00, 0x00, // number of questions
@@ -1587,14 +1593,15 @@ TEST(DnsResponseWriteTest, AnswerWithAuthorityRecord) {
{} /* additional records */, absl::nullopt);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
}
TEST(DnsResponseWriteTest, AnswerWithRcode) {
- const char response_data[] = {
+ const uint8_t response_data[] = {
0x12, 0x12, // ID
0x80, 0x03, // flags (response with non-existent domain)
0x00, 0x00, // number of questions
@@ -1608,7 +1615,8 @@ TEST(DnsResponseWriteTest, AnswerWithRcode) {
dns_protocol::kRcodeNXDOMAIN);
ASSERT_NE(nullptr, response.io_buffer());
EXPECT_TRUE(response.IsValid());
- std::string expected_response(response_data, sizeof(response_data));
+ std::string expected_response(reinterpret_cast<const char*>(response_data),
+ sizeof(response_data));
std::string actual_response(response.io_buffer()->data(),
response.io_buffer_size());
EXPECT_EQ(expected_response, actual_response);
@@ -1681,6 +1689,23 @@ TEST(DnsResponseWriteTest, WrittenResponseCanBeParsed) {
EXPECT_EQ(additional_record.owned_rdata, parsed_record.rdata);
}
+TEST(DnsResponseWriteTest, CreateEmptyNoDataResponse) {
+ DnsResponse response = DnsResponse::CreateEmptyNoDataResponse(
+ /*id=*/4,
+ /*is_authoritative=*/true, "\x04name\x04test\x00", dns_protocol::kTypeA);
+
+ EXPECT_TRUE(response.IsValid());
+ EXPECT_THAT(response.id(), testing::Optional(4));
+ EXPECT_TRUE(response.flags() & dns_protocol::kFlagAA);
+ EXPECT_EQ(response.question_count(), 1u);
+ EXPECT_EQ(response.answer_count(), 0u);
+ EXPECT_EQ(response.authority_count(), 0u);
+ EXPECT_EQ(response.additional_answer_count(), 0u);
+
+ EXPECT_THAT(response.qtypes(), testing::ElementsAre(dns_protocol::kTypeA));
+ EXPECT_THAT(response.dotted_qnames(), testing::ElementsAre("name.test"));
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/dns/dns_session.cc b/chromium/net/dns/dns_session.cc
index 996a515f837..1e54cd24da6 100644
--- a/chromium/net/dns/dns_session.cc
+++ b/chromium/net/dns/dns_session.cc
@@ -11,7 +11,6 @@
#include "base/bind.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "net/dns/dns_config.h"
#include "net/dns/dns_socket_allocator.h"
#include "net/log/net_log.h"
diff --git a/chromium/net/dns/dns_test_util.cc b/chromium/net/dns/dns_test_util.cc
index 4c86ee8434d..0ab7403fb66 100644
--- a/chromium/net/dns/dns_test_util.cc
+++ b/chromium/net/dns/dns_test_util.cc
@@ -14,6 +14,7 @@
#include "base/location.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
+#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -166,7 +167,15 @@ DnsResourceRecord BuildTestHttpsServiceRecord(
rdata.append(num_buffer, 2);
std::string service_domain;
- CHECK(DNSDomainFromDot(service_name, &service_domain));
+ if (service_name == ".") {
+ // HTTPS records have special behavior for `service_name == "."` (that it
+ // will be treated as if the service name is the same as the record owner
+ // name), so allow such inputs despite normally being disallowed for
+ // Chrome-encoded DNS names.
+ service_domain = '\x00';
+ } else {
+ CHECK(DNSDomainFromDot(service_name, &service_domain));
+ }
rdata.append(service_domain);
for (auto& param : params) {
@@ -305,11 +314,12 @@ DnsResponse BuildTestDnsServiceResponse(
}
MockDnsClientRule::Result::Result(ResultType type,
- absl::optional<DnsResponse> response)
- : type(type), response(std::move(response)) {}
+ absl::optional<DnsResponse> response,
+ absl::optional<int> net_error)
+ : type(type), response(std::move(response)), net_error(net_error) {}
MockDnsClientRule::Result::Result(DnsResponse response)
- : type(OK), response(std::move(response)) {}
+ : type(OK), response(std::move(response)), net_error(absl::nullopt) {}
MockDnsClientRule::Result::Result(Result&& result) = default;
@@ -339,7 +349,7 @@ class MockDnsTransactionFactory::MockTransaction
public base::SupportsWeakPtr<MockTransaction> {
public:
MockTransaction(const MockDnsClientRuleList& rules,
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
bool secure,
bool force_doh_server_available,
@@ -348,7 +358,7 @@ class MockDnsTransactionFactory::MockTransaction
bool fast_timeout,
DnsTransactionFactory::CallbackType callback)
: result_(MockDnsClientRule::FAIL),
- hostname_(hostname),
+ hostname_(std::move(hostname)),
qtype_(qtype),
callback_(std::move(callback)),
started_(false),
@@ -359,17 +369,18 @@ class MockDnsTransactionFactory::MockTransaction
resolve_context->NumAvailableDohServers(
resolve_context->current_session_for_testing()) > 0) {
// Find the relevant rule which matches |qtype|, |secure|, prefix of
- // |hostname|, and |url_request_context| (iff the rule context is not
+ // |hostname_|, and |url_request_context| (iff the rule context is not
// null).
for (size_t i = 0; i < rules.size(); ++i) {
const std::string& prefix = rules[i].prefix;
if ((rules[i].qtype == qtype) && (rules[i].secure == secure) &&
- (hostname.size() >= prefix.size()) &&
- (hostname.compare(0, prefix.size(), prefix) == 0) &&
+ (hostname_.size() >= prefix.size()) &&
+ (hostname_.compare(0, prefix.size(), prefix) == 0) &&
(!rules[i].context ||
rules[i].context == resolve_context->url_request_context())) {
const MockDnsClientRule::Result* result = &rules[i].result;
result_ = MockDnsClientRule::Result(result->type);
+ result_.net_error = result->net_error;
delayed_ = rules[i].delay;
// Generate a DnsResponse when not provided with the rule.
@@ -395,6 +406,9 @@ class MockDnsTransactionFactory::MockTransaction
: 0);
break;
case MockDnsClientRule::FAIL:
+ if (result->response)
+ SetResponse(result);
+ break;
case MockDnsClientRule::TIMEOUT:
DCHECK(!result->response); // Not expected to be provided.
break;
@@ -409,6 +423,11 @@ class MockDnsTransactionFactory::MockTransaction
DCHECK(!result->response); // Not expected to be provided.
result_.response = CreateMalformedResponse(hostname_, qtype_);
break;
+ case MockDnsClientRule::UNEXPECTED:
+ ADD_FAILURE()
+ << "Unexpected DNS transaction created for hostname "
+ << hostname_;
+ break;
}
break;
@@ -466,32 +485,42 @@ class MockDnsTransactionFactory::MockTransaction
void Finish() {
switch (result_.type) {
case MockDnsClientRule::NODOMAIN:
- case MockDnsClientRule::FAIL:
- std::move(callback_).Run(
- this, ERR_NAME_NOT_RESOLVED,
- result_.response ? &result_.response.value() : nullptr,
- absl::nullopt);
+ case MockDnsClientRule::FAIL: {
+ int error = result_.net_error.value_or(ERR_NAME_NOT_RESOLVED);
+ DCHECK_NE(error, OK);
+ std::move(callback_).Run(this, error,
+ base::OptionalOrNullptr(result_.response),
+ absl::nullopt);
break;
+ }
case MockDnsClientRule::EMPTY:
case MockDnsClientRule::OK:
case MockDnsClientRule::MALFORMED:
+ DCHECK(!result_.net_error.has_value());
std::move(callback_).Run(
- this, OK, result_.response ? &result_.response.value() : nullptr,
- absl::nullopt);
+ this, OK, base::OptionalOrNullptr(result_.response), absl::nullopt);
break;
case MockDnsClientRule::TIMEOUT:
+ DCHECK(!result_.net_error.has_value());
std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
absl::nullopt);
break;
case MockDnsClientRule::SLOW:
if (result_.response) {
std::move(callback_).Run(
- this, OK, result_.response ? &result_.response.value() : nullptr,
+ this, result_.net_error.value_or(OK),
+ result_.response ? &result_.response.value() : nullptr,
absl::nullopt);
} else {
+ DCHECK(!result_.net_error.has_value());
std::move(callback_).Run(this, ERR_DNS_TIMED_OUT, nullptr,
absl::nullopt);
}
+ break;
+ case MockDnsClientRule::UNEXPECTED:
+ ADD_FAILURE() << "Unexpected DNS transaction completed for hostname "
+ << hostname_;
+ break;
}
}
@@ -537,7 +566,7 @@ MockDnsTransactionFactory::MockDnsTransactionFactory(
MockDnsTransactionFactory::~MockDnsTransactionFactory() = default;
std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
DnsTransactionFactory::CallbackType callback,
const NetLogWithSource&,
@@ -546,9 +575,10 @@ std::unique_ptr<DnsTransaction> MockDnsTransactionFactory::CreateTransaction(
ResolveContext* resolve_context,
bool fast_timeout) {
std::unique_ptr<MockTransaction> transaction =
- std::make_unique<MockTransaction>(
- rules_, hostname, qtype, secure, force_doh_server_available_,
- secure_dns_mode, resolve_context, fast_timeout, std::move(callback));
+ std::make_unique<MockTransaction>(rules_, std::move(hostname), qtype,
+ secure, force_doh_server_available_,
+ secure_dns_mode, resolve_context,
+ fast_timeout, std::move(callback));
if (transaction->delayed())
delayed_transactions_.push_back(transaction->AsWeakPtr());
return transaction;
diff --git a/chromium/net/dns/dns_test_util.h b/chromium/net/dns/dns_test_util.h
index 5e2895b4964..a0de3f50fe0 100644
--- a/chromium/net/dns/dns_test_util.h
+++ b/chromium/net/dns/dns_test_util.h
@@ -14,9 +14,9 @@
#include <utility>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
-#include "base/stl_util.h"
#include "base/time/time.h"
#include "net/dns/dns_client.h"
#include "net/dns/dns_config.h"
@@ -270,7 +270,8 @@ struct MockDnsClientRule {
enum ResultType {
// Fail asynchronously with ERR_NAME_NOT_RESOLVED and NXDOMAIN.
NODOMAIN,
- // Fail asynchronously with ERR_NAME_NOT_RESOLVED.
+ // Fail asynchronously with `net_error` or (if nullopt)
+ // ERR_NAME_NOT_RESOLVED and `response` if not nullopt.
FAIL,
// Fail asynchronously with ERR_DNS_TIMED_OUT.
TIMEOUT,
@@ -283,6 +284,9 @@ struct MockDnsClientRule {
EMPTY,
// "Succeed" but with an unparsable response.
MALFORMED,
+ // Immediately records a test failure if queried. Used to catch unexpected
+ // queries.
+ UNEXPECTED,
// Results in the response in |Result::response| or, if null, results in a
// localhost IP response.
@@ -291,7 +295,8 @@ struct MockDnsClientRule {
struct Result {
explicit Result(ResultType type,
- absl::optional<DnsResponse> response = absl::nullopt);
+ absl::optional<DnsResponse> response = absl::nullopt,
+ absl::optional<int> net_error = absl::nullopt);
explicit Result(DnsResponse response);
Result(Result&& result);
~Result();
@@ -300,6 +305,7 @@ struct MockDnsClientRule {
ResultType type;
absl::optional<DnsResponse> response;
+ absl::optional<int> net_error;
};
// If |delay| is true, matching transactions will be delayed until triggered
@@ -330,7 +336,7 @@ class MockDnsTransactionFactory : public DnsTransactionFactory {
~MockDnsTransactionFactory() override;
std::unique_ptr<DnsTransaction> CreateTransaction(
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
DnsTransactionFactory::CallbackType callback,
const NetLogWithSource&,
diff --git a/chromium/net/dns/dns_transaction.cc b/chromium/net/dns/dns_transaction.cc
index bb17713af78..7be16510cf0 100644
--- a/chromium/net/dns/dns_transaction.cc
+++ b/chromium/net/dns/dns_transaction.cc
@@ -26,7 +26,6 @@
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_checker.h"
@@ -1041,7 +1040,7 @@ class DnsTransactionImpl : public DnsTransaction,
public base::SupportsWeakPtr<DnsTransactionImpl> {
public:
DnsTransactionImpl(DnsSession* session,
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
DnsTransactionFactory::CallbackType callback,
const NetLogWithSource& net_log,
@@ -1051,7 +1050,7 @@ class DnsTransactionImpl : public DnsTransaction,
ResolveContext* resolve_context,
bool fast_timeout)
: session_(session),
- hostname_(hostname),
+ hostname_(std::move(hostname)),
qtype_(qtype),
opt_rdata_(opt_rdata),
secure_(secure),
@@ -1649,7 +1648,7 @@ class DnsTransactionFactoryImpl : public DnsTransactionFactory {
}
std::unique_ptr<DnsTransaction> CreateTransaction(
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
CallbackType callback,
const NetLogWithSource& net_log,
@@ -1658,8 +1657,8 @@ class DnsTransactionFactoryImpl : public DnsTransactionFactory {
ResolveContext* resolve_context,
bool fast_timeout) override {
return std::make_unique<DnsTransactionImpl>(
- session_.get(), hostname, qtype, std::move(callback), net_log,
- opt_rdata_.get(), secure, secure_dns_mode, resolve_context,
+ session_.get(), std::move(hostname), qtype, std::move(callback),
+ net_log, opt_rdata_.get(), secure, secure_dns_mode, resolve_context,
fast_timeout);
}
diff --git a/chromium/net/dns/dns_transaction.h b/chromium/net/dns/dns_transaction.h
index ad04ad80ac4..3b47b8a3016 100644
--- a/chromium/net/dns/dns_transaction.h
+++ b/chromium/net/dns/dns_transaction.h
@@ -16,6 +16,7 @@
#include "net/base/request_priority.h"
#include "net/dns/public/secure_dns_mode.h"
#include "net/dns/record_rdata.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
@@ -111,7 +112,7 @@ class NET_EXPORT_PRIVATE DnsTransactionFactory {
// and it would be beneficial to move on to those options sooner on signals
// that the transaction is potentially slow or problematic.
virtual std::unique_ptr<DnsTransaction> CreateTransaction(
- const std::string& hostname,
+ std::string hostname,
uint16_t qtype,
CallbackType callback,
const NetLogWithSource& net_log,
diff --git a/chromium/net/dns/dns_transaction_unittest.cc b/chromium/net/dns/dns_transaction_unittest.cc
index a7561dfbe45..303eb67ac17 100644
--- a/chromium/net/dns/dns_transaction_unittest.cc
+++ b/chromium/net/dns/dns_transaction_unittest.cc
@@ -14,10 +14,10 @@
#include "base/base64url.h"
#include "base/bind.h"
#include "base/containers/circular_deque.h"
+#include "base/cxx17_backports.h"
#include "base/numerics/safe_math.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
@@ -2411,7 +2411,8 @@ TEST_F(DnsTransactionTest, HttpsPostTestNoCookies) {
config_.dns_over_https_servers[0].server_template));
auto cookie = CanonicalCookie::Create(
cookie_url, "test-cookie=you-still-fail", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
request_context_->cookie_store()->SetCanonicalCookieAsync(
std::move(cookie), cookie_url, CookieOptions(),
base::BindOnce(&CookieCallback::SetCookieCallback,
diff --git a/chromium/net/dns/dns_util.cc b/chromium/net/dns/dns_util.cc
index 362320ff05f..8b1a025f2d4 100644
--- a/chromium/net/dns/dns_util.cc
+++ b/chromium/net/dns/dns_util.cc
@@ -304,6 +304,7 @@ uint16_t DnsQueryTypeToQtype(DnsQueryType dns_query_type) {
case DnsQueryType::INTEGRITY:
return dns_protocol::kExperimentalTypeIntegrity;
case DnsQueryType::HTTPS:
+ case DnsQueryType::HTTPS_EXPERIMENTAL:
return dns_protocol::kTypeHttps;
}
}
diff --git a/chromium/net/dns/dns_util_unittest.cc b/chromium/net/dns/dns_util_unittest.cc
index 0bcb4c8176d..5303a11f8e3 100644
--- a/chromium/net/dns/dns_util_unittest.cc
+++ b/chromium/net/dns/dns_util_unittest.cc
@@ -10,8 +10,8 @@
#include <string>
#include "base/big_endian.h"
+#include "base/cxx17_backports.h"
#include "base/numerics/safe_conversions.h"
-#include "base/stl_util.h"
#include "net/dns/public/dns_protocol.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/dns/host_cache.cc b/chromium/net/dns/host_cache.cc
index 17bd553e878..e90fb519db7 100644
--- a/chromium/net/dns/host_cache.cc
+++ b/chromium/net/dns/host_cache.cc
@@ -9,11 +9,13 @@
#include <vector>
#include "base/bind.h"
+#include "base/check_op.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/time/default_tick_clock.h"
#include "base/trace_event/trace_event.h"
#include "base/value_iterators.h"
@@ -21,8 +23,11 @@
#include "net/base/ip_endpoint.h"
#include "net/base/trace_constants.h"
#include "net/dns/host_resolver.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/log/net_log.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -38,8 +43,9 @@ namespace {
UMA_HISTOGRAM_ENUMERATION("DNS.HostCache." name, value, max)
// String constants for dictionary keys.
+const char kSchemeKey[] = "scheme";
const char kHostnameKey[] = "hostname";
-const char kAddressFamilyKey[] = "address_family";
+const char kPortKey[] = "port";
const char kDnsQueryTypeKey[] = "dns_query_type";
const char kFlagsKey[] = "flags";
const char kHostResolverSourceKey[] = "host_resolver_source";
@@ -85,6 +91,35 @@ void MergeLists(absl::optional<T>* target, const absl::optional<T>& source) {
}
}
+// Used to reject empty and IP literal (whether or not surrounded by brackets)
+// hostnames.
+bool IsValidHostname(base::StringPiece hostname) {
+ if (hostname.empty())
+ return false;
+
+ IPAddress ip_address;
+ if (ip_address.AssignFromIPLiteral(hostname) ||
+ ParseURLHostnameToAddress(hostname, &ip_address)) {
+ return false;
+ }
+
+ return true;
+}
+
+const std::string& GetHostname(
+ const absl::variant<url::SchemeHostPort, std::string>& host) {
+ const std::string* hostname;
+ if (absl::holds_alternative<url::SchemeHostPort>(host)) {
+ hostname = &absl::get<url::SchemeHostPort>(host).host();
+ } else {
+ DCHECK(absl::holds_alternative<std::string>(host));
+ hostname = &absl::get<std::string>(host);
+ }
+
+ DCHECK(IsValidHostname(*hostname));
+ return *hostname;
+}
+
} // namespace
// Used in histograms; do not modify existing values.
@@ -112,21 +147,27 @@ enum HostCache::EraseReason : int {
MAX_ERASE_REASON
};
-HostCache::Key::Key(const std::string& hostname,
+HostCache::Key::Key(absl::variant<url::SchemeHostPort, std::string> host,
DnsQueryType dns_query_type,
HostResolverFlags host_resolver_flags,
HostResolverSource host_resolver_source,
const NetworkIsolationKey& network_isolation_key)
- : hostname(hostname),
+ : host(std::move(host)),
dns_query_type(dns_query_type),
host_resolver_flags(host_resolver_flags),
host_resolver_source(host_resolver_source),
- network_isolation_key(network_isolation_key) {}
+ network_isolation_key(network_isolation_key) {
+ DCHECK(IsValidHostname(GetHostname(this->host)));
+ if (absl::holds_alternative<url::SchemeHostPort>(this->host))
+ DCHECK(absl::get<url::SchemeHostPort>(this->host).IsValid());
+}
HostCache::Key::Key() = default;
HostCache::Key::Key(const Key& key) = default;
HostCache::Key::Key(Key&& key) = default;
+HostCache::Key::~Key() = default;
+
HostCache::Entry::Entry(int error,
Source source,
absl::optional<base::TimeDelta> ttl)
@@ -621,6 +662,25 @@ void HostCache::Set(const Key& key,
delegate_->ScheduleWrite();
}
+const HostCache::Key* HostCache::GetMatchingKeyForTesting(
+ base::StringPiece hostname,
+ HostCache::Entry::Source* source_out,
+ HostCache::EntryStaleness* stale_out) const {
+ for (const EntryMap::value_type& entry : entries_) {
+ if (GetHostname(entry.first.host) == hostname) {
+ if (source_out != nullptr)
+ *source_out = entry.second.source();
+ if (stale_out != nullptr) {
+ entry.second.GetStaleness(tick_clock_->NowTicks(), network_changes_,
+ stale_out);
+ }
+ return &entry.first;
+ }
+ }
+
+ return nullptr;
+}
+
void HostCache::AddEntry(const Key& key, Entry&& entry) {
DCHECK_EQ(0u, entries_.count(key));
entries_.emplace(key, std::move(entry));
@@ -662,7 +722,7 @@ void HostCache::ClearForHosts(
for (auto it = entries_.begin(); it != entries_.end();) {
auto next_it = std::next(it);
- if (host_filter.Run(it->first.hostname)) {
+ if (host_filter.Run(GetHostname(it->first.host))) {
entries_.erase(it);
changed = true;
}
@@ -678,7 +738,7 @@ void HostCache::GetAsListValue(base::ListValue* entry_list,
bool include_staleness,
SerializationType serialization_type) const {
DCHECK(entry_list);
- entry_list->Clear();
+ entry_list->ClearList();
for (const auto& pair : entries_) {
const Key& key = pair.first;
@@ -700,7 +760,15 @@ void HostCache::GetAsListValue(base::ListValue* entry_list,
auto entry_dict =
std::make_unique<base::Value>(entry.GetAsValue(include_staleness));
- entry_dict->SetStringKey(kHostnameKey, key.hostname);
+ const auto* host = absl::get_if<url::SchemeHostPort>(&key.host);
+ if (host) {
+ entry_dict->SetStringKey(kSchemeKey, host->scheme());
+ entry_dict->SetStringKey(kHostnameKey, host->host());
+ entry_dict->SetIntKey(kPortKey, host->port());
+ } else {
+ entry_dict->SetStringKey(kHostnameKey, absl::get<std::string>(key.host));
+ }
+
entry_dict->SetIntKey(kDnsQueryTypeKey,
static_cast<int>(key.dns_query_type));
entry_dict->SetIntKey(kFlagsKey, key.host_resolver_flags);
@@ -728,36 +796,41 @@ bool HostCache::RestoreFromListValue(const base::ListValue& old_cache) {
return false;
const std::string* hostname_ptr = entry_dict.FindStringKey(kHostnameKey);
+ if (!hostname_ptr || !IsValidHostname(*hostname_ptr)) {
+ return false;
+ }
+
+ // Use presence of scheme to determine host type.
+ const std::string* scheme_ptr = entry_dict.FindStringKey(kSchemeKey);
+ absl::variant<url::SchemeHostPort, std::string> host;
+ if (scheme_ptr) {
+ absl::optional<int> port = entry_dict.FindIntKey(kPortKey);
+ if (!port || !base::IsValueInRangeForNumericType<uint16_t>(port.value()))
+ return false;
+
+ url::SchemeHostPort scheme_host_port(*scheme_ptr, *hostname_ptr,
+ port.value());
+ if (!scheme_host_port.IsValid())
+ return false;
+ host = std::move(scheme_host_port);
+ } else {
+ host = *hostname_ptr;
+ }
+
const std::string* expiration_ptr =
entry_dict.FindStringKey(kExpirationKey);
absl::optional<int> maybe_flags = entry_dict.FindIntKey(kFlagsKey);
- if (hostname_ptr == nullptr || expiration_ptr == nullptr ||
- !maybe_flags.has_value()) {
+ if (expiration_ptr == nullptr || !maybe_flags.has_value())
return false;
- }
- std::string hostname(*hostname_ptr);
std::string expiration(*expiration_ptr);
HostResolverFlags flags = maybe_flags.value();
- // If there is no DnsQueryType, look for an AddressFamily.
- //
- // TODO(crbug.com/846423): Remove kAddressFamilyKey support after a enough
- // time has passed to minimize loss-of-persistence impact from backwards
- // incompatibility.
absl::optional<int> maybe_dns_query_type =
entry_dict.FindIntKey(kDnsQueryTypeKey);
- DnsQueryType dns_query_type;
- if (maybe_dns_query_type.has_value()) {
- dns_query_type = static_cast<DnsQueryType>(maybe_dns_query_type.value());
- } else {
- absl::optional<int> maybe_address_family =
- entry_dict.FindIntKey(kAddressFamilyKey);
- if (!maybe_address_family.has_value()) {
- return false;
- }
- dns_query_type = AddressFamilyToDnsQueryType(
- static_cast<AddressFamily>(maybe_address_family.value()));
- }
+ if (!maybe_dns_query_type.has_value())
+ return false;
+ DnsQueryType dns_query_type =
+ static_cast<DnsQueryType>(maybe_dns_query_type.value());
// HostResolverSource is optional.
int host_resolver_source =
@@ -851,7 +924,7 @@ bool HostCache::RestoreFromListValue(const base::ListValue& old_cache) {
address_list.emplace();
}
- Key key(hostname, dns_query_type, flags,
+ Key key(std::move(host), dns_query_type, flags,
static_cast<HostResolverSource>(host_resolver_source),
network_isolation_key);
key.secure = secure;
@@ -925,34 +998,4 @@ bool HostCache::HasActivePin(const Entry& entry) {
return entry.pinned() && entry.network_changes() == network_changes();
}
-const HostCache::Key* HostCache::GetMatchingKey(
- base::StringPiece hostname,
- HostCache::Entry::Source* source_out,
- HostCache::EntryStaleness* stale_out) {
- net::HostCache::Key cache_key;
- cache_key.hostname = std::string(hostname);
-
- const std::pair<const HostCache::Key, HostCache::Entry>* cache_result =
- LookupStale(cache_key, tick_clock_->NowTicks(), stale_out,
- true /* ignore_secure */);
- if (!cache_result && IsAddressType(cache_key.dns_query_type)) {
- // Might not have found the cache entry because the address_family or
- // host_resolver_flags in cache_key do not match those used for the
- // original DNS lookup. Try another common combination of address_family
- // and host_resolver_flags in an attempt to find a matching cache entry.
- cache_key.dns_query_type = DnsQueryType::A;
- cache_key.host_resolver_flags =
- net::HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
- cache_result = LookupStale(cache_key, tick_clock_->NowTicks(), stale_out,
- true /* ignore_secure */);
- if (!cache_result)
- return nullptr;
- }
-
- if (source_out != nullptr)
- *source_out = cache_result->second.source();
-
- return &cache_result->first;
-}
-
} // namespace net
diff --git a/chromium/net/dns/host_cache.h b/chromium/net/dns/host_cache.h
index 0aa5e3793da..f4f8ba9a4dc 100644
--- a/chromium/net/dns/host_cache.h
+++ b/chromium/net/dns/host_cache.h
@@ -30,10 +30,12 @@
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
#include "net/dns/dns_util.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/log/net_log_capture_mode.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
namespace base {
class ListValue;
@@ -46,7 +48,10 @@ namespace net {
class NET_EXPORT HostCache {
public:
struct NET_EXPORT Key {
- Key(const std::string& hostname,
+ // Hostnames in `host` must not be IP literals. IP literals should be
+ // resolved directly to the IP address and not be stored/queried in
+ // HostCache.
+ Key(absl::variant<url::SchemeHostPort, std::string> host,
DnsQueryType dns_query_type,
HostResolverFlags host_resolver_flags,
HostResolverSource host_resolver_source,
@@ -54,26 +59,31 @@ class NET_EXPORT HostCache {
Key();
Key(const Key& key);
Key(Key&& key);
+ ~Key();
// This is a helper used in comparing keys. The order of comparisons of
- // |Key| fields is arbitrary, but the tuple is constructed with
- // |dns_query_type| and |host_resolver_flags| before |hostname| under the
+ // `Key` fields is arbitrary, but the tuple is constructed with
+ // `dns_query_type` and `host_resolver_flags` before `host` under the
// assumption that integer comparisons are faster than string comparisons.
- auto GetTuple(const Key* key) const {
- return std::tie(key->dns_query_type, key->host_resolver_flags,
- key->hostname, key->host_resolver_source,
- key->network_isolation_key, key->secure);
+ static auto GetTuple(const Key* key) {
+ return std::tie(key->dns_query_type, key->host_resolver_flags, key->host,
+ key->host_resolver_source, key->network_isolation_key,
+ key->secure);
}
bool operator==(const Key& other) const {
return GetTuple(this) == GetTuple(&other);
}
+ bool operator!=(const Key& other) const {
+ return GetTuple(this) != GetTuple(&other);
+ }
+
bool operator<(const Key& other) const {
return GetTuple(this) < GetTuple(&other);
}
- std::string hostname;
+ absl::variant<url::SchemeHostPort, std::string> host;
DnsQueryType dns_query_type = DnsQueryType::UNSPECIFIED;
HostResolverFlags host_resolver_flags = 0;
HostResolverSource host_resolver_source = HostResolverSource::ANY;
@@ -337,16 +347,17 @@ class NET_EXPORT HostCache {
base::TimeTicks now,
base::TimeDelta ttl);
- // Checks whether an entry exists for |hostname|.
+ // Checks whether an entry exists for `hostname`.
// If so, returns the matching key and writes the source (e.g. DNS, HOSTS
- // file, etc.) to |source_out| and the staleness to |stale_out| (if they are
- // not null). It tries using two common address_family and host_resolver_flag
- // combinations when performing lookups in the cache; this means false
- // negatives are possible, but unlikely. It also ignores the secure field
- // while searching for matches. If no entry exists, returns nullptr.
- const HostCache::Key* GetMatchingKey(base::StringPiece hostname,
- HostCache::Entry::Source* source_out,
- HostCache::EntryStaleness* stale_out);
+ // file, etc.) to `source_out` and the staleness to `stale_out` (if they are
+ // not null). If no entry exists, returns nullptr.
+ //
+ // For testing use only and not very performant. Production code should only
+ // do lookups by precise Key.
+ const HostCache::Key* GetMatchingKeyForTesting(
+ base::StringPiece hostname,
+ HostCache::Entry::Source* source_out = nullptr,
+ HostCache::EntryStaleness* stale_out = nullptr) const;
// Marks all entries as stale on account of a network change.
void Invalidate();
diff --git a/chromium/net/dns/host_cache_unittest.cc b/chromium/net/dns/host_cache_unittest.cc
index 2cd409786c2..141a56e18f1 100644
--- a/chromium/net/dns/host_cache_unittest.cc
+++ b/chromium/net/dns/host_cache_unittest.cc
@@ -10,9 +10,10 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
@@ -21,11 +22,15 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
+using ::testing::_;
using ::testing::ElementsAre;
using ::testing::ElementsAreArray;
using ::testing::Optional;
using ::testing::Pair;
+using ::testing::Pointee;
using ::testing::Property;
using ::testing::UnorderedElementsAre;
@@ -37,8 +42,9 @@ const int kMaxCacheEntries = 10;
// Builds a key for |hostname|, defaulting the query type to unspecified.
HostCache::Key Key(const std::string& hostname) {
- return HostCache::Key(hostname, DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
+ return HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, hostname, 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
}
bool FoobarIndexIsOdd(const std::string& foobarx_com) {
@@ -119,9 +125,64 @@ TEST(HostCacheTest, Basic) {
EXPECT_FALSE(cache.Lookup(key2, now));
}
+// Test that Keys without scheme are allowed and treated as completely different
+// from similar Keys with scheme.
+TEST(HostCacheTest, HandlesKeysWithoutScheme) {
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache cache(kMaxCacheEntries);
+
+ // t=0.
+ base::TimeTicks now;
+
+ HostCache::Key key("host1.test", DnsQueryType::UNSPECIFIED, 0,
+ HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Key key_with_scheme(
+ url::SchemeHostPort(url::kHttpsScheme, "host1.test", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
+ ASSERT_NE(key, key_with_scheme);
+ HostCache::Entry entry =
+ HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
+
+ ASSERT_EQ(0U, cache.size());
+ ASSERT_FALSE(cache.Lookup(key, now));
+ ASSERT_FALSE(cache.Lookup(key_with_scheme, now));
+
+ // Add entry for `key`.
+ cache.Set(key, entry, now, kTTL);
+ EXPECT_EQ(1U, cache.size());
+ EXPECT_TRUE(cache.Lookup(key, now));
+ EXPECT_FALSE(cache.Lookup(key_with_scheme, now));
+
+ // Add entry for `key_with_scheme`.
+ cache.Set(key_with_scheme, entry, now, kTTL);
+ EXPECT_EQ(2U, cache.size());
+ EXPECT_TRUE(cache.Lookup(key, now));
+ EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
+
+ // Clear the cache and try adding in reverse order.
+ cache.clear();
+ ASSERT_EQ(0U, cache.size());
+ ASSERT_FALSE(cache.Lookup(key, now));
+ ASSERT_FALSE(cache.Lookup(key_with_scheme, now));
+
+ // Add entry for `key_with_scheme`.
+ cache.Set(key_with_scheme, entry, now, kTTL);
+ EXPECT_EQ(1U, cache.size());
+ EXPECT_FALSE(cache.Lookup(key, now));
+ EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
+
+ // Add entry for `key`.
+ cache.Set(key, entry, now, kTTL);
+ EXPECT_EQ(2U, cache.size());
+ EXPECT_TRUE(cache.Lookup(key, now));
+ EXPECT_TRUE(cache.Lookup(key_with_scheme, now));
+}
+
// Make sure NetworkIsolationKey is respected.
TEST(HostCacheTest, NetworkIsolationKey) {
- const char kHostname[] = "hostname.test";
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "hostname.test", 443);
const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
const SchemefulSite kSite1(GURL("https://site1.test/"));
@@ -129,9 +190,9 @@ TEST(HostCacheTest, NetworkIsolationKey) {
const SchemefulSite kSite2(GURL("https://site2.test/"));
const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
- HostCache::Key key1(kHostname, DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, kNetworkIsolationKey1);
- HostCache::Key key2(kHostname, DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, kNetworkIsolationKey2);
HostCache::Entry entry1 =
HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
@@ -280,9 +341,11 @@ TEST(HostCacheTest, DnsQueryTypeIsPartOfKey) {
// t=0.
base::TimeTicks now;
- HostCache::Key key1("foobar.com", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
- HostCache::Key key2("foobar.com", DnsQueryType::A, 0, HostResolverSource::ANY,
+ HostCache::Key key1(url::SchemeHostPort(url::kHttpScheme, "foobar.com", 80),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
+ HostCache::Key key2(url::SchemeHostPort(url::kHttpScheme, "foobar.com", 80),
+ DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey());
HostCache::Entry entry =
HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
@@ -309,6 +372,7 @@ TEST(HostCacheTest, DnsQueryTypeIsPartOfKey) {
// Tests that the same hostname can be duplicated in the cache, so long as
// the HostResolverFlags differ.
TEST(HostCacheTest, HostResolverFlagsArePartOfKey) {
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
HostCache cache(kMaxCacheEntries);
@@ -316,13 +380,12 @@ TEST(HostCacheTest, HostResolverFlagsArePartOfKey) {
// t=0.
base::TimeTicks now;
- HostCache::Key key1("foobar.com", DnsQueryType::A, 0, HostResolverSource::ANY,
+ HostCache::Key key1(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey());
- HostCache::Key key2("foobar.com", DnsQueryType::A, HOST_RESOLVER_CANONNAME,
+ HostCache::Key key2(kHost, DnsQueryType::A, HOST_RESOLVER_CANONNAME,
+ HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Key key3(kHost, DnsQueryType::A, HOST_RESOLVER_LOOPBACK_ONLY,
HostResolverSource::ANY, NetworkIsolationKey());
- HostCache::Key key3("foobar.com", DnsQueryType::A,
- HOST_RESOLVER_LOOPBACK_ONLY, HostResolverSource::ANY,
- NetworkIsolationKey());
HostCache::Entry entry =
HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
@@ -356,6 +419,7 @@ TEST(HostCacheTest, HostResolverFlagsArePartOfKey) {
// Tests that the same hostname can be duplicated in the cache, so long as
// the HostResolverSource differs.
TEST(HostCacheTest, HostResolverSourceIsPartOfKey) {
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10);
HostCache cache(kMaxCacheEntries);
@@ -363,9 +427,9 @@ TEST(HostCacheTest, HostResolverSourceIsPartOfKey) {
// t=0.
base::TimeTicks now;
- HostCache::Key key1("foobar.com", DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
- HostCache::Key key2("foobar.com", DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::DNS, NetworkIsolationKey());
HostCache::Entry entry =
HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
@@ -392,6 +456,7 @@ TEST(HostCacheTest, HostResolverSourceIsPartOfKey) {
// Tests that the same hostname can be duplicated in the cache, so long as
// the secure field in the key differs.
TEST(HostCacheTest, SecureIsPartOfKey) {
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10);
HostCache cache(kMaxCacheEntries);
@@ -400,10 +465,10 @@ TEST(HostCacheTest, SecureIsPartOfKey) {
base::TimeTicks now;
HostCache::EntryStaleness stale;
- HostCache::Key key1("foobar.com", DnsQueryType::A, 0, HostResolverSource::ANY,
+ HostCache::Key key1(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey());
key1.secure = true;
- HostCache::Key key2("foobar.com", DnsQueryType::A, 0, HostResolverSource::ANY,
+ HostCache::Key key2(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey());
key2.secure = false;
HostCache::Entry entry =
@@ -437,6 +502,7 @@ TEST(HostCacheTest, SecureIsPartOfKey) {
}
TEST(HostCacheTest, PreferLessStaleMoreSecure) {
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "foobar.test", 443);
const base::TimeDelta kSuccessEntryTTL = base::TimeDelta::FromSeconds(10);
HostCache cache(kMaxCacheEntries);
@@ -445,10 +511,10 @@ TEST(HostCacheTest, PreferLessStaleMoreSecure) {
base::TimeTicks now;
HostCache::EntryStaleness stale;
- HostCache::Key insecure_key("foobar.com", DnsQueryType::A, 0,
+ HostCache::Key insecure_key(kHost, DnsQueryType::A, 0,
HostResolverSource::ANY, NetworkIsolationKey());
- HostCache::Key secure_key("foobar.com", DnsQueryType::A, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Key secure_key(kHost, DnsQueryType::A, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
secure_key.secure = true;
HostCache::Entry entry =
HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
@@ -904,62 +970,113 @@ TEST(HostCacheTest, KeyComparators) {
int expected_comparison;
};
std::vector<CacheTestParameters> tests = {
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
- HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
0},
- {HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY,
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::A, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
NetworkIsolationKey()),
- HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
1},
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
- HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY,
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey()),
-1},
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
- HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
-1},
- {HostCache::Key("host1", DnsQueryType::A, 0, HostResolverSource::ANY,
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::A, 0, HostResolverSource::ANY,
NetworkIsolationKey()),
- HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ 1},
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
+ DnsQueryType::A, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ -1},
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
+ HostResolverSource::ANY, NetworkIsolationKey()),
+ -1},
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
HostResolverSource::ANY, NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
1},
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
+ HostResolverSource::ANY, NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host2", 443),
+ DnsQueryType::UNSPECIFIED, HOST_RESOLVER_CANONNAME,
HostResolverSource::ANY, NetworkIsolationKey()),
- HostCache::Key("host2", DnsQueryType::A, 0, HostResolverSource::ANY,
+ -1},
+ // 9: Different host scheme.
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ 1},
+ // 10: Different host port.
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey()),
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 1544),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
NetworkIsolationKey()),
-1},
+ // 11: Same host name without scheme/port.
{HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey()),
- HostCache::Key("host1", DnsQueryType::UNSPECIFIED,
- HOST_RESOLVER_CANONNAME, HostResolverSource::ANY,
- NetworkIsolationKey()),
+ HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
+ HostResolverSource::ANY, NetworkIsolationKey()),
+ 0},
+ // 12: Different host name without scheme/port.
+ {HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
+ HostResolverSource::ANY, NetworkIsolationKey()),
+ HostCache::Key("host2", DnsQueryType::UNSPECIFIED, 0,
+ HostResolverSource::ANY, NetworkIsolationKey()),
-1},
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED,
- HOST_RESOLVER_CANONNAME, HostResolverSource::ANY,
+ // 13: Only one with scheme/port.
+ {HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
NetworkIsolationKey()),
HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey()),
- 1},
- {HostCache::Key("host1", DnsQueryType::UNSPECIFIED,
- HOST_RESOLVER_CANONNAME, HostResolverSource::ANY,
- NetworkIsolationKey()),
- HostCache::Key("host2", DnsQueryType::UNSPECIFIED,
- HOST_RESOLVER_CANONNAME, HostResolverSource::ANY,
- NetworkIsolationKey()),
-1},
};
HostCache::Key insecure_key =
- HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
HostCache::Key secure_key =
- HostCache::Key("host1", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Key(url::SchemeHostPort(url::kHttpsScheme, "host1", 443),
+ DnsQueryType::UNSPECIFIED, 0, HostResolverSource::ANY,
+ NetworkIsolationKey());
secure_key.secure = true;
tests.emplace_back(insecure_key, secure_key, -1);
@@ -1125,8 +1242,36 @@ TEST(HostCacheTest, SerializeAndDeserialize) {
EXPECT_EQ(2u, restored_cache.last_restore_size());
}
+TEST(HostCacheTest, SerializeAndDeserializeEntryWithoutScheme) {
+ const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
+
+ HostCache::Key key("host.test", DnsQueryType::UNSPECIFIED, 0,
+ HostResolverSource::ANY, NetworkIsolationKey());
+ HostCache::Entry entry =
+ HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_UNKNOWN);
+
+ base::TimeTicks now;
+ HostCache cache(kMaxCacheEntries);
+
+ cache.Set(key, entry, now, kTTL);
+ ASSERT_TRUE(cache.Lookup(key, now));
+ ASSERT_EQ(cache.size(), 1u);
+
+ base::ListValue serialized_cache;
+ cache.GetAsListValue(&serialized_cache, /*include_staleness=*/false,
+ HostCache::SerializationType::kRestorable);
+ HostCache restored_cache(kMaxCacheEntries);
+ EXPECT_TRUE(restored_cache.RestoreFromListValue(serialized_cache));
+ EXPECT_EQ(restored_cache.size(), 1u);
+
+ HostCache::EntryStaleness staleness;
+ EXPECT_THAT(restored_cache.LookupStale(key, now, &staleness),
+ Pointee(Pair(key, _)));
+}
+
TEST(HostCacheTest, SerializeAndDeserializeWithNetworkIsolationKey) {
- const char kHostname[] = "hostname.test";
+ const url::SchemeHostPort kHost =
+ url::SchemeHostPort(url::kHttpsScheme, "hostname.test", 443);
const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
const SchemefulSite kSite(GURL("https://site.test/"));
const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
@@ -1134,9 +1279,9 @@ TEST(HostCacheTest, SerializeAndDeserializeWithNetworkIsolationKey) {
const NetworkIsolationKey kOpaqueNetworkIsolationKey(kOpaqueSite,
kOpaqueSite);
- HostCache::Key key1(kHostname, DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key1(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, kNetworkIsolationKey);
- HostCache::Key key2(kHostname, DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key2(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, kOpaqueNetworkIsolationKey);
IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
@@ -1169,19 +1314,20 @@ TEST(HostCacheTest, SerializeAndDeserializeWithNetworkIsolationKey) {
restored_cache.LookupStale(key1, now, &stale);
ASSERT_TRUE(result);
EXPECT_EQ(kNetworkIsolationKey, result->first.network_isolation_key);
- EXPECT_EQ(kHostname, result->first.hostname);
+ EXPECT_THAT(result->first.host,
+ testing::VariantWith<url::SchemeHostPort>(kHost));
ASSERT_EQ(1u, result->second.addresses().value().size());
EXPECT_EQ(endpoint, result->second.addresses().value().front());
EXPECT_FALSE(restored_cache.Lookup(key2, now));
}
TEST(HostCacheTest, SerializeForDebugging) {
- const char kHostname[] = "hostname.test";
+ const url::SchemeHostPort kHost(url::kHttpsScheme, "hostname.test", 443);
const base::TimeDelta kTTL = base::TimeDelta::FromSeconds(10);
const NetworkIsolationKey kNetworkIsolationKey =
NetworkIsolationKey::CreateTransient();
- HostCache::Key key(kHostname, DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(kHost, DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, kNetworkIsolationKey);
IPEndPoint endpoint(IPAddress(1, 2, 3, 4), 0);
@@ -1217,7 +1363,8 @@ TEST(HostCacheTest, SerializeAndDeserialize_Text) {
base::TimeDelta ttl = base::TimeDelta::FromSeconds(99);
std::vector<std::string> text_records({"foo", "bar"});
- HostCache::Key key("example.com", DnsQueryType::A, 0, HostResolverSource::DNS,
+ HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
+ DnsQueryType::A, 0, HostResolverSource::DNS,
NetworkIsolationKey());
key.secure = true;
HostCache::Entry entry(OK, text_records, HostCache::Entry::SOURCE_DNS, ttl);
@@ -1252,7 +1399,8 @@ TEST(HostCacheTest, SerializeAndDeserialize_Hostname) {
base::TimeDelta ttl = base::TimeDelta::FromSeconds(99);
std::vector<HostPortPair> hostnames(
{HostPortPair("example.com", 95), HostPortPair("chromium.org", 122)});
- HostCache::Key key("example.com", DnsQueryType::A, 0, HostResolverSource::DNS,
+ HostCache::Key key(url::SchemeHostPort(url::kHttpsScheme, "example.com", 443),
+ DnsQueryType::A, 0, HostResolverSource::DNS,
NetworkIsolationKey());
HostCache::Entry entry(OK, hostnames, HostCache::Entry::SOURCE_DNS, ttl);
EXPECT_TRUE(entry.hostnames());
@@ -1744,80 +1892,4 @@ TEST(HostCacheTest, MergeEntries_BackCannonnameUsable) {
EXPECT_THAT(result.addresses().value().dns_aliases(), ElementsAre("name2"));
}
-void GetMatchingKeyHelper(const HostCache::Key key, bool expect_match) {
- HostCache cache(kMaxCacheEntries);
- HostCache::Entry entry =
- HostCache::Entry(OK, AddressList(), HostCache::Entry::SOURCE_DNS);
-
- // t=0.
- base::TimeTicks now;
- HostCache::Entry::Source source;
- HostCache::EntryStaleness stale;
-
- cache.Set(key, entry, now, base::TimeDelta::FromSeconds(10));
-
- const HostCache::Key* result =
- cache.GetMatchingKey(key.hostname, &source, &stale);
- EXPECT_EQ(expect_match, (result != nullptr));
- if (result) {
- EXPECT_EQ(key.hostname, result->hostname);
- EXPECT_EQ(key.secure, result->secure);
- EXPECT_EQ(key.dns_query_type, result->dns_query_type);
- EXPECT_EQ(key.host_resolver_flags, result->host_resolver_flags);
- EXPECT_EQ(HostCache::Entry::SOURCE_DNS, source);
- }
-}
-
-TEST(HostCacheTest, GetMatchingKey_ExactMatch) {
- // Should find match because this mimics the default Key struct.
- GetMatchingKeyHelper(
- HostCache::Key("foobar.com", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey()),
- true);
-}
-
-TEST(HostCacheTest, GetMatchingKey_IgnoreSecureField) {
- // Should find match because lookups ignore the secure field.
- HostCache::Key secure_key =
- HostCache::Key("foobar.com", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::ANY, NetworkIsolationKey());
- secure_key.secure = true;
- GetMatchingKeyHelper(secure_key, true);
-}
-
-TEST(HostCacheTest, GetMatchingKey_UnsupportedDnsQueryType) {
- // Should not find match because the DnsQueryType field matters.
- GetMatchingKeyHelper(
- HostCache::Key("foobar.com", DnsQueryType::A, 0, HostResolverSource::ANY,
- NetworkIsolationKey()),
- false);
-}
-
-TEST(HostCacheTest, GetMatchingKey_UnsupportedHostResolverFlags) {
- // Should not find match because the HostResolverFlags field matters.
- GetMatchingKeyHelper(
- HostCache::Key("foobar.com", DnsQueryType::UNSPECIFIED,
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6,
- HostResolverSource::ANY, NetworkIsolationKey()),
- false);
-}
-
-TEST(HostCacheTest, GetMatchingKey_UnsupportedHostResolverSource) {
- // Should not find match because the HostResolverSource field matters.
- GetMatchingKeyHelper(
- HostCache::Key("foobar.com", DnsQueryType::UNSPECIFIED, 0,
- HostResolverSource::DNS, NetworkIsolationKey()),
- false);
-}
-
-TEST(HostCacheTest, GetMatchingKey_AlternativeMatch) {
- // Should find match because a lookup with these alternate fields is tried.
- HostCache::Key secure_key =
- HostCache::Key("foobar.com", DnsQueryType::A,
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6,
- HostResolverSource::ANY, NetworkIsolationKey());
- secure_key.secure = true;
- GetMatchingKeyHelper(secure_key, true);
-}
-
} // namespace net
diff --git a/chromium/net/dns/host_resolver.cc b/chromium/net/dns/host_resolver.cc
index 16c6589c098..405cf5339d9 100644
--- a/chromium/net/dns/host_resolver.cc
+++ b/chromium/net/dns/host_resolver.cc
@@ -72,9 +72,8 @@ class FailingRequestImpl : public HostResolver::ResolveHostRequest,
const absl::optional<HostCache::EntryStaleness>& GetStaleInfo()
const override {
- static const base::NoDestructor<absl::optional<HostCache::EntryStaleness>>
- nullopt_result;
- return *nullopt_result;
+ static const absl::optional<HostCache::EntryStaleness> nullopt_result;
+ return nullopt_result;
}
private:
@@ -254,7 +253,8 @@ int HostResolver::SquashErrorCode(int error) {
// ERR_NOT_IMPLEMENTED.
// TODO(crbug.com/1043281): Consider squashing ERR_INTERNET_DISCONNECTED.
if (error == OK || error == ERR_IO_PENDING || error == ERR_NOT_IMPLEMENTED ||
- error == ERR_INTERNET_DISCONNECTED || error == ERR_NAME_NOT_RESOLVED) {
+ error == ERR_INTERNET_DISCONNECTED || error == ERR_NAME_NOT_RESOLVED ||
+ error == ERR_DNS_NAME_HTTPS_ONLY) {
return error;
} else {
return ERR_NAME_NOT_RESOLVED;
diff --git a/chromium/net/dns/host_resolver.h b/chromium/net/dns/host_resolver.h
index 334527d69c2..339182f61b7 100644
--- a/chromium/net/dns/host_resolver.h
+++ b/chromium/net/dns/host_resolver.h
@@ -17,14 +17,18 @@
#include "net/base/address_family.h"
#include "net/base/completion_once_callback.h"
#include "net/base/host_port_pair.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/request_priority.h"
#include "net/dns/host_cache.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/public/dns_config_overrides.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
+#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/public/secure_dns_policy.h"
+#include "net/log/net_log_with_source.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace base {
class Value;
@@ -38,7 +42,6 @@ class DnsClient;
struct DnsConfigOverrides;
class HostResolverManager;
class NetLog;
-class NetLogWithSource;
class URLRequestContext;
// This class represents the task of resolving hostnames (or IP address
@@ -280,23 +283,21 @@ class NET_EXPORT HostResolver {
// multiple types for the same host.
class Delegate {
public:
- enum class UpdateType { ADDED, CHANGED, REMOVED };
-
virtual ~Delegate() {}
- virtual void OnAddressResult(UpdateType update_type,
+ virtual void OnAddressResult(MdnsListenerUpdateType update_type,
DnsQueryType result_type,
IPEndPoint address) = 0;
- virtual void OnTextResult(UpdateType update_type,
+ virtual void OnTextResult(MdnsListenerUpdateType update_type,
DnsQueryType result_type,
std::vector<std::string> text_records) = 0;
- virtual void OnHostnameResult(UpdateType update_type,
+ virtual void OnHostnameResult(MdnsListenerUpdateType update_type,
DnsQueryType result_type,
HostPortPair host) = 0;
// For results which may be valid MDNS but are not handled/parsed by
// HostResolver, e.g. pointers to the root domain.
- virtual void OnUnhandledResult(UpdateType update_type,
+ virtual void OnUnhandledResult(MdnsListenerUpdateType update_type,
DnsQueryType result_type) = 0;
};
@@ -324,7 +325,15 @@ class NET_EXPORT HostResolver {
// Profiling information for the request is saved to |net_log| if non-NULL.
//
// Additional parameters may be set using |optional_parameters|. Reasonable
- // defaults will be used if passed |absl::nullopt|.
+ // defaults will be used if passed |nullptr|.
+ virtual std::unique_ptr<ResolveHostRequest> CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) = 0;
+
+ // Create requests when scheme is unknown or non-standard.
+ // TODO(crbug.com/1206799): Rename to discourage use when scheme is known.
virtual std::unique_ptr<ResolveHostRequest> CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
diff --git a/chromium/net/dns/host_resolver_manager.cc b/chromium/net/dns/host_resolver_manager.cc
index de8f73f85b4..04445e37470 100644
--- a/chromium/net/dns/host_resolver_manager.cc
+++ b/chromium/net/dns/host_resolver_manager.cc
@@ -3,20 +3,6 @@
// found in the LICENSE file.
#include "net/dns/host_resolver_manager.h"
-#include "base/task/thread_pool.h"
-#include "net/dns/public/secure_dns_mode.h"
-#include "net/dns/public/secure_dns_policy.h"
-
-#if defined(OS_WIN)
-#include <Winsock2.h>
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include <netdb.h>
-#include <netinet/in.h>
-#include <net/if.h>
-#if !defined(OS_ANDROID)
-#include <ifaddrs.h>
-#endif // !defined(OS_ANDROID)
-#endif // defined(OS_WIN)
#include <algorithm>
#include <cmath>
@@ -47,6 +33,7 @@
#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "base/single_thread_task_runner.h"
+#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -54,6 +41,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/default_tick_clock.h"
@@ -80,6 +68,7 @@
#include "net/dns/dns_response_result_extractor.h"
#include "net/dns/dns_transaction.h"
#include "net/dns/dns_util.h"
+#include "net/dns/host_cache.h"
#include "net/dns/host_resolver_mdns_listener_impl.h"
#include "net/dns/host_resolver_mdns_task.h"
#include "net/dns/host_resolver_proc.h"
@@ -88,6 +77,8 @@
#include "net/dns/public/dns_protocol.h"
#include "net/dns/public/dns_query_type.h"
#include "net/dns/public/resolve_error_info.h"
+#include "net/dns/public/secure_dns_mode.h"
+#include "net/dns/public/secure_dns_policy.h"
#include "net/dns/record_parsed.h"
#include "net/dns/resolve_context.h"
#include "net/log/net_log.h"
@@ -98,21 +89,31 @@
#include "net/log/net_log_with_source.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/datagram_client_socket.h"
-#include "url/third_party/mozilla/url_parse.h"
-#include "url/url_canon_ip.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
#if BUILDFLAG(ENABLE_MDNS)
#include "net/dns/mdns_client_impl.h"
#endif
#if defined(OS_WIN)
+#include <Winsock2.h>
#include "net/base/winsock_init.h"
#endif
+#if defined(OS_POSIX) || defined(OS_FUCHSIA)
+#include <net/if.h>
+#include <netdb.h>
+#include <netinet/in.h>
#if defined(OS_ANDROID)
#include "base/android/build_info.h"
#include "net/android/network_library.h"
-#endif
+#else // !defined(OS_ANDROID)
+#include <ifaddrs.h>
+#endif // defined(OS_ANDROID)
+#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
namespace net {
@@ -170,7 +171,7 @@ bool ContainsIcannNameCollisionIp(const AddressList& addr_list) {
}
// True if |hostname| ends with either ".local" or ".local.".
-bool ResemblesMulticastDNSName(const std::string& hostname) {
+bool ResemblesMulticastDNSName(base::StringPiece hostname) {
const char kSuffix[] = ".local.";
const size_t kSuffixLen = sizeof(kSuffix) - 1;
const size_t kSuffixLenTrimmed = kSuffixLen - 1;
@@ -323,7 +324,7 @@ base::Value NetLogDnsTaskFailedParams(const HostCache::Entry& results,
// Creates NetLog parameters for the creation of a HostResolverManager::Job.
base::Value NetLogJobCreationParams(const NetLogSource& source,
- const std::string& host) {
+ base::StringPiece host) {
base::Value dict(base::Value::Type::DICTIONARY);
source.AddToEventParameters(&dict);
dict.SetStringKey("host", host);
@@ -463,6 +464,83 @@ void NetLogHostCacheEntry(const NetLogWithSource& net_log,
net_log.AddEntry(type, phase, [&] { return results.NetLogParams(); });
}
+base::Value ToLogStringValue(
+ const absl::variant<url::SchemeHostPort, HostPortPair>& host) {
+ if (absl::holds_alternative<url::SchemeHostPort>(host))
+ return base::Value(absl::get<url::SchemeHostPort>(host).Serialize());
+
+ return base::Value(absl::get<HostPortPair>(host).ToString());
+}
+
+// Returns empty string if `host` has no known scheme.
+base::StringPiece GetScheme(
+ const absl::variant<url::SchemeHostPort, std::string>& host) {
+ if (absl::holds_alternative<url::SchemeHostPort>(host))
+ return absl::get<url::SchemeHostPort>(host).scheme();
+
+ return base::StringPiece();
+}
+
+base::StringPiece GetHostname(
+ const absl::variant<url::SchemeHostPort, HostPortPair>& host) {
+ if (absl::holds_alternative<url::SchemeHostPort>(host)) {
+ base::StringPiece hostname = absl::get<url::SchemeHostPort>(host).host();
+ if (hostname.size() >= 2 && hostname.front() == '[' &&
+ hostname.back() == ']') {
+ hostname = hostname.substr(1, hostname.size() - 2);
+ }
+ return hostname;
+ }
+
+ return absl::get<HostPortPair>(host).host();
+}
+
+base::StringPiece GetHostname(
+ const absl::variant<url::SchemeHostPort, std::string>& host) {
+ if (absl::holds_alternative<url::SchemeHostPort>(host)) {
+ base::StringPiece hostname = absl::get<url::SchemeHostPort>(host).host();
+ if (hostname.size() >= 2 && hostname.front() == '[' &&
+ hostname.back() == ']') {
+ hostname = hostname.substr(1, hostname.size() - 2);
+ }
+ return hostname;
+ }
+
+ return absl::get<std::string>(host);
+}
+
+uint16_t GetPort(const absl::variant<url::SchemeHostPort, HostPortPair>& host) {
+ if (absl::holds_alternative<url::SchemeHostPort>(host)) {
+ return absl::get<url::SchemeHostPort>(host).port();
+ }
+
+ return absl::get<HostPortPair>(host).port();
+}
+
+// Only use scheme/port in JobKey if `features::kUseDnsHttpsSvcb` is enabled
+// (or the query is explicitly for HTTPS). Otherwise DNS will not give different
+// results for the same hostname.
+absl::variant<url::SchemeHostPort, std::string> CreateHostForJobKey(
+ const absl::variant<url::SchemeHostPort, HostPortPair>& input,
+ DnsQueryType query_type) {
+ if ((base::FeatureList::IsEnabled(features::kUseDnsHttpsSvcb) ||
+ query_type == DnsQueryType::HTTPS) &&
+ absl::holds_alternative<url::SchemeHostPort>(input)) {
+ return absl::get<url::SchemeHostPort>(input);
+ }
+
+ return std::string(GetHostname(input));
+}
+
+DnsResponse CreateFakeEmptyResponse(base::StringPiece hostname,
+ DnsQueryType query_type) {
+ std::string qname;
+ CHECK(DNSDomainFromDot(hostname, &qname));
+ return DnsResponse::CreateEmptyNoDataResponse(
+ /*id=*/0u, /*is_authoritative=*/true, qname,
+ DnsQueryTypeToQtype(query_type));
+}
+
} // namespace
//-----------------------------------------------------------------------------
@@ -493,22 +571,22 @@ class HostResolverManager::RequestImpl
: public CancellableResolveHostRequest,
public base::LinkNode<HostResolverManager::RequestImpl> {
public:
- RequestImpl(const NetLogWithSource& source_net_log,
- const HostPortPair& request_host,
- const NetworkIsolationKey& network_isolation_key,
- const absl::optional<ResolveHostParameters>& optional_parameters,
+ RequestImpl(NetLogWithSource source_net_log,
+ absl::variant<url::SchemeHostPort, HostPortPair> request_host,
+ NetworkIsolationKey network_isolation_key,
+ absl::optional<ResolveHostParameters> optional_parameters,
ResolveContext* resolve_context,
HostCache* host_cache,
base::WeakPtr<HostResolverManager> resolver,
const base::TickClock* tick_clock)
- : source_net_log_(source_net_log),
- request_host_(request_host),
+ : source_net_log_(std::move(source_net_log)),
+ request_host_(std::move(request_host)),
network_isolation_key_(
base::FeatureList::IsEnabled(
net::features::kSplitHostCacheByNetworkIsolationKey)
- ? network_isolation_key
+ ? std::move(network_isolation_key)
: NetworkIsolationKey()),
- parameters_(optional_parameters ? optional_parameters.value()
+ parameters_(optional_parameters ? std::move(optional_parameters).value()
: ResolveHostParameters()),
resolve_context_(resolve_context),
host_cache_(host_cache),
@@ -670,7 +748,9 @@ class HostResolverManager::RequestImpl
// NetLog for the source, passed in HostResolver::Resolve.
const NetLogWithSource& source_net_log() { return source_net_log_; }
- const HostPortPair& request_host() const { return request_host_; }
+ const absl::variant<url::SchemeHostPort, HostPortPair>& request_host() const {
+ return request_host_;
+ }
const NetworkIsolationKey& network_isolation_key() const {
return network_isolation_key_;
@@ -711,7 +791,7 @@ class HostResolverManager::RequestImpl
source_net_log_.BeginEvent(
NetLogEventType::HOST_RESOLVER_IMPL_REQUEST, [this] {
base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetStringKey("host", request_host_.ToString());
+ dict.SetKey("host", ToLogStringValue(request_host_));
dict.SetIntKey("dns_query_type",
static_cast<int>(parameters_.dns_query_type));
dict.SetBoolKey("allow_cached_response",
@@ -730,17 +810,6 @@ class HostResolverManager::RequestImpl
source_net_log_.EndEventWithNetErrorCode(
NetLogEventType::HOST_RESOLVER_IMPL_REQUEST, net_error);
- url::HostSafetyStatus host_safety_status = url::CheckHostnameSafety(
- request_host_.host().c_str(),
- url::Component(0, request_host_.host().size()));
- if (net_error == net::OK) {
- UMA_HISTOGRAM_ENUMERATION("Net.DNS.Request.Success.HostSafetyStatus",
- host_safety_status);
- } else {
- UMA_HISTOGRAM_ENUMERATION("Net.DNS.Request.Failure.HostSafetyStatus",
- host_safety_status);
- }
-
if (!parameters_.is_speculative) {
DCHECK(!request_time_.is_null());
base::TimeDelta duration = tick_clock_->NowTicks() - request_time_;
@@ -759,7 +828,7 @@ class HostResolverManager::RequestImpl
const NetLogWithSource source_net_log_;
- const HostPortPair request_host_;
+ const absl::variant<url::SchemeHostPort, HostPortPair> request_host_;
const NetworkIsolationKey network_isolation_key_;
ResolveHostParameters parameters_;
// TODO(ericorth@chromium.org): Use base::UnownedPtr once available.
@@ -1098,7 +1167,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
class Delegate {
public:
virtual void OnDnsTaskComplete(base::TimeTicks start_time,
- const HostCache::Entry& results,
+ HostCache::Entry results,
bool secure) = 0;
// Called when a job succeeds and there are more transactions needed. If
@@ -1116,7 +1185,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
};
DnsTask(DnsClient* client,
- base::StringPiece hostname,
+ absl::variant<url::SchemeHostPort, std::string> host,
DnsQueryType query_type,
ResolveContext* resolve_context,
bool secure,
@@ -1126,7 +1195,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
const base::TickClock* tick_clock,
bool fallback_available)
: client_(client),
- hostname_(hostname),
+ host_(std::move(host)),
resolve_context_(resolve_context),
secure_(secure),
secure_dns_mode_(secure_dns_mode),
@@ -1147,26 +1216,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
} else {
transactions_needed_.push(DnsQueryType::A);
transactions_needed_.push(DnsQueryType::AAAA);
-
- // Queue up an INTEGRITY/HTTPS query if we are allowed to.
- const bool is_httpssvc_experiment_domain =
- httpssvc_domain_cache_.IsExperimental(hostname);
- const bool is_httpssvc_control_domain =
- httpssvc_domain_cache_.IsControl(hostname);
- const bool can_query_via_insecure =
- !secure_ && features::kDnsHttpssvcEnableQueryOverInsecure.Get() &&
- client_->CanQueryAdditionalTypesViaInsecureDns();
- if (base::FeatureList::IsEnabled(features::kDnsHttpssvc) &&
- (secure_ || can_query_via_insecure) &&
- (is_httpssvc_experiment_domain || is_httpssvc_control_domain)) {
- httpssvc_metrics_.emplace(
- is_httpssvc_experiment_domain /* expect_intact */);
-
- if (features::kDnsHttpssvcUseIntegrity.Get())
- transactions_needed_.push(DnsQueryType::INTEGRITY);
- if (features::kDnsHttpssvcUseHttpssvc.Get())
- transactions_needed_.push(DnsQueryType::HTTPS);
- }
+ MaybeQueueHttpsTransaction();
}
num_needed_transactions_ = transactions_needed_.size();
@@ -1193,7 +1243,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
DnsQueryType type = transactions_needed_.front();
transactions_needed_.pop();
- DCHECK(type != DnsQueryType::HTTPS || secure_ ||
+ DCHECK(IsAddressType(type) || secure_ ||
client_->CanQueryAdditionalTypesViaInsecureDns());
// Record how long this transaction has been waiting to be created.
@@ -1208,13 +1258,94 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
}
private:
+ void MaybeQueueHttpsTransaction() {
+ // `features::kUseDnsHttpsSvcb` has precedence, so if enabled, ignore any
+ // other related features.
+ if (base::FeatureList::IsEnabled(features::kUseDnsHttpsSvcb)) {
+ base::StringPiece scheme = GetScheme(host_);
+ if (scheme != url::kHttpScheme && scheme != url::kHttpsScheme &&
+ scheme != url::kWsScheme && scheme != url::kWssScheme) {
+ return;
+ }
+
+ if (!secure_ && (!features::kUseDnsHttpsSvcbEnableInsecure.Get() ||
+ !client_->CanQueryAdditionalTypesViaInsecureDns()))
+ return;
+
+ transactions_needed_.push(DnsQueryType::HTTPS);
+ return;
+ }
+
+ if (base::FeatureList::IsEnabled(features::kDnsHttpssvc)) {
+ const bool is_httpssvc_experiment_domain =
+ httpssvc_domain_cache_.IsExperimental(GetHostname(host_));
+ const bool is_httpssvc_control_domain =
+ httpssvc_domain_cache_.IsControl(GetHostname(host_));
+ const bool can_query_via_insecure =
+ !secure_ && features::kDnsHttpssvcEnableQueryOverInsecure.Get() &&
+ client_->CanQueryAdditionalTypesViaInsecureDns();
+ if (base::FeatureList::IsEnabled(features::kDnsHttpssvc) &&
+ (secure_ || can_query_via_insecure) &&
+ (is_httpssvc_experiment_domain || is_httpssvc_control_domain)) {
+ httpssvc_metrics_.emplace(
+ is_httpssvc_experiment_domain /* expect_intact */);
+
+ if (features::kDnsHttpssvcUseIntegrity.Get())
+ transactions_needed_.push(DnsQueryType::INTEGRITY);
+ if (features::kDnsHttpssvcUseHttpssvc.Get())
+ transactions_needed_.push(DnsQueryType::HTTPS_EXPERIMENTAL);
+ }
+ }
+ }
+
std::unique_ptr<DnsTransaction> CreateTransaction(
DnsQueryType dns_query_type) {
DCHECK_NE(DnsQueryType::UNSPECIFIED, dns_query_type);
+ std::string transaction_hostname(GetHostname(host_));
+
+ // For HTTPS, prepend "_<port>._https." for any non-default port.
+ if (dns_query_type == DnsQueryType::HTTPS &&
+ absl::holds_alternative<url::SchemeHostPort>(host_)) {
+ const auto& scheme_host_port = absl::get<url::SchemeHostPort>(host_);
+
+ DCHECK(!scheme_host_port.host().empty() &&
+ scheme_host_port.host().front() != '.');
+
+ // Normalize ws/wss schemes to http/https.
+ base::StringPiece normalized_scheme = scheme_host_port.scheme();
+ if (normalized_scheme == url::kWsScheme) {
+ normalized_scheme = url::kHttpScheme;
+ } else if (normalized_scheme == url::kWssScheme) {
+ normalized_scheme = url::kHttpsScheme;
+ }
+
+ // For http-schemed hosts, request the corresponding upgraded https host
+ // per the rules in draft-ietf-dnsop-svcb-https-06, Section 8.5.
+ uint16_t port = scheme_host_port.port();
+ if (normalized_scheme == url::kHttpScheme) {
+ normalized_scheme = url::kHttpsScheme;
+ if (port == 80)
+ port = 443;
+ }
+
+ // Scheme should always end up normalized to "https" to create HTTPS
+ // transactions.
+ DCHECK_EQ(normalized_scheme, url::kHttpsScheme);
+
+ // Per the rules in draft-ietf-dnsop-svcb-https-06, Section 8.1 and 2.3,
+ // encode scheme and port in the transaction hostname, unless the port is
+ // the default 443.
+ if (port != 443) {
+ transaction_hostname = base::StrCat({"_", base::NumberToString(port),
+ "._https.", transaction_hostname});
+ }
+ }
+
std::unique_ptr<DnsTransaction> trans =
client_->GetTransactionFactory()->CreateTransaction(
- hostname_, DnsQueryTypeToQtype(dns_query_type),
+ std::move(transaction_hostname),
+ DnsQueryTypeToQtype(dns_query_type),
base::BindOnce(&DnsTask::OnTransactionComplete,
base::Unretained(this), tick_clock_->NowTicks(),
dns_query_type),
@@ -1288,32 +1419,47 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
}
}
+ // Handle network errors. Note that for NXDOMAIN, DnsTransaction returns
+ // ERR_NAME_NOT_RESOLVED, so that is not a network error if received with a
+ // valid response.
+ absl::optional<DnsResponse> fake_response;
+ if (net_error != OK && !(net_error == ERR_NAME_NOT_RESOLVED && response &&
+ response->IsValid())) {
+ if (dns_query_type == DnsQueryType::INTEGRITY ||
+ dns_query_type == DnsQueryType::HTTPS_EXPERIMENTAL ||
+ (dns_query_type == DnsQueryType::HTTPS &&
+ !IsFatalHttpsTransactionFailure(net_error, response))) {
+ // For non-fatal failures, synthesize an empty response.
+ fake_response =
+ CreateFakeEmptyResponse(GetHostname(host_), dns_query_type);
+ response = &fake_response.value();
+ } else {
+ // Fail completely on network failure.
+ OnFailure(net_error, DnsResponseResultExtractor::ExtractionError::kOk,
+ absl::nullopt);
+ return;
+ }
+ }
+
HostCache::Entry results(ERR_FAILED, HostCache::Entry::SOURCE_UNKNOWN);
- // Parse NOERROR results or NXDOMAIN (signified from DnsTransaction by
- // ERR_NAME_NOT_RESOLVED) results with a valid response to parse.
- if (net_error == OK || (net_error == ERR_NAME_NOT_RESOLVED && response &&
- response->IsValid())) {
- DnsResponseResultExtractor extractor(response);
- DnsResponseResultExtractor::ExtractionError extraction_error =
- extractor.ExtractDnsResults(dns_query_type, &results);
- DCHECK_NE(extraction_error,
- DnsResponseResultExtractor::ExtractionError::kUnexpected);
-
- if (results.error() != OK && results.error() != ERR_NAME_NOT_RESOLVED) {
+ DnsResponseResultExtractor extractor(response);
+ DnsResponseResultExtractor::ExtractionError extraction_error =
+ extractor.ExtractDnsResults(dns_query_type, &results);
+ DCHECK_NE(extraction_error,
+ DnsResponseResultExtractor::ExtractionError::kUnexpected);
+
+ if (results.error() != OK && results.error() != ERR_NAME_NOT_RESOLVED) {
+ if (dns_query_type == DnsQueryType::INTEGRITY ||
+ dns_query_type == DnsQueryType::HTTPS ||
+ dns_query_type == DnsQueryType::HTTPS_EXPERIMENTAL) {
+ // Ignore extraction errors of these types. In most cases treating them
+ // as fatal would only result in fallback to resolution without querying
+ // the type. Instead, synthesize empty results.
+ results = DnsResponseResultExtractor::CreateEmptyResult(dns_query_type);
+ } else {
OnFailure(results.error(), extraction_error, results.GetOptionalTtl());
return;
}
- } else if (dns_query_type == DnsQueryType::INTEGRITY ||
- dns_query_type == DnsQueryType::HTTPS) {
- // Do not allow an experimental query to fail the whole DnsTask. Instead
- // pretend an empty result that can be cleanly merged with address
- // results.
- results = DnsResponseResultExtractor::CreateEmptyResult(dns_query_type);
- } else {
- // Fail completely on network failure.
- OnFailure(net_error, DnsResponseResultExtractor::ExtractionError::kOk,
- absl::nullopt);
- return;
}
if (httpssvc_metrics_) {
@@ -1325,7 +1471,8 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
// experimental query timer runs out (OnExperimentalQueryTimeout).
httpssvc_metrics_->SaveForIntegrity(doh_provider_id, rcode_for_httpssvc,
*condensed, elapsed_time);
- } else if (dns_query_type == DnsQueryType::HTTPS) {
+ } else if (dns_query_type == DnsQueryType::HTTPS ||
+ dns_query_type == DnsQueryType::HTTPS_EXPERIMENTAL) {
const absl::optional<std::vector<bool>>& condensed =
results.experimental_results();
CHECK(condensed.has_value());
@@ -1337,6 +1484,18 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
}
}
+ // Trigger HTTP->HTTPS upgrade if an HTTPS record is received for an "http"
+ // or "ws" request.
+ if (features::kUseDnsHttpsSvcbHttpUpgrade.Get() &&
+ dns_query_type == DnsQueryType::HTTPS && results.error() == OK &&
+ (GetScheme(host_) == url::kHttpScheme ||
+ GetScheme(host_) == url::kWsScheme)) {
+ OnFailure(ERR_DNS_NAME_HTTPS_ONLY,
+ DnsResponseResultExtractor::ExtractionError::kOk,
+ results.GetOptionalTtl());
+ return;
+ }
+
// Merge results with saved results from previous transactions.
if (saved_results_) {
DCHECK_LE(2, num_needed_transactions());
@@ -1357,6 +1516,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
break;
case DnsQueryType::INTEGRITY:
case DnsQueryType::HTTPS:
+ case DnsQueryType::HTTPS_EXPERIMENTAL:
// No particular importance to order.
results = HostCache::Entry::MergeEntries(
std::move(results), std::move(saved_results_).value());
@@ -1388,6 +1548,30 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
ProcessResultsOnCompletion();
}
+ bool IsFatalHttpsTransactionFailure(int transaction_error,
+ const DnsResponse* response) {
+ // Shouldn't call this method if there wasn't a transaction failure.
+ DCHECK_NE(transaction_error, OK);
+ DCHECK(transaction_error != ERR_NAME_NOT_RESOLVED || !response ||
+ !response->IsValid());
+
+ // HTTPS failures are never fatal via insecure DNS.
+ if (!secure_)
+ return false;
+
+ // Feature must be enabled for HTTPS to be fatal.
+ if (!features::kUseDnsHttpsSvcbEnforceSecureResponse.Get())
+ return false;
+
+ // For server failures, only SERVFAIL is fatal.
+ if (transaction_error == ERR_DNS_SERVER_FAILED && response &&
+ response->rcode() != dns_protocol::kRcodeSERVFAIL) {
+ return false;
+ }
+
+ return true;
+ }
+
// Postprocesses the transactions' aggregated results after all
// transactions have completed.
void ProcessResultsOnCompletion() {
@@ -1414,7 +1598,7 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
return;
}
- OnSuccess(results);
+ OnSuccess(std::move(results));
}
void OnSortComplete(base::TimeTicks sort_start_time,
@@ -1442,9 +1626,12 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
return;
}
- OnSuccess(results);
+ OnSuccess(std::move(results));
}
+ // TODO(crbug.com/1225776): Disallow fallback after a fatal HTTPS error. Also
+ // prevent A/AAAA errors from leading to immediate fallback if an HTTPS query
+ // is still pending that may lead to a fatal HTTPS error.
void OnFailure(int net_error,
DnsResponseResultExtractor::ExtractionError extraction_error,
absl::optional<base::TimeDelta> ttl) {
@@ -1459,13 +1646,13 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
static_cast<int>(extraction_error));
});
- delegate_->OnDnsTaskComplete(task_start_time_, results, secure_);
+ delegate_->OnDnsTaskComplete(task_start_time_, std::move(results), secure_);
}
- void OnSuccess(const HostCache::Entry& results) {
+ void OnSuccess(HostCache::Entry results) {
NetLogHostCacheEntry(net_log_, NetLogEventType::HOST_RESOLVER_IMPL_DNS_TASK,
NetLogEventPhase::END, results);
- delegate_->OnDnsTaskComplete(task_start_time_, results, secure_);
+ delegate_->OnDnsTaskComplete(task_start_time_, std::move(results), secure_);
}
// Returns whether all transactions left to execute are of transaction type
@@ -1494,13 +1681,15 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
absl::optional<std::string> doh_provider_id) {
DCHECK(!transactions_started_.empty());
- // Abort if neither HTTPSSVC nor INTEGRITY querying is enabled.
+ // Abort if neither HTTPSSVC nor INTEGRITY experimental querying is enabled.
if (!base::FeatureList::IsEnabled(features::kDnsHttpssvc) ||
(!features::kDnsHttpssvcUseIntegrity.Get() &&
!features::kDnsHttpssvcUseHttpssvc.Get())) {
return;
}
+ // TODO(crbug.com/1225776): Control based on DnsQueryTypes instead of
+ // transaction qtypes to allow differentiating HTTPS and HTTPS_EXPERIMENTAL.
if (!experimental_query_cancellation_timer_.IsRunning() &&
TaskIsCompleteOrOnlyQtypeTransactionsRemain(
{dns_protocol::kExperimentalTypeIntegrity,
@@ -1528,7 +1717,9 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
}
DnsClient* client_;
- std::string hostname_;
+
+ absl::variant<url::SchemeHostPort, std::string> host_;
+
// TODO(ericorth@chromium.org): Use base::UnownedPtr once available.
ResolveContext* const resolve_context_;
@@ -1573,21 +1764,26 @@ class HostResolverManager::DnsTask : public base::SupportsWeakPtr<DnsTask> {
struct HostResolverManager::JobKey {
bool operator<(const JobKey& other) const {
return std::forward_as_tuple(query_type, flags, source, secure_dns_mode,
- resolve_context, hostname,
- network_isolation_key_) <
+ resolve_context, host, network_isolation_key) <
std::forward_as_tuple(other.query_type, other.flags, other.source,
other.secure_dns_mode, other.resolve_context,
- other.hostname, other.network_isolation_key_);
+ other.host, other.network_isolation_key);
}
- std::string hostname;
- NetworkIsolationKey network_isolation_key_;
+ absl::variant<url::SchemeHostPort, std::string> host;
+ NetworkIsolationKey network_isolation_key;
DnsQueryType query_type;
HostResolverFlags flags;
HostResolverSource source;
SecureDnsMode secure_dns_mode;
// TODO(ericorth@chromium.org): Use base::UnownedPtr once available.
ResolveContext* resolve_context;
+
+ HostCache::Key ToCacheKey(bool secure) const {
+ HostCache::Key key(host, query_type, flags, source, network_isolation_key);
+ key.secure = secure;
+ return key;
+ }
};
// Aggregates all Requests for the same Key. Dispatched via
@@ -1598,14 +1794,8 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// Creates new job for |key| where |request_net_log| is bound to the
// request that spawned it.
Job(const base::WeakPtr<HostResolverManager>& resolver,
- base::StringPiece hostname,
- const NetworkIsolationKey& network_isolation_key,
- DnsQueryType query_type,
- HostResolverFlags host_resolver_flags,
- HostResolverSource requested_source,
+ JobKey key,
ResolveHostParameters::CacheUsage cache_usage,
- SecureDnsMode secure_dns_mode,
- ResolveContext* resolve_context,
HostCache* host_cache,
std::deque<TaskType> tasks,
RequestPriority priority,
@@ -1613,14 +1803,8 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
const NetLogWithSource& source_net_log,
const base::TickClock* tick_clock)
: resolver_(resolver),
- hostname_(hostname),
- network_isolation_key_(network_isolation_key),
- query_type_(query_type),
- host_resolver_flags_(host_resolver_flags),
- requested_source_(requested_source),
+ key_(std::move(key)),
cache_usage_(cache_usage),
- secure_dns_mode_(secure_dns_mode),
- resolve_context_(resolve_context),
host_cache_(host_cache),
tasks_(tasks),
job_running_(false),
@@ -1638,7 +1822,8 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
source_net_log.AddEvent(NetLogEventType::HOST_RESOLVER_IMPL_CREATE_JOB);
net_log_.BeginEvent(NetLogEventType::HOST_RESOLVER_IMPL_JOB, [&] {
- return NetLogJobCreationParams(source_net_log.source(), hostname_);
+ return NetLogJobCreationParams(source_net_log.source(),
+ GetHostname(key_.host));
});
}
@@ -1692,7 +1877,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// HostCache. Since the ResolveContext is part of the JobKey, any request
// added to any existing Job should share the same HostCache.
DCHECK_EQ(host_cache_, request->host_cache());
- DCHECK_EQ(hostname_, request->request_host().host());
+ // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
+ // separated by scheme/port.
+ DCHECK_EQ(GetHostname(key_.host), GetHostname(request->request_host()));
request->AssignJob(this);
@@ -1716,7 +1903,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
}
void ChangeRequestPriority(RequestImpl* req, RequestPriority priority) {
- DCHECK_EQ(hostname_, req->request_host().host());
+ // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
+ // separated by scheme/port.
+ DCHECK_EQ(GetHostname(key_.host), GetHostname(req->request_host()));
priority_tracker_.Remove(req->priority());
req->set_priority(priority);
@@ -1727,7 +1916,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// Detach cancelled request. If it was the last active Request, also finishes
// this Job.
void CancelRequest(RequestImpl* request) {
- DCHECK_EQ(hostname_, request->request_host().host());
+ // TODO(crbug.com/1206799): Check equality of whole host once Jobs are
+ // separated by scheme/port.
+ DCHECK_EQ(GetHostname(key_.host), GetHostname(request->request_host()));
DCHECK(!requests_.empty());
priority_tracker_.Remove(request->priority());
@@ -1818,9 +2009,8 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
bool ServeFromHosts() {
DCHECK_GT(num_active_requests(), 0u);
absl::optional<HostCache::Entry> results = resolver_->ServeFromHosts(
- hostname_, query_type_,
- host_resolver_flags_ & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6,
- tasks_);
+ GetHostname(key_.host), key_.query_type,
+ key_.flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6, tasks_);
if (results) {
// This will destroy the Job.
CompleteRequests(results.value(), base::TimeDelta(),
@@ -1923,13 +2113,6 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
bool is_running() const { return job_running_; }
private:
- HostCache::Key GenerateCacheKey(bool secure) const {
- HostCache::Key cache_key(hostname_, query_type_, host_resolver_flags_,
- requested_source_, network_isolation_key_);
- cache_key.secure = secure;
- return cache_key;
- }
-
void KillDnsTask() {
if (dns_task_) {
if (dispatcher_) {
@@ -1995,11 +2178,12 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
void StartProcTask() {
DCHECK(dispatcher_);
DCHECK_EQ(1, num_occupied_job_slots_);
- DCHECK(IsAddressType(query_type_));
+ DCHECK(IsAddressType(key_.query_type));
proc_task_ = std::make_unique<ProcTask>(
- hostname_, HostResolver::DnsQueryTypeToAddressFamily(query_type_),
- host_resolver_flags_, resolver_->proc_params_,
+ std::string(GetHostname(key_.host)),
+ HostResolver::DnsQueryTypeToAddressFamily(key_.query_type), key_.flags,
+ resolver_->proc_params_,
base::BindOnce(&Job::OnProcTaskComplete, base::Unretained(this),
tick_clock_->NowTicks()),
proc_task_runner_, net_log_, tick_clock_);
@@ -2047,7 +2231,7 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
DCHECK(cache_usage_ != ResolveHostParameters::CacheUsage::STALE_ALLOWED);
absl::optional<HostCache::EntryStaleness> stale_info;
absl::optional<HostCache::Entry> resolved = resolver_->MaybeServeFromCache(
- host_cache_, GenerateCacheKey(false), cache_usage_,
+ host_cache_, key_.ToCacheKey(/*secure=*/false), cache_usage_,
false /* ignore_secure */, net_log_, &stale_info);
if (resolved) {
@@ -2066,9 +2250,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// Need to create the task even if we're going to post a failure instead of
// running it, as a "started" job needs a task to be properly cleaned up.
dns_task_ = std::make_unique<DnsTask>(
- resolver_->dns_client_.get(), hostname_, query_type_, resolve_context_,
- secure, secure_dns_mode_, this, net_log_, tick_clock_,
- !tasks_.empty() /* fallback_available */);
+ resolver_->dns_client_.get(), key_.host, key_.query_type,
+ key_.resolve_context, secure, key_.secure_dns_mode, this, net_log_,
+ tick_clock_, !tasks_.empty() /* fallback_available */);
dns_task_->StartNextTransaction();
// Schedule a second transaction, if needed. DoH queries can bypass the
// dispatcher and start all of their transactions immediately.
@@ -2097,11 +2281,11 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
bool secure) {
DCHECK_NE(OK, failure_results.error());
- if (secure_dns_mode_ == SecureDnsMode::kSecure) {
+ if (key_.secure_dns_mode == SecureDnsMode::kSecure) {
DCHECK(secure);
UMA_HISTOGRAM_LONG_TIMES_100(
"Net.DNS.SecureDnsTask.DnsModeSecure.FailureTime", duration);
- } else if (secure_dns_mode_ == SecureDnsMode::kAutomatic && secure) {
+ } else if (key_.secure_dns_mode == SecureDnsMode::kAutomatic && secure) {
UMA_HISTOGRAM_LONG_TIMES_100(
"Net.DNS.SecureDnsTask.DnsModeAutomatic.FailureTime", duration);
} else {
@@ -2130,10 +2314,18 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// HostResolverManager::DnsTask::Delegate implementation:
void OnDnsTaskComplete(base::TimeTicks start_time,
- const HostCache::Entry& results,
+ HostCache::Entry results,
bool secure) override {
DCHECK(dns_task_);
+ // `UNSPECIFIED`-type queries are only considered successful overall if they
+ // find address results, but DnsTask may claim success if any transaction,
+ // e.g. a supplemental HTTPS transaction, finds results.
+ if (key_.query_type == DnsQueryType::UNSPECIFIED && results.error() == OK &&
+ (!results.addresses() || results.addresses().value().empty())) {
+ results.set_error(ERR_NAME_NOT_RESOLVED);
+ }
+
base::TimeDelta duration = tick_clock_->NowTicks() - start_time;
if (results.error() != OK) {
OnDnsTaskFailure(dns_task_->AsWeakPtr(), duration, results, secure);
@@ -2194,21 +2386,20 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// No flags are supported for MDNS except
// HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6 (which is not actually an
// input flag).
- DCHECK_EQ(0, host_resolver_flags_ &
- ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6);
+ DCHECK_EQ(0, key_.flags & ~HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6);
std::vector<DnsQueryType> query_types;
- if (query_type_ == DnsQueryType::UNSPECIFIED) {
+ if (key_.query_type == DnsQueryType::UNSPECIFIED) {
query_types.push_back(DnsQueryType::A);
query_types.push_back(DnsQueryType::AAAA);
} else {
- query_types.push_back(query_type_);
+ query_types.push_back(key_.query_type);
}
MDnsClient* client = nullptr;
int rv = resolver_->GetOrCreateMdnsClient(&client);
- mdns_task_ =
- std::make_unique<HostResolverMdnsTask>(client, hostname_, query_types);
+ mdns_task_ = std::make_unique<HostResolverMdnsTask>(
+ client, std::string(GetHostname(key_.host)), query_types);
if (rv == OK) {
mdns_task_->Start(
@@ -2292,8 +2483,9 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
if (had_non_speculative_request_) {
UmaHistogramMediumTimes(
- base::StringPrintf("Net.DNS.SecureDnsMode.%s.ResolveTime",
- SecureDnsModeToString(secure_dns_mode_).c_str()),
+ base::StringPrintf(
+ "Net.DNS.SecureDnsMode.%s.ResolveTime",
+ SecureDnsModeToString(key_.secure_dns_mode).c_str()),
duration);
}
}
@@ -2304,8 +2496,7 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
// If the request did not complete, don't cache it.
if (!results.did_complete())
return;
- HostCache::Key cache_key = GenerateCacheKey(secure);
- resolver_->CacheResult(host_cache_, cache_key, results, ttl);
+ resolver_->CacheResult(host_cache_, key_.ToCacheKey(secure), results, ttl);
}
// Performs Job's last rites. Completes all Requests. Deletes this.
@@ -2372,7 +2563,7 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
if (results.error() == OK && !req->parameters().is_speculative) {
req->set_results(
- results.CopyWithDefaultPort(req->request_host().port()));
+ results.CopyWithDefaultPort(GetPort(req->request_host())));
// TODO(cammie): Move the sanitization deeper, possibly in
// HttpCache::Entry::SetResult(AddressList addresses), so that it
@@ -2422,15 +2613,8 @@ class HostResolverManager::Job : public PrioritizedDispatcher::Job,
base::WeakPtr<HostResolverManager> resolver_;
- const std::string hostname_;
- const NetworkIsolationKey network_isolation_key_;
- const DnsQueryType query_type_;
- const HostResolverFlags host_resolver_flags_;
- const HostResolverSource requested_source_;
+ const JobKey key_;
const ResolveHostParameters::CacheUsage cache_usage_;
- const SecureDnsMode secure_dns_mode_;
- // TODO(ericorth@chromium.org): Use base::UnownedPtr once available.
- ResolveContext* const resolve_context_;
// TODO(crbug.com/969847): Consider allowing requests within a single Job to
// have different HostCaches.
HostCache* const host_cache_;
@@ -2572,10 +2756,10 @@ HostResolverManager::~HostResolverManager() {
std::unique_ptr<HostResolverManager::CancellableResolveHostRequest>
HostResolverManager::CreateRequest(
- const HostPortPair& host,
- const NetworkIsolationKey& network_isolation_key,
- const NetLogWithSource& net_log,
- const absl::optional<ResolveHostParameters>& optional_parameters,
+ absl::variant<url::SchemeHostPort, HostPortPair> host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters,
ResolveContext* resolve_context,
HostCache* host_cache) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
@@ -2586,8 +2770,9 @@ HostResolverManager::CreateRequest(
DCHECK(registered_contexts_.HasObserver(resolve_context));
return std::make_unique<RequestImpl>(
- net_log, host, network_isolation_key, optional_parameters,
- resolve_context, host_cache, weak_ptr_factory_.GetWeakPtr(), tick_clock_);
+ std::move(net_log), std::move(host), std::move(network_isolation_key),
+ std::move(optional_parameters), resolve_context, host_cache,
+ weak_ptr_factory_.GetWeakPtr(), tick_clock_);
}
std::unique_ptr<HostResolverManager::CancellableProbeRequest>
@@ -2763,25 +2948,34 @@ int HostResolverManager::Resolve(RequestImpl* request) {
ResolveHostParameters::CacheUsage::ALLOWED);
DCHECK(!invalidation_in_progress_);
- DnsQueryType effective_query_type;
- HostResolverFlags effective_host_resolver_flags;
- SecureDnsMode effective_secure_dns_mode;
+ const auto& parameters = request->parameters();
+ JobKey job_key;
+ job_key.host =
+ CreateHostForJobKey(request->request_host(), parameters.dns_query_type);
+ job_key.network_isolation_key = request->network_isolation_key();
+ job_key.source = parameters.source;
+ job_key.resolve_context = request->resolve_context();
+
+ IPAddress ip_address;
+ bool is_ip = ip_address.AssignFromIPLiteral(GetHostname(job_key.host));
+
+ GetEffectiveParametersForRequest(
+ GetHostname(job_key.host), parameters.dns_query_type,
+ request->host_resolver_flags(), parameters.secure_dns_policy,
+ parameters.cache_usage, is_ip, request->source_net_log(),
+ &job_key.query_type, &job_key.flags, &job_key.secure_dns_mode);
+
std::deque<TaskType> tasks;
absl::optional<HostCache::EntryStaleness> stale_info;
HostCache::Entry results = ResolveLocally(
- request->request_host().host(), request->network_isolation_key(),
- request->parameters().dns_query_type, request->parameters().source,
- request->host_resolver_flags(), request->parameters().secure_dns_policy,
- request->parameters().cache_usage, request->source_net_log(),
- request->host_cache(), request->resolve_context(), &effective_query_type,
- &effective_host_resolver_flags, &effective_secure_dns_mode, &tasks,
- &stale_info);
+ job_key, ip_address, parameters.cache_usage, request->source_net_log(),
+ request->host_cache(), &tasks, &stale_info);
if (results.error() != ERR_DNS_CACHE_MISS ||
request->parameters().source == HostResolverSource::LOCAL_ONLY ||
tasks.empty()) {
if (results.error() == OK && !request->parameters().is_speculative) {
request->set_results(
- results.CopyWithDefaultPort(request->request_host().port()));
+ results.CopyWithDefaultPort(GetPort(request->request_host())));
// TODO(cammie): Sanitize before adding to the cache instead.
request->SanitizeDnsAliasResults();
@@ -2793,79 +2987,59 @@ int HostResolverManager::Resolve(RequestImpl* request) {
return HostResolver::SquashErrorCode(results.error());
}
- CreateAndStartJob(effective_query_type, effective_host_resolver_flags,
- effective_secure_dns_mode, std::move(tasks), request);
+ CreateAndStartJob(std::move(job_key), std::move(tasks), request);
return ERR_IO_PENDING;
}
HostCache::Entry HostResolverManager::ResolveLocally(
- const std::string& hostname,
- const NetworkIsolationKey& network_isolation_key,
- DnsQueryType dns_query_type,
- HostResolverSource source,
- HostResolverFlags flags,
- SecureDnsPolicy secure_dns_policy,
+ const JobKey& job_key,
+ const IPAddress& ip_address,
ResolveHostParameters::CacheUsage cache_usage,
const NetLogWithSource& source_net_log,
HostCache* cache,
- ResolveContext* resolve_context,
- DnsQueryType* out_effective_query_type,
- HostResolverFlags* out_effective_host_resolver_flags,
- SecureDnsMode* out_effective_secure_dns_mode,
std::deque<TaskType>* out_tasks,
absl::optional<HostCache::EntryStaleness>* out_stale_info) {
DCHECK(out_stale_info);
*out_stale_info = absl::nullopt;
- IPAddress ip_address;
- IPAddress* ip_address_ptr = nullptr;
- if (ip_address.AssignFromIPLiteral(hostname)) {
- ip_address_ptr = &ip_address;
- }
-
- GetEffectiveParametersForRequest(
- hostname, dns_query_type, source, flags, secure_dns_policy, cache_usage,
- ip_address_ptr, source_net_log, resolve_context, out_effective_query_type,
- out_effective_host_resolver_flags, out_effective_secure_dns_mode,
- out_tasks);
+ CreateTaskSequence(job_key, cache_usage, out_tasks);
if (!ip_address.IsValid()) {
// Check that the caller supplied a valid hostname to resolve. For
// MULTICAST_DNS, we are less restrictive.
// TODO(ericorth): Control validation based on an explicit flag rather
// than implicitly based on |source|.
- const bool is_valid_hostname = source == HostResolverSource::MULTICAST_DNS
- ? IsValidUnrestrictedDNSDomain(hostname)
- : IsValidDNSDomain(hostname);
+ const bool is_valid_hostname =
+ job_key.source == HostResolverSource::MULTICAST_DNS
+ ? IsValidUnrestrictedDNSDomain(GetHostname(job_key.host))
+ : IsValidDNSDomain(GetHostname(job_key.host));
if (!is_valid_hostname) {
return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
HostCache::Entry::SOURCE_UNKNOWN);
}
}
- bool resolve_canonname =
- *out_effective_host_resolver_flags & HOST_RESOLVER_CANONNAME;
+ bool resolve_canonname = job_key.flags & HOST_RESOLVER_CANONNAME;
bool default_family_due_to_no_ipv6 =
- *out_effective_host_resolver_flags &
- HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
+ job_key.flags & HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
// The result of |getaddrinfo| for empty hosts is inconsistent across systems.
// On Windows it gives the default interface's address, whereas on Linux it
// gives an error. We will make it fail on all platforms for consistency.
- if (hostname.empty() || hostname.size() > kMaxHostLength) {
+ if (GetHostname(job_key.host).empty() ||
+ GetHostname(job_key.host).size() > kMaxHostLength) {
return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
HostCache::Entry::SOURCE_UNKNOWN);
}
- absl::optional<HostCache::Entry> resolved =
- ResolveAsIP(*out_effective_query_type, resolve_canonname, ip_address_ptr);
- if (resolved)
- return resolved.value();
+ if (ip_address.IsValid())
+ return ResolveAsIP(job_key.query_type, resolve_canonname, ip_address);
// Special-case localhost names, as per the recommendations in
// https://tools.ietf.org/html/draft-west-let-localhost-be-localhost.
- resolved = ServeLocalhost(hostname, *out_effective_query_type,
- default_family_due_to_no_ipv6);
+ absl::optional<HostCache::Entry> resolved =
+ ServeLocalhost(GetHostname(job_key.host), job_key.query_type,
+ default_family_due_to_no_ipv6);
if (resolved)
return resolved.value();
@@ -2874,12 +3048,8 @@ HostCache::Entry HostResolverManager::ResolveLocally(
(out_tasks->front() == TaskType::SECURE_CACHE_LOOKUP ||
out_tasks->front() == TaskType::INSECURE_CACHE_LOOKUP ||
out_tasks->front() == TaskType::CACHE_LOOKUP)) {
- HostCache::Key key(hostname, *out_effective_query_type,
- *out_effective_host_resolver_flags, source,
- network_isolation_key);
-
- if (out_tasks->front() == TaskType::SECURE_CACHE_LOOKUP)
- key.secure = true;
+ bool secure = out_tasks->front() == TaskType::SECURE_CACHE_LOOKUP;
+ HostCache::Key key = job_key.ToCacheKey(secure);
bool ignore_secure = false;
if (out_tasks->front() == TaskType::CACHE_LOOKUP)
@@ -2903,7 +3073,7 @@ HostCache::Entry HostResolverManager::ResolveLocally(
// TODO(szym): Do not do this if nsswitch.conf instructs not to.
// http://crbug.com/117655
- resolved = ServeFromHosts(hostname, *out_effective_query_type,
+ resolved = ServeFromHosts(GetHostname(job_key.host), job_key.query_type,
default_family_due_to_no_ipv6, *out_tasks);
if (resolved) {
NetLogHostCacheEntry(source_net_log,
@@ -2915,30 +3085,18 @@ HostCache::Entry HostResolverManager::ResolveLocally(
return HostCache::Entry(ERR_DNS_CACHE_MISS, HostCache::Entry::SOURCE_UNKNOWN);
}
-void HostResolverManager::CreateAndStartJob(
- DnsQueryType effective_query_type,
- HostResolverFlags effective_host_resolver_flags,
- SecureDnsMode effective_secure_dns_mode,
- std::deque<TaskType> tasks,
- RequestImpl* request) {
+void HostResolverManager::CreateAndStartJob(JobKey key,
+ std::deque<TaskType> tasks,
+ RequestImpl* request) {
DCHECK(!tasks.empty());
- JobKey key = {
- request->request_host().host(), request->network_isolation_key(),
- effective_query_type, effective_host_resolver_flags,
- request->parameters().source, effective_secure_dns_mode,
- request->resolve_context()};
auto jobit = jobs_.find(key);
Job* job;
if (jobit == jobs_.end()) {
auto new_job = std::make_unique<Job>(
- weak_ptr_factory_.GetWeakPtr(), request->request_host().host(),
- request->network_isolation_key(), effective_query_type,
- effective_host_resolver_flags, request->parameters().source,
- request->parameters().cache_usage, effective_secure_dns_mode,
- request->resolve_context(), request->host_cache(), std::move(tasks),
- request->priority(), proc_task_runner_, request->source_net_log(),
- tick_clock_);
+ weak_ptr_factory_.GetWeakPtr(), key, request->parameters().cache_usage,
+ request->host_cache(), std::move(tasks), request->priority(),
+ proc_task_runner_, request->source_net_log(), tick_clock_);
job = new_job.get();
auto insert_result = jobs_.emplace(std::move(key), std::move(new_job));
DCHECK(insert_result.second);
@@ -2951,22 +3109,22 @@ void HostResolverManager::CreateAndStartJob(
}
}
-absl::optional<HostCache::Entry> HostResolverManager::ResolveAsIP(
- DnsQueryType query_type,
- bool resolve_canonname,
- const IPAddress* ip_address) {
- if (ip_address == nullptr || !IsAddressType(query_type))
- return absl::nullopt;
+HostCache::Entry HostResolverManager::ResolveAsIP(DnsQueryType query_type,
+ bool resolve_canonname,
+ const IPAddress& ip_address) {
+ DCHECK(ip_address.IsValid());
- AddressFamily family = GetAddressFamily(*ip_address);
+ // IP literals cannot resolve unless the query type is an address query that
+ // allows addresses with the same address family as the literal. E.g., don't
+ // return IPv6 addresses for IPv4 queries or anything for a non-address query.
+ AddressFamily family = GetAddressFamily(ip_address);
if (query_type != DnsQueryType::UNSPECIFIED &&
query_type != AddressFamilyToDnsQueryType(family)) {
- // Don't return IPv6 addresses for IPv4 queries, and vice versa.
return HostCache::Entry(ERR_NAME_NOT_RESOLVED,
HostCache::Entry::SOURCE_UNKNOWN);
}
- AddressList addresses = AddressList::CreateFromIPAddress(*ip_address, 0);
+ AddressList addresses = AddressList::CreateFromIPAddress(ip_address, 0);
if (resolve_canonname)
addresses.SetDefaultCanonicalName();
return HostCache::Entry(OK, std::move(addresses),
@@ -3223,24 +3381,17 @@ void HostResolverManager::PushDnsTasks(bool proc_task_allowed,
}
void HostResolverManager::CreateTaskSequence(
- const std::string& hostname,
- DnsQueryType dns_query_type,
- HostResolverSource source,
- HostResolverFlags flags,
- SecureDnsPolicy secure_dns_policy,
+ const JobKey& job_key,
ResolveHostParameters::CacheUsage cache_usage,
- ResolveContext* resolve_context,
- SecureDnsMode* out_effective_secure_dns_mode,
std::deque<TaskType>* out_tasks) {
DCHECK(out_tasks->empty());
- *out_effective_secure_dns_mode = GetEffectiveSecureDnsMode(secure_dns_policy);
// A cache lookup should generally be performed first. For jobs involving a
// DnsTask, this task may be replaced.
bool allow_cache =
cache_usage != ResolveHostParameters::CacheUsage::DISALLOWED;
if (allow_cache) {
- if (*out_effective_secure_dns_mode == SecureDnsMode::kSecure) {
+ if (job_key.secure_dns_mode == SecureDnsMode::kSecure) {
out_tasks->push_front(TaskType::SECURE_CACHE_LOOKUP);
} else {
out_tasks->push_front(TaskType::CACHE_LOOKUP);
@@ -3251,7 +3402,7 @@ void HostResolverManager::CreateTaskSequence(
bool prioritize_local_lookups =
cache_usage ==
HostResolver::ResolveHostParameters::CacheUsage::STALE_ALLOWED;
- switch (source) {
+ switch (job_key.source) {
case HostResolverSource::ANY:
// Force address queries with canonname to use ProcTask to counter poor
// CNAME support in DnsTask. See https://crbug.com/872665
@@ -3260,25 +3411,26 @@ void HostResolverManager::CreateTaskSequence(
// address queries). But if hostname appears to be an MDNS name (ends in
// *.local), go with ProcTask for address queries and MdnsTask for non-
// address queries.
- if ((flags & HOST_RESOLVER_CANONNAME) && IsAddressType(dns_query_type)) {
+ if ((job_key.flags & HOST_RESOLVER_CANONNAME) &&
+ IsAddressType(job_key.query_type)) {
out_tasks->push_back(TaskType::PROC);
- } else if (!ResemblesMulticastDNSName(hostname)) {
+ } else if (!ResemblesMulticastDNSName(GetHostname(job_key.host))) {
bool proc_task_allowed =
- IsAddressType(dns_query_type) &&
- *out_effective_secure_dns_mode != SecureDnsMode::kSecure;
+ IsAddressType(job_key.query_type) &&
+ job_key.secure_dns_mode != SecureDnsMode::kSecure;
if (dns_client_ && dns_client_->GetEffectiveConfig()) {
bool insecure_allowed =
dns_client_->CanUseInsecureDnsTransactions() &&
!dns_client_->FallbackFromInsecureTransactionPreferred() &&
- (IsAddressType(dns_query_type) ||
+ (IsAddressType(job_key.query_type) ||
dns_client_->CanQueryAdditionalTypesViaInsecureDns());
- PushDnsTasks(proc_task_allowed, *out_effective_secure_dns_mode,
+ PushDnsTasks(proc_task_allowed, job_key.secure_dns_mode,
insecure_allowed, allow_cache, prioritize_local_lookups,
- resolve_context, out_tasks);
+ job_key.resolve_context, out_tasks);
} else if (proc_task_allowed) {
out_tasks->push_back(TaskType::PROC);
}
- } else if (IsAddressType(dns_query_type)) {
+ } else if (IsAddressType(job_key.query_type)) {
// For *.local address queries, try the system resolver even if the
// secure dns mode is SECURE. Public recursive resolvers aren't expected
// to handle these queries.
@@ -3294,12 +3446,11 @@ void HostResolverManager::CreateTaskSequence(
if (dns_client_ && dns_client_->GetEffectiveConfig()) {
bool insecure_allowed =
dns_client_->CanUseInsecureDnsTransactions() &&
- (IsAddressType(dns_query_type) ||
+ (IsAddressType(job_key.query_type) ||
dns_client_->CanQueryAdditionalTypesViaInsecureDns());
- PushDnsTasks(false /* proc_task_allowed */,
- *out_effective_secure_dns_mode, insecure_allowed,
- allow_cache, prioritize_local_lookups, resolve_context,
- out_tasks);
+ PushDnsTasks(false /* proc_task_allowed */, job_key.secure_dns_mode,
+ insecure_allowed, allow_cache, prioritize_local_lookups,
+ job_key.resolve_context, out_tasks);
}
break;
case HostResolverSource::MULTICAST_DNS:
@@ -3312,19 +3463,16 @@ void HostResolverManager::CreateTaskSequence(
}
void HostResolverManager::GetEffectiveParametersForRequest(
- const std::string& hostname,
+ base::StringPiece hostname,
DnsQueryType dns_query_type,
- HostResolverSource source,
HostResolverFlags flags,
SecureDnsPolicy secure_dns_policy,
ResolveHostParameters::CacheUsage cache_usage,
- const IPAddress* ip_address,
+ bool is_ip,
const NetLogWithSource& net_log,
- ResolveContext* resolve_context,
DnsQueryType* out_effective_type,
HostResolverFlags* out_effective_flags,
- SecureDnsMode* out_effective_secure_dns_mode,
- std::deque<TaskType>* out_tasks) {
+ SecureDnsMode* out_effective_secure_dns_mode) {
*out_effective_flags = flags | additional_resolver_flags_;
*out_effective_type = dns_query_type;
@@ -3342,14 +3490,12 @@ void HostResolverManager::GetEffectiveParametersForRequest(
// that this query is UNSPECIFIED (see effective_query_type check above)
// so the code requesting the resolution should be amenable to receiving a
// IPv6 resolution.
- !use_local_ipv6 && ip_address == nullptr && !IsIPv6Reachable(net_log)) {
+ !use_local_ipv6 && !is_ip && !IsIPv6Reachable(net_log)) {
*out_effective_type = DnsQueryType::A;
*out_effective_flags |= HOST_RESOLVER_DEFAULT_FAMILY_SET_DUE_TO_NO_IPV6;
}
- CreateTaskSequence(hostname, *out_effective_type, source,
- *out_effective_flags, secure_dns_policy, cache_usage,
- resolve_context, out_effective_secure_dns_mode, out_tasks);
+ *out_effective_secure_dns_mode = GetEffectiveSecureDnsMode(secure_dns_policy);
}
bool HostResolverManager::IsIPv6Reachable(const NetLogWithSource& net_log) {
diff --git a/chromium/net/dns/host_resolver_manager.h b/chromium/net/dns/host_resolver_manager.h
index 7eeed606dd2..ac4e682738d 100644
--- a/chromium/net/dns/host_resolver_manager.h
+++ b/chromium/net/dns/host_resolver_manager.h
@@ -20,10 +20,13 @@
#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/strings/string_piece.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "net/base/completion_once_callback.h"
+#include "net/base/host_port_pair.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/prioritized_dispatcher.h"
#include "net/dns/dns_config.h"
#include "net/dns/host_cache.h"
@@ -35,7 +38,11 @@
#include "net/dns/public/secure_dns_policy.h"
#include "net/dns/resolve_context.h"
#include "net/dns/system_dns_config_change_notifier.h"
+#include "net/log/net_log_with_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
namespace base {
class TickClock;
@@ -46,13 +53,10 @@ namespace net {
class AddressList;
class DnsClient;
class DnsProbeRunner;
-class HostPortPair;
class IPAddress;
class MDnsClient;
class MDnsSocketFactory;
class NetLog;
-class NetLogWithSource;
-class NetworkIsolationKey;
// Scheduler and controller of host resolution requests. Because of the global
// nature of host resolutions, this class is generally expected to be singleton
@@ -149,10 +153,10 @@ class NET_EXPORT HostResolverManager
// TODO(crbug.com/1022059): Use the HostCache out of the ResolveContext
// instead of passing it separately.
std::unique_ptr<CancellableResolveHostRequest> CreateRequest(
- const HostPortPair& host,
- const NetworkIsolationKey& network_isolation_key,
- const NetLogWithSource& net_log,
- const absl::optional<ResolveHostParameters>& optional_parameters,
+ absl::variant<url::SchemeHostPort, HostPortPair> host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters,
ResolveContext* resolve_context,
HostCache* host_cache);
// |resolve_context| is the context to use for the probes, and it is expected
@@ -273,9 +277,7 @@ class NET_EXPORT HostResolverManager
// or ERR_DNS_CACHE_MISS if the host could not be resolved using local
// sources.
//
- // On ERR_DNS_CACHE_MISS and OK, effective request parameters are written to
- // |out_effective_query_type|, |out_effective_host_resolver_flags|, and
- // |out_effective_secure_dns_mode|. |out_tasks| contains the tentative
+ // On ERR_DNS_CACHE_MISS and OK, |out_tasks| contains the tentative
// sequence of tasks that a future job should run.
//
// If results are returned from the host cache, |out_stale_info| will be
@@ -285,35 +287,24 @@ class NET_EXPORT HostResolverManager
// If |cache_usage == ResolveHostParameters::CacheUsage::STALE_ALLOWED|, then
// stale cache entries can be returned.
HostCache::Entry ResolveLocally(
- const std::string& hostname,
- const NetworkIsolationKey& network_isolation_key,
- DnsQueryType requested_address_family,
- HostResolverSource source,
- HostResolverFlags flags,
- SecureDnsPolicy secure_dns_policy,
+ const JobKey& job_key,
+ const IPAddress& ip_address,
ResolveHostParameters::CacheUsage cache_usage,
const NetLogWithSource& request_net_log,
HostCache* cache,
- ResolveContext* resolve_context,
- DnsQueryType* out_effective_query_type,
- HostResolverFlags* out_effective_host_resolver_flags,
- SecureDnsMode* out_effective_secure_dns_mode,
std::deque<TaskType>* out_tasks,
absl::optional<HostCache::EntryStaleness>* out_stale_info);
// Creates and starts a Job to asynchronously attempt to resolve
// |request|.
- void CreateAndStartJob(DnsQueryType effective_query_type,
- HostResolverFlags effective_host_resolver_flags,
- SecureDnsMode effective_secure_dns_mode,
+ void CreateAndStartJob(JobKey key,
std::deque<TaskType> tasks,
RequestImpl* request);
- // Tries to resolve |key| and its possible IP address representation,
- // |ip_address|. Returns a results entry iff the input can be resolved.
- absl::optional<HostCache::Entry> ResolveAsIP(DnsQueryType query_type,
- bool resolve_canonname,
- const IPAddress* ip_address);
+ // Resolves the IP literal hostname represented by `ip_address`.
+ HostCache::Entry ResolveAsIP(DnsQueryType query_type,
+ bool resolve_canonname,
+ const IPAddress& ip_address);
// Returns the result iff |cache_usage| permits cache lookups and a positive
// match is found for |key| in |cache|. |out_stale_info| must be non-null, and
@@ -364,32 +355,23 @@ class NET_EXPORT HostResolverManager
// Initialized the sequence of tasks to run to resolve a request. The sequence
// may be adjusted later and not all tasks need to be run.
- void CreateTaskSequence(const std::string& hostname,
- DnsQueryType dns_query_type,
- HostResolverSource source,
- HostResolverFlags flags,
- SecureDnsPolicy secure_dns_policy,
+ void CreateTaskSequence(const JobKey& job_key,
ResolveHostParameters::CacheUsage cache_usage,
- ResolveContext* resolve_context,
- SecureDnsMode* out_effective_secure_dns_mode,
std::deque<TaskType>* out_tasks);
// Determines "effective" request parameters using manager properties and IPv6
// reachability.
void GetEffectiveParametersForRequest(
- const std::string& hostname,
+ base::StringPiece hostname,
DnsQueryType dns_query_type,
- HostResolverSource source,
HostResolverFlags flags,
SecureDnsPolicy secure_dns_policy,
ResolveHostParameters::CacheUsage cache_usage,
- const IPAddress* ip_address,
+ bool is_ip,
const NetLogWithSource& net_log,
- ResolveContext* resolve_context,
DnsQueryType* out_effective_type,
HostResolverFlags* out_effective_flags,
- SecureDnsMode* out_effective_secure_dns_mode,
- std::deque<TaskType>* out_tasks);
+ SecureDnsMode* out_effective_secure_dns_mode);
// Probes IPv6 support and returns true if IPv6 support is enabled.
// Results are cached, i.e. when called repeatedly this method returns result
diff --git a/chromium/net/dns/host_resolver_manager_fuzzer.cc b/chromium/net/dns/host_resolver_manager_fuzzer.cc
index a6ae1ddaf81..f2581923235 100644
--- a/chromium/net/dns/host_resolver_manager_fuzzer.cc
+++ b/chromium/net/dns/host_resolver_manager_fuzzer.cc
@@ -22,8 +22,8 @@
#include "net/dns/context_host_resolver.h"
#include "net/dns/fuzzed_host_resolver_util.h"
#include "net/dns/host_resolver.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/log/net_log_with_source.h"
#include "net/log/test_net_log.h"
#include "net/net_buildflags.h"
diff --git a/chromium/net/dns/host_resolver_manager_unittest.cc b/chromium/net/dns/host_resolver_manager_unittest.cc
index dd0fd46efce..cf694aab6fd 100644
--- a/chromium/net/dns/host_resolver_manager_unittest.cc
+++ b/chromium/net/dns/host_resolver_manager_unittest.cc
@@ -22,7 +22,6 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -62,6 +61,7 @@
#include "net/dns/public/dns_config_overrides.h"
#include "net/dns/public/dns_over_https_server_config.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/public/secure_dns_mode.h"
#include "net/dns/public/secure_dns_policy.h"
@@ -80,6 +80,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
#if BUILDFLAG(ENABLE_MDNS)
#include "net/dns/mdns_client_impl.h"
@@ -664,6 +666,31 @@ TEST_F(HostResolverManagerTest, AsynchronousLookup) {
EXPECT_TRUE(cache_result);
}
+// TODO(crbug.com/1206799): Confirm scheme behavior once it affects behavior.
+TEST_F(HostResolverManagerTest, AsynchronousLookupWithScheme) {
+ proc_->AddRuleForAllFamilies("host.test", "192.168.1.42");
+ proc_->SignalMultiple(1u);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, "host.test", 80),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt,
+ resolve_context_.get(), resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_THAT(response.top_level_result_error(), IsOk());
+ EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(CreateExpected("192.168.1.42", 80)));
+ EXPECT_FALSE(response.request()->GetStaleInfo());
+
+ EXPECT_EQ("host.test", proc_->GetCaptureList()[0].hostname);
+
+ const std::pair<const HostCache::Key, HostCache::Entry>* cache_result =
+ GetCacheHit(HostCache::Key(
+ "host.test", DnsQueryType::UNSPECIFIED, 0 /* host_resolver_flags */,
+ HostResolverSource::ANY, NetworkIsolationKey()));
+ EXPECT_TRUE(cache_result);
+}
+
TEST_F(HostResolverManagerTest, JobsClearedOnCompletion) {
proc_->AddRuleForAllFamilies("just.testing", "192.168.1.42");
proc_->SignalMultiple(1u);
@@ -687,7 +714,7 @@ TEST_F(HostResolverManagerTest, JobsClearedOnCompletion_MultipleRequests) {
NetLogWithSource(), absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache()));
ResolveHostResponseHelper response2(resolver_->CreateRequest(
- HostPortPair("just.testing", 85), NetworkIsolationKey(),
+ HostPortPair("just.testing", 80), NetworkIsolationKey(),
NetLogWithSource(), absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache()));
EXPECT_EQ(1u, resolver_->num_jobs_for_testing());
@@ -904,6 +931,17 @@ TEST_F(HostResolverManagerTest, NumericIPv4Address) {
testing::ElementsAre(CreateExpected("127.1.2.3", 5555)));
}
+TEST_F(HostResolverManagerTest, NumericIPv4AddressWithScheme) {
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, "127.1.2.3", 5555),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt,
+ resolve_context_.get(), resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(CreateExpected("127.1.2.3", 5555)));
+}
+
TEST_F(HostResolverManagerTest, NumericIPv6Address) {
// Resolve a plain IPv6 address. Don't worry about [brackets], because
// the caller should have removed them.
@@ -917,6 +955,17 @@ TEST_F(HostResolverManagerTest, NumericIPv6Address) {
testing::ElementsAre(CreateExpected("2001:db8::1", 5555)));
}
+TEST_F(HostResolverManagerTest, NumericIPv6AddressWithScheme) {
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kFtpScheme, "[2001:db8::1]", 5555),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt,
+ resolve_context_.get(), resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(CreateExpected("2001:db8::1", 5555)));
+}
+
TEST_F(HostResolverManagerTest, EmptyHost) {
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(std::string(), 5555), NetworkIsolationKey(),
@@ -965,6 +1014,49 @@ TEST_F(HostResolverManagerTest, DeDupeRequests) {
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
+ HostPortPair("b", 80), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache())));
+ responses.emplace_back(
+ std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache())));
+ responses.emplace_back(
+ std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
+ HostPortPair("b", 80), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache())));
+
+ for (auto& response : responses) {
+ ASSERT_FALSE(response->complete());
+ }
+
+ proc_->SignalMultiple(2u); // One for "a:80", one for "b:80".
+
+ for (auto& response : responses) {
+ EXPECT_THAT(response->result_error(), IsOk());
+ }
+}
+
+// TODO(crbug.com/1206799): Delete/adapt once requests with different ports are
+// not deduped.
+TEST_F(HostResolverManagerTest, DeDupeRequestsWithDifferentPorts) {
+ // Start 5 requests, duplicating hosts "a" and "b". Since the resolver_proc is
+ // blocked, these should all pile up until we signal it.
+ std::vector<std::unique_ptr<ResolveHostResponseHelper>> responses;
+ responses.emplace_back(
+ std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache())));
+ responses.emplace_back(
+ std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
+ HostPortPair("b", 80), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache())));
+ responses.emplace_back(
+ std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
HostPortPair("b", 81), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
@@ -1004,17 +1096,17 @@ TEST_F(HostResolverManagerTest, CancelMultipleRequests) {
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("b", 81), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("b", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("a", 82), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("b", 83), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("b", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
@@ -1022,7 +1114,7 @@ TEST_F(HostResolverManagerTest, CancelMultipleRequests) {
ASSERT_FALSE(response->complete());
}
- // Cancel everything except request for requests[3] ("a", 82).
+ // Cancel everything except request for requests[3] ("a", 80).
responses[0]->CancelRequest();
responses[1]->CancelRequest();
responses[2]->CancelRequest();
@@ -1055,7 +1147,7 @@ TEST_F(HostResolverManagerTest, CanceledRequestsReleaseJobSlots) {
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair(hostname, 81), NetworkIsolationKey(),
+ HostPortPair(hostname, 80), NetworkIsolationKey(),
NetLogWithSource(), absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
ASSERT_FALSE(responses.back()->complete());
@@ -1104,12 +1196,12 @@ TEST_F(HostResolverManagerTest, CancelWithinCallback) {
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("a", 81), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("a", 82), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
@@ -1200,7 +1292,7 @@ TEST_F(HostResolverManagerTest, DeleteWithinAbortedCallback) {
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("a", 81), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("a", 80), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
responses.emplace_back(
@@ -1210,7 +1302,7 @@ TEST_F(HostResolverManagerTest, DeleteWithinAbortedCallback) {
resolve_context_->host_cache())));
responses.emplace_back(
std::make_unique<ResolveHostResponseHelper>(resolver_->CreateRequest(
- HostPortPair("b", 83), NetworkIsolationKey(), NetLogWithSource(),
+ HostPortPair("b", 82), NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache())));
@@ -1352,7 +1444,7 @@ TEST_F(HostResolverManagerTest, StartWithinEvictionCallback_SameRequest) {
auto custom_callback = base::BindLambdaForTesting(
[&](CompletionOnceCallback completion_callback, int error) {
new_response = std::make_unique<ResolveHostResponseHelper>(
- resolver_->CreateRequest(HostPortPair("evictor", 70),
+ resolver_->CreateRequest(HostPortPair("evictor", 80),
NetworkIsolationKey(), NetLogWithSource(),
absl::nullopt, resolve_context_.get(),
resolve_context_->host_cache()));
@@ -3196,36 +3288,31 @@ TEST_F(HostResolverManagerTest, Mdns_ListenFailure) {
// received results in maps.
class TestMdnsListenerDelegate : public HostResolver::MdnsListener::Delegate {
public:
- using UpdateKey =
- std::pair<HostResolver::MdnsListener::Delegate::UpdateType, DnsQueryType>;
+ using UpdateKey = std::pair<MdnsListenerUpdateType, DnsQueryType>;
- void OnAddressResult(
- HostResolver::MdnsListener::Delegate::UpdateType update_type,
- DnsQueryType result_type,
- IPEndPoint address) override {
+ void OnAddressResult(MdnsListenerUpdateType update_type,
+ DnsQueryType result_type,
+ IPEndPoint address) override {
address_results_.insert({{update_type, result_type}, address});
}
- void OnTextResult(
- HostResolver::MdnsListener::Delegate::UpdateType update_type,
- DnsQueryType result_type,
- std::vector<std::string> text_records) override {
+ void OnTextResult(MdnsListenerUpdateType update_type,
+ DnsQueryType result_type,
+ std::vector<std::string> text_records) override {
for (auto& text_record : text_records) {
text_results_.insert(
{{update_type, result_type}, std::move(text_record)});
}
}
- void OnHostnameResult(
- HostResolver::MdnsListener::Delegate::UpdateType update_type,
- DnsQueryType result_type,
- HostPortPair host) override {
+ void OnHostnameResult(MdnsListenerUpdateType update_type,
+ DnsQueryType result_type,
+ HostPortPair host) override {
hostname_results_.insert({{update_type, result_type}, std::move(host)});
}
- void OnUnhandledResult(
- HostResolver::MdnsListener::Delegate::UpdateType update_type,
- DnsQueryType result_type) override {
+ void OnUnhandledResult(MdnsListenerUpdateType update_type,
+ DnsQueryType result_type) override {
unhandled_results_.insert({update_type, result_type});
}
@@ -3247,7 +3334,7 @@ class TestMdnsListenerDelegate : public HostResolver::MdnsListener::Delegate {
template <typename T>
static std::pair<UpdateKey, T> CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
DnsQueryType query_type,
T result) {
return std::make_pair(std::make_pair(update_type, query_type), result);
@@ -3294,14 +3381,14 @@ TEST_F(HostResolverManagerTest, MdnsListener) {
EXPECT_THAT(delegate.address_results(),
testing::ElementsAre(
TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::A, CreateExpected("1.2.3.4", 80)),
+ MdnsListenerUpdateType::kAdded, DnsQueryType::A,
+ CreateExpected("1.2.3.4", 80)),
TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::CHANGED,
- DnsQueryType::A, CreateExpected("5.6.7.8", 80)),
+ MdnsListenerUpdateType::kChanged, DnsQueryType::A,
+ CreateExpected("5.6.7.8", 80)),
TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::REMOVED,
- DnsQueryType::A, CreateExpected("5.6.7.8", 80))));
+ MdnsListenerUpdateType::kRemoved, DnsQueryType::A,
+ CreateExpected("5.6.7.8", 80))));
EXPECT_THAT(delegate.text_results(), testing::IsEmpty());
EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty());
@@ -3349,8 +3436,8 @@ TEST_F(HostResolverManagerTest, MdnsListener_Expiration) {
EXPECT_THAT(
delegate.address_results(),
testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::A, CreateExpected("1.2.3.4", 100))));
+ MdnsListenerUpdateType::kAdded, DnsQueryType::A,
+ CreateExpected("1.2.3.4", 100))));
clock.Advance(base::TimeDelta::FromSeconds(16));
cache_cleanup_timer_ptr->Fire();
@@ -3358,11 +3445,11 @@ TEST_F(HostResolverManagerTest, MdnsListener_Expiration) {
EXPECT_THAT(delegate.address_results(),
testing::ElementsAre(
TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::A, CreateExpected("1.2.3.4", 100)),
+ MdnsListenerUpdateType::kAdded, DnsQueryType::A,
+ CreateExpected("1.2.3.4", 100)),
TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::REMOVED,
- DnsQueryType::A, CreateExpected("1.2.3.4", 100))));
+ MdnsListenerUpdateType::kRemoved, DnsQueryType::A,
+ CreateExpected("1.2.3.4", 100))));
EXPECT_THAT(delegate.text_results(), testing::IsEmpty());
EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty());
@@ -3385,14 +3472,13 @@ TEST_F(HostResolverManagerTest, MdnsListener_Txt) {
socket_factory_ptr->SimulateReceive(kMdnsResponseTxt,
sizeof(kMdnsResponseTxt));
- EXPECT_THAT(delegate.text_results(),
- testing::ElementsAre(
- TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::TXT, "foo"),
- TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::TXT, "bar")));
+ EXPECT_THAT(
+ delegate.text_results(),
+ testing::ElementsAre(
+ TestMdnsListenerDelegate::CreateExpectedResult(
+ MdnsListenerUpdateType::kAdded, DnsQueryType::TXT, "foo"),
+ TestMdnsListenerDelegate::CreateExpectedResult(
+ MdnsListenerUpdateType::kAdded, DnsQueryType::TXT, "bar")));
EXPECT_THAT(delegate.address_results(), testing::IsEmpty());
EXPECT_THAT(delegate.hostname_results(), testing::IsEmpty());
@@ -3418,8 +3504,8 @@ TEST_F(HostResolverManagerTest, MdnsListener_Ptr) {
EXPECT_THAT(
delegate.hostname_results(),
testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::PTR, HostPortPair("foo.com", 13))));
+ MdnsListenerUpdateType::kAdded, DnsQueryType::PTR,
+ HostPortPair("foo.com", 13))));
EXPECT_THAT(delegate.address_results(), testing::IsEmpty());
EXPECT_THAT(delegate.text_results(), testing::IsEmpty());
@@ -3445,8 +3531,8 @@ TEST_F(HostResolverManagerTest, MdnsListener_Srv) {
EXPECT_THAT(
delegate.hostname_results(),
testing::ElementsAre(TestMdnsListenerDelegate::CreateExpectedResult(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::SRV, HostPortPair("foo.com", 8265))));
+ MdnsListenerUpdateType::kAdded, DnsQueryType::SRV,
+ HostPortPair("foo.com", 8265))));
EXPECT_THAT(delegate.address_results(), testing::IsEmpty());
EXPECT_THAT(delegate.text_results(), testing::IsEmpty());
@@ -3492,8 +3578,7 @@ TEST_F(HostResolverManagerTest, MdnsListener_RootDomain) {
EXPECT_THAT(delegate.unhandled_results(),
testing::ElementsAre(std::make_pair(
- HostResolver::MdnsListener::Delegate::UpdateType::ADDED,
- DnsQueryType::PTR)));
+ MdnsListenerUpdateType::kAdded, DnsQueryType::PTR)));
EXPECT_THAT(delegate.address_results(), testing::IsEmpty());
EXPECT_THAT(delegate.text_results(), testing::IsEmpty());
@@ -4303,6 +4388,21 @@ TEST_F(HostResolverManagerDnsTest, DnsTask) {
testing::ElementsAre(CreateExpected("192.168.1.102", 80)));
}
+TEST_F(HostResolverManagerDnsTest, DnsTaskWithScheme) {
+ ChangeDnsConfig(CreateValidDnsConfig());
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kWsScheme, "ok_fail", 80), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ // Resolved by MockDnsClient.
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_THAT(response.request()->GetAddressResults().value().endpoints(),
+ testing::UnorderedElementsAre(CreateExpected("127.0.0.1", 80),
+ CreateExpected("::1", 80)));
+}
+
// Test successful and failing resolutions in HostResolverManager::DnsTask when
// fallback to ProcTask is disabled.
TEST_F(HostResolverManagerDnsTest, NoFallbackToProcTask) {
@@ -8146,6 +8246,32 @@ TEST_F(HostResolverManagerDnsTest, TxtQuery) {
bar_records.begin(), bar_records.end()));
}
+TEST_F(HostResolverManagerDnsTest, TxtQueryRejectsIpLiteral) {
+ MockDnsClientRuleList rules;
+
+ // Entry that would resolve if DNS is mistakenly queried to ensure that does
+ // not happen.
+ rules.emplace_back("8.8.8.8", dns_protocol::kTypeTXT, /*secure=*/false,
+ MockDnsClientRule::Result(
+ BuildTestDnsTextResponse("8.8.8.8", {{"text"}})),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::TXT;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(),
+ parameters, resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
// Test that TXT records can be extracted from a response that also contains
// unrecognized record types.
TEST_F(HostResolverManagerDnsTest, TxtQuery_MixedWithUnrecognizedType) {
@@ -8538,12 +8664,15 @@ TEST_F(HostResolverManagerDnsTest, PtrQuery) {
HostPortPair("foo.com", 108), HostPortPair("bar.com", 108))));
}
-TEST_F(HostResolverManagerDnsTest, PtrQuery_Ip) {
+TEST_F(HostResolverManagerDnsTest, PtrQueryRejectsIpLiteral) {
MockDnsClientRuleList rules;
- rules.emplace_back("8.8.8.8", dns_protocol::kTypePTR, false /* secure */,
+
+ // Entry that would resolve if DNS is mistakenly queried to ensure that does
+ // not happen.
+ rules.emplace_back("8.8.8.8", dns_protocol::kTypePTR, /*secure=*/false,
MockDnsClientRule::Result(BuildTestDnsPointerResponse(
"8.8.8.8", {"foo.com", "bar.com"})),
- false /* delay */);
+ /*delay=*/false);
CreateResolver();
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
@@ -8554,6 +8683,31 @@ TEST_F(HostResolverManagerDnsTest, PtrQuery_Ip) {
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, PtrQueryHandlesReverseIpLookup) {
+ const char kHostname[] = "8.8.8.8.in-addr.arpa";
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kHostname, dns_protocol::kTypePTR, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsPointerResponse(
+ kHostname, {"dns.google.test", "foo.test"})),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::PTR;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ HostPortPair(kHostname, 108), NetworkIsolationKey(), NetLogWithSource(),
+ parameters, resolve_context_.get(), resolve_context_->host_cache()));
EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetTextResults());
@@ -8562,7 +8716,8 @@ TEST_F(HostResolverManagerDnsTest, PtrQuery_Ip) {
// Order between separate records is undefined.
EXPECT_THAT(response.request()->GetHostnameResults(),
testing::Optional(testing::UnorderedElementsAre(
- HostPortPair("foo.com", 108), HostPortPair("bar.com", 108))));
+ HostPortPair("dns.google.test", 108),
+ HostPortPair("foo.test", 108))));
}
TEST_F(HostResolverManagerDnsTest, PtrQuery_NonexistentDomain) {
@@ -8854,6 +9009,33 @@ TEST_F(HostResolverManagerDnsTest, SrvQuery) {
HostPortPair("google.com", 5)));
}
+TEST_F(HostResolverManagerDnsTest, SrvQueryRejectsIpLiteral) {
+ MockDnsClientRuleList rules;
+
+ // Entry that would resolve if DNS is mistakenly queried to ensure that does
+ // not happen.
+ rules.emplace_back("8.8.8.8", dns_protocol::kTypeSRV, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsServiceResponse(
+ "8.8.8.8", {{/*priority=*/4, /*weight=*/0, /*port=*/90,
+ /*target=*/"google.test"}})),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::SRV;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ HostPortPair("8.8.8.8", 108), NetworkIsolationKey(), NetLogWithSource(),
+ parameters, resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
// 0-weight services are allowed. Ensure that we can handle such records,
// especially the case where all entries have weight 0.
TEST_F(HostResolverManagerDnsTest, SrvQuery_ZeroWeight) {
@@ -9153,6 +9335,174 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery) {
MockDnsClientRuleList rules;
std::vector<DnsResourceRecord> records = {
BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), parameters, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ // TODO(crbug.com/1225776): Check non-experimental HTTPS output once
+ // available.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQueryForNonStandardPort) {
+ const std::string kName = "https.test";
+ const std::string kExpectedQueryName = "_1111._https." + kName;
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kExpectedQueryName, "alias.test")};
+ rules.emplace_back(
+ kExpectedQueryName, dns_protocol::kTypeHttps,
+ /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kExpectedQueryName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 1111),
+ NetworkIsolationKey(), NetLogWithSource(), parameters,
+ resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ // TODO(crbug.com/1225776): Check non-experimental HTTPS output once
+ // available.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQueryForHttpUpgrade) {
+ const std::string kName = "https.test";
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 80), NetworkIsolationKey(),
+ NetLogWithSource(), parameters, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ // TODO(crbug.com/1225776): Check non-experimental HTTPS output once
+ // available.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+// Test that HTTPS requests for an http host with port 443 will result in a
+// transaction hostname without prepending port and scheme, despite not having
+// the default port for an http host. The request host ("http://https.test:443")
+// will be mapped to the equivalent https upgrade host
+// ("https://https.test:443") at port 443, which is the default port for an
+// https host, so port and scheme are not prefixed.
+TEST_F(HostResolverManagerDnsTest, HttpsQueryForHttpUpgradeFromHttpsPort) {
+ const std::string kName = "https.test";
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), parameters, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ // TODO(crbug.com/1225776): Check non-experimental HTTPS output once
+ // available.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ HttpsQueryForHttpUpgradeWithNonStandardPort) {
+ const std::string kName = "https.test";
+ const std::string kExpectedQueryName = "_1111._https." + kName;
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kExpectedQueryName, "alias.test")};
+ rules.emplace_back(
+ kExpectedQueryName, dns_protocol::kTypeHttps,
+ /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kExpectedQueryName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 1111), NetworkIsolationKey(),
+ NetLogWithSource(), parameters, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ // TODO(crbug.com/1225776): Check non-experimental HTTPS output once
+ // available.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery) {
+ const std::string kName = "https.test";
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
rules.emplace_back(kName, dns_protocol::kTypeHttps, false /* secure */,
MockDnsClientRule::Result(BuildTestDnsResponse(
kName, dns_protocol::kTypeHttps, records)),
@@ -9162,22 +9512,49 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQueryRejectsIpLiteral) {
+ MockDnsClientRuleList rules;
+
+ // Entry that would resolve if DNS is mistakenly queried to ensure that does
+ // not happen.
+ rules.emplace_back("8.8.8.8", dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ "8.8.8.8", dns_protocol::kTypeHttps,
+ {BuildTestHttpsAliasRecord("8.8.8.8", "alias.test")})),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ HostResolver::ResolveHostParameters parameters;
+ parameters.dns_query_type = DnsQueryType::HTTPS;
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, "8.8.8.8", 443),
+ NetworkIsolationKey(), NetLogWithSource(), parameters,
+ resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
TEST_F(HostResolverManagerDnsTest,
- HttpsInsecureQueryDisallowedWhenAdditionalTypesDisallowed) {
+ ExperimentalHttpsInsecureQueryDisallowedWhenAdditionalTypesDisallowed) {
const std::string kName = "https.test";
ChangeDnsConfig(CreateValidDnsConfig());
@@ -9189,7 +9566,7 @@ TEST_F(HostResolverManagerDnsTest,
/*additional_dns_types_enabled=*/false);
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9203,7 +9580,7 @@ TEST_F(HostResolverManagerDnsTest,
}
TEST_F(HostResolverManagerDnsTest,
- HttpsSecureQueryAllowedWhenAdditionalTypesDisallowed) {
+ ExperimentalHttpsSecureQueryAllowedWhenAdditionalTypesDisallowed) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9224,22 +9601,22 @@ TEST_F(HostResolverManagerDnsTest,
/*additional_dns_types_enabled=*/false);
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
// Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
- EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
}
TEST_F(HostResolverManagerDnsTest,
- HttpsFallbackQueryDisallowedWhenAdditionalTypesDisallowed) {
+ ExperimentalHttpsFallbackQueryDisallowedWhenAdditionalTypesDisallowed) {
const char kName[] = "https.test";
MockDnsClientRuleList rules;
@@ -9258,7 +9635,7 @@ TEST_F(HostResolverManagerDnsTest,
/*additional_dns_types_enabled=*/false);
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9273,7 +9650,8 @@ TEST_F(HostResolverManagerDnsTest,
// Test that HTTPS records can be extracted from a response that also contains
// unrecognized record types.
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_MixedWithUnrecognizedType) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsQuery_MixedWithUnrecognizedType) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9290,21 +9668,20 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_MixedWithUnrecognizedType) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
- EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_MultipleResults) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_MultipleResults) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9320,27 +9697,26 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_MultipleResults) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
- EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true, true)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_InvalidConfig) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_InvalidConfig) {
set_allow_fallback_to_proctask(false);
// Set empty DnsConfig.
InvalidateDnsConfig();
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair("https.test", 108), NetworkIsolationKey(),
@@ -9349,7 +9725,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_InvalidConfig) {
EXPECT_THAT(response.result_error(), IsError(ERR_DNS_CACHE_MISS));
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_NonexistentDomain) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_NonexistentDomain) {
const std::string kName = "https.test";
// Setup fallback to confirm it is not used for non-address results.
@@ -9366,7 +9742,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_NonexistentDomain) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9378,7 +9754,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_NonexistentDomain) {
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_Failure) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_Failure) {
const std::string kName = "https.test";
// Setup fallback to confirm it is not used for non-address results.
@@ -9395,7 +9771,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Failure) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9410,7 +9786,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Failure) {
EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_Timeout) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_Timeout) {
const std::string kName = "https.test";
// Setup fallback to confirm it is not used for non-address results.
@@ -9427,12 +9803,11 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Timeout) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so expect errors to be ignored.
EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetTextResults());
@@ -9443,7 +9818,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Timeout) {
EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_Empty) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_Empty) {
const std::string kName = "https.test";
// Setup fallback to confirm it is not used for non-address results.
@@ -9460,7 +9835,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Empty) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9472,7 +9847,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Empty) {
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_Malformed) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_Malformed) {
const std::string kName = "https.test";
// Setup fallback to confirm it is not used for non-address results.
@@ -9489,24 +9864,22 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_Malformed) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
// Expect result not cached.
EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_MismatchedName) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_MismatchedName) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9521,24 +9894,22 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_MismatchedName) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
// Expect result not cached.
EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_AdditionalRecords) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_AdditionalRecords) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9557,21 +9928,21 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_AdditionalRecords) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
- EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+ // Additional records aren't currently used in results.
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsQuery_WrongType) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsQuery_WrongType) {
const std::string kName = "https.test";
// Respond to an HTTPS query with an A response.
@@ -9587,29 +9958,27 @@ TEST_F(HostResolverManagerDnsTest, HttpsQuery_WrongType) {
UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
HostResolver::ResolveHostParameters parameters;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
// Responses for the wrong type should be ignored.
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
// Expect result not cached.
EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
}
-// Same as HttpsQuery except we specify DNS HostResolverSource instead of
-// relying on automatic determination. Expect same results since DNS should be
-// what we automatically determine, but some slightly different logic paths are
-// involved.
-TEST_F(HostResolverManagerDnsTest, HttpsDnsQuery) {
+// Same as ExperimentalHttpsQuery except we specify DNS HostResolverSource
+// instead of relying on automatic determination. Expect same results since DNS
+// should be what we automatically determine, but some slightly different logic
+// paths are involved.
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsDnsQuery) {
const std::string kName = "https.test";
MockDnsClientRuleList rules;
@@ -9625,26 +9994,26 @@ TEST_F(HostResolverManagerDnsTest, HttpsDnsQuery) {
HostResolver::ResolveHostParameters parameters;
parameters.source = HostResolverSource::DNS;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
parameters, resolve_context_.get(), resolve_context_->host_cache()));
- // Experimental type, so does not affect overall result.
- EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_THAT(response.result_error(), IsOk());
EXPECT_FALSE(response.request()->GetAddressResults());
EXPECT_FALSE(response.request()->GetHostnameResults());
EXPECT_FALSE(response.request()->GetTextResults());
- // Results never saved when overall result not OK.
- EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
}
-// Same as HttpsInsecureQueryDisallowedWhenAdditionalTypesDisallowed except we
-// specify DNS HostResolverSource instead of relying on automatic determination.
-// Expect same results since DNS should be what we automatically determine, but
-// some slightly different logic paths are involved.
-TEST_F(HostResolverManagerDnsTest,
- HttpsDnsInsecureQueryDisallowedWhenAdditionalTypesDisallowed) {
+// Same as ExperimentalHttpsInsecureQueryDisallowedWhenAdditionalTypesDisallowed
+// except we specify DNS HostResolverSource instead of relying on automatic
+// determination. Expect same results since DNS should be what we automatically
+// determine, but some slightly different logic paths are involved.
+TEST_F(
+ HostResolverManagerDnsTest,
+ ExperimentalHttpsDnsInsecureQueryDisallowedWhenAdditionalTypesDisallowed) {
const std::string kName = "https.test";
DnsConfigOverrides overrides;
@@ -9656,7 +10025,7 @@ TEST_F(HostResolverManagerDnsTest,
HostResolver::ResolveHostParameters parameters;
parameters.source = HostResolverSource::DNS;
- parameters.dns_query_type = DnsQueryType::HTTPS;
+ parameters.dns_query_type = DnsQueryType::HTTPS_EXPERIMENTAL;
ResolveHostResponseHelper response(resolver_->CreateRequest(
HostPortPair(kName, 108), NetworkIsolationKey(), NetLogWithSource(),
@@ -9670,6 +10039,942 @@ TEST_F(HostResolverManagerDnsTest,
}
TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQueryWithNonstandardPort) {
+ const char kName[] = "name.test";
+ const char kExpectedHttpsQueryName[] = "_108._https.name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kExpectedHttpsQueryName, "alias.test")};
+ rules.emplace_back(
+ kExpectedHttpsQueryName, dns_protocol::kTypeHttps,
+ /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kExpectedHttpsQueryName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 108), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQueryWithoutAddresses) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ // No address results overrides overall result.
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ // No results maintained when overall error is ERR_NAME_NOT_RESOLVED.
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsQueriedInAddressQueryButNoResults) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+// For a response where DnsTransaction can at least do its basic parsing and
+// return a DnsResponse object to HostResolverManager. See
+// `UnparsableHttpsInAddressRequestIsFatal` for a response so unparsable that
+// DnsTransaction couldn't do that.
+TEST_F(HostResolverManagerDnsTest,
+ MalformedHttpsInResponseInAddressRequestIsIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::MALFORMED),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ MalformedHttpsRdataInAddressRequestIsIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, /*answers=*/
+ {BuildTestDnsRecord(kName, dns_protocol::kTypeHttps,
+ /*rdata=*/"malformed rdata")})),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ FailedHttpsInAddressRequestIsFatalWhenFeatureEnabled) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_NAME_NOT_RESOLVED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+
+ // Expect result not cached.
+ EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ FailedHttpsInAddressRequestIgnoredWhenFeatureDisabled) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "false"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest, TimeoutHttpsInAddressRequestIsFatal) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_DNS_TIMED_OUT));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+
+ // Expect result not cached.
+ EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, ServfailHttpsInAddressRequestIsFatal) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(
+ kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(
+ MockDnsClientRule::FAIL,
+ BuildTestDnsResponse(kName, dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/{}, /*additional=*/{},
+ dns_protocol::kRcodeSERVFAIL),
+ ERR_DNS_SERVER_FAILED),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_DNS_SERVER_FAILED));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+
+ // Expect result not cached.
+ EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+// For a response so malformed that DnsTransaction can't do its basic parsing to
+// determine an RCODE and return a DnsResponse object to HostResolverManager.
+// Essentially equivalent to a network error. See
+// `MalformedHttpsInResponseInAddressRequestIsFatal` for a malformed response
+// that can at least send a DnsResponse to HostResolverManager.
+TEST_F(HostResolverManagerDnsTest, UnparsableHttpsInAddressRequestIsFatal) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::FAIL,
+ /*response=*/absl::nullopt,
+ ERR_DNS_MALFORMED_RESPONSE),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsError(ERR_DNS_MALFORMED_RESPONSE));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+
+ // Expect result not cached.
+ EXPECT_EQ(resolve_context_->host_cache()->size(), 0u);
+}
+
+TEST_F(HostResolverManagerDnsTest, RefusedHttpsInAddressRequestIsIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb,
+ {{"UseDnsHttpsSvcbEnforceSecureResponse", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(
+ kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(
+ MockDnsClientRule::FAIL,
+ BuildTestDnsResponse(kName, dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/{}, /*additional=*/{},
+ dns_protocol::kRcodeREFUSED),
+ ERR_DNS_SERVER_FAILED),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInAddressQueryForWssScheme) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kWssScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, NoHttpsInAddressQueryWithoutScheme) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ // Should not be queried.
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::UNEXPECTED),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ HostPortPair(kName, 443), NetworkIsolationKey(), NetLogWithSource(),
+ absl::nullopt, resolve_context_.get(), resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, NoHttpsInAddressQueryForNonHttpScheme) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features(features::kUseDnsHttpsSvcb);
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ // Should not be queried.
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::UNEXPECTED),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kFtpScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ HttpsInAddressQueryForHttpSchemeWhenUpgradeDisabled) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "false"}});
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsServiceRecord(kName, /*priority=*/1, /*service_name=*/".",
+ /*params=*/{})};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 80), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ // With the param disabled, expect the HTTPS record to have no effect on
+ // results (except GetExperimentalResultsForTesting()).
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ HttpsInAddressQueryForHttpSchemeWhenUpgradeEnabled) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsServiceRecord(kName, /*priority=*/1, /*service_name=*/".",
+ /*params=*/{})};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 80), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsError(ERR_DNS_NAME_HTTPS_ONLY));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+// Even if no addresses are received for a request, finding an HTTPS record
+// should still force an HTTP->HTTPS upgrade.
+TEST_F(HostResolverManagerDnsTest,
+ HttpsInAddressQueryForHttpSchemeWhenUpgradeEnabledWithoutAddresses) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbHttpUpgrade", "true"}});
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsServiceRecord(kName, /*priority=*/1, /*service_name=*/".",
+ /*params=*/{})};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::EMPTY),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, kName, 80), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsError(ERR_DNS_NAME_HTTPS_ONLY));
+ EXPECT_FALSE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, HttpsInInsecureAddressQuery) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "true"}});
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, records)),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(true)));
+}
+
+TEST_F(HostResolverManagerDnsTest, FailedHttpsInInsecureAddressRequestIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::FAIL),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ TimeoutHttpsInInsecureAddressRequestIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::TIMEOUT),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ ServfailHttpsInInsecureAddressRequestIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(
+ kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(
+ MockDnsClientRule::FAIL,
+ BuildTestDnsResponse(kName, dns_protocol::kTypeHttps, /*answers=*/{},
+ /*authority=*/{}, /*additional=*/{},
+ dns_protocol::kRcodeSERVFAIL),
+ ERR_DNS_SERVER_FAILED),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ UnparsableHttpsInInsecureAddressRequestIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "true"}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::FAIL,
+ /*response=*/absl::nullopt,
+ ERR_DNS_MALFORMED_RESPONSE),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ NoHttpsInInsecureAddressQueryWhenInsecureHttpsDisabled) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kUseDnsHttpsSvcb, {{"UseDnsHttpsSvcbEnableInsecure", "false"}});
+
+ MockDnsClientRuleList rules;
+ std::vector<DnsResourceRecord> records = {
+ BuildTestHttpsAliasRecord(kName, "alias.test")};
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ // Should not be queried.
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/false,
+ MockDnsClientRule::Result(MockDnsClientRule::UNEXPECTED),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 443), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
+}
+
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsInAddressQuery) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9708,7 +11013,8 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery) {
testing::Optional(testing::ElementsAre(true)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_MultipleResults) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsInAddressQuery_MultipleResults) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9751,7 +11057,8 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_MultipleResults) {
testing::Optional(testing::UnorderedElementsAre(true, true, false)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesOnly) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsInAddressQuery_AddressesOnly) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9787,7 +11094,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesOnly) {
testing::Optional(testing::IsEmpty()));
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsOnly) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsInAddressQuery_HttpsOnly) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9826,7 +11133,8 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsOnly) {
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressError) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsInAddressQuery_AddressError) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9865,7 +11173,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressError) {
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsError) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsInAddressQuery_HttpsError) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9901,7 +11209,86 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsError) {
testing::Optional(testing::IsEmpty()));
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_NoData) {
+TEST_F(HostResolverManagerDnsTest,
+ MalformedExperimentalHttpsResponseInAddressRequestIsIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+ {"DnsHttpssvcExperimentDomains", kName}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::MALFORMED),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 108), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::IsEmpty()));
+}
+
+TEST_F(HostResolverManagerDnsTest,
+ MalformedExperimentalHttpsRecordInAddressRequestIsIgnored) {
+ const char kName[] = "name.test";
+
+ base::test::ScopedFeatureList features;
+ features.InitAndEnableFeatureWithParameters(
+ features::kDnsHttpssvc, {{"DnsHttpssvcUseHttpssvc", "true"},
+ {"DnsHttpssvcExperimentDomains", kName}});
+
+ MockDnsClientRuleList rules;
+ rules.emplace_back(kName, dns_protocol::kTypeHttps, /*secure=*/true,
+ MockDnsClientRule::Result(BuildTestDnsResponse(
+ kName, dns_protocol::kTypeHttps, /*answers=*/
+ {BuildTestDnsRecord(kName, dns_protocol::kTypeHttps,
+ /*rdata=*/"malformed rdata")})),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+ rules.emplace_back(kName, dns_protocol::kTypeAAAA, /*secure=*/true,
+ MockDnsClientRule::Result(MockDnsClientRule::OK),
+ /*delay=*/false);
+
+ CreateResolver();
+ UseMockDnsClient(CreateValidDnsConfig(), std::move(rules));
+ DnsConfigOverrides overrides;
+ overrides.secure_dns_mode = SecureDnsMode::kSecure;
+ resolver_->SetDnsConfigOverrides(overrides);
+
+ ResolveHostResponseHelper response(resolver_->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, kName, 108), NetworkIsolationKey(),
+ NetLogWithSource(), absl::nullopt, resolve_context_.get(),
+ resolve_context_->host_cache()));
+ EXPECT_THAT(response.result_error(), IsOk());
+ EXPECT_TRUE(response.request()->GetAddressResults());
+ EXPECT_FALSE(response.request()->GetTextResults());
+ EXPECT_FALSE(response.request()->GetHostnameResults());
+ EXPECT_THAT(response.request()->GetExperimentalResultsForTesting(),
+ testing::Optional(testing::ElementsAre(false)));
+}
+
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsInAddressQuery_NoData) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9937,7 +11324,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_NoData) {
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsLast) {
+TEST_F(HostResolverManagerDnsTest, ExperimentalHttpsInAddressQuery_HttpsLast) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -9972,8 +11359,8 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsLast) {
base::RunLoop().RunUntilIdle();
ASSERT_FALSE(response.complete());
- ASSERT_TRUE(
- dns_client_->CompleteOneDelayedTransactionOfType(DnsQueryType::HTTPS));
+ ASSERT_TRUE(dns_client_->CompleteOneDelayedTransactionOfType(
+ DnsQueryType::HTTPS_EXPERIMENTAL));
EXPECT_THAT(response.result_error(), IsOk());
EXPECT_TRUE(response.request()->GetAddressResults());
@@ -9983,7 +11370,8 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_HttpsLast) {
testing::Optional(testing::ElementsAre(true)));
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesLast) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsInAddressQuery_AddressesLast) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10032,7 +11420,7 @@ TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_AddressesLast) {
}
TEST_F(HostResolverManagerDnsTest,
- HttpsInInsecureAddressQueryDisallowedWhenInsecureFeatureDisabled) {
+ ExperimentalHttpsInInsecureAddressQueryDisallowedWhenParamDisabled) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10068,8 +11456,9 @@ TEST_F(HostResolverManagerDnsTest,
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest,
- HttpsInInsecureAddressQueryAllowedWhenInsecureFeatureEnabled) {
+TEST_F(
+ HostResolverManagerDnsTest,
+ ExperimentalHttpsInInsecureAddressQueryAllowedWhenInsecureFeatureEnabled) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10111,8 +11500,9 @@ TEST_F(HostResolverManagerDnsTest,
testing::Optional(testing::ElementsAre(true)));
}
-TEST_F(HostResolverManagerDnsTest,
- HttpsInInsecureAddressQueryDisallowedWhenAdditionalTypesDisallowed) {
+TEST_F(
+ HostResolverManagerDnsTest,
+ ExperimentalHttpsInInsecureAddressQueryDisallowedWithoutAdditionalTypes) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10158,7 +11548,7 @@ TEST_F(HostResolverManagerDnsTest,
}
TEST_F(HostResolverManagerDnsTest,
- HttpsInSecureAddressQueryAllowedWhenAdditionalQueriesDisallowed) {
+ ExperimentalHttpsInSecureAddressQueryAllowedWithoutAdditionalTypes) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10205,7 +11595,7 @@ TEST_F(HostResolverManagerDnsTest,
}
TEST_F(HostResolverManagerDnsTest,
- HttpsInAddressFallbackWhenAdditionalQueriesDisallowedIsDisallowed) {
+ ExperimentalHttpsInAddressFallbackDisallowedWithoutAdditionalTypes) {
const char kName[] = "combined.test";
base::test::ScopedFeatureList features;
@@ -10259,7 +11649,8 @@ TEST_F(HostResolverManagerDnsTest,
EXPECT_FALSE(response.request()->GetExperimentalResultsForTesting());
}
-TEST_F(HostResolverManagerDnsTest, HttpsInAddressQuery_ExperimentalTimeout) {
+TEST_F(HostResolverManagerDnsTest,
+ ExperimentalHttpsInAddressQuery_ExperimentalTimeout) {
const char kName[] = "combined.test";
const base::TimeDelta kTimeout = base::TimeDelta::FromSeconds(2);
diff --git a/chromium/net/dns/host_resolver_mdns_listener_impl.cc b/chromium/net/dns/host_resolver_mdns_listener_impl.cc
index 0287be7ddee..9c4fa1b5839 100644
--- a/chromium/net/dns/host_resolver_mdns_listener_impl.cc
+++ b/chromium/net/dns/host_resolver_mdns_listener_impl.cc
@@ -9,21 +9,21 @@
#include "net/base/host_port_pair.h"
#include "net/dns/host_cache.h"
#include "net/dns/host_resolver_mdns_task.h"
+#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/record_parsed.h"
namespace net {
namespace {
-HostResolver::MdnsListener::Delegate::UpdateType ConvertUpdateType(
- net::MDnsListener::UpdateType type) {
+MdnsListenerUpdateType ConvertUpdateType(net::MDnsListener::UpdateType type) {
switch (type) {
case net::MDnsListener::RECORD_ADDED:
- return HostResolver::MdnsListener::Delegate::UpdateType::ADDED;
+ return MdnsListenerUpdateType::kAdded;
case net::MDnsListener::RECORD_CHANGED:
- return HostResolver::MdnsListener::Delegate::UpdateType::CHANGED;
+ return MdnsListenerUpdateType::kChanged;
case net::MDnsListener::RECORD_REMOVED:
- return HostResolver::MdnsListener::Delegate::UpdateType::REMOVED;
+ return MdnsListenerUpdateType::kRemoved;
}
}
@@ -75,6 +75,7 @@ void HostResolverMdnsListenerImpl::OnRecordUpdate(
case DnsQueryType::UNSPECIFIED:
case DnsQueryType::INTEGRITY:
case DnsQueryType::HTTPS:
+ case DnsQueryType::HTTPS_EXPERIMENTAL:
NOTREACHED();
break;
case DnsQueryType::A:
diff --git a/chromium/net/dns/host_resolver_mdns_task.cc b/chromium/net/dns/host_resolver_mdns_task.cc
index 687b957f574..cf3dedf7e75 100644
--- a/chromium/net/dns/host_resolver_mdns_task.cc
+++ b/chromium/net/dns/host_resolver_mdns_task.cc
@@ -127,9 +127,9 @@ class HostResolverMdnsTask::Transaction {
HostResolverMdnsTask::HostResolverMdnsTask(
MDnsClient* mdns_client,
- const std::string& hostname,
+ std::string hostname,
const std::vector<DnsQueryType>& query_types)
- : mdns_client_(mdns_client), hostname_(hostname) {
+ : mdns_client_(mdns_client), hostname_(std::move(hostname)) {
DCHECK(!query_types.empty());
for (DnsQueryType query_type : query_types) {
transactions_.emplace_back(query_type, this);
@@ -199,6 +199,7 @@ HostCache::Entry HostResolverMdnsTask::ParseResult(
case DnsQueryType::UNSPECIFIED:
// Should create two separate transactions with specified type.
case DnsQueryType::HTTPS:
+ case DnsQueryType::HTTPS_EXPERIMENTAL:
// Not supported.
// TODO(ericorth@chromium.org): Consider support for HTTPS in mDNS if it
// is ever decided to support HTTPS via non-DoH.
diff --git a/chromium/net/dns/host_resolver_mdns_task.h b/chromium/net/dns/host_resolver_mdns_task.h
index e0e408afdf0..b91e77bd1c0 100644
--- a/chromium/net/dns/host_resolver_mdns_task.h
+++ b/chromium/net/dns/host_resolver_mdns_task.h
@@ -30,7 +30,7 @@ class HostResolverMdnsTask {
public:
// |mdns_client| must outlive |this|.
HostResolverMdnsTask(MDnsClient* mdns_client,
- const std::string& hostname,
+ std::string hostname,
const std::vector<DnsQueryType>& query_types);
~HostResolverMdnsTask();
diff --git a/chromium/net/dns/mapped_host_resolver.cc b/chromium/net/dns/mapped_host_resolver.cc
index be7238106a1..0faf128db11 100644
--- a/chromium/net/dns/mapped_host_resolver.cc
+++ b/chromium/net/dns/mapped_host_resolver.cc
@@ -11,6 +11,14 @@
#include "base/values.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
+#include "net/base/url_util.h"
+#include "net/dns/host_resolver.h"
+#include "net/log/net_log_with_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_canon.h"
namespace net {
@@ -25,6 +33,33 @@ void MappedHostResolver::OnShutdown() {
std::unique_ptr<HostResolver::ResolveHostRequest>
MappedHostResolver::CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource source_net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) {
+ GURL rewritten_url = host.GetURL();
+ HostMappingRules::RewriteResult result = rules_.RewriteUrl(rewritten_url);
+
+ switch (result) {
+ case HostMappingRules::RewriteResult::kRewritten:
+ DCHECK(rewritten_url.is_valid());
+ DCHECK_NE(rewritten_url.host_piece(), "~NOTFOUND");
+ return impl_->CreateRequest(
+ url::SchemeHostPort(rewritten_url), std::move(network_isolation_key),
+ std::move(source_net_log), std::move(optional_parameters));
+ case HostMappingRules::RewriteResult::kInvalidRewrite:
+ // Treat any invalid mapping as if it was "~NOTFOUND" (which should itself
+ // result in `kInvalidRewrite`).
+ return CreateFailingRequest(ERR_NAME_NOT_RESOLVED);
+ case HostMappingRules::RewriteResult::kNoMatchingRule:
+ return impl_->CreateRequest(
+ std::move(host), std::move(network_isolation_key),
+ std::move(source_net_log), std::move(optional_parameters));
+ }
+}
+
+std::unique_ptr<HostResolver::ResolveHostRequest>
+MappedHostResolver::CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& source_net_log,
diff --git a/chromium/net/dns/mapped_host_resolver.h b/chromium/net/dns/mapped_host_resolver.h
index f27bb71a61c..477f5848830 100644
--- a/chromium/net/dns/mapped_host_resolver.h
+++ b/chromium/net/dns/mapped_host_resolver.h
@@ -12,8 +12,12 @@
#include "net/base/completion_once_callback.h"
#include "net/base/host_mapping_rules.h"
#include "net/base/net_export.h"
+#include "net/base/network_isolation_key.h"
#include "net/dns/dns_config.h"
#include "net/dns/host_resolver.h"
+#include "net/log/net_log_with_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -51,6 +55,11 @@ class NET_EXPORT MappedHostResolver : public HostResolver {
// HostResolver methods:
std::unique_ptr<ResolveHostRequest> CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) override;
+ std::unique_ptr<ResolveHostRequest> CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& net_log,
diff --git a/chromium/net/dns/mapped_host_resolver_unittest.cc b/chromium/net/dns/mapped_host_resolver_unittest.cc
index 8fb3c71f7fc..d5ca366f2a2 100644
--- a/chromium/net/dns/mapped_host_resolver_unittest.cc
+++ b/chromium/net/dns/mapped_host_resolver_unittest.cc
@@ -4,17 +4,24 @@
#include "net/dns/mapped_host_resolver.h"
+#include <memory>
#include <utility>
#include "base/test/task_environment.h"
#include "net/base/address_list.h"
+#include "net/base/ip_address.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/log/net_log_with_source.h"
#include "net/test/gtest_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -100,6 +107,138 @@ TEST(MappedHostResolverTest, Inclusion) {
FirstAddress(request->GetAddressResults().value()));
}
+TEST(MappedHostResolverTest, MapsHostWithScheme) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("remapped.test", "192.168.1.22");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+ ASSERT_TRUE(resolver->AddRuleFromString("MAP to.map.test remapped.test"));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, "to.map.test", 155),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+
+ EXPECT_THAT(callback.GetResult(rv), IsOk());
+ EXPECT_THAT(
+ request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 22), 155)));
+}
+
+TEST(MappedHostResolverTest, MapsHostWithSchemeToIpLiteral) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("host.test", "192.168.1.22");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+ ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test [1234:5678::000A]"));
+
+ IPAddress expected_address;
+ ASSERT_TRUE(expected_address.AssignFromIPLiteral("1234:5678::000A"));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, "host.test", 156),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+
+ EXPECT_THAT(callback.GetResult(rv), IsOk());
+ EXPECT_THAT(request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(expected_address, 156)));
+}
+
+// Tests that remapped URL gets canonicalized when passing scheme.
+TEST(MappedHostResolverTest, MapsHostWithSchemeToNonCanon) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("remapped.test", "192.168.1.23");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+ ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test reMapped.TEST"));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, "host.test", 157),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+
+ EXPECT_THAT(callback.GetResult(rv), IsOk());
+ EXPECT_THAT(
+ request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 23), 157)));
+}
+
+TEST(MappedHostResolverTest, MapsHostWithSchemeToNameWithPort) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("remapped.test", "192.168.1.24");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+ ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test remapped.test:258"));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpScheme, "host.test", 158),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+
+ EXPECT_THAT(callback.GetResult(rv), IsOk());
+ EXPECT_THAT(
+ request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 24), 258)));
+}
+
+TEST(MappedHostResolverTest, HandlesUnmappedHostWithScheme) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("unmapped.test", "192.168.1.23");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kHttpsScheme, "unmapped.test", 155),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+
+ EXPECT_THAT(callback.GetResult(rv), IsOk());
+ EXPECT_THAT(
+ request->GetAddressResults().value().endpoints(),
+ testing::ElementsAre(IPEndPoint(IPAddress(192, 168, 1, 23), 155)));
+}
+
// Tests that exclusions are respected.
TEST(MappedHostResolverTest, Exclusion) {
base::test::TaskEnvironment task_environment;
@@ -242,6 +381,28 @@ TEST(MappedHostResolverTest, MapToError) {
FirstAddress(request->GetAddressResults().value()));
}
+TEST(MappedHostResolverTest, MapHostWithSchemeToError) {
+ base::test::TaskEnvironment task_environment;
+
+ // Create a mock host resolver, with specific hostname to IP mappings.
+ std::unique_ptr<MockHostResolver> resolver_impl(new MockHostResolver());
+ resolver_impl->rules()->AddRule("host.test", "192.168.1.25");
+
+ // Create a remapped resolver that uses `resolver_impl`.
+ std::unique_ptr<MappedHostResolver> resolver(
+ new MappedHostResolver(std::move(resolver_impl)));
+ ASSERT_TRUE(resolver->AddRuleFromString("MAP host.test ~NOTFOUND"));
+
+ std::unique_ptr<HostResolver::ResolveHostRequest> request =
+ resolver->CreateRequest(
+ url::SchemeHostPort(url::kWssScheme, "host.test", 155),
+ NetworkIsolationKey(), NetLogWithSource(), absl::nullopt);
+
+ TestCompletionCallback callback;
+ int rv = request->Start(callback.callback());
+ EXPECT_THAT(callback.GetResult(rv), IsError(ERR_NAME_NOT_RESOLVED));
+}
+
} // namespace
} // namespace net
diff --git a/chromium/net/dns/mdns_client_unittest.cc b/chromium/net/dns/mdns_client_unittest.cc
index 811f3d3b60d..f432500a715 100644
--- a/chromium/net/dns/mdns_client_unittest.cc
+++ b/chromium/net/dns/mdns_client_unittest.cc
@@ -1259,7 +1259,7 @@ class FailingSocketFactory : public MDnsSocketFactory {
std::vector<std::unique_ptr<DatagramServerSocket>>* sockets) override {
auto socket =
std::make_unique<MockMDnsDatagramServerSocket>(ADDRESS_FAMILY_IPV4);
- EXPECT_CALL(*socket, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket, RecvFrom(_, _, _, _))
.WillRepeatedly(Return(ERR_FAILED));
sockets->push_back(std::move(socket));
}
@@ -1372,9 +1372,9 @@ class MDnsConnectionTest : public TestWithTaskEnvironment {
TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
socket_ipv6_->SetResponsePacket(sample_packet_);
- EXPECT_CALL(*socket_ipv4_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
.WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*socket_ipv6_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
.WillOnce(
Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvNow))
.WillOnce(Return(ERR_IO_PENDING));
@@ -1386,9 +1386,9 @@ TEST_F(MDnsConnectionTest, ReceiveSynchronous) {
TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
socket_ipv6_->SetResponsePacket(sample_packet_);
- EXPECT_CALL(*socket_ipv4_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
.WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*socket_ipv6_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
.Times(2)
.WillOnce(
Invoke(socket_ipv6_, &MockMDnsDatagramServerSocket::HandleRecvLater))
@@ -1402,17 +1402,20 @@ TEST_F(MDnsConnectionTest, ReceiveAsynchronous) {
}
TEST_F(MDnsConnectionTest, Error) {
- CompletionRepeatingCallback callback;
+ CompletionOnceCallback callback;
- EXPECT_CALL(*socket_ipv4_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
.WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*socket_ipv6_, RecvFromInternal(_, _, _, _))
- .WillOnce(DoAll(SaveArg<3>(&callback), Return(ERR_IO_PENDING)));
+ EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
+ .WillOnce([&](auto, auto, auto, auto cb) {
+ callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
ASSERT_THAT(InitConnection(), test::IsOk());
EXPECT_CALL(delegate_, OnConnectionError(ERR_SOCKET_NOT_CONNECTED));
- callback.Run(ERR_SOCKET_NOT_CONNECTED);
+ std::move(callback).Run(ERR_SOCKET_NOT_CONNECTED);
base::RunLoop().RunUntilIdle();
}
@@ -1420,9 +1423,9 @@ class MDnsConnectionSendTest : public MDnsConnectionTest {
protected:
void SetUp() override {
MDnsConnectionTest::SetUp();
- EXPECT_CALL(*socket_ipv4_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv4_, RecvFrom(_, _, _, _))
.WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*socket_ipv6_, RecvFromInternal(_, _, _, _))
+ EXPECT_CALL(*socket_ipv6_, RecvFrom(_, _, _, _))
.WillOnce(Return(ERR_IO_PENDING));
EXPECT_THAT(InitConnection(), test::IsOk());
}
@@ -1456,11 +1459,14 @@ TEST_F(MDnsConnectionSendTest, SendQueued) {
.Times(2)
.WillRepeatedly(Return(OK));
- CompletionRepeatingCallback callback;
+ CompletionOnceCallback callback;
// Delay sending data. Only the first call should be made.
EXPECT_CALL(*socket_ipv6_,
SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
- .WillOnce(DoAll(SaveArg<2>(&callback), Return(ERR_IO_PENDING)));
+ .WillOnce([&](auto, auto, auto cb) {
+ callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
connection_.Send(sample_buffer_, sample_packet_.size());
connection_.Send(sample_buffer_, sample_packet_.size());
@@ -1473,7 +1479,7 @@ TEST_F(MDnsConnectionSendTest, SendQueued) {
EXPECT_CALL(*socket_ipv6_,
SendToInternal(sample_packet_, "[ff02::fb]:5353", _))
.WillOnce(Return(OK));
- callback.Run(OK);
+ std::move(callback).Run(OK);
}
TEST(MDnsSocketTest, CreateSocket) {
diff --git a/chromium/net/dns/mock_host_resolver.cc b/chromium/net/dns/mock_host_resolver.cc
index 6590e6cae53..db280775950 100644
--- a/chromium/net/dns/mock_host_resolver.cc
+++ b/chromium/net/dns/mock_host_resolver.cc
@@ -17,7 +17,6 @@
#include "base/memory/ref_counted.h"
#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/pattern.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -30,12 +29,18 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/dns_alias_utility.h"
#include "net/dns/host_cache.h"
+#include "net/dns/public/host_resolver_source.h"
+#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/public/resolve_error_info.h"
#include "net/dns/public/secure_dns_policy.h"
+#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request_context.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
#if defined(OS_WIN)
#include "net/base/winsock_init.h"
@@ -314,22 +319,22 @@ class MockHostResolverBase::MdnsListenerImpl
return OK;
}
- void TriggerAddressResult(Delegate::UpdateType update_type,
+ void TriggerAddressResult(MdnsListenerUpdateType update_type,
IPEndPoint address) {
delegate_->OnAddressResult(update_type, query_type_, std::move(address));
}
- void TriggerTextResult(Delegate::UpdateType update_type,
+ void TriggerTextResult(MdnsListenerUpdateType update_type,
std::vector<std::string> text_records) {
delegate_->OnTextResult(update_type, query_type_, std::move(text_records));
}
- void TriggerHostnameResult(Delegate::UpdateType update_type,
+ void TriggerHostnameResult(MdnsListenerUpdateType update_type,
HostPortPair host) {
delegate_->OnHostnameResult(update_type, query_type_, std::move(host));
}
- void TriggerUnhandledResult(Delegate::UpdateType update_type) {
+ void TriggerUnhandledResult(MdnsListenerUpdateType update_type) {
delegate_->OnUnhandledResult(update_type, query_type_);
}
@@ -373,6 +378,17 @@ void MockHostResolverBase::OnShutdown() {
std::unique_ptr<HostResolver::ResolveHostRequest>
MockHostResolverBase::CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) {
+ // TODO(crbug.com/1206799): Propagate scheme and make affect behavior.
+ return CreateRequest(HostPortPair::FromSchemeHostPort(host),
+ network_isolation_key, net_log, optional_parameters);
+}
+
+std::unique_ptr<HostResolver::ResolveHostRequest>
+MockHostResolverBase::CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& source_net_log,
@@ -493,7 +509,7 @@ void MockHostResolverBase::ResolveOnlyRequestNow() {
void MockHostResolverBase::TriggerMdnsListeners(
const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const IPEndPoint& address_result) {
for (auto* listener : listeners_) {
if (listener->host() == host && listener->query_type() == query_type)
@@ -504,7 +520,7 @@ void MockHostResolverBase::TriggerMdnsListeners(
void MockHostResolverBase::TriggerMdnsListeners(
const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const std::vector<std::string>& text_result) {
for (auto* listener : listeners_) {
if (listener->host() == host && listener->query_type() == query_type)
@@ -515,7 +531,7 @@ void MockHostResolverBase::TriggerMdnsListeners(
void MockHostResolverBase::TriggerMdnsListeners(
const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const HostPortPair& host_result) {
for (auto* listener : listeners_) {
if (listener->host() == host && listener->query_type() == query_type)
@@ -526,7 +542,7 @@ void MockHostResolverBase::TriggerMdnsListeners(
void MockHostResolverBase::TriggerMdnsListeners(
const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type) {
+ MdnsListenerUpdateType update_type) {
for (auto* listener : listeners_) {
if (listener->host() == host && listener->query_type() == query_type)
listener->TriggerUnhandledResult(update_type);
@@ -1109,6 +1125,17 @@ void HangingHostResolver::OnShutdown() {
std::unique_ptr<HostResolver::ResolveHostRequest>
HangingHostResolver::CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) {
+ // TODO(crbug.com/1206799): Propagate scheme and make affect behavior.
+ return CreateRequest(HostPortPair::FromSchemeHostPort(host),
+ network_isolation_key, net_log, optional_parameters);
+}
+
+std::unique_ptr<HostResolver::ResolveHostRequest>
+HangingHostResolver::CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& source_net_log,
diff --git a/chromium/net/dns/mock_host_resolver.h b/chromium/net/dns/mock_host_resolver.h
index 1b1214659c8..1d6238cce94 100644
--- a/chromium/net/dns/mock_host_resolver.h
+++ b/chromium/net/dns/mock_host_resolver.h
@@ -24,9 +24,13 @@
#include "net/base/network_isolation_key.h"
#include "net/dns/host_resolver.h"
#include "net/dns/host_resolver_proc.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
+#include "net/dns/public/mdns_listener_update_type.h"
#include "net/dns/public/secure_dns_policy.h"
+#include "net/log/net_log_with_source.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace base {
class TickClock;
@@ -122,6 +126,11 @@ class MockHostResolverBase
// HostResolver methods:
void OnShutdown() override;
std::unique_ptr<ResolveHostRequest> CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) override;
+ std::unique_ptr<ResolveHostRequest> CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& net_log,
@@ -213,19 +222,19 @@ class MockHostResolverBase
void TriggerMdnsListeners(const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const IPEndPoint& address_result);
void TriggerMdnsListeners(const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const std::vector<std::string>& text_result);
void TriggerMdnsListeners(const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type,
+ MdnsListenerUpdateType update_type,
const HostPortPair& host_result);
void TriggerMdnsListeners(const HostPortPair& host,
DnsQueryType query_type,
- MdnsListener::Delegate::UpdateType update_type);
+ MdnsListenerUpdateType update_type);
void set_tick_clock(const base::TickClock* tick_clock) {
tick_clock_ = tick_clock;
@@ -507,6 +516,11 @@ class HangingHostResolver : public HostResolver {
~HangingHostResolver() override;
void OnShutdown() override;
std::unique_ptr<ResolveHostRequest> CreateRequest(
+ url::SchemeHostPort host,
+ NetworkIsolationKey network_isolation_key,
+ NetLogWithSource net_log,
+ absl::optional<ResolveHostParameters> optional_parameters) override;
+ std::unique_ptr<ResolveHostRequest> CreateRequest(
const HostPortPair& host,
const NetworkIsolationKey& network_isolation_key,
const NetLogWithSource& net_log,
diff --git a/chromium/net/dns/mock_mdns_socket_factory.cc b/chromium/net/dns/mock_mdns_socket_factory.cc
index 794dcc654f5..b12bdc4f1aa 100644
--- a/chromium/net/dns/mock_mdns_socket_factory.cc
+++ b/chromium/net/dns/mock_mdns_socket_factory.cc
@@ -32,15 +32,7 @@ int MockMDnsDatagramServerSocket::SendTo(IOBuffer* buf,
const IPEndPoint& address,
CompletionOnceCallback callback) {
return SendToInternal(std::string(buf->data(), buf_len), address.ToString(),
- base::AdaptCallbackForRepeating(std::move(callback)));
-}
-
-int MockMDnsDatagramServerSocket::RecvFrom(IOBuffer* buffer,
- int size,
- IPEndPoint* address,
- CompletionOnceCallback callback) {
- return RecvFromInternal(buffer, size, address,
- base::AdaptCallbackForRepeating(std::move(callback)));
+ std::move(callback));
}
int MockMDnsDatagramServerSocket::GetLocalAddress(IPEndPoint* address) const {
@@ -57,7 +49,7 @@ int MockMDnsDatagramServerSocket::HandleRecvNow(
IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback) {
+ CompletionOnceCallback callback) {
int size_returned =
std::min(response_packet_.size(), static_cast<size_t>(size));
memcpy(buffer->data(), response_packet_.data(), size_returned);
@@ -68,10 +60,10 @@ int MockMDnsDatagramServerSocket::HandleRecvLater(
IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback) {
- int rv = HandleRecvNow(buffer, size, address, callback);
- base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(callback, rv));
+ CompletionOnceCallback callback) {
+ int rv = HandleRecvNow(buffer, size, address, base::DoNothing());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(std::move(callback), rv));
return ERR_IO_PENDING;
}
@@ -96,7 +88,7 @@ void MockMDnsSocketFactory::CreateSocket(
this,
&MockMDnsSocketFactory::SendToInternal));
- ON_CALL(*new_socket, RecvFromInternal(_, _, _, _))
+ ON_CALL(*new_socket, RecvFrom(_, _, _, _))
.WillByDefault(Invoke(this, &MockMDnsSocketFactory::RecvFromInternal));
sockets->push_back(std::move(new_socket));
@@ -111,14 +103,13 @@ void MockMDnsSocketFactory::SimulateReceive(const uint8_t* packet, int size) {
std::move(recv_callback_).Run(size);
}
-int MockMDnsSocketFactory::RecvFromInternal(
- IOBuffer* buffer,
- int size,
- IPEndPoint* address,
- CompletionRepeatingCallback callback) {
+int MockMDnsSocketFactory::RecvFromInternal(IOBuffer* buffer,
+ int size,
+ IPEndPoint* address,
+ CompletionOnceCallback callback) {
recv_buffer_ = buffer;
recv_buffer_size_ = size;
- recv_callback_ = callback;
+ recv_callback_ = std::move(callback);
return ERR_IO_PENDING;
}
diff --git a/chromium/net/dns/mock_mdns_socket_factory.h b/chromium/net/dns/mock_mdns_socket_factory.h
index 8f0d5b593a1..78036efb186 100644
--- a/chromium/net/dns/mock_mdns_socket_factory.h
+++ b/chromium/net/dns/mock_mdns_socket_factory.h
@@ -29,18 +29,11 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
// DatagramServerSocket implementation:
MOCK_METHOD1(Listen, int(const IPEndPoint& address));
- // GMock cannot handle move-only types like CompletionOnceCallback, so it
- // needs to be converted into the copyable type CompletionRepeatingCallback.
- int RecvFrom(IOBuffer* buffer,
- int size,
- IPEndPoint* address,
- CompletionOnceCallback callback) override;
-
- MOCK_METHOD4(RecvFromInternal,
+ MOCK_METHOD4(RecvFrom,
int(IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback));
+ CompletionOnceCallback callback));
int SendTo(IOBuffer* buf,
int buf_len,
@@ -50,7 +43,7 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
MOCK_METHOD3(SendToInternal,
int(const std::string& packet,
const std::string address,
- CompletionRepeatingCallback callback));
+ CompletionOnceCallback callback));
MOCK_METHOD1(SetReceiveBufferSize, int(int32_t size));
MOCK_METHOD1(SetSendBufferSize, int(int32_t size));
@@ -87,12 +80,12 @@ class MockMDnsDatagramServerSocket : public DatagramServerSocket {
int HandleRecvNow(IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback);
+ CompletionOnceCallback callback);
int HandleRecvLater(IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback);
+ CompletionOnceCallback callback);
private:
std::string response_packet_;
@@ -121,7 +114,7 @@ class MockMDnsSocketFactory : public MDnsSocketFactory {
int RecvFromInternal(IOBuffer* buffer,
int size,
IPEndPoint* address,
- CompletionRepeatingCallback callback);
+ CompletionOnceCallback callback);
void CreateSocket(
AddressFamily address_family,
@@ -129,7 +122,7 @@ class MockMDnsSocketFactory : public MDnsSocketFactory {
scoped_refptr<IOBuffer> recv_buffer_;
int recv_buffer_size_;
- CompletionRepeatingCallback recv_callback_;
+ CompletionOnceCallback recv_callback_;
};
} // namespace net
diff --git a/chromium/net/dns/public/BUILD.gn b/chromium/net/dns/public/BUILD.gn
index b436ce59f4a..338dbdb1c94 100644
--- a/chromium/net/dns/public/BUILD.gn
+++ b/chromium/net/dns/public/BUILD.gn
@@ -27,6 +27,8 @@ source_set("public") {
"dns_query_type.h",
"doh_provider_entry.cc",
"doh_provider_entry.h",
+ "host_resolver_source.h",
+ "mdns_listener_update_type.h",
"resolve_error_info.cc",
"resolve_error_info.h",
"secure_dns_mode.h",
diff --git a/chromium/net/dns/public/dns_query_type.h b/chromium/net/dns/public/dns_query_type.h
index 11aa0b69fdc..07178a4c952 100644
--- a/chromium/net/dns/public/dns_query_type.h
+++ b/chromium/net/dns/public/dns_query_type.h
@@ -5,7 +5,7 @@
#ifndef NET_DNS_PUBLIC_DNS_QUERY_TYPE_H_
#define NET_DNS_PUBLIC_DNS_QUERY_TYPE_H_
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/net_export.h"
namespace net {
@@ -22,13 +22,19 @@ enum class DnsQueryType {
SRV,
INTEGRITY,
HTTPS,
- MAX = HTTPS
+ HTTPS_EXPERIMENTAL,
+ MAX = HTTPS_EXPERIMENTAL
};
-const DnsQueryType kDnsQueryTypes[] = {
- DnsQueryType::UNSPECIFIED, DnsQueryType::A, DnsQueryType::AAAA,
- DnsQueryType::TXT, DnsQueryType::PTR, DnsQueryType::SRV,
- DnsQueryType::INTEGRITY, DnsQueryType::HTTPS};
+const DnsQueryType kDnsQueryTypes[] = {DnsQueryType::UNSPECIFIED,
+ DnsQueryType::A,
+ DnsQueryType::AAAA,
+ DnsQueryType::TXT,
+ DnsQueryType::PTR,
+ DnsQueryType::SRV,
+ DnsQueryType::INTEGRITY,
+ DnsQueryType::HTTPS,
+ DnsQueryType::HTTPS_EXPERIMENTAL};
static_assert(base::size(kDnsQueryTypes) ==
static_cast<unsigned>(DnsQueryType::MAX) + 1,
diff --git a/chromium/net/dns/public/doh_provider_entry.cc b/chromium/net/dns/public/doh_provider_entry.cc
index 720620c3a79..9362d8a0900 100644
--- a/chromium/net/dns/public/doh_provider_entry.cc
+++ b/chromium/net/dns/public/doh_provider_entry.cc
@@ -34,7 +34,7 @@ const DohProviderEntry::List& DohProviderEntry::GetList() {
//
// The provider names in these entries should be kept in sync with the
// DohProviderId histogram suffix list in
- // tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml.
+ // tools/metrics/histograms/metadata/histogram_suffixes_list.xml.
static const base::NoDestructor<DohProviderEntry::List> providers{{
new DohProviderEntry("AlekBergNl", DohProviderIdForHistogram::kAlekBergNl,
{} /* ip_strs */, {} /* dns_over_tls_hostnames */,
@@ -93,6 +93,13 @@ const DohProviderEntry::List& DohProviderEntry::GetList() {
"https://doh.xfinity.com/dns-query{?dns}", "" /* ui_name */,
"" /* privacy_policy */, false /* display_globally */,
{} /* display_countries */, LoggingLevel::kExtra),
+ new DohProviderEntry("Cox", /*provider_id_for_histogram=*/absl::nullopt,
+ {"68.105.28.11", "68.105.28.12", "2001:578:3f::30"},
+ /*dns_over_tls_hostnames=*/{"dot.cox.net"},
+ "https://doh.cox.net/dns-query",
+ /*ui_name=*/"", /*privacy_policy=*/"",
+ /*display_globally=*/false, /*display_countries=*/{},
+ LoggingLevel::kNormal),
new DohProviderEntry(
"Cznic", DohProviderIdForHistogram::kCznic,
{"185.43.135.1", "193.17.47.1", "2001:148f:fffe::1",
@@ -102,23 +109,13 @@ const DohProviderEntry::List& DohProviderEntry::GetList() {
"https://www.nic.cz/odvr/" /* privacy_policy */,
false /* display_globally */, {"CZ"} /* display_countries */,
LoggingLevel::kNormal),
- // Note: DNS.SB has separate entries for autoupgrade and settings UI to
- // allow the extra |no_ecs| parameter for autoupgrade. This parameter
- // disables EDNS Client Subnet (ECS) handling in order to match the
- // behavior of the upgraded-from classic DNS server.
- new DohProviderEntry(
- "Dnssb", absl::nullopt /* provider_id_for_histogram */,
- {"185.222.222.222", "185.184.222.222", "2a09::", "2a09::1"},
- {"dns.sb"} /* dns_over_tls_hostnames */,
- "https://doh.dns.sb/dns-query?no_ecs=true{&dns}", "" /* ui_name */,
- "" /* privacy_policy */, false /* display_globally */,
- {} /* display_countries */, LoggingLevel::kNormal),
new DohProviderEntry(
- "DnssbUserSelected", DohProviderIdForHistogram::kDnsSb,
- {} /* ip_strs */, {} /* dns_over_tls_hostnames */,
- "https://doh.dns.sb/dns-query{?dns}", "DNS.SB" /* ui_name */,
- "https://dns.sb/privacy/" /* privacy_policy */,
- false /* display_globally */, {"EE", "DE"} /* display_countries */,
+ "Dnssb", DohProviderIdForHistogram::kDnsSb,
+ {"185.222.222.222", "45.11.45.11", "2a09::", "2a11::"},
+ /*dns_over_tls_hostnames=*/{"dns.sb"},
+ "https://doh.dns.sb/dns-query{?dns}", /*ui_name=*/"DNS.SB",
+ /*privacy_policy=*/"https://dns.sb/privacy/",
+ /*display_globally=*/false, /*display_countries=*/{"EE", "DE"},
LoggingLevel::kNormal),
new DohProviderEntry("Google", DohProviderIdForHistogram::kGoogle,
{"8.8.8.8", "8.8.4.4", "2001:4860:4860::8888",
diff --git a/chromium/net/dns/host_resolver_source.h b/chromium/net/dns/public/host_resolver_source.h
index cf9633be8b2..d9b3ed3f098 100644
--- a/chromium/net/dns/host_resolver_source.h
+++ b/chromium/net/dns/public/host_resolver_source.h
@@ -2,10 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_DNS_HOST_RESOLVER_SOURCE_H_
-#define NET_DNS_HOST_RESOLVER_SOURCE_H_
+#ifndef NET_DNS_PUBLIC_HOST_RESOLVER_SOURCE_H_
+#define NET_DNS_PUBLIC_HOST_RESOLVER_SOURCE_H_
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
namespace net {
@@ -47,4 +47,4 @@ static_assert(
} // namespace net
-#endif // NET_DNS_HOST_RESOLVER_SOURCE_H_
+#endif // NET_DNS_PUBLIC_HOST_RESOLVER_SOURCE_H_
diff --git a/chromium/net/dns/public/mdns_listener_update_type.h b/chromium/net/dns/public/mdns_listener_update_type.h
new file mode 100644
index 00000000000..f2b5e01e3e4
--- /dev/null
+++ b/chromium/net/dns/public/mdns_listener_update_type.h
@@ -0,0 +1,19 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_DNS_PUBLIC_MDNS_LISTENER_UPDATE_TYPE_H_
+#define NET_DNS_PUBLIC_MDNS_LISTENER_UPDATE_TYPE_H_
+
+namespace net {
+
+// Types of update notifications from a HostResolver::MdnsListener
+enum class MdnsListenerUpdateType {
+ kAdded,
+ kChanged,
+ kRemoved,
+};
+
+} // namespace net
+
+#endif // NET_DNS_PUBLIC_MDNS_LISTENER_UPDATE_TYPE_H_
diff --git a/chromium/net/dns/resolve_context.h b/chromium/net/dns/resolve_context.h
index 0af99b232b8..4e57ea62a1c 100644
--- a/chromium/net/dns/resolve_context.h
+++ b/chromium/net/dns/resolve_context.h
@@ -18,7 +18,6 @@
#include "net/base/net_export.h"
#include "net/dns/dns_config.h"
#include "net/dns/public/secure_dns_mode.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
diff --git a/chromium/net/dns/resolve_context_unittest.cc b/chromium/net/dns/resolve_context_unittest.cc
index 7f6a6ebcf2a..579361b3ae5 100644
--- a/chromium/net/dns/resolve_context_unittest.cc
+++ b/chromium/net/dns/resolve_context_unittest.cc
@@ -26,10 +26,10 @@
#include "net/dns/dns_session.h"
#include "net/dns/dns_socket_allocator.h"
#include "net/dns/host_cache.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/public/dns_over_https_server_config.h"
#include "net/dns/public/dns_protocol.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/socket/socket_test_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/url_request/url_request_context.h"
diff --git a/chromium/net/docs/adding_doh_providers.md b/chromium/net/docs/adding_doh_providers.md
index bcce38e4568..2baf7610efd 100644
--- a/chromium/net/docs/adding_doh_providers.md
+++ b/chromium/net/docs/adding_doh_providers.md
@@ -105,7 +105,7 @@ Chrome team on approval of the request.
issues requiring that provider to be disabled for auto upgrade.
1. Update histogram entries as necessary.
* If new providers were added, new `provider` strings must be added to the
- [`DohProviderId`](/tools/metrics/histograms/histograms_xml/histogram_suffixes_list.xml)
+ [`DohProviderId`](/tools/metrics/histograms/metadata/histogram_suffixes_list.xml)
histogram suffix.
* If new enum values were added for `provider_id_for_histogram`, the value
must also be added to the
diff --git a/chromium/net/docs/life-of-a-feature.md b/chromium/net/docs/life-of-a-feature.md
index 6046a6ccfcc..87a6a9efe96 100644
--- a/chromium/net/docs/life-of-a-feature.md
+++ b/chromium/net/docs/life-of-a-feature.md
@@ -92,7 +92,7 @@ configuration of proxies, but which requires it be supplied as part of the
`URLRequestContextGetter` building, if proxies are going to be supported.
An example of injecting configuration flags can be seen in the
-`HttpNetworkSession::Params` structure, which is used to provide much of
+`HttpNetworkSessionParams` structure, which is used to provide much of
the initialization parameters for the HTTP layer.
The ideal form of injection is to pass ownership of the injected object,
diff --git a/chromium/net/extras/preload_data/decoder.cc b/chromium/net/extras/preload_data/decoder.cc
index f20e955e0b0..6fa812205fd 100644
--- a/chromium/net/extras/preload_data/decoder.cc
+++ b/chromium/net/extras/preload_data/decoder.cc
@@ -309,7 +309,7 @@ bool PreloadDecoder::Decode(const std::string& search, bool* out_found) {
}
}
}
- return false;
+ NOTREACHED();
}
} // namespace extras
diff --git a/chromium/net/extras/sqlite/DIR_METADATA b/chromium/net/extras/sqlite/DIR_METADATA
new file mode 100644
index 00000000000..c9091f0ad1e
--- /dev/null
+++ b/chromium/net/extras/sqlite/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Internals>Storage"
+}
diff --git a/chromium/net/extras/sqlite/OWNERS b/chromium/net/extras/sqlite/OWNERS
index 836bc3bd663..b364c82be79 100644
--- a/chromium/net/extras/sqlite/OWNERS
+++ b/chromium/net/extras/sqlite/OWNERS
@@ -4,5 +4,3 @@ mek@chromium.org
per-file sqlite_persistent_cookie_store*=file://net/cookies/OWNERS
per-file sqlite_persistent_reporting_and_nel_store*=file://net/reporting/OWNERS
per-file sqlite_persistent_reporting_and_nel_store*=file://net/network_error_logging/OWNERS
-
-# Component: Internals>Storage
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
index 63e607af47f..59da92d0cde 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store.cc
@@ -123,6 +123,7 @@ namespace {
// Version number of the database.
//
+// Version 15 - 2021/07/01 - https://crrev.com/c/3001822
// Version 14 - 2021/02/23 - https://crrev.com/c/2036899
// Version 13 - 2020/10/28 - https://crrev.com/c/2505468
// Version 12 - 2019/11/20 - https://crrev.com/c/1898301
@@ -137,6 +138,14 @@ namespace {
// Version 5 - 2011/12/05 - https://codereview.chromium.org/8533013
// Version 4 - 2009/09/01 - https://codereview.chromium.org/183021
//
+// Version 15 adds one new field: "top_frame_site_key" (if not empty then the
+// string is the scheme and site of the topmost-level frame the cookie was
+// created in). This field is deserialized into the cookie's partition key.
+// top_frame_site_key is *NOT* the site-for-cookies when the cookie was created.
+// In migrating, top_frame_site_key defaults to empty string. This change also
+// changes the uniqueness constraint on cookies to include the
+// top_frame_site_key as well.
+//
// Version 14 just reads all encrypted cookies and re-writes them out again to
// make sure the new encryption key is in use. This active migration only
// happens on Windows, on other OS, this migration is a no-op.
@@ -198,8 +207,8 @@ namespace {
// Version 3 updated the database to include the last access time, so we can
// expire them in decreasing order of use when we've reached the maximum
// number of cookies.
-const int kCurrentVersionNumber = 14;
-const int kCompatibleVersionNumber = 14;
+const int kCurrentVersionNumber = 15;
+const int kCompatibleVersionNumber = 15;
} // namespace
@@ -375,8 +384,7 @@ class SQLitePersistentCookieStore::Backend
}
typedef std::list<std::unique_ptr<PendingOperation>> PendingOperationsForKey;
- typedef std::map<std::tuple<std::string, std::string, std::string>,
- PendingOperationsForKey>
+ typedef std::map<CanonicalCookie::UniqueCookieKey, PendingOperationsForKey>
PendingOperationsMap;
PendingOperationsMap pending_ GUARDED_BY(lock_);
PendingOperationsMap::size_type num_pending_ GUARDED_BY(lock_);
@@ -595,15 +603,17 @@ bool CreateV11Schema(sql::Database* db) {
// Initializes the cookies table, returning true on success.
// The table cannot exist when calling this function.
-bool CreateV13Schema(sql::Database* db) {
+bool CreateV15Schema(sql::Database* db) {
DCHECK(!db->DoesTableExist("cookies"));
std::string stmt(base::StringPrintf(
"CREATE TABLE cookies("
"creation_utc INTEGER NOT NULL,"
+ "top_frame_site_key TEXT NOT NULL,"
"host_key TEXT NOT NULL,"
"name TEXT NOT NULL,"
"value TEXT NOT NULL,"
+ "encrypted_value BLOB DEFAULT '',"
"path TEXT NOT NULL,"
"expires_utc INTEGER NOT NULL,"
"is_secure INTEGER NOT NULL,"
@@ -612,12 +622,11 @@ bool CreateV13Schema(sql::Database* db) {
"has_expires INTEGER NOT NULL DEFAULT 1,"
"is_persistent INTEGER NOT NULL DEFAULT 1,"
"priority INTEGER NOT NULL DEFAULT %d,"
- "encrypted_value BLOB DEFAULT '',"
"samesite INTEGER NOT NULL DEFAULT %d,"
"source_scheme INTEGER NOT NULL DEFAULT %d,"
"source_port INTEGER NOT NULL DEFAULT %d,"
"is_same_party INTEGER NOT NULL DEFAULT 0,"
- "UNIQUE (host_key, name, path))",
+ "UNIQUE (top_frame_site_key, host_key, name, path))",
CookiePriorityToDBCookiePriority(COOKIE_PRIORITY_DEFAULT),
CookieSameSiteToDBCookieSameSite(CookieSameSite::UNSPECIFIED),
static_cast<int>(CookieSourceScheme::kUnset), kDefaultUnknownPort));
@@ -627,13 +636,6 @@ bool CreateV13Schema(sql::Database* db) {
return true;
}
-// Initializes the cookies table, returning true on success.
-// The table cannot exist when calling this function.
-bool CreateV14Schema(sql::Database* db) {
- // Schema did not change between v13 and v14.
- return CreateV13Schema(db);
-}
-
} // namespace
void SQLitePersistentCookieStore::Backend::Load(
@@ -787,7 +789,7 @@ bool SQLitePersistentCookieStore::Backend::CreateDatabaseSchema() {
if (db()->DoesTableExist("cookies"))
return true;
- return CreateV14Schema(db());
+ return CreateV15Schema(db());
}
bool SQLitePersistentCookieStore::Backend::DoInitializeDatabase() {
@@ -858,6 +860,7 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
const std::set<std::string>& domains) {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
+ // TODO(crbug.com/1225444) Query top_frame_site_key from database.
sql::Statement smt, delete_statement;
if (restore_old_session_cookies_) {
smt.Assign(db()->GetCachedStatement(
@@ -865,17 +868,20 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
"SELECT creation_utc, host_key, name, value, path, expires_utc, "
"is_secure, is_httponly, last_access_utc, has_expires, is_persistent, "
"priority, encrypted_value, samesite, source_scheme, source_port, "
- "is_same_party FROM cookies WHERE host_key = ?"));
+ "is_same_party FROM cookies WHERE top_frame_site_key = ? AND "
+ "host_key = ?"));
} else {
smt.Assign(db()->GetCachedStatement(
SQL_FROM_HERE,
"SELECT creation_utc, host_key, name, value, path, expires_utc, "
"is_secure, is_httponly, last_access_utc, has_expires, is_persistent, "
"priority, encrypted_value, samesite, source_scheme, source_port, "
- "is_same_party FROM cookies WHERE host_key = ? AND is_persistent = 1"));
+ "is_same_party FROM cookies WHERE top_frame_site_key = ? AND "
+ "host_key = ? AND is_persistent = 1"));
}
delete_statement.Assign(db()->GetCachedStatement(
- SQL_FROM_HERE, "DELETE FROM cookies WHERE host_key = ?"));
+ SQL_FROM_HERE,
+ "DELETE FROM cookies WHERE top_frame_site_key = ? AND host_key = ?"));
if (!smt.is_valid() || !delete_statement.is_valid()) {
delete_statement.Clear();
smt.Clear(); // Disconnect smt_ref from db_.
@@ -887,7 +893,8 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
auto it = domains.begin();
bool ok = true;
for (; it != domains.end() && ok; ++it) {
- smt.BindString(0, *it);
+ smt.BindString(0, net::kEmptyCookiePartitionKey);
+ smt.BindString(1, *it);
ok = MakeCookiesFromSQLStatement(&cookies, &smt);
smt.Reset(true);
}
@@ -904,7 +911,8 @@ bool SQLitePersistentCookieStore::Backend::LoadCookiesForDomains(
//
// For data consistency, we drop the entire eTLD group.
for (const std::string& domain : domains) {
- delete_statement.BindString(0, domain);
+ delete_statement.BindString(0, net::kEmptyCookiePartitionKey);
+ delete_statement.BindString(1, domain);
if (!delete_statement.Run()) {
// TODO(morlovich): Is something more drastic called for here?
RecordCookieLoadProblem(COOKIE_LOAD_PROBLEM_RECOVERY_FAILED);
@@ -950,8 +958,11 @@ bool SQLitePersistentCookieStore::Backend::MakeCookiesFromSQLStatement(
DBCookiePriorityToCookiePriority(
static_cast<DBCookiePriority>(smt.ColumnInt(11))), // priority
smt.ColumnBool(16), // is_same_party
- DBToCookieSourceScheme(smt.ColumnInt(14)), // source_scheme
- smt.ColumnInt(15)); // source_port
+ // TODO(crbug.com/1225444) Deserialize top_frame_site_key into the
+ // cookie partition key.
+ absl::nullopt, // top_frame_site_key
+ DBToCookieSourceScheme(smt.ColumnInt(14)), // source_scheme
+ smt.ColumnInt(15)); // source_port
if (cc) {
DLOG_IF(WARNING, cc->CreationDate() > Time::Now())
<< L"CreationDate too recent";
@@ -1179,6 +1190,44 @@ SQLitePersistentCookieStore::Backend::DoMigrateDatabaseSchema() {
base::TimeTicks::Now() - start_time);
}
+ if (cur_version == 14) {
+ SCOPED_UMA_HISTOGRAM_TIMER("Cookie.TimeDatabaseMigrationToV15");
+
+ sql::Transaction transaction(db());
+ if (!transaction.Begin())
+ return absl::nullopt;
+
+ if (!db()->Execute("DROP TABLE IF EXISTS cookies_old"))
+ return absl::nullopt;
+ if (!db()->Execute("ALTER TABLE cookies RENAME TO cookies_old"))
+ return absl::nullopt;
+
+ if (!CreateV15Schema(db()))
+ return absl::nullopt;
+ std::string insert_cookies_sql = base::StringPrintf(
+ "INSERT OR REPLACE INTO cookies "
+ "(creation_utc, top_frame_site_key, host_key, name, value, "
+ " encrypted_value, path, expires_utc, is_secure, is_httponly, "
+ " last_access_utc, has_expires, is_persistent, priority, samesite, "
+ " source_scheme, source_port, is_same_party) "
+ "SELECT creation_utc, '%s', host_key, name, value, encrypted_value, "
+ " path, expires_utc, is_secure, is_httponly, last_access_utc, "
+ " has_expires, is_persistent, priority, samesite, source_scheme, "
+ " source_port, is_same_party "
+ "FROM cookies_old ORDER BY creation_utc ASC",
+ net::kEmptyCookiePartitionKey);
+ if (!db()->Execute(insert_cookies_sql.c_str()))
+ return absl::nullopt;
+ if (!db()->Execute("DROP TABLE cookies_old"))
+ return absl::nullopt;
+
+ ++cur_version;
+ meta_table()->SetVersionNumber(cur_version);
+ meta_table()->SetCompatibleVersionNumber(
+ std::min(cur_version, kCompatibleVersionNumber));
+ transaction.Commit();
+ }
+
// Put future migration cases here.
return absl::make_optional(cur_version);
@@ -1277,25 +1326,27 @@ void SQLitePersistentCookieStore::Backend::DoCommit() {
sql::Statement add_statement(db()->GetCachedStatement(
SQL_FROM_HERE,
- "INSERT INTO cookies (creation_utc, host_key, name, value, path, "
- "expires_utc, is_secure, is_httponly, last_access_utc, has_expires, "
- "is_persistent, priority, encrypted_value, samesite, source_scheme, "
- "source_port, is_same_party) "
- "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ "INSERT INTO cookies (creation_utc, top_frame_site_key, host_key, name, "
+ "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
+ "last_access_utc, has_expires, is_persistent, priority, samesite, "
+ "source_scheme, source_port, is_same_party) "
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
if (!add_statement.is_valid())
return;
sql::Statement update_access_statement(
db()->GetCachedStatement(SQL_FROM_HERE,
"UPDATE cookies SET last_access_utc=? WHERE "
- "name=? AND host_key=? AND path=?"));
+ "name=? AND top_frame_site_key=? AND host_key=? "
+ "AND path=?"));
if (!update_access_statement.is_valid())
return;
sql::Statement delete_statement(
db()->GetCachedStatement(SQL_FROM_HERE,
"DELETE FROM cookies WHERE "
- "name=? AND host_key=? AND path=?"));
+ "name=? AND top_frame_site_key=? AND host_key=? "
+ "AND path=?"));
if (!delete_statement.is_valid())
return;
@@ -1311,8 +1362,11 @@ void SQLitePersistentCookieStore::Backend::DoCommit() {
case PendingOperation::COOKIE_ADD:
add_statement.Reset(true);
add_statement.BindTime(0, po->cc().CreationDate());
- add_statement.BindString(1, po->cc().Domain());
- add_statement.BindString(2, po->cc().Name());
+ // TODO(crbug.com/1225444) Serialize cookie's partition key into this
+ // column.
+ add_statement.BindString(1, net::kEmptyCookiePartitionKey);
+ add_statement.BindString(2, po->cc().Domain());
+ add_statement.BindString(3, po->cc().Name());
if (crypto_ && crypto_->ShouldEncrypt()) {
std::string encrypted_value;
if (!crypto_->EncryptString(po->cc().Value(), &encrypted_value)) {
@@ -1320,29 +1374,28 @@ void SQLitePersistentCookieStore::Backend::DoCommit() {
RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ENCRYPT_FAILED);
continue;
}
- add_statement.BindCString(3, ""); // value
+ add_statement.BindCString(4, ""); // value
// BindBlob() immediately makes an internal copy of the data.
- add_statement.BindBlob(12, encrypted_value.data(),
- static_cast<int>(encrypted_value.length()));
+ add_statement.BindBlob(5, encrypted_value);
} else {
- add_statement.BindString(3, po->cc().Value());
- add_statement.BindBlob(12, "", 0); // encrypted_value
+ add_statement.BindString(4, po->cc().Value());
+ add_statement.BindBlob(5,
+ base::span<uint8_t>()); // encrypted_value
}
- add_statement.BindString(4, po->cc().Path());
- add_statement.BindTime(5, po->cc().ExpiryDate());
- add_statement.BindBool(6, po->cc().IsSecure());
- add_statement.BindBool(7, po->cc().IsHttpOnly());
- add_statement.BindTime(8, po->cc().LastAccessDate());
- add_statement.BindBool(9, po->cc().IsPersistent());
- add_statement.BindBool(10, po->cc().IsPersistent());
+ add_statement.BindString(6, po->cc().Path());
+ add_statement.BindTime(7, po->cc().ExpiryDate());
+ add_statement.BindBool(8, po->cc().IsSecure());
+ add_statement.BindBool(9, po->cc().IsHttpOnly());
+ add_statement.BindTime(10, po->cc().LastAccessDate());
+ add_statement.BindBool(11, po->cc().IsPersistent());
+ add_statement.BindBool(12, po->cc().IsPersistent());
add_statement.BindInt(
- 11, CookiePriorityToDBCookiePriority(po->cc().Priority()));
- // 12, encrypted_value, inserted above.
+ 13, CookiePriorityToDBCookiePriority(po->cc().Priority()));
add_statement.BindInt(
- 13, CookieSameSiteToDBCookieSameSite(po->cc().SameSite()));
- add_statement.BindInt(14, static_cast<int>(po->cc().SourceScheme()));
- add_statement.BindInt(15, po->cc().SourcePort());
- add_statement.BindBool(16, po->cc().IsSameParty());
+ 14, CookieSameSiteToDBCookieSameSite(po->cc().SameSite()));
+ add_statement.BindInt(15, static_cast<int>(po->cc().SourceScheme()));
+ add_statement.BindInt(16, po->cc().SourcePort());
+ add_statement.BindBool(17, po->cc().IsSameParty());
if (!add_statement.Run()) {
DLOG(WARNING) << "Could not add a cookie to the DB.";
RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_ADD);
@@ -1353,8 +1406,11 @@ void SQLitePersistentCookieStore::Backend::DoCommit() {
update_access_statement.Reset(true);
update_access_statement.BindTime(0, po->cc().LastAccessDate());
update_access_statement.BindString(1, po->cc().Name());
- update_access_statement.BindString(2, po->cc().Domain());
- update_access_statement.BindString(3, po->cc().Path());
+ // TODO(crbug.com/1225444) Update to use the cookie's actual
+ // partition key.
+ update_access_statement.BindString(2, net::kEmptyCookiePartitionKey);
+ update_access_statement.BindString(3, po->cc().Domain());
+ update_access_statement.BindString(4, po->cc().Path());
if (!update_access_statement.Run()) {
DLOG(WARNING)
<< "Could not update cookie last access time in the DB.";
@@ -1365,8 +1421,11 @@ void SQLitePersistentCookieStore::Backend::DoCommit() {
case PendingOperation::COOKIE_DELETE:
delete_statement.Reset(true);
delete_statement.BindString(0, po->cc().Name());
- delete_statement.BindString(1, po->cc().Domain());
- delete_statement.BindString(2, po->cc().Path());
+ // TODO(crbug.com/1225444) Update to use the cookie's actual
+ // partition key.
+ delete_statement.BindString(1, net::kEmptyCookiePartitionKey);
+ delete_statement.BindString(2, po->cc().Domain());
+ delete_statement.BindString(3, po->cc().Path());
if (!delete_statement.Run()) {
DLOG(WARNING) << "Could not delete a cookie from the DB.";
RecordCookieCommitProblem(COOKIE_COMMIT_PROBLEM_DELETE);
@@ -1414,16 +1473,12 @@ void SQLitePersistentCookieStore::Backend::DeleteAllInList(
void SQLitePersistentCookieStore::Backend::DeleteSessionCookiesOnStartup() {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
- base::Time start_time = base::Time::Now();
if (!db()->Execute("DELETE FROM cookies WHERE is_persistent != 1"))
LOG(WARNING) << "Unable to delete session cookies.";
-
- UMA_HISTOGRAM_TIMES("Cookie.Startup.TimeSpentDeletingCookies",
- base::Time::Now() - start_time);
- UMA_HISTOGRAM_COUNTS_1M("Cookie.Startup.NumberOfCookiesDeleted",
- db()->GetLastChangeCount());
}
+// TODO(crbug.com/1225444) Investigate including top_frame_site_key in the WHERE
+// clause.
void SQLitePersistentCookieStore::Backend::BackgroundDeleteAllInList(
const std::list<CookieOrigin>& cookies) {
DCHECK(background_task_runner()->RunsTasksInCurrentSequence());
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
index b4cecb46e98..92777f98dec 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_cookie_store_unittest.cc
@@ -4,6 +4,8 @@
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
+#include <stdint.h>
+
#include <map>
#include <memory>
#include <set>
@@ -11,6 +13,7 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/containers/span.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/location.h"
@@ -591,10 +594,10 @@ TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookiesAndFixupDb) {
std::unique_ptr<sql::Database> db(std::make_unique<sql::Database>());
ASSERT_TRUE(db->Open(store_name));
sql::Statement stmt(db->GetUniqueStatement(
- "INSERT INTO cookies (creation_utc, host_key, name, value, "
- "encrypted_value, path, expires_utc, is_secure, is_httponly, "
+ "INSERT INTO cookies (creation_utc, top_frame_site_key, host_key, name, "
+ "value, encrypted_value, path, expires_utc, is_secure, is_httponly, "
"samesite, last_access_utc, has_expires, is_persistent, priority) "
- "VALUES (?,?,?,?,'',?,0,0,0,0,0,1,1,0)"));
+ "VALUES (?,?,?,?,?,'',?,0,0,0,0,0,1,1,0)"));
ASSERT_TRUE(stmt.is_valid());
struct CookieInfo {
@@ -619,10 +622,13 @@ TEST_F(SQLitePersistentCookieStoreTest, FilterBadCookiesAndFixupDb) {
stmt.Reset(true);
stmt.BindInt64(0, creation_time++);
- stmt.BindString(1, cookie_info.domain);
- stmt.BindString(2, cookie_info.name);
- stmt.BindString(3, cookie_info.value);
- stmt.BindString(4, cookie_info.path);
+ // TODO(crbug.com/1225444) Test some non-empty values when CanonicalCookie
+ // supports partition key.
+ stmt.BindString(1, net::kEmptyCookiePartitionKey);
+ stmt.BindString(2, cookie_info.domain);
+ stmt.BindString(3, cookie_info.name);
+ stmt.BindString(4, cookie_info.value);
+ stmt.BindString(5, cookie_info.path);
ASSERT_TRUE(stmt.Run());
}
stmt.Clear();
@@ -926,6 +932,7 @@ TEST_F(SQLitePersistentCookieStoreTest, SourcePortIsPersistent) {
/*secure=*/true, false, CookieSameSite::LAX_MODE,
COOKIE_PRIORITY_DEFAULT,
/*same_party=*/false,
+ /*partition_key=*/absl::nullopt,
CookieSourceScheme::kUnset /* Doesn't matter for this test. */,
input.port));
}
@@ -1172,7 +1179,7 @@ bool AddV9CookiesToDBImpl(sql::Database* db,
statement.BindString(1, cookies[i].Domain());
statement.BindString(2, cookies[i].Name());
statement.BindString(3, cookies[i].Value());
- statement.BindBlob(4, "", 0); // encrypted_value
+ statement.BindBlob(4, base::span<uint8_t>()); // encrypted_value
statement.BindString(5, cookies[i].Path());
statement.BindInt64(
6, cookies[i].ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
@@ -1385,7 +1392,8 @@ TEST_F(SQLitePersistentCookieStoreTest, KeyInconsistency) {
GURL ftp_url("ftp://subdomain.ftperiffic.com/page/");
auto cookie =
CanonicalCookie::Create(ftp_url, "A=B; max-age=3600", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cookie_monster->SetCanonicalCookieAsync(std::move(cookie), ftp_url,
CookieOptions::MakeAllInclusive(),
set_cookie_callback.MakeCallback());
@@ -1399,7 +1407,8 @@ TEST_F(SQLitePersistentCookieStoreTest, KeyInconsistency) {
GURL url(base::StringPrintf("http://example%d.com/", i));
auto canonical_cookie =
CanonicalCookie::Create(url, "A=B; max-age=3600", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cookie_monster->SetCanonicalCookieAsync(
std::move(canonical_cookie), url, CookieOptions::MakeAllInclusive(),
set_cookie_callback2.MakeCallback());
@@ -1453,7 +1462,8 @@ TEST_F(SQLitePersistentCookieStoreTest, OpsIfInitFailed) {
GURL url("http://www.example.com/");
auto cookie =
CanonicalCookie::Create(url, "A=B; max-age=3600", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cookie_monster->SetCanonicalCookieAsync(std::move(cookie), url,
CookieOptions::MakeAllInclusive(),
set_cookie_callback.MakeCallback());
@@ -1486,7 +1496,8 @@ TEST_F(SQLitePersistentCookieStoreTest, Coalescing) {
std::unique_ptr<CanonicalCookie> cookie = CanonicalCookie::Create(
GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
for (const TestCase& testcase : testcases) {
Create(false, false, true /* want current thread to invoke the store. */);
@@ -1539,11 +1550,13 @@ TEST_F(SQLitePersistentCookieStoreTest, NoCoalesceUnrelated) {
std::unique_ptr<CanonicalCookie> cookie1 = CanonicalCookie::Create(
GURL("http://www.example.com/path"), "Tasty=Yes", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
std::unique_ptr<CanonicalCookie> cookie2 = CanonicalCookie::Create(
GURL("http://not.example.com/path"), "Tasty=No", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
// Wedge the background thread to make sure that it doesn't start consuming
// the queue.
@@ -1639,7 +1652,7 @@ bool AddV10CookiesToDBImpl(sql::Database* db,
statement.BindString(1, cookies[i].Domain());
statement.BindString(2, cookies[i].Name());
statement.BindString(3, cookies[i].Value());
- statement.BindBlob(4, "", 0); // encrypted_value
+ statement.BindBlob(4, base::span<uint8_t>()); // encrypted_value
statement.BindString(5, cookies[i].Path());
statement.BindInt64(
6, cookies[i].ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
@@ -1798,6 +1811,40 @@ bool CreateV12Schema(sql::Database* db) {
return true;
}
+bool CreateV13Schema(sql::Database* db) {
+ sql::MetaTable meta_table;
+ if (!meta_table.Init(db, /* version = */ 13,
+ /* earliest compatible version = */ 13)) {
+ return false;
+ }
+
+ // Version 13 schema
+ static constexpr char kCreateSql[] =
+ "CREATE TABLE cookies("
+ "creation_utc INTEGER NOT NULL,"
+ "host_key TEXT NOT NULL,"
+ "name TEXT NOT NULL,"
+ "value TEXT NOT NULL,"
+ "path TEXT NOT NULL,"
+ "expires_utc INTEGER NOT NULL,"
+ "is_secure INTEGER NOT NULL,"
+ "is_httponly INTEGER NOT NULL,"
+ "last_access_utc INTEGER NOT NULL,"
+ "has_expires INTEGER NOT NULL DEFAULT 1,"
+ "is_persistent INTEGER NOT NULL DEFAULT 1,"
+ "priority INTEGER NOT NULL DEFAULT 1," // COOKIE_PRIORITY_DEFAULT
+ "encrypted_value BLOB DEFAULT '',"
+ "samesite INTEGER NOT NULL DEFAULT -1," // UNSPECIFIED
+ "source_scheme INTEGER NOT NULL DEFAULT 0," // CookieSourceScheme::kUnset
+ "source_port INTEGER NOT NULL DEFAULT -1," // UNKNOWN
+ "is_same_party INTEGER NOT NULL DEFAULT 0,"
+ "UNIQUE (host_key, name, path))";
+ if (!db->Execute(kCreateSql))
+ return false;
+
+ return true;
+}
+
std::vector<CanonicalCookie> CookiesForMigrationTest() {
static base::Time now = base::Time::Now();
@@ -1854,7 +1901,7 @@ bool AddV11CookiesToDB(sql::Database* db) {
statement.BindString(1, cookies[i].Domain());
statement.BindString(2, cookies[i].Name());
statement.BindString(3, cookies[i].Value());
- statement.BindBlob(4, "", 0); // encrypted_value
+ statement.BindBlob(4, base::span<uint8_t>()); // encrypted_value
statement.BindString(5, cookies[i].Path());
statement.BindInt64(
6, cookies[i].ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
@@ -1902,7 +1949,55 @@ bool AddV12CookiesToDB(sql::Database* db) {
statement.BindString(1, cookie.Domain());
statement.BindString(2, cookie.Name());
statement.BindString(3, cookie.Value());
- statement.BindBlob(4, "", 0); // encrypted_value
+ statement.BindBlob(4, base::span<uint8_t>()); // encrypted_value
+ statement.BindString(5, cookie.Path());
+ statement.BindInt64(
+ 6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ statement.BindInt(7, cookie.IsSecure());
+ statement.BindInt(8, cookie.IsHttpOnly());
+ // Note that this, Priority(), and SourceScheme() below nominally rely on
+ // the enums in sqlite_persistent_cookie_store.cc having the same values as
+ // the ones in ../../cookies/cookie_constants.h. But nothing in this test
+ // relies on that equivalence, so it's not worth the hassle to guarantee
+ // that.
+ statement.BindInt(9, static_cast<int>(cookie.SameSite()));
+ statement.BindInt64(
+ 10,
+ cookie.LastAccessDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ statement.BindInt(11, cookie.IsPersistent());
+ statement.BindInt(12, cookie.IsPersistent());
+ statement.BindInt(13, static_cast<int>(cookie.Priority()));
+ statement.BindInt(14, static_cast<int>(cookie.SourceScheme()));
+ if (!statement.Run())
+ return false;
+ }
+ if (!transaction.Commit())
+ return false;
+
+ return true;
+}
+
+bool AddV13CookiesToDB(sql::Database* db) {
+ std::vector<CanonicalCookie> cookies = CookiesForMigrationTest();
+ sql::Statement statement(db->GetCachedStatement(
+ SQL_FROM_HERE,
+ "INSERT INTO cookies (creation_utc, host_key, name, value, "
+ "encrypted_value, path, expires_utc, is_secure, is_httponly, "
+ "samesite, last_access_utc, has_expires, is_persistent, priority, "
+ "source_scheme, source_port, is_same_party)"
+ "VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)"));
+ if (!statement.is_valid())
+ return false;
+ sql::Transaction transaction(db);
+ transaction.Begin();
+ for (const CanonicalCookie& cookie : cookies) {
+ statement.Reset(true);
+ statement.BindInt64(
+ 0, cookie.CreationDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
+ statement.BindString(1, cookie.Domain());
+ statement.BindString(2, cookie.Name());
+ statement.BindString(3, cookie.Value());
+ statement.BindBlob(4, base::span<uint8_t>()); // encrypted_value
statement.BindString(5, cookie.Path());
statement.BindInt64(
6, cookie.ExpiryDate().ToDeltaSinceWindowsEpoch().InMicroseconds());
@@ -1921,6 +2016,8 @@ bool AddV12CookiesToDB(sql::Database* db) {
statement.BindInt(12, cookie.IsPersistent());
statement.BindInt(13, static_cast<int>(cookie.Priority()));
statement.BindInt(14, static_cast<int>(cookie.SourceScheme()));
+ statement.BindInt(15, cookie.SourcePort());
+ statement.BindInt(16, cookie.IsSameParty());
if (!statement.Run())
return false;
}
@@ -1932,7 +2029,8 @@ bool AddV12CookiesToDB(sql::Database* db) {
// Confirm the cookie list passed in has the above cookies in it.
void ConfirmCookiesAfterMigrationTest(
- std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies) {
+ std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies,
+ bool expect_same_party_cookies = false) {
std::sort(read_in_cookies.begin(), read_in_cookies.end(), &CompareCookies);
int i = 0;
EXPECT_EQ("A", read_in_cookies[i]->Name());
@@ -1959,7 +2057,7 @@ void ConfirmCookiesAfterMigrationTest(
EXPECT_EQ("/", read_in_cookies[i]->Path());
EXPECT_TRUE(read_in_cookies[i]->IsSecure());
EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
- EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
+ EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty());
i++;
EXPECT_EQ("C", read_in_cookies[i]->Name());
@@ -1968,7 +2066,7 @@ void ConfirmCookiesAfterMigrationTest(
EXPECT_EQ("/", read_in_cookies[i]->Path());
EXPECT_TRUE(read_in_cookies[i]->IsSecure());
EXPECT_EQ(CookieSourceScheme::kUnset, read_in_cookies[i]->SourceScheme());
- EXPECT_FALSE(read_in_cookies[i]->IsSameParty());
+ EXPECT_EQ(expect_same_party_cookies, read_in_cookies[i]->IsSameParty());
i++;
EXPECT_EQ("C", read_in_cookies[i]->Name());
@@ -2016,4 +2114,17 @@ TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion13) {
ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies));
}
+TEST_F(SQLitePersistentCookieStoreTest, UpgradeToSchemaVersion15) {
+ // Open db
+ sql::Database connection;
+ ASSERT_TRUE(connection.Open(temp_dir_.GetPath().Append(kCookieFilename)));
+ ASSERT_TRUE(CreateV13Schema(&connection));
+ ASSERT_TRUE(AddV13CookiesToDB(&connection));
+ connection.Close();
+
+ std::vector<std::unique_ptr<CanonicalCookie>> read_in_cookies;
+ CreateAndLoad(false, false, &read_in_cookies);
+ ConfirmCookiesAfterMigrationTest(std::move(read_in_cookies), true);
+}
+
} // namespace net
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc b/chromium/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
index dbed66d5ada..da409b5f06b 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_reporting_and_nel_store_unittest.cc
@@ -306,7 +306,8 @@ TEST_F(SQLitePersistentReportingAndNelStoreTest, TestInvalidMetaTableRecovery) {
LoadNelPolicies(&policies);
ASSERT_EQ(0U, policies.size());
- hist_tester.ExpectUniqueSample("ReportingAndNEL.CorruptMetaTable", 1, 1);
+ hist_tester.ExpectUniqueSample("Net.SQLite.CorruptMetaTableRecovered", true,
+ 1);
// Verify that, after, recovery, the database persists properly.
NetworkErrorLoggingService::NelPolicy policy2 = MakeNelPolicy(
diff --git a/chromium/net/extras/sqlite/sqlite_persistent_store_backend_base.cc b/chromium/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
index b47d3d5f8d3..ab58d3ffdcc 100644
--- a/chromium/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
+++ b/chromium/net/extras/sqlite/sqlite_persistent_store_backend_base.cc
@@ -11,6 +11,7 @@
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/metrics/histogram_functions.h"
+#include "base/metrics/histogram_macros_local.h"
#include "base/sequenced_task_runner.h"
#include "base/time/time.h"
#include "sql/database.h"
@@ -191,16 +192,15 @@ bool SQLitePersistentStoreBackendBase::MigrateDatabaseSchema() {
if (!cur_version.has_value())
return false;
+ // Metatable is corrupted. Try to recover.
if (cur_version.value() < current_version_number_) {
- base::UmaHistogramCounts100(histogram_tag_ + ".CorruptMetaTable", 1);
-
meta_table_.Reset();
db_ = std::make_unique<sql::Database>();
- if (!sql::Database::Delete(path_) || !db()->Open(path_) ||
- !meta_table_.Init(db(), current_version_number_,
- compatible_version_number_)) {
- base::UmaHistogramCounts100(
- histogram_tag_ + ".CorruptMetaTableRecoveryFailed", 1);
+ bool recovered = sql::Database::Delete(path_) && db()->Open(path_) &&
+ meta_table_.Init(db(), current_version_number_,
+ compatible_version_number_);
+ LOCAL_HISTOGRAM_BOOLEAN("Net.SQLite.CorruptMetaTableRecovered", recovered);
+ if (!recovered) {
NOTREACHED() << "Unable to reset the " << histogram_tag_ << " DB.";
meta_table_.Reset();
db_.reset();
diff --git a/chromium/net/features.gni b/chromium/net/features.gni
index 25729120aaa..c35c40eb9c5 100644
--- a/chromium/net/features.gni
+++ b/chromium/net/features.gni
@@ -11,7 +11,10 @@ declare_args() {
# WebSockets and socket stream code are not used on iOS and are optional in
# cronet.
enable_websockets = !is_ios
- disable_ftp_support = is_ios || is_chromecast
+
+ # Disable FTP support.
+ # TODO(https://crbug.com/333943): Fully remove FTP code.
+ disable_ftp_support = true
# Enable Kerberos authentication. It is disabled by default on iOS, Fuchsia
# and Chromecast, at least for now. This feature needs configuration
@@ -45,4 +48,8 @@ declare_args() {
# flag. This does not include platforms where the builtin cert verifier is
# the only verifier supported.
builtin_cert_verifier_feature_supported = is_mac
+
+ # Platforms for which the builtin cert verifier can use the Chrome Root Store.
+ # See https://crbug.com/1216547 for status.
+ chrome_root_store_supported = false
}
diff --git a/chromium/net/filter/brotli_source_stream_unittest.cc b/chromium/net/filter/brotli_source_stream_unittest.cc
index d1aabc3d094..bb49912c419 100644
--- a/chromium/net/filter/brotli_source_stream_unittest.cc
+++ b/chromium/net/filter/brotli_source_stream_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/bit_cast.h"
#include "base/callback.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
diff --git a/chromium/net/filter/gzip_source_stream_unittest.cc b/chromium/net/filter/gzip_source_stream_unittest.cc
index 6b2f0dc0d5c..550ad2e2712 100644
--- a/chromium/net/filter/gzip_source_stream_unittest.cc
+++ b/chromium/net/filter/gzip_source_stream_unittest.cc
@@ -6,7 +6,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/bit_cast.h"
#include "base/callback.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
diff --git a/chromium/net/ftp/ftp_directory_listing_parser.cc b/chromium/net/ftp/ftp_directory_listing_parser.cc
index be8afe401a2..7b103320313 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser.cc
@@ -6,9 +6,9 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/i18n/encoding_detection.h"
#include "base/i18n/icu_string_conversions.h"
-#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
index 07689d59c82..d64a564b413 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_ls_unittest.cc
@@ -4,8 +4,8 @@
#include "net/ftp/ftp_directory_listing_parser_unittest.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/ftp/ftp_directory_listing_parser_ls.h"
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
index bbf5cfc36aa..b864ba34ab1 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_vms.cc
@@ -6,8 +6,8 @@
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/numerics/safe_math.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
index 315d6863dca..88deedd5e2d 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_vms_unittest.cc
@@ -4,8 +4,8 @@
#include "net/ftp/ftp_directory_listing_parser_unittest.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/net/ftp/ftp_directory_listing_parser_windows_unittest.cc b/chromium/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
index f3984708223..08b01b88f60 100644
--- a/chromium/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
+++ b/chromium/net/ftp/ftp_directory_listing_parser_windows_unittest.cc
@@ -4,8 +4,8 @@
#include "net/ftp/ftp_directory_listing_parser_unittest.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "net/ftp/ftp_directory_listing_parser_windows.h"
diff --git a/chromium/net/ftp/ftp_network_transaction.cc b/chromium/net/ftp/ftp_network_transaction.cc
index c028d31b4db..4029a996f17 100644
--- a/chromium/net/ftp/ftp_network_transaction.cc
+++ b/chromium/net/ftp/ftp_network_transaction.cc
@@ -30,6 +30,7 @@
#include "net/log/net_log_source.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/stream_socket.h"
+#include "url/scheme_host_port.h"
#include "url/url_constants.h"
namespace net {
@@ -664,7 +665,7 @@ int FtpNetworkTransaction::DoCtrlResolveHost() {
// Using an empty NetworkIsolationKey here, since FTP support is deprecated,
// and should go away soon.
resolve_request_ =
- resolver_->CreateRequest(HostPortPair::FromURL(request_->url),
+ resolver_->CreateRequest(url::SchemeHostPort(request_->url),
NetworkIsolationKey(), net_log_, absl::nullopt);
return resolve_request_->Start(base::BindOnce(
&FtpNetworkTransaction::OnIOComplete, base::Unretained(this)));
diff --git a/chromium/net/ftp/ftp_network_transaction_unittest.cc b/chromium/net/ftp/ftp_network_transaction_unittest.cc
index b090b1f2d84..fb2facdd3c6 100644
--- a/chromium/net/ftp/ftp_network_transaction_unittest.cc
+++ b/chromium/net/ftp/ftp_network_transaction_unittest.cc
@@ -12,6 +12,7 @@
#include "base/strings/utf_string_conversions.h"
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/sys_addrinfo.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
#include "net/ftp/ftp_request_info.h"
diff --git a/chromium/net/ftp/ftp_util_unittest.cc b/chromium/net/ftp/ftp_util_unittest.cc
index 8a269073209..ffeaaa541d7 100644
--- a/chromium/net/ftp/ftp_util_unittest.cc
+++ b/chromium/net/ftp/ftp_util_unittest.cc
@@ -4,8 +4,8 @@
#include "net/ftp/ftp_util.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/http/bidirectional_stream_unittest.cc b/chromium/net/http/bidirectional_stream_unittest.cc
index 819659024b0..48e31ad92ba 100644
--- a/chromium/net/http/bidirectional_stream_unittest.cc
+++ b/chromium/net/http/bidirectional_stream_unittest.cc
@@ -10,10 +10,10 @@
#include <vector>
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/time.h"
#include "base/timer/mock_timer.h"
@@ -66,7 +66,7 @@ void ExpectLoadTimingValid(const LoadTimingInfo& load_timing_info) {
EXPECT_FALSE(load_timing_info.receive_headers_end.is_null());
EXPECT_FALSE(load_timing_info.send_start.is_null());
EXPECT_FALSE(load_timing_info.send_end.is_null());
- EXPECT_TRUE(load_timing_info.request_start <
+ EXPECT_TRUE(load_timing_info.request_start <=
load_timing_info.receive_headers_end);
EXPECT_TRUE(load_timing_info.send_start <= load_timing_info.send_end);
}
diff --git a/chromium/net/http/http_auth.cc b/chromium/net/http/http_auth.cc
index 986f0330f7e..081944c902b 100644
--- a/chromium/net/http/http_auth.cc
+++ b/chromium/net/http/http_auth.cc
@@ -6,7 +6,7 @@
#include <algorithm>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/values.h"
diff --git a/chromium/net/http/http_auth_cache.cc b/chromium/net/http/http_auth_cache.cc
index 6c5f4ff2ff7..912fd547661 100644
--- a/chromium/net/http/http_auth_cache.cc
+++ b/chromium/net/http/http_auth_cache.cc
@@ -4,9 +4,9 @@
#include "net/http/http_auth_cache.h"
+#include "base/containers/cxx20_erase.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
namespace {
@@ -166,7 +166,6 @@ HttpAuthCache::Entry* HttpAuthCache::Add(
HttpAuthCache::Entry* entry =
Lookup(origin, target, realm, scheme, network_isolation_key);
if (!entry) {
- bool evicted = false;
// Failsafe to prevent unbounded memory growth of the cache.
//
// Data was collected in June of 2019, before entries were keyed on either
@@ -178,7 +177,6 @@ HttpAuthCache::Entry* HttpAuthCache::Add(
if (entries_.size() >= kMaxNumRealmEntries) {
DLOG(WARNING) << "Num auth cache entries reached limit -- evicting";
EvictLeastRecentlyUsedEntry();
- evicted = true;
}
entry = &(entries_
.emplace(std::make_pair(
@@ -244,7 +242,6 @@ void HttpAuthCache::Entry::AddPath(const std::string& path) {
// Remove any entries that have been subsumed by the new entry.
base::EraseIf(paths_, IsEnclosedBy(parent_dir));
- bool evicted = false;
// Failsafe to prevent unbounded memory growth of the cache.
//
// Data collected on June of 2019 indicate that when we get here, the list
@@ -253,7 +250,6 @@ void HttpAuthCache::Entry::AddPath(const std::string& path) {
DLOG(WARNING) << "Num path entries for " << origin()
<< " has grown too large -- evicting";
paths_.pop_back();
- evicted = true;
}
// Add new path.
diff --git a/chromium/net/http/http_auth_controller.cc b/chromium/net/http/http_auth_controller.cc
index 10d02bb9b9e..c0d92628cea 100644
--- a/chromium/net/http/http_auth_controller.cc
+++ b/chromium/net/http/http_auth_controller.cc
@@ -341,7 +341,7 @@ int HttpAuthController::HandleAuthChallenge(
// We are establishing a tunnel, we can't show the error page because an
// active network attacker could control its contents. Instead, we just
// fail to establish the tunnel.
- DCHECK(target_ == HttpAuth::AUTH_PROXY);
+ DCHECK_EQ(target_, HttpAuth::AUTH_PROXY);
net_log_.EndEventWithNetErrorCode(
NetLogEventType::AUTH_HANDLE_CHALLENGE, ERR_PROXY_AUTH_UNSUPPORTED);
return ERR_PROXY_AUTH_UNSUPPORTED;
diff --git a/chromium/net/http/http_auth_filter_unittest.cc b/chromium/net/http/http_auth_filter_unittest.cc
index 17f93542ff7..e009a63c414 100644
--- a/chromium/net/http/http_auth_filter_unittest.cc
+++ b/chromium/net/http/http_auth_filter_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include <ostream>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
diff --git a/chromium/net/http/http_auth_gssapi_posix.cc b/chromium/net/http/http_auth_gssapi_posix.cc
index ddc3da51117..8c3defbfda5 100644
--- a/chromium/net/http/http_auth_gssapi_posix.cc
+++ b/chromium/net/http/http_auth_gssapi_posix.cc
@@ -9,10 +9,10 @@
#include "base/base64.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/http/http_auth_gssapi_posix_unittest.cc b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
index ac76434af06..d39d5bfddf8 100644
--- a/chromium/net/http/http_auth_gssapi_posix_unittest.cc
+++ b/chromium/net/http/http_auth_gssapi_posix_unittest.cc
@@ -9,10 +9,10 @@
#include "base/base_paths.h"
#include "base/bind.h"
#include "base/check.h"
+#include "base/cxx17_backports.h"
#include "base/json/json_reader.h"
#include "base/native_library.h"
#include "base/path_service.h"
-#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth_challenge_tokenizer.h"
#include "net/http/mock_gssapi_library_posix.h"
diff --git a/chromium/net/http/http_auth_handler_basic_unittest.cc b/chromium/net/http/http_auth_handler_basic_unittest.cc
index 8e391d1514b..1c05b814607 100644
--- a/chromium/net/http/http_auth_handler_basic_unittest.cc
+++ b/chromium/net/http/http_auth_handler_basic_unittest.cc
@@ -7,7 +7,7 @@
#include <memory>
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/http/http_auth_handler_digest_unittest.cc b/chromium/net/http/http_auth_handler_digest_unittest.cc
index 26fba7593e0..6cfdf1c2172 100644
--- a/chromium/net/http/http_auth_handler_digest_unittest.cc
+++ b/chromium/net/http/http_auth_handler_digest_unittest.cc
@@ -4,7 +4,7 @@
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/http/http_auth_handler_factory.cc b/chromium/net/http/http_auth_handler_factory.cc
index 4617186a22a..516066c16e0 100644
--- a/chromium/net/http/http_auth_handler_factory.cc
+++ b/chromium/net/http/http_auth_handler_factory.cc
@@ -29,14 +29,20 @@
namespace {
-base::Value NetLogParamsForCreateAuth(const std::string& scheme,
- const std::string& challenge,
- const int net_error,
- net::NetLogCaptureMode capture_mode) {
+base::Value NetLogParamsForCreateAuth(
+ const std::string& scheme,
+ const std::string& challenge,
+ const int net_error,
+ const GURL& origin,
+ const absl::optional<bool>& allows_default_credentials,
+ net::NetLogCaptureMode capture_mode) {
base::Value dict(base::Value::Type::DICTIONARY);
dict.SetKey("scheme", net::NetLogStringValue(scheme));
if (net::NetLogCaptureIncludesSensitive(capture_mode))
dict.SetKey("challenge", net::NetLogStringValue(challenge));
+ dict.SetStringKey("origin", origin.spec());
+ if (allows_default_credentials)
+ dict.SetBoolKey("allows_default_credentials", *allows_default_credentials);
if (net_error < 0)
dict.SetIntKey("net_error", net_error);
return dict;
@@ -246,7 +252,10 @@ int HttpAuthHandlerRegistryFactory::CreateAuthHandler(
net_log.AddEvent(NetLogEventType::AUTH_HANDLER_CREATE_RESULT,
[&](NetLogCaptureMode capture_mode) {
return NetLogParamsForCreateAuth(
- scheme, challenge->challenge_text(), net_error,
+ scheme, challenge->challenge_text(), net_error, origin,
+ *handler ? absl::make_optional(
+ (*handler)->AllowsDefaultCredentials())
+ : absl::nullopt,
capture_mode);
});
return net_error;
diff --git a/chromium/net/http/http_auth_handler_negotiate_unittest.cc b/chromium/net/http/http_auth_handler_negotiate_unittest.cc
index 6eb2dc6b31b..626bbf720a4 100644
--- a/chromium/net/http/http_auth_handler_negotiate_unittest.cc
+++ b/chromium/net/http/http_auth_handler_negotiate_unittest.cc
@@ -8,8 +8,8 @@
#include <string>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
diff --git a/chromium/net/http/http_auth_handler_ntlm.h b/chromium/net/http/http_auth_handler_ntlm.h
index 653a5baff6a..ab83e618710 100644
--- a/chromium/net/http/http_auth_handler_ntlm.h
+++ b/chromium/net/http/http_auth_handler_ntlm.h
@@ -28,7 +28,6 @@
#include <string>
#include <vector>
-#include "base/containers/span.h"
#include "base/macros.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/http/http_auth_handler_ntlm_portable_unittest.cc b/chromium/net/http/http_auth_handler_ntlm_portable_unittest.cc
index 005df5dd514..e6cf4bb0dce 100644
--- a/chromium/net/http/http_auth_handler_ntlm_portable_unittest.cc
+++ b/chromium/net/http/http_auth_handler_ntlm_portable_unittest.cc
@@ -7,7 +7,7 @@
#include "base/base64.h"
#include "base/containers/span.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/http/http_auth_preferences.cc b/chromium/net/http/http_auth_preferences.cc
index f7c9cb5d607..64fdf4ae5e2 100644
--- a/chromium/net/http/http_auth_preferences.cc
+++ b/chromium/net/http/http_auth_preferences.cc
@@ -6,7 +6,6 @@
#include <utility>
-#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
diff --git a/chromium/net/http/http_auth_unittest.cc b/chromium/net/http/http_auth_unittest.cc
index 059385e9a6a..06f2295a54d 100644
--- a/chromium/net/http/http_auth_unittest.cc
+++ b/chromium/net/http/http_auth_unittest.cc
@@ -8,8 +8,8 @@
#include <set>
#include <string>
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/http/http_basic_state.cc b/chromium/net/http/http_basic_state.cc
index a836a4f70ab..eace6fe5168 100644
--- a/chromium/net/http/http_basic_state.cc
+++ b/chromium/net/http/http_basic_state.cc
@@ -7,8 +7,8 @@
#include <utility>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/no_destructor.h"
-#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_body_drainer.h"
diff --git a/chromium/net/http/http_basic_state.h b/chromium/net/http/http_basic_state.h
index 5fd1ee514ca..06c46df6be8 100644
--- a/chromium/net/http/http_basic_state.h
+++ b/chromium/net/http/http_basic_state.h
@@ -10,6 +10,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/net/http/http_basic_stream.h b/chromium/net/http/http_basic_stream.h
index e50f6baa27d..eeea6749ded 100644
--- a/chromium/net/http/http_basic_stream.h
+++ b/chromium/net/http/http_basic_stream.h
@@ -13,6 +13,7 @@
#include <memory>
#include <string>
+#include <vector>
#include "base/macros.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/net/http/http_byte_range_unittest.cc b/chromium/net/http/http_byte_range_unittest.cc
index 4188bee5b05..10fc28d4c93 100644
--- a/chromium/net/http/http_byte_range_unittest.cc
+++ b/chromium/net/http/http_byte_range_unittest.cc
@@ -3,7 +3,7 @@
// found in the LICENSE file.
#include "net/http/http_byte_range.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace net {
diff --git a/chromium/net/http/http_cache.cc b/chromium/net/http/http_cache.cc
index 7aef8c20480..093510bf793 100644
--- a/chromium/net/http/http_cache.cc
+++ b/chromium/net/http/http_cache.cc
@@ -37,6 +37,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/upload_data_stream.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_cache_lookup_manager.h"
diff --git a/chromium/net/http/http_cache.h b/chromium/net/http/http_cache.h
index 4cccbc17404..ab76ecd0fd4 100644
--- a/chromium/net/http/http_cache.h
+++ b/chromium/net/http/http_cache.h
@@ -19,9 +19,9 @@
#include <memory>
#include <string>
#include <unordered_map>
+#include <unordered_set>
#include "base/files/file_path.h"
-#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/threading/thread_checker.h"
#include "base/time/clock.h"
@@ -29,9 +29,9 @@
#include "net/base/cache_type.h"
#include "net/base/completion_once_callback.h"
#include "net/base/load_states.h"
+#include "net/base/net_errors.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
-#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
class GURL;
@@ -57,6 +57,7 @@ namespace net {
class HttpNetworkSession;
class HttpResponseInfo;
class NetLog;
+class NetworkIsolationKey;
struct HttpRequestInfo;
class NET_EXPORT HttpCache : public HttpTransactionFactory {
@@ -184,6 +185,9 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory {
std::unique_ptr<BackendFactory> backend_factory,
bool is_main_cache);
+ HttpCache(const HttpCache&) = delete;
+ HttpCache& operator=(const HttpCache&) = delete;
+
~HttpCache() override;
HttpTransactionFactory* network_layer() { return network_layer_.get(); }
@@ -679,8 +683,6 @@ class NET_EXPORT HttpCache : public HttpTransactionFactory {
THREAD_CHECKER(thread_checker_);
base::WeakPtrFactory<HttpCache> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(HttpCache);
};
} // namespace net
diff --git a/chromium/net/http/http_cache_lookup_manager.cc b/chromium/net/http/http_cache_lookup_manager.cc
index c0ebc274db0..3f71c650c1b 100644
--- a/chromium/net/http/http_cache_lookup_manager.cc
+++ b/chromium/net/http/http_cache_lookup_manager.cc
@@ -10,6 +10,7 @@
#include "base/containers/contains.h"
#include "base/values.h"
#include "net/base/load_flags.h"
+#include "net/http/http_request_info.h"
namespace net {
diff --git a/chromium/net/http/http_cache_lookup_manager.h b/chromium/net/http/http_cache_lookup_manager.h
index d7ece6785d7..948386db946 100644
--- a/chromium/net/http/http_cache_lookup_manager.h
+++ b/chromium/net/http/http_cache_lookup_manager.h
@@ -12,6 +12,8 @@
namespace net {
+struct HttpRequestInfo;
+
// An implementation of ServerPushDelegate that issues an HttpCache::Transaction
// to lookup whether the response to the pushed URL is cached and cancel the
// push in that case.
diff --git a/chromium/net/http/http_cache_transaction.cc b/chromium/net/http/http_cache_transaction.cc
index 64691b3045f..e23f3b0ab7b 100644
--- a/chromium/net/http/http_cache_transaction.cc
+++ b/chromium/net/http/http_cache_transaction.cc
@@ -19,13 +19,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/power_monitor/power_monitor.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h" // For HexEncode.
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h" // For LowerCaseEqualsASCII.
diff --git a/chromium/net/http/http_cache_unittest.cc b/chromium/net/http/http_cache_unittest.cc
index 295694e390f..1151e744d69 100644
--- a/chromium/net/http/http_cache_unittest.cc
+++ b/chromium/net/http/http_cache_unittest.cc
@@ -13,12 +13,12 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/containers/cxx20_erase.h"
#include "base/files/scoped_temp_dir.h"
#include "base/format_macros.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/http/http_cache_writers.h b/chromium/net/http/http_cache_writers.h
index b0dd098d236..e77e98c47c9 100644
--- a/chromium/net/http/http_cache_writers.h
+++ b/chromium/net/http/http_cache_writers.h
@@ -12,10 +12,12 @@
#include "base/memory/weak_ptr.h"
#include "net/base/completion_once_callback.h"
#include "net/http/http_cache.h"
+#include "net/http/http_response_info.h"
namespace net {
class HttpResponseInfo;
+class IOBuffer;
class PartialData;
// If multiple HttpCache::Transactions are accessing the same cache entry
diff --git a/chromium/net/http/http_chunked_decoder_unittest.cc b/chromium/net/http/http_chunked_decoder_unittest.cc
index 246512d67bf..533e11b6e44 100644
--- a/chromium/net/http/http_chunked_decoder_unittest.cc
+++ b/chromium/net/http/http_chunked_decoder_unittest.cc
@@ -8,8 +8,8 @@
#include <string>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "net/base/net_errors.h"
#include "net/test/gtest_util.h"
diff --git a/chromium/net/http/http_content_disposition_unittest.cc b/chromium/net/http/http_content_disposition_unittest.cc
index fd31df37744..104cbba59a1 100644
--- a/chromium/net/http/http_content_disposition_unittest.cc
+++ b/chromium/net/http/http_content_disposition_unittest.cc
@@ -4,7 +4,7 @@
#include "net/http/http_content_disposition.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/http/http_network_layer.h b/chromium/net/http/http_network_layer.h
index 51223d98684..49ec224753f 100644
--- a/chromium/net/http/http_network_layer.h
+++ b/chromium/net/http/http_network_layer.h
@@ -6,7 +6,6 @@
#define NET_HTTP_HTTP_NETWORK_LAYER_H_
#include <memory>
-#include <string>
#include "base/compiler_specific.h"
#include "base/macros.h"
diff --git a/chromium/net/http/http_network_layer_unittest.cc b/chromium/net/http/http_network_layer_unittest.cc
index 648e8397edc..d7d54b70e38 100644
--- a/chromium/net/http/http_network_layer_unittest.cc
+++ b/chromium/net/http/http_network_layer_unittest.cc
@@ -50,7 +50,7 @@ class HttpNetworkLayerTest : public PlatformTest, public WithTaskEnvironment {
cert_verifier_ = std::make_unique<MockCertVerifier>();
transport_security_state_ = std::make_unique<TransportSecurityState>();
proxy_resolution_service_ = std::move(proxy_resolution_service);
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.client_socket_factory = &mock_socket_factory_;
session_context.host_resolver = &host_resolver_;
session_context.cert_verifier = cert_verifier_.get();
@@ -61,7 +61,7 @@ class HttpNetworkLayerTest : public PlatformTest, public WithTaskEnvironment {
session_context.http_server_properties = &http_server_properties_;
session_context.quic_context = &quic_context_;
network_session_ = std::make_unique<HttpNetworkSession>(
- HttpNetworkSession::Params(), session_context);
+ HttpNetworkSessionParams(), session_context);
factory_ = std::make_unique<HttpNetworkLayer>(network_session_.get());
}
diff --git a/chromium/net/http/http_network_session.cc b/chromium/net/http/http_network_session.cc
index 4e542af9dc5..ecf57095588 100644
--- a/chromium/net/http/http_network_session.cc
+++ b/chromium/net/http/http_network_session.cc
@@ -79,7 +79,7 @@ spdy::SettingsMap AddDefaultHttp2Settings(spdy::SettingsMap http2_settings) {
} // unnamed namespace
-HttpNetworkSession::Params::Params()
+HttpNetworkSessionParams::HttpNetworkSessionParams()
: enable_server_push_cancellation(false),
ignore_certificate_errors(false),
testing_fixed_http_port(0),
@@ -102,11 +102,12 @@ HttpNetworkSession::Params::Params()
base::FeatureList::IsEnabled(features::kEnableTLS13EarlyData);
}
-HttpNetworkSession::Params::Params(const Params& other) = default;
+HttpNetworkSessionParams::HttpNetworkSessionParams(
+ const HttpNetworkSessionParams& other) = default;
-HttpNetworkSession::Params::~Params() = default;
+HttpNetworkSessionParams::~HttpNetworkSessionParams() = default;
-HttpNetworkSession::Context::Context()
+HttpNetworkSessionContext::HttpNetworkSessionContext()
: client_socket_factory(nullptr),
host_resolver(nullptr),
cert_verifier(nullptr),
@@ -130,13 +131,14 @@ HttpNetworkSession::Context::Context()
QuicCryptoClientStreamFactory::GetDefaultFactory()) {
}
-HttpNetworkSession::Context::Context(const Context& other) = default;
+HttpNetworkSessionContext::HttpNetworkSessionContext(
+ const HttpNetworkSessionContext& other) = default;
-HttpNetworkSession::Context::~Context() = default;
+HttpNetworkSessionContext::~HttpNetworkSessionContext() = default;
// TODO(mbelshe): Move the socket factories into HttpStreamFactory.
-HttpNetworkSession::HttpNetworkSession(const Params& params,
- const Context& context)
+HttpNetworkSession::HttpNetworkSession(const HttpNetworkSessionParams& params,
+ const HttpNetworkSessionContext& context)
: net_log_(context.net_log),
http_server_properties_(context.http_server_properties),
cert_verifier_(context.cert_verifier),
diff --git a/chromium/net/http/http_network_session.h b/chromium/net/http/http_network_session.h
index 0329622f9ab..f2289256cee 100644
--- a/chromium/net/http/http_network_session.h
+++ b/chromium/net/http/http_network_session.h
@@ -83,106 +83,103 @@ const uint32_t kSpdyMaxHeaderListSize = 256 * 1024;
// Specifies the maximum concurrent streams server could send (via push).
const uint32_t kSpdyMaxConcurrentPushedStreams = 1000;
-// This class holds session objects used by HttpNetworkTransaction objects.
-class NET_EXPORT HttpNetworkSession {
- public:
// Self-contained structure with all the simple configuration options
// supported by the HttpNetworkSession.
- struct NET_EXPORT Params {
- Params();
- Params(const Params& other);
- ~Params();
-
- bool enable_server_push_cancellation;
- HostMappingRules host_mapping_rules;
- bool ignore_certificate_errors;
- uint16_t testing_fixed_http_port;
- uint16_t testing_fixed_https_port;
- bool enable_user_alternate_protocol_ports;
-
- // Use SPDY ping frames to test for connection health after idle.
- bool enable_spdy_ping_based_connection_checking;
- bool enable_http2;
- size_t spdy_session_max_recv_window_size;
- // Maximum number of capped frames that can be queued at any time.
- int spdy_session_max_queued_capped_frames;
- // HTTP/2 connection settings.
- // Unknown settings will still be sent to the server.
- // Might contain unknown setting identifiers from a predefined set that
- // servers are supposed to ignore, see
- // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00.
- // The same setting will be sent on every connection to prevent the retry
- // logic from hiding broken servers.
- spdy::SettingsMap http2_settings;
- // If set, an HTTP/2 frame with a reserved frame type will be sent after
- // every HTTP/2 SETTINGS frame and before every HTTP/2 DATA frame.
- // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00.
- // The same frame will be sent out on all connections to prevent the retry
- // logic from hiding broken servers.
- absl::optional<SpdySessionPool::GreasedHttp2Frame> greased_http2_frame;
- // If set, the HEADERS frame carrying a request without body will not have
- // the END_STREAM flag set. The stream will be closed by a subsequent empty
- // DATA frame with END_STREAM. Does not affect bidirectional or proxy
- // streams.
- // If unset, the HEADERS frame will have the END_STREAM flag set on.
- // This is useful in conjuction with |greased_http2_frame| so that a frame
- // of reserved type can be sent out even on requests without a body.
- bool http2_end_stream_with_data_frame;
- // Source of time for SPDY connections.
- SpdySessionPool::TimeFunc time_func;
- // Whether to enable HTTP/2 Alt-Svc entries.
- bool enable_http2_alternative_service;
- // Whether to enable Websocket over HTTP/2.
- bool enable_websocket_over_http2;
-
- // Enables 0-RTT support.
- bool enable_early_data;
-
- // Enables QUIC support.
- bool enable_quic;
-
- // If true, HTTPS URLs can be sent to QUIC proxies.
- bool enable_quic_proxies_for_https_urls;
-
- // If non-empty, QUIC will only be spoken to hosts in this list.
- base::flat_set<std::string> quic_host_allowlist;
-
- // If true, idle sockets won't be closed when memory pressure happens.
- bool disable_idle_sockets_close_on_memory_pressure;
-
- bool key_auth_cache_server_entries_by_network_isolation_key;
-
- // If true, enable sending PRIORITY_UPDATE frames until SETTINGS frame
- // arrives. After SETTINGS frame arrives, do not send PRIORITY_UPDATE
- // frames any longer if SETTINGS_DEPRECATE_HTTP2_PRIORITIES is missing or
- // has zero 0, but continue and also stop sending HTTP/2-style priority
- // information in HEADERS frames and PRIORITY frames if it has value 1.
- bool enable_priority_update;
- };
+struct NET_EXPORT HttpNetworkSessionParams {
+ HttpNetworkSessionParams();
+ HttpNetworkSessionParams(const HttpNetworkSessionParams& other);
+ ~HttpNetworkSessionParams();
+
+ bool enable_server_push_cancellation;
+ HostMappingRules host_mapping_rules;
+ bool ignore_certificate_errors;
+ uint16_t testing_fixed_http_port;
+ uint16_t testing_fixed_https_port;
+ bool enable_user_alternate_protocol_ports;
+
+ // Use SPDY ping frames to test for connection health after idle.
+ bool enable_spdy_ping_based_connection_checking;
+ bool enable_http2;
+ size_t spdy_session_max_recv_window_size;
+ // Maximum number of capped frames that can be queued at any time.
+ int spdy_session_max_queued_capped_frames;
+ // HTTP/2 connection settings.
+ // Unknown settings will still be sent to the server.
+ // Might contain unknown setting identifiers from a predefined set that
+ // servers are supposed to ignore, see
+ // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00.
+ // The same setting will be sent on every connection to prevent the retry
+ // logic from hiding broken servers.
+ spdy::SettingsMap http2_settings;
+ // If set, an HTTP/2 frame with a reserved frame type will be sent after
+ // every HTTP/2 SETTINGS frame and before every HTTP/2 DATA frame.
+ // https://tools.ietf.org/html/draft-bishop-httpbis-grease-00.
+ // The same frame will be sent out on all connections to prevent the retry
+ // logic from hiding broken servers.
+ absl::optional<SpdySessionPool::GreasedHttp2Frame> greased_http2_frame;
+ // If set, the HEADERS frame carrying a request without body will not have
+ // the END_STREAM flag set. The stream will be closed by a subsequent empty
+ // DATA frame with END_STREAM. Does not affect bidirectional or proxy
+ // streams.
+ // If unset, the HEADERS frame will have the END_STREAM flag set on.
+ // This is useful in conjunction with |greased_http2_frame| so that a frame
+ // of reserved type can be sent out even on requests without a body.
+ bool http2_end_stream_with_data_frame;
+ // Source of time for SPDY connections.
+ SpdySessionPool::TimeFunc time_func;
+ // Whether to enable HTTP/2 Alt-Svc entries.
+ bool enable_http2_alternative_service;
+ // Whether to enable Websocket over HTTP/2.
+ bool enable_websocket_over_http2;
+
+ // Enables 0-RTT support.
+ bool enable_early_data;
+
+ // Enables QUIC support.
+ bool enable_quic;
+
+ // If true, HTTPS URLs can be sent to QUIC proxies.
+ bool enable_quic_proxies_for_https_urls;
+
+ // If non-empty, QUIC will only be spoken to hosts in this list.
+ base::flat_set<std::string> quic_host_allowlist;
+
+ // If true, idle sockets won't be closed when memory pressure happens.
+ bool disable_idle_sockets_close_on_memory_pressure;
+
+ bool key_auth_cache_server_entries_by_network_isolation_key;
+
+ // If true, enable sending PRIORITY_UPDATE frames until SETTINGS frame
+ // arrives. After SETTINGS frame arrives, do not send PRIORITY_UPDATE
+ // frames any longer if SETTINGS_DEPRECATE_HTTP2_PRIORITIES is missing or
+ // has zero 0, but continue and also stop sending HTTP/2-style priority
+ // information in HEADERS frames and PRIORITY frames if it has value 1.
+ bool enable_priority_update;
+};
// Structure with pointers to the dependencies of the HttpNetworkSession.
// These objects must all outlive the HttpNetworkSession.
- struct NET_EXPORT Context {
- Context();
- Context(const Context& other);
- ~Context();
-
- ClientSocketFactory* client_socket_factory;
- HostResolver* host_resolver;
- CertVerifier* cert_verifier;
- TransportSecurityState* transport_security_state;
- CTPolicyEnforcer* ct_policy_enforcer;
- SCTAuditingDelegate* sct_auditing_delegate;
- ProxyResolutionService* proxy_resolution_service;
- ProxyDelegate* proxy_delegate;
- const HttpUserAgentSettings* http_user_agent_settings;
- SSLConfigService* ssl_config_service;
- HttpAuthHandlerFactory* http_auth_handler_factory;
- HttpServerProperties* http_server_properties;
- NetLog* net_log;
- SocketPerformanceWatcherFactory* socket_performance_watcher_factory;
- NetworkQualityEstimator* network_quality_estimator;
- QuicContext* quic_context;
+struct NET_EXPORT HttpNetworkSessionContext {
+ HttpNetworkSessionContext();
+ HttpNetworkSessionContext(const HttpNetworkSessionContext& other);
+ ~HttpNetworkSessionContext();
+
+ ClientSocketFactory* client_socket_factory;
+ HostResolver* host_resolver;
+ CertVerifier* cert_verifier;
+ TransportSecurityState* transport_security_state;
+ CTPolicyEnforcer* ct_policy_enforcer;
+ SCTAuditingDelegate* sct_auditing_delegate;
+ ProxyResolutionService* proxy_resolution_service;
+ ProxyDelegate* proxy_delegate;
+ const HttpUserAgentSettings* http_user_agent_settings;
+ SSLConfigService* ssl_config_service;
+ HttpAuthHandlerFactory* http_auth_handler_factory;
+ HttpServerProperties* http_server_properties;
+ NetLog* net_log;
+ SocketPerformanceWatcherFactory* socket_performance_watcher_factory;
+ NetworkQualityEstimator* network_quality_estimator;
+ QuicContext* quic_context;
#if BUILDFLAG(ENABLE_REPORTING)
ReportingService* reporting_service;
NetworkErrorLoggingService* network_error_logging_service;
@@ -190,15 +187,19 @@ class NET_EXPORT HttpNetworkSession {
// Optional factory to use for creating QuicCryptoClientStreams.
QuicCryptoClientStreamFactory* quic_crypto_client_stream_factory;
- };
+};
+// This class holds session objects used by HttpNetworkTransaction objects.
+class NET_EXPORT HttpNetworkSession {
+ public:
enum SocketPoolType {
NORMAL_SOCKET_POOL,
WEBSOCKET_SOCKET_POOL,
NUM_SOCKET_POOL_TYPES
};
- HttpNetworkSession(const Params& params, const Context& context);
+ HttpNetworkSession(const HttpNetworkSessionParams& params,
+ const HttpNetworkSessionContext& context);
~HttpNetworkSession();
HttpAuthCache* http_auth_cache() { return &http_auth_cache_; }
@@ -259,9 +260,9 @@ class NET_EXPORT HttpNetworkSession {
void CloseIdleConnections(const char* net_log_reason_utf8);
// Returns the original Params used to construct this session.
- const Params& params() const { return params_; }
+ const HttpNetworkSessionParams& params() const { return params_; }
// Returns the original Context used to construct this session.
- const Context& context() const { return context_; }
+ const HttpNetworkSessionContext& context() const { return context_; }
void SetServerPushDelegate(std::unique_ptr<ServerPushDelegate> push_delegate);
@@ -335,8 +336,8 @@ class NET_EXPORT HttpNetworkSession {
NextProtoVector next_protos_;
SSLConfig::ApplicationSettings application_settings_;
- Params params_;
- Context context_;
+ HttpNetworkSessionParams params_;
+ HttpNetworkSessionContext context_;
std::unique_ptr<base::MemoryPressureListener> memory_pressure_listener_;
diff --git a/chromium/net/http/http_network_session_peer.cc b/chromium/net/http/http_network_session_peer.cc
index c9440d65df8..547596adba0 100644
--- a/chromium/net/http/http_network_session_peer.cc
+++ b/chromium/net/http/http_network_session_peer.cc
@@ -4,6 +4,7 @@
#include "net/http/http_network_session_peer.h"
+#include "net/http/http_network_session.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/transport_client_socket_pool.h"
@@ -25,7 +26,7 @@ void HttpNetworkSessionPeer::SetHttpStreamFactory(
session_->http_stream_factory_.swap(http_stream_factory);
}
-HttpNetworkSession::Params* HttpNetworkSessionPeer::params() {
+HttpNetworkSessionParams* HttpNetworkSessionPeer::params() {
return &(session_->params_);
}
diff --git a/chromium/net/http/http_network_session_peer.h b/chromium/net/http/http_network_session_peer.h
index b173f5de684..f70223fb263 100644
--- a/chromium/net/http/http_network_session_peer.h
+++ b/chromium/net/http/http_network_session_peer.h
@@ -10,12 +10,13 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
-#include "net/http/http_network_session.h"
namespace net {
class ClientSocketPoolManager;
class HttpStreamFactory;
+class HttpNetworkSession;
+struct HttpNetworkSessionParams;
class NET_EXPORT_PRIVATE HttpNetworkSessionPeer {
public:
@@ -29,7 +30,7 @@ class NET_EXPORT_PRIVATE HttpNetworkSessionPeer {
void SetHttpStreamFactory(
std::unique_ptr<HttpStreamFactory> http_stream_factory);
- HttpNetworkSession::Params* params();
+ HttpNetworkSessionParams* params();
private:
HttpNetworkSession* const session_;
diff --git a/chromium/net/http/http_network_transaction.cc b/chromium/net/http/http_network_transaction.cc
index af5aca2a2d5..47cb01bfa08 100644
--- a/chromium/net/http/http_network_transaction.cc
+++ b/chromium/net/http/http_network_transaction.cc
@@ -18,7 +18,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/sparse_histogram.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/time/time.h"
@@ -1244,13 +1243,14 @@ int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
return rv;
#if BUILDFLAG(ENABLE_REPORTING)
+ // Note: This just handles the legacy Report-To header, which is still
+ // required for NEL. The newer Reporting-Endpoints header is processed in
+ // network::PopulateParsedHeaders().
+ ProcessReportToHeader();
+
// Note: Unless there is a pre-existing NEL policy for this origin, any NEL
// reports generated before the NEL header is processed here will just be
// dropped by the NetworkErrorLoggingService.
- ProcessReportToHeader();
- if (base::FeatureList::IsEnabled(net::features::kDocumentReporting)) {
- ProcessReportingEndpointsHeader();
- }
ProcessNetworkErrorLoggingHeader();
// Generate NEL report here if we have to report an HTTP error (4xx or 5xx
@@ -1383,26 +1383,6 @@ int HttpNetworkTransaction::DoDrainBodyForAuthRestartComplete(int result) {
}
#if BUILDFLAG(ENABLE_REPORTING)
-void HttpNetworkTransaction::ProcessReportingEndpointsHeader() {
- std::string value;
- if (!response_.headers->GetNormalizedHeader("Reporting-Endpoints", &value))
- return;
-
- ReportingService* service = session_->reporting_service();
- if (!service)
- return;
-
- // Only accept Reporting-Endpoints headers on HTTPS connections that have no
- // certificate errors.
- if (!response_.ssl_info.is_valid())
- return;
- if (IsCertStatusError(response_.ssl_info.cert_status))
- return;
-
- service->ProcessReportingEndpointsHeader(url::Origin::Create(url_),
- network_isolation_key_, value);
-}
-
void HttpNetworkTransaction::ProcessReportToHeader() {
std::string value;
if (!response_.headers->GetNormalizedHeader("Report-To", &value))
diff --git a/chromium/net/http/http_network_transaction_unittest.cc b/chromium/net/http/http_network_transaction_unittest.cc
index 34289b75ea5..82bd8046029 100644
--- a/chromium/net/http/http_network_transaction_unittest.cc
+++ b/chromium/net/http/http_network_transaction_unittest.cc
@@ -17,6 +17,7 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
@@ -24,7 +25,6 @@
#include "base/memory/ptr_util.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -123,6 +123,8 @@
#include "testing/platform_test.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
#if defined(NTLM_PORTABLE)
#include "base/base64.h"
@@ -12663,21 +12665,19 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
{
"", // unused
"http://www.example.org/direct",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
- ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
false,
},
{
"", // unused
"http://[2001:1418:13:1::25]/direct",
- ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 80),
- ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpScheme, "[2001:1418:13:1::25]", 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
false,
},
@@ -12685,31 +12685,30 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForDirectConnections) {
{
"", // unused
"https://www.example.org/direct_ssl",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
{
"", // unused
"https://[2001:1418:13:1::25]/direct",
- ClientSocketPool::GroupId(HostPortPair("2001:1418:13:1::25", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "[2001:1418:13:1::25]",
+ 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
{
"", // unused
"https://host.with.alternate/direct",
- ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
+ 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
};
@@ -12742,11 +12741,10 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
{
"http_proxy",
"http://www.example.org/http_proxy_normal",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
- ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
false,
},
@@ -12754,22 +12752,21 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForHTTPProxyConnections) {
{
"http_proxy",
"https://www.example.org/http_connect_ssl",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
{
"http_proxy",
"https://host.with.alternate/direct",
- ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
+ 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
};
@@ -12804,21 +12801,19 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
{
"socks4://socks_proxy:1080",
"http://www.example.org/socks4_direct",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
- ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
false,
},
{
"socks5://socks_proxy:1080",
"http://www.example.org/socks5_direct",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 80),
- ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpScheme, "www.example.org", 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
false,
},
@@ -12826,32 +12821,30 @@ TEST_F(HttpNetworkTransactionTest, GroupIdForSOCKSConnections) {
{
"socks4://socks_proxy:1080",
"https://www.example.org/socks4_ssl",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
{
"socks5://socks_proxy:1080",
"https://www.example.org/socks5_ssl",
- ClientSocketPool::GroupId(HostPortPair("www.example.org", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
{
"socks4://socks_proxy:1080",
"https://host.with.alternate/direct",
- ClientSocketPool::GroupId(HostPortPair("host.with.alternate", 443),
- ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED,
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ ClientSocketPool::GroupId(
+ url::SchemeHostPort(url::kHttpsScheme, "host.with.alternate",
+ 443),
+ PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow),
true,
},
};
@@ -16033,7 +16026,7 @@ TEST_F(HttpNetworkTransactionTest, MultiRoundAuth) {
session_deps_.socket_factory->AddSocketDataProvider(&data_provider);
const ClientSocketPool::GroupId kSocketGroup(
- HostPortPair("www.example.com", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "www.example.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
@@ -19952,7 +19945,7 @@ class HttpNetworkTransactionReportingTest
}
// Makes an HTTPS request that should install a valid Reporting policy
- // using either Report-To header or Reporting-Endpoints header.
+ // using Report-To header.
void RequestPolicy(CertStatus cert_status = 0) {
HttpRequestInfo request;
request.method = "GET";
@@ -19968,15 +19961,10 @@ class HttpNetworkTransactionReportingTest
};
MockRead reporting_header;
- if (UseDocumentReporting()) {
- reporting_header = MockRead(
- "Reporting-Endpoints: nel=\"https://www.example.org/upload/\"\r\n");
- } else {
- reporting_header = MockRead(
- "Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
- "\"endpoints\": [{\"url\": "
- "\"https://www.example.org/upload/\"}]}\r\n");
- }
+ reporting_header = MockRead(
+ "Report-To: {\"group\": \"nel\", \"max_age\": 86400, "
+ "\"endpoints\": [{\"url\": "
+ "\"https://www.example.org/upload/\"}]}\r\n");
MockRead data_reads[] = {
MockRead("HTTP/1.0 200 OK\r\n"),
std::move(reporting_header),
diff --git a/chromium/net/http/http_proxy_connect_job.cc b/chromium/net/http/http_proxy_connect_job.cc
index 1cca4aed86c..a2596b76066 100644
--- a/chromium/net/http/http_proxy_connect_job.cc
+++ b/chromium/net/http/http_proxy_connect_job.cc
@@ -4,20 +4,21 @@
#include "net/http/http_proxy_connect_job.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
-#include "base/numerics/ranges.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "net/base/host_port_pair.h"
#include "net/base/http_user_agent_settings.h"
#include "net/base/net_errors.h"
#include "net/log/net_log_source_type.h"
@@ -38,7 +39,9 @@
#include "net/spdy/spdy_stream.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -122,9 +125,8 @@ class HttpProxyTimeoutExperiments {
};
HttpProxyTimeoutExperiments* GetProxyTimeoutExperiments() {
- static base::NoDestructor<HttpProxyTimeoutExperiments>
- proxy_timeout_experiments;
- return proxy_timeout_experiments.get();
+ static HttpProxyTimeoutExperiments proxy_timeout_experiments;
+ return &proxy_timeout_experiments;
}
} // namespace
@@ -152,10 +154,32 @@ HttpProxySocketParams::HttpProxySocketParams(
// implies |transport_params_| is null, per the above DCHECKs.
if (is_quic_)
DCHECK(ssl_params_);
+
+ // Only supports proxy endpoints without scheme for now.
+ // TODO(crbug.com/1206799): Handle scheme.
+ if (transport_params_) {
+ DCHECK(absl::holds_alternative<HostPortPair>(
+ transport_params_->destination()));
+ } else {
+ DCHECK(absl::holds_alternative<HostPortPair>(
+ ssl_params_->GetDirectConnectionParams()->destination()));
+ }
}
HttpProxySocketParams::~HttpProxySocketParams() = default;
+std::unique_ptr<HttpProxyConnectJob> HttpProxyConnectJob::Factory::Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<HttpProxySocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) {
+ return std::make_unique<HttpProxyConnectJob>(
+ priority, socket_tag, common_connect_job_params, std::move(params),
+ delegate, net_log);
+}
+
HttpProxyConnectJob::HttpProxyConnectJob(
RequestPriority priority,
const SocketTag& socket_tag,
@@ -295,7 +319,7 @@ base::TimeDelta HttpProxyConnectJob::AlternateNestedConnectionTimeout(
base::TimeDelta timeout = multiplier * http_rtt_estimate.value();
// Ensure that connection timeout is between
// |min_proxy_connection_timeout_| and |max_proxy_connection_timeout_|.
- return base::ClampToRange(
+ return base::clamp(
timeout, GetProxyTimeoutExperiments()->min_proxy_connection_timeout(),
GetProxyTimeoutExperiments()->max_proxy_connection_timeout());
}
@@ -657,8 +681,7 @@ int HttpProxyConnectJob::DoQuicProxyCreateSession() {
ResetTimer(kHttpProxyConnectJobTunnelTimeout);
next_state_ = STATE_QUIC_PROXY_CREATE_STREAM;
- const HostPortPair& proxy_server =
- ssl_params->GetDirectConnectionParams()->destination();
+ const HostPortPair& proxy_server = GetDestination();
quic_stream_request_ = std::make_unique<QuicStreamRequest>(
common_connect_job_params()->quic_stream_factory);
@@ -666,8 +689,12 @@ int HttpProxyConnectJob::DoQuicProxyCreateSession() {
quic::ParsedQuicVersion quic_version =
common_connect_job_params()->quic_supported_versions->front();
return quic_stream_request_->Request(
- proxy_server, quic_version, ssl_params->privacy_mode(),
- kH2QuicTunnelPriority, socket_tag(), params_->network_isolation_key(),
+ // TODO(crbug.com/1206799) Pass the destination directly once it's
+ // converted to contain scheme.
+ url::SchemeHostPort(url::kHttpsScheme, proxy_server.host(),
+ proxy_server.port()),
+ quic_version, ssl_params->privacy_mode(), kH2QuicTunnelPriority,
+ socket_tag(), params_->network_isolation_key(),
ssl_params->GetDirectConnectionParams()->secure_dns_policy(),
/*use_dns_aliases=*/false, ssl_params->ssl_config().GetCertVerifyFlags(),
GURL("https://" + proxy_server.ToString()), net_log(),
@@ -809,12 +836,18 @@ void HttpProxyConnectJob::OnAuthChallenge() {
weak_ptr_factory_.GetWeakPtr()));
}
-const HostPortPair& HttpProxyConnectJob::GetDestination() {
+const HostPortPair& HttpProxyConnectJob::GetDestination() const {
+ const TransportSocketParams* transport_params;
if (params_->transport_params()) {
- return params_->transport_params()->destination();
+ transport_params = params_->transport_params().get();
} else {
- return params_->ssl_params()->GetDirectConnectionParams()->destination();
+ transport_params = params_->ssl_params()->GetDirectConnectionParams().get();
}
+
+ // TODO(crbug.com/1206799): Handle proxy destination with scheme.
+ DCHECK(
+ absl::holds_alternative<HostPortPair>(transport_params->destination()));
+ return absl::get<HostPortPair>(transport_params->destination());
}
std::string HttpProxyConnectJob::GetUserAgent() const {
@@ -825,8 +858,7 @@ std::string HttpProxyConnectJob::GetUserAgent() const {
SpdySessionKey HttpProxyConnectJob::CreateSpdySessionKey() const {
return SpdySessionKey(
- params_->ssl_params()->GetDirectConnectionParams()->destination(),
- ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
+ GetDestination(), ProxyServer::Direct(), PRIVACY_MODE_DISABLED,
SpdySessionKey::IsProxySession::kTrue, socket_tag(),
params_->network_isolation_key(),
params_->ssl_params()->GetDirectConnectionParams()->secure_dns_policy());
diff --git a/chromium/net/http/http_proxy_connect_job.h b/chromium/net/http/http_proxy_connect_job.h
index a676ea53b2b..e8e50014b0c 100644
--- a/chromium/net/http/http_proxy_connect_job.h
+++ b/chromium/net/http/http_proxy_connect_job.h
@@ -88,6 +88,20 @@ class NET_EXPORT_PRIVATE HttpProxySocketParams
class NET_EXPORT_PRIVATE HttpProxyConnectJob : public ConnectJob,
public ConnectJob::Delegate {
public:
+ class NET_EXPORT_PRIVATE Factory {
+ public:
+ Factory() = default;
+ virtual ~Factory() = default;
+
+ virtual std::unique_ptr<HttpProxyConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<HttpProxySocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log);
+ };
+
HttpProxyConnectJob(RequestPriority priority,
const SocketTag& socket_tag,
const CommonConnectJobParams* common_connect_job_params,
@@ -201,7 +215,7 @@ class NET_EXPORT_PRIVATE HttpProxyConnectJob : public ConnectJob,
void OnAuthChallenge();
- const HostPortPair& GetDestination();
+ const HostPortPair& GetDestination() const;
std::string GetUserAgent() const;
diff --git a/chromium/net/http/http_proxy_connect_job_unittest.cc b/chromium/net/http/http_proxy_connect_job_unittest.cc
index 7790e735179..5023c491454 100644
--- a/chromium/net/http/http_proxy_connect_job_unittest.cc
+++ b/chromium/net/http/http_proxy_connect_job_unittest.cc
@@ -9,10 +9,10 @@
#include <string>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/metrics/field_trial_params.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/net/http/http_response_body_drainer.h b/chromium/net/http/http_response_body_drainer.h
index 7f72b066ee6..bb30ba7e1bd 100644
--- a/chromium/net/http/http_response_body_drainer.h
+++ b/chromium/net/http/http_response_body_drainer.h
@@ -7,14 +7,13 @@
#include <memory>
-#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/timer/timer.h"
#include "net/base/net_export.h"
-#include "net/http/http_network_session.h"
namespace net {
+class HttpNetworkSession;
class HttpStream;
class IOBuffer;
@@ -28,6 +27,8 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
static const int kTimeoutInSeconds = 5;
explicit HttpResponseBodyDrainer(HttpStream* stream);
+ HttpResponseBodyDrainer(const HttpResponseBodyDrainer&) = delete;
+ HttpResponseBodyDrainer& operator=(const HttpResponseBodyDrainer&) = delete;
~HttpResponseBodyDrainer();
// Starts reading the body until completion, or we hit the buffer limit, or we
@@ -57,8 +58,6 @@ class NET_EXPORT_PRIVATE HttpResponseBodyDrainer {
int total_read_;
base::OneShotTimer timer_;
HttpNetworkSession* session_;
-
- DISALLOW_COPY_AND_ASSIGN(HttpResponseBodyDrainer);
};
} // namespace net
diff --git a/chromium/net/http/http_response_body_drainer_unittest.cc b/chromium/net/http/http_response_body_drainer_unittest.cc
index c646c61b560..9dc7f4805ad 100644
--- a/chromium/net/http/http_response_body_drainer_unittest.cc
+++ b/chromium/net/http/http_response_body_drainer_unittest.cc
@@ -251,7 +251,7 @@ class HttpResponseBodyDrainerTest : public TestWithTaskEnvironment {
~HttpResponseBodyDrainerTest() override = default;
HttpNetworkSession* CreateNetworkSession() {
- HttpNetworkSession::Context context;
+ HttpNetworkSessionContext context;
context.proxy_resolution_service = proxy_resolution_service_.get();
context.ssl_config_service = ssl_config_service_.get();
context.http_server_properties = http_server_properties_.get();
@@ -259,7 +259,7 @@ class HttpResponseBodyDrainerTest : public TestWithTaskEnvironment {
context.transport_security_state = &transport_security_state_;
context.ct_policy_enforcer = &ct_policy_enforcer_;
context.quic_context = &quic_context_;
- return new HttpNetworkSession(HttpNetworkSession::Params(), context);
+ return new HttpNetworkSession(HttpNetworkSessionParams(), context);
}
std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
diff --git a/chromium/net/http/http_response_headers.cc b/chromium/net/http/http_response_headers.cc
index 2b148ba8584..0a1ddcc23e2 100644
--- a/chromium/net/http/http_response_headers.cc
+++ b/chromium/net/http/http_response_headers.cc
@@ -15,17 +15,18 @@
#include <unordered_map>
#include <utility>
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/pickle.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/escape.h"
#include "net/base/parse_number.h"
@@ -150,6 +151,13 @@ struct HttpResponseHeaders::ParsedHeader {
std::string::const_iterator name_end;
std::string::const_iterator value_begin;
std::string::const_iterator value_end;
+
+ // Write a representation of this object into a tracing proto.
+ void WriteIntoTrace(perfetto::TracedValue context) const {
+ auto dict = std::move(context).WriteDictionary();
+ dict.Add("name", base::MakeStringPiece(name_begin, name_end));
+ dict.Add("value", base::MakeStringPiece(value_begin, value_end));
+ }
};
//-----------------------------------------------------------------------------
@@ -753,24 +761,42 @@ size_t HttpResponseHeaders::FindHeader(size_t from,
bool HttpResponseHeaders::GetCacheControlDirective(base::StringPiece directive,
TimeDelta* result) const {
- base::StringPiece name("cache-control");
+ static constexpr base::StringPiece name("cache-control");
std::string value;
size_t directive_size = directive.size();
size_t iter = 0;
while (EnumerateHeader(&iter, name, &value)) {
- if (value.size() > directive_size + 1 &&
- base::StartsWith(value, directive,
- base::CompareCase::INSENSITIVE_ASCII) &&
- value[directive_size] == '=') {
- int64_t seconds;
- base::StringToInt64(base::MakeStringPiece(
- value.begin() + directive_size + 1, value.end()),
- &seconds);
- *result = TimeDelta::FromSeconds(seconds);
- return true;
+ if (!base::StartsWith(value, directive,
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ continue;
+ }
+ if (value.size() == directive_size || value[directive_size] != '=')
+ continue;
+ // 1*DIGIT with leading and trailing spaces, as described at
+ // https://datatracker.ietf.org/doc/html/rfc7234#section-1.2.1.
+ auto start = value.cbegin() + directive_size + 1;
+ auto end = value.cend();
+ while (start < end && *start == ' ') {
+ // leading spaces
+ ++start;
}
+ while (start < end - 1 && *(end - 1) == ' ') {
+ // trailing spaces
+ --end;
+ }
+ if (start == end ||
+ !std::all_of(start, end, [](char c) { return '0' <= c && c <= '9'; })) {
+ continue;
+ }
+ int64_t seconds = 0;
+ base::StringToInt64(base::MakeStringPiece(start, end), &seconds);
+ // We ignore the return value because we've already checked the input
+ // string. For the overflow case we use TimeDelta::FiniteMax().InSeconds().
+ seconds = std::min(seconds, base::TimeDelta::FiniteMax().InSeconds());
+ *result = TimeDelta::FromSeconds(seconds);
+ return true;
}
return false;
@@ -1364,4 +1390,10 @@ bool HttpResponseHeaders::IsCookieResponseHeader(base::StringPiece name) {
return false;
}
+void HttpResponseHeaders::WriteIntoTrace(perfetto::TracedValue context) const {
+ perfetto::TracedDictionary dict = std::move(context).WriteDictionary();
+ dict.Add("response_code", response_code_);
+ dict.Add("headers", parsed_);
+}
+
} // namespace net
diff --git a/chromium/net/http/http_response_headers.h b/chromium/net/http/http_response_headers.h
index 1b8d7cff1bc..ca5d8d15458 100644
--- a/chromium/net/http/http_response_headers.h
+++ b/chromium/net/http/http_response_headers.h
@@ -20,6 +20,7 @@
#include "net/base/net_export.h"
#include "net/http/http_version.h"
#include "net/log/net_log_capture_mode.h"
+#include "third_party/perfetto/include/perfetto/tracing/traced_value_forward.h"
namespace base {
class Pickle;
@@ -333,6 +334,9 @@ class NET_EXPORT HttpResponseHeaders
// with |PERSIST_SANS_COOKIES|.
static bool IsCookieResponseHeader(base::StringPiece name);
+ // Write a representation of this object into tracing proto.
+ void WriteIntoTrace(perfetto::TracedValue context) const;
+
private:
friend class base::RefCountedThreadSafe<HttpResponseHeaders>;
diff --git a/chromium/net/http/http_response_headers_unittest.cc b/chromium/net/http/http_response_headers_unittest.cc
index 54ac9588a02..d53c50d27bd 100644
--- a/chromium/net/http/http_response_headers_unittest.cc
+++ b/chromium/net/http/http_response_headers_unittest.cc
@@ -14,11 +14,13 @@
#include "base/pickle.h"
#include "base/time/time.h"
+#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_util.h"
#include "net/log/net_log_capture_mode.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/test/traced_value_test_support.h"
namespace net {
@@ -1825,6 +1827,16 @@ TEST(HttpResponseHeadersTest, SetHeader) {
ToSimpleString(headers));
}
+TEST(HttpResponseHeadersTest, TracingSupport) {
+ scoped_refptr<HttpResponseHeaders> headers = HttpResponseHeaders::TryToCreate(
+ "HTTP/1.1 200 OK\n"
+ "connection: keep-alive\n");
+ ASSERT_TRUE(headers);
+
+ EXPECT_EQ(perfetto::TracedValueToString(headers),
+ "{response_code:200,headers:[{name:connection,value:keep-alive}]}");
+}
+
struct RemoveHeaderTestData {
const char* orig_headers;
const char* to_remove;
@@ -2184,22 +2196,39 @@ TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeWithSpaceParameterRejected) {
EXPECT_FALSE(headers()->GetMaxAgeValue(TimeDeltaPointer()));
}
+TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeWithInterimSpaceIsRejected) {
+ InitializeHeadersWithCacheControl("max-age=1 2");
+ EXPECT_FALSE(headers()->GetMaxAgeValue(TimeDeltaPointer()));
+}
+
+TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeWithMinusSignIsRejected) {
+ InitializeHeadersWithCacheControl("max-age=-7");
+ EXPECT_FALSE(headers()->GetMaxAgeValue(TimeDeltaPointer()));
+}
+
TEST_F(HttpResponseHeadersCacheControlTest,
MaxAgeWithSpaceBeforeEqualsIsRejected) {
InitializeHeadersWithCacheControl("max-age = 7");
EXPECT_FALSE(headers()->GetMaxAgeValue(TimeDeltaPointer()));
}
+TEST_F(HttpResponseHeadersCacheControlTest,
+ MaxAgeWithLeadingandTrailingSpaces) {
+ InitializeHeadersWithCacheControl("max-age= 7 ");
+ EXPECT_EQ(TimeDelta::FromSeconds(7), GetMaxAgeValue());
+}
+
TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeFirstMatchUsed) {
InitializeHeadersWithCacheControl("max-age=10, max-age=20");
EXPECT_EQ(TimeDelta::FromSeconds(10), GetMaxAgeValue());
}
TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeBogusFirstMatchUsed) {
- // "max-age10" isn't parsed as "max-age"; "max-age=now" is parsed as
- // "max-age=0" and so "max-age=20" is not used.
- InitializeHeadersWithCacheControl("max-age10, max-age=now, max-age=20");
- EXPECT_EQ(TimeDelta::FromSeconds(0), GetMaxAgeValue());
+ // "max-age10" isn't parsed as "max-age"; "max-age=now" is bogus and
+ // ignored and so "max-age=20" is used.
+ InitializeHeadersWithCacheControl(
+ "max-age10, max-age=now, max-age=20, max-age=30");
+ EXPECT_EQ(TimeDelta::FromSeconds(20), GetMaxAgeValue());
}
TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeCaseInsensitive) {
@@ -2207,9 +2236,14 @@ TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeCaseInsensitive) {
EXPECT_EQ(TimeDelta::FromSeconds(15), GetMaxAgeValue());
}
+TEST_F(HttpResponseHeadersCacheControlTest, MaxAgeOverflow) {
+ InitializeHeadersWithCacheControl("max-age=99999999999999999999");
+ EXPECT_EQ(TimeDelta::FiniteMax().InSeconds(), GetMaxAgeValue().InSeconds());
+}
+
struct MaxAgeTestData {
const char* max_age_string;
- const int64_t expected_seconds;
+ const absl::optional<int64_t> expected_seconds;
};
class MaxAgeEdgeCasesTest
@@ -2223,27 +2257,31 @@ TEST_P(MaxAgeEdgeCasesTest, MaxAgeEdgeCases) {
std::string max_age = "max-age=";
InitializeHeadersWithCacheControl(
(max_age + test.max_age_string).c_str());
- EXPECT_EQ(test.expected_seconds, GetMaxAgeValue().InSeconds())
- << " for max-age=" << test.max_age_string;
+ if (test.expected_seconds.has_value()) {
+ EXPECT_EQ(test.expected_seconds.value(), GetMaxAgeValue().InSeconds())
+ << " for max-age=" << test.max_age_string;
+ } else {
+ EXPECT_FALSE(headers()->GetMaxAgeValue(TimeDeltaPointer()));
+ }
}
const MaxAgeTestData max_age_tests[] = {
{" 1 ", 1}, // Spaces are ignored.
- {"-1", -1}, // Negative numbers are passed through.
- {"--1", 0}, // Leading junk gives 0.
- {"2s", 2}, // Trailing junk is ignored.
- {"3 days", 3},
- {"'4'", 0}, // Single quotes don't work.
- {"\"5\"", 0}, // Double quotes don't work.
- {"0x6", 0}, // Hex not parsed as hex.
- {"7F", 7}, // Hex without 0x still not parsed as hex.
- {"010", 10}, // Octal not parsed as octal.
+ {"-1", absl::nullopt},
+ {"--1", absl::nullopt},
+ {"2s", absl::nullopt},
+ {"3 days", absl::nullopt},
+ {"'4'", absl::nullopt},
+ {"\"5\"", absl::nullopt},
+ {"0x6", absl::nullopt}, // Hex not parsed as hex.
+ {"7F", absl::nullopt}, // Hex without 0x still not parsed as hex.
+ {"010", 10}, // Octal not parsed as octal.
+ {"9223372036853", 9223372036853},
{"9223372036854", 9223372036854},
- // {"9223372036855", -9223372036854}, // Undefined behaviour.
- // {"9223372036854775806", -2}, // Undefined behaviour.
- {"9223372036854775807", 9223372036854775807},
- {"20000000000000000000",
- std::numeric_limits<int64_t>::max()}, // Overflow int64_t.
+ {"9223372036855", 9223372036854},
+ {"9223372036854775806", 9223372036854},
+ {"9223372036854775807", 9223372036854},
+ {"20000000000000000000", 9223372036854}, // Overflow int64_t.
};
INSTANTIATE_TEST_SUITE_P(HttpResponseHeadersCacheControl,
@@ -2263,9 +2301,9 @@ TEST_F(HttpResponseHeadersCacheControlTest,
}
TEST_F(HttpResponseHeadersCacheControlTest,
- StaleWhileRevalidateWithInvalidValueTreatedAsZero) {
+ StaleWhileRevalidateWithInvalidValueIgnored) {
InitializeHeadersWithCacheControl("max-age=3600,stale-while-revalidate=true");
- EXPECT_EQ(TimeDelta(), GetStaleWhileRevalidateValue());
+ EXPECT_FALSE(headers()->GetStaleWhileRevalidateValue(TimeDeltaPointer()));
}
TEST_F(HttpResponseHeadersCacheControlTest, StaleWhileRevalidateValueReturned) {
diff --git a/chromium/net/http/http_server_properties_manager.cc b/chromium/net/http/http_server_properties_manager.cc
index bc0a134f4c3..611e2712496 100644
--- a/chromium/net/http/http_server_properties_manager.cc
+++ b/chromium/net/http/http_server_properties_manager.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/metrics/histogram_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/time/tick_clock.h"
#include "base/values.h"
diff --git a/chromium/net/http/http_server_properties_manager_unittest.cc b/chromium/net/http/http_server_properties_manager_unittest.cc
index 67891013df6..5db04127164 100644
--- a/chromium/net/http/http_server_properties_manager_unittest.cc
+++ b/chromium/net/http/http_server_properties_manager_unittest.cc
@@ -1515,8 +1515,8 @@ TEST_F(HttpServerPropertiesManagerTest, PersistAdvertisedVersionsToPref) {
"\"isolation\":[],"
"\"server\":\"https://www.google.com:80\"},"
"{\"alternative_service\":[{"
- "\"advertised_alpns\":[\"h3-Q050\",\"h3-29\"],\"expiration\":"
- "\"9223372036854775807\","
+ "\"advertised_alpns\":[\"h3\",\"h3-29\",\"h3-Q050\"],"
+ "\"expiration\":\"9223372036854775807\","
"\"host\":\"foo.google.com\",\"port\":444,\"protocol_str\":\"quic\"}],"
"\"isolation\":[],"
"\"network_stats\":{\"srtt\":42},"
@@ -1627,7 +1627,8 @@ TEST_F(HttpServerPropertiesManagerTest,
"\"server_id\":\"https://mail.google.com:80\","
"\"server_info\":\"quic_server_info1\"}],"
"\"servers\":["
- "{\"alternative_service\":[{\"advertised_alpns\":[\"h3-Q050\",\"h3-29\"],"
+ "{\"alternative_service\":[{"
+ "\"advertised_alpns\":[\"h3\",\"h3-29\",\"h3-Q050\"],"
"\"expiration\":\"13756212000000000\",\"port\":443,"
"\"protocol_str\":\"quic\"}],"
"\"isolation\":[],"
diff --git a/chromium/net/http/http_stream_factory.cc b/chromium/net/http/http_stream_factory.cc
index 8a92dd2c069..aa425ed260a 100644
--- a/chromium/net/http/http_stream_factory.cc
+++ b/chromium/net/http/http_stream_factory.cc
@@ -10,7 +10,6 @@
#include "base/check.h"
#include "base/metrics/histogram_macros.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/http/http_stream_factory_job.cc b/chromium/net/http/http_stream_factory_job.cc
index a07072b3518..082d0729707 100644
--- a/chromium/net/http/http_stream_factory_job.cc
+++ b/chromium/net/http/http_stream_factory_job.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <memory>
#include <string>
+#include <utility>
#include "base/bind.h"
#include "base/callback_helpers.h"
@@ -24,6 +25,7 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "build/build_config.h"
+#include "net/base/host_port_pair.h"
#include "net/base/port_util.h"
#include "net/base/proxy_delegate.h"
#include "net/base/trace_constants.h"
@@ -55,6 +57,7 @@
#include "net/spdy/spdy_session.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+#include "url/scheme_host_port.h"
#include "url/url_constants.h"
namespace net {
@@ -103,7 +106,7 @@ HttpStreamFactory::Job::Job(Delegate* delegate,
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -122,7 +125,7 @@ HttpStreamFactory::Job::Job(Delegate* delegate,
connection_(new ClientSocketHandle),
session_(session),
next_state_(STATE_NONE),
- destination_(destination),
+ destination_(std::move(destination)),
origin_url_(origin_url),
is_websocket_(is_websocket),
try_websocket_over_http2_(is_websocket_ &&
@@ -139,12 +142,9 @@ HttpStreamFactory::Job::Job(Delegate* delegate,
job_type_(job_type),
using_ssl_(origin_url_.SchemeIs(url::kHttpsScheme) ||
origin_url_.SchemeIs(url::kWssScheme)),
- using_quic_(alternative_protocol == kProtoQUIC ||
- (ShouldForceQuic(session,
- destination,
- origin_url,
- proxy_info,
- using_ssl_))),
+ using_quic_(
+ alternative_protocol == kProtoQUIC ||
+ (ShouldForceQuic(session, destination_, proxy_info, using_ssl_))),
quic_version_(quic_version),
expect_spdy_(alternative_protocol == kProtoHTTP2 && !using_quic_),
using_spdy_(false),
@@ -170,6 +170,10 @@ HttpStreamFactory::Job::Job(Delegate* delegate,
request_info_.secure_dns_policy)),
stream_type_(HttpStreamRequest::BIDIRECTIONAL_STREAM),
init_connection_already_resumed_(false) {
+ // Websocket `destination` schemes should be converted to HTTP(S).
+ DCHECK(base::LowerCaseEqualsASCII(destination_.scheme(), url::kHttpScheme) ||
+ base::LowerCaseEqualsASCII(destination_.scheme(), url::kHttpsScheme));
+
// QUIC can only be spoken to servers, never to proxies.
if (alternative_protocol == kProtoQUIC)
DCHECK(proxy_info_.is_direct());
@@ -177,8 +181,7 @@ HttpStreamFactory::Job::Job(Delegate* delegate,
// The Job is forced to use QUIC without a designated version, try the
// preferred QUIC version that is supported by default.
if (quic_version_ == quic::ParsedQuicVersion::Unsupported() &&
- ShouldForceQuic(session, destination, origin_url, proxy_info,
- using_ssl_)) {
+ ShouldForceQuic(session, destination_, proxy_info, using_ssl_)) {
quic_version_ =
session->context().quic_context->params()->supported_versions[0];
}
@@ -345,11 +348,11 @@ void HttpStreamFactory::Job::GetSSLInfo(SSLInfo* ssl_info) {
}
// static
-bool HttpStreamFactory::Job::ShouldForceQuic(HttpNetworkSession* session,
- const HostPortPair& destination,
- const GURL& origin_url,
- const ProxyInfo& proxy_info,
- bool using_ssl) {
+bool HttpStreamFactory::Job::ShouldForceQuic(
+ HttpNetworkSession* session,
+ const url::SchemeHostPort& destination,
+ const ProxyInfo& proxy_info,
+ bool using_ssl) {
if (!session->IsQuicEnabled())
return false;
// If this is going through a QUIC proxy, only force QUIC for insecure
@@ -358,10 +361,14 @@ bool HttpStreamFactory::Job::ShouldForceQuic(HttpNetworkSession* session,
if (proxy_info.is_quic())
return !using_ssl;
const QuicParams* quic_params = session->context().quic_context->params();
+ // TODO(crbug.com/1206799): Consider converting `origins_to_force_quic_on` to
+ // use url::SchemeHostPort.
return (base::Contains(quic_params->origins_to_force_quic_on,
HostPortPair()) ||
- base::Contains(quic_params->origins_to_force_quic_on, destination)) &&
- proxy_info.is_direct() && origin_url.SchemeIs(url::kHttpsScheme);
+ base::Contains(quic_params->origins_to_force_quic_on,
+ HostPortPair::FromSchemeHostPort(destination))) &&
+ proxy_info.is_direct() &&
+ base::LowerCaseEqualsASCII(destination.scheme(), url::kHttpsScheme);
}
// static
@@ -813,9 +820,10 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() {
if (job_type_ == PRECONNECT) {
DCHECK(!is_websocket_);
DCHECK(request_info_.socket_tag == SocketTag());
+
return PreconnectSocketsForHttpRequest(
- GetSocketGroup(), destination_, request_info_.load_flags, priority_,
- session_, proxy_info_, server_ssl_config_, proxy_ssl_config_,
+ destination_, request_info_.load_flags, priority_, session_,
+ proxy_info_, server_ssl_config_, proxy_ssl_config_,
request_info_.privacy_mode, request_info_.network_isolation_key,
request_info_.secure_dns_policy, net_log_, num_streams_);
}
@@ -829,32 +837,33 @@ int HttpStreamFactory::Job::DoInitConnectionImpl() {
SSLConfig websocket_server_ssl_config = server_ssl_config_;
websocket_server_ssl_config.alpn_protos.clear();
return InitSocketHandleForWebSocketRequest(
- GetSocketGroup(), destination_, request_info_.load_flags, priority_,
- session_, proxy_info_, websocket_server_ssl_config, proxy_ssl_config_,
+ destination_, request_info_.load_flags, priority_, session_,
+ proxy_info_, websocket_server_ssl_config, proxy_ssl_config_,
request_info_.privacy_mode, request_info_.network_isolation_key,
net_log_, connection_.get(), io_callback_, proxy_auth_callback);
}
return InitSocketHandleForHttpRequest(
- GetSocketGroup(), destination_, request_info_.load_flags, priority_,
- session_, proxy_info_, server_ssl_config_, proxy_ssl_config_,
- request_info_.privacy_mode, request_info_.network_isolation_key,
- request_info_.secure_dns_policy, request_info_.socket_tag, net_log_,
- connection_.get(), io_callback_, proxy_auth_callback);
+ destination_, request_info_.load_flags, priority_, session_, proxy_info_,
+ server_ssl_config_, proxy_ssl_config_, request_info_.privacy_mode,
+ request_info_.network_isolation_key, request_info_.secure_dns_policy,
+ request_info_.socket_tag, net_log_, connection_.get(), io_callback_,
+ proxy_auth_callback);
}
int HttpStreamFactory::Job::DoInitConnectionImplQuic() {
- HostPortPair destination;
+ url::SchemeHostPort destination;
SSLConfig* ssl_config;
GURL url(request_info_.url);
if (proxy_info_.is_quic()) {
- // A proxy's certificate is expected to be valid for the proxy hostname.
- destination = proxy_info_.proxy_server().host_port_pair();
ssl_config = &proxy_ssl_config_;
GURL::Replacements replacements;
replacements.SetSchemeStr(url::kHttpsScheme);
- replacements.SetHostStr(destination.host());
- const std::string new_port = base::NumberToString(destination.port());
+ const HostPortPair& proxy_endpoint =
+ proxy_info_.proxy_server().host_port_pair();
+ // A proxy's certificate is expected to be valid for the proxy hostname.
+ replacements.SetHostStr(proxy_endpoint.host());
+ const std::string new_port = base::NumberToString(proxy_endpoint.port());
replacements.SetPortStr(new_port);
replacements.ClearUsername();
replacements.ClearPassword();
@@ -862,6 +871,7 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic() {
replacements.ClearQuery();
replacements.ClearRef();
url = url.ReplaceComponents(replacements);
+ destination = url::SchemeHostPort(url);
} else {
DCHECK(using_ssl_);
// The certificate of a QUIC alternative server is expected to be valid
@@ -870,9 +880,11 @@ int HttpStreamFactory::Job::DoInitConnectionImplQuic() {
destination = destination_;
ssl_config = &server_ssl_config_;
}
+ DCHECK(url.SchemeIs(url::kHttpsScheme));
+
int rv = quic_request_.Request(
- destination, quic_version_, request_info_.privacy_mode, priority_,
- request_info_.socket_tag, request_info_.network_isolation_key,
+ std::move(destination), quic_version_, request_info_.privacy_mode,
+ priority_, request_info_.socket_tag, request_info_.network_isolation_key,
request_info_.secure_dns_policy, proxy_info_.is_direct(),
ssl_config->GetCertVerifyFlags(), url, net_log_, &net_error_details_,
base::BindOnce(&Job::OnFailedOnDefaultNetwork, ptr_factory_.GetWeakPtr()),
@@ -1228,17 +1240,6 @@ int HttpStreamFactory::Job::ReconsiderProxyAfterError(int error) {
return error;
}
-ClientSocketPoolManager::SocketGroupType
-HttpStreamFactory::Job::GetSocketGroup() const {
- std::string scheme = origin_url_.scheme();
-
- if (scheme == url::kHttpsScheme || scheme == url::kWssScheme)
- return ClientSocketPoolManager::SSL_GROUP;
-
- DCHECK(scheme == url::kHttpScheme || scheme == url::kWsScheme);
- return ClientSocketPoolManager::NORMAL_GROUP;
-}
-
// If the connection succeeds, failed connection attempts leading up to the
// success will be returned via the successfully connected socket. If the
// connection fails, failed connection attempts will be returned via the
@@ -1270,14 +1271,14 @@ HttpStreamFactory::JobFactory::CreateMainJob(
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
bool is_websocket,
bool enable_ip_based_pooling,
NetLog* net_log) {
return std::make_unique<HttpStreamFactory::Job>(
delegate, job_type, session, request_info, priority, proxy_info,
- server_ssl_config, proxy_ssl_config, destination, origin_url,
+ server_ssl_config, proxy_ssl_config, std::move(destination), origin_url,
kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), is_websocket,
enable_ip_based_pooling, net_log);
}
@@ -1292,7 +1293,7 @@ HttpStreamFactory::JobFactory::CreateAltSvcJob(
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -1301,7 +1302,7 @@ HttpStreamFactory::JobFactory::CreateAltSvcJob(
NetLog* net_log) {
return std::make_unique<HttpStreamFactory::Job>(
delegate, job_type, session, request_info, priority, proxy_info,
- server_ssl_config, proxy_ssl_config, destination, origin_url,
+ server_ssl_config, proxy_ssl_config, std::move(destination), origin_url,
alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling,
net_log);
}
diff --git a/chromium/net/http/http_stream_factory_job.h b/chromium/net/http/http_stream_factory_job.h
index e75520de44f..f271699d3b0 100644
--- a/chromium/net/http/http_stream_factory_job.h
+++ b/chromium/net/http/http_stream_factory_job.h
@@ -34,6 +34,7 @@
#include "net/spdy/spdy_session_key.h"
#include "net/spdy/spdy_session_pool.h"
#include "net/ssl/ssl_config_service.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -156,7 +157,7 @@ class HttpStreamFactory::Job
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -314,8 +315,7 @@ class HttpStreamFactory::Job
// Called in Job constructor: should Job be forced to use QUIC.
static bool ShouldForceQuic(HttpNetworkSession* session,
- const HostPortPair& destination,
- const GURL& origin_url,
+ const url::SchemeHostPort& destination,
const ProxyInfo& proxy_info,
bool using_ssl);
@@ -340,8 +340,6 @@ class HttpStreamFactory::Job
// code is simply returned.
int ReconsiderProxyAfterError(int error);
- ClientSocketPoolManager::SocketGroupType GetSocketGroup() const;
-
void MaybeCopyConnectionAttemptsFromSocketOrHandle();
// Returns true if the request should be throttled to allow for only one
@@ -363,7 +361,7 @@ class HttpStreamFactory::Job
// The server we are trying to reach, could be that of the origin or of the
// alternative service (after applying host mapping rules).
- const HostPortPair destination_;
+ const url::SchemeHostPort destination_;
// The origin url we're trying to reach. This url may be different from the
// original request when host mapping rules are set-up.
@@ -483,7 +481,7 @@ class HttpStreamFactory::JobFactory {
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
bool is_websocket,
bool enable_ip_based_pooling,
@@ -498,7 +496,7 @@ class HttpStreamFactory::JobFactory {
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
diff --git a/chromium/net/http/http_stream_factory_job_controller.cc b/chromium/net/http/http_stream_factory_job_controller.cc
index 4c34611f1c8..7693e320cf2 100644
--- a/chromium/net/http/http_stream_factory_job_controller.cc
+++ b/chromium/net/http/http_stream_factory_job_controller.cc
@@ -28,6 +28,10 @@
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_resolution_request.h"
#include "net/spdy/spdy_session.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/third_party/mozilla/url_parse.h"
+#include "url/url_canon.h"
#include "url/url_constants.h"
namespace net {
@@ -45,6 +49,36 @@ base::Value NetLogHttpStreamJobProxyServerResolved(
return dict;
}
+GURL CreateAltSvcUrl(const GURL& origin_url,
+ const HostPortPair& alternative_destination) {
+ DCHECK(origin_url.is_valid());
+ DCHECK(origin_url.IsStandard());
+
+ url::Replacements<char> replacements;
+ std::string port_str = base::NumberToString(alternative_destination.port());
+ replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
+ replacements.SetHost(
+ alternative_destination.host().c_str(),
+ url::Component(0, alternative_destination.host().size()));
+
+ return origin_url.ReplaceComponents(replacements);
+}
+
+void ConvertWsToHttp(url::SchemeHostPort& input) {
+ if (base::EqualsCaseInsensitiveASCII(input.scheme(), url::kHttpScheme) ||
+ base::EqualsCaseInsensitiveASCII(input.scheme(), url::kHttpsScheme)) {
+ return;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(input.scheme(), url::kWsScheme)) {
+ input = url::SchemeHostPort(url::kHttpScheme, input.host(), input.port());
+ return;
+ }
+
+ DCHECK(base::EqualsCaseInsensitiveASCII(input.scheme(), url::kWssScheme));
+ input = url::SchemeHostPort(url::kHttpsScheme, input.host(), input.port());
+}
+
} // namespace
// The maximum time to wait for the alternate job to complete before resuming
@@ -105,6 +139,15 @@ HttpStreamFactory::JobController::JobController(
session->net_log(),
NetLogSourceType::HTTP_STREAM_JOB_CONTROLLER)) {
DCHECK(factory);
+ DCHECK(base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+ url::kHttpScheme) ||
+ base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+ url::kHttpsScheme) ||
+ base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+ url::kWsScheme) ||
+ base::EqualsCaseInsensitiveASCII(request_info_.url.scheme_piece(),
+ url::kWssScheme));
+
net_log_.BeginEvent(NetLogEventType::HTTP_STREAM_JOB_CONTROLLER, [&] {
return NetLogJobControllerParams(request_info.url, is_preconnect);
});
@@ -613,8 +656,8 @@ int HttpStreamFactory::JobController::DoResolveProxy() {
return OK;
}
- HostPortPair destination(HostPortPair::FromURL(request_info_.url));
- GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
+ GURL origin_url = request_info_.url;
+ RewriteUrlWithHostMappingRules(origin_url);
CompletionOnceCallback io_callback =
base::BindOnce(&JobController::OnIOComplete, base::Unretained(this));
@@ -658,9 +701,15 @@ int HttpStreamFactory::JobController::DoResolveProxyComplete(int rv) {
int HttpStreamFactory::JobController::DoCreateJobs() {
DCHECK(!main_job_);
DCHECK(!alternative_job_);
+ DCHECK(request_info_.url.is_valid());
+ DCHECK(request_info_.url.IsStandard());
- HostPortPair destination(HostPortPair::FromURL(request_info_.url));
- GURL origin_url = ApplyHostMappingRules(request_info_.url, &destination);
+ GURL origin_url = request_info_.url;
+ RewriteUrlWithHostMappingRules(origin_url);
+
+ url::SchemeHostPort destination(origin_url);
+ DCHECK(destination.IsValid());
+ ConvertWsToHttp(destination);
// Create an alternative job if alternative service is set up for this domain,
// but only if we'll be speaking directly to the server, since QUIC through
@@ -682,27 +731,33 @@ int HttpStreamFactory::JobController::DoCreateJobs() {
// preconnects is currently ignored (see RequestSocketsForPool()), but could
// be used at some point for proxy resolution or something.
if (alternative_service_info_.protocol() != kProtoUnknown) {
- HostPortPair alternative_destination(
- alternative_service_info_.host_port_pair());
- ignore_result(
- ApplyHostMappingRules(request_info_.url, &alternative_destination));
+ GURL alternative_url = CreateAltSvcUrl(
+ origin_url, alternative_service_info_.host_port_pair());
+ RewriteUrlWithHostMappingRules(alternative_url);
+
+ url::SchemeHostPort alternative_destination =
+ url::SchemeHostPort(alternative_url);
+ ConvertWsToHttp(alternative_destination);
+
main_job_ = job_factory_->CreateAltSvcJob(
this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
- server_ssl_config_, proxy_ssl_config_, alternative_destination,
- origin_url, alternative_service_info_.protocol(), quic_version,
- is_websocket_, enable_ip_based_pooling_, session_->net_log());
+ server_ssl_config_, proxy_ssl_config_,
+ std::move(alternative_destination), origin_url,
+ alternative_service_info_.protocol(), quic_version, is_websocket_,
+ enable_ip_based_pooling_, session_->net_log());
} else {
main_job_ = job_factory_->CreateMainJob(
this, PRECONNECT, session_, request_info_, IDLE, proxy_info_,
- server_ssl_config_, proxy_ssl_config_, destination, origin_url,
- is_websocket_, enable_ip_based_pooling_, session_->net_log());
+ server_ssl_config_, proxy_ssl_config_, std::move(destination),
+ origin_url, is_websocket_, enable_ip_based_pooling_,
+ session_->net_log());
}
main_job_->Preconnect(num_streams_);
return OK;
}
main_job_ = job_factory_->CreateMainJob(
this, MAIN, session_, request_info_, priority_, proxy_info_,
- server_ssl_config_, proxy_ssl_config_, destination, origin_url,
+ server_ssl_config_, proxy_ssl_config_, std::move(destination), origin_url,
is_websocket_, enable_ip_based_pooling_, net_log_.net_log());
// Alternative Service can only be set for HTTPS requests while Alternative
// Proxy is set for HTTP requests.
@@ -713,15 +768,20 @@ int HttpStreamFactory::JobController::DoCreateJobs() {
<< " port: " << alternative_service_info_.host_port_pair().port()
<< " version: " << quic_version << ")";
- HostPortPair alternative_destination(
- alternative_service_info_.host_port_pair());
- ignore_result(
- ApplyHostMappingRules(request_info_.url, &alternative_destination));
+ GURL alternative_url =
+ CreateAltSvcUrl(origin_url, alternative_service_info_.host_port_pair());
+ RewriteUrlWithHostMappingRules(alternative_url);
+
+ url::SchemeHostPort alternative_destination =
+ url::SchemeHostPort(alternative_url);
+ ConvertWsToHttp(alternative_destination);
+
alternative_job_ = job_factory_->CreateAltSvcJob(
this, ALTERNATIVE, session_, request_info_, priority_, proxy_info_,
- server_ssl_config_, proxy_ssl_config_, alternative_destination,
- origin_url, alternative_service_info_.protocol(), quic_version,
- is_websocket_, enable_ip_based_pooling_, net_log_.net_log());
+ server_ssl_config_, proxy_ssl_config_,
+ std::move(alternative_destination), origin_url,
+ alternative_service_info_.protocol(), quic_version, is_websocket_,
+ enable_ip_based_pooling_, net_log_.net_log());
main_job_is_blocked_ = true;
alternative_job_->Start(request_->stream_type());
@@ -892,18 +952,9 @@ void HttpStreamFactory::JobController::NotifyRequestFailed(int rv) {
ProxyInfo(), ResolveErrorInfo());
}
-GURL HttpStreamFactory::JobController::ApplyHostMappingRules(
- const GURL& url,
- HostPortPair* endpoint) {
- if (session_->params().host_mapping_rules.RewriteHost(endpoint)) {
- url::Replacements<char> replacements;
- const std::string port_str = base::NumberToString(endpoint->port());
- replacements.SetPort(port_str.c_str(), url::Component(0, port_str.size()));
- replacements.SetHost(endpoint->host().c_str(),
- url::Component(0, endpoint->host().size()));
- return url.ReplaceComponents(replacements);
- }
- return url;
+void HttpStreamFactory::JobController::RewriteUrlWithHostMappingRules(
+ GURL& url) {
+ session_->params().host_mapping_rules.RewriteUrl(url);
}
AlternativeServiceInfo
@@ -949,12 +1000,12 @@ HttpStreamFactory::JobController::GetAlternativeServiceInfoInternal(
if (!original_url.SchemeIs(url::kHttpsScheme))
return AlternativeServiceInfo();
- url::SchemeHostPort origin(original_url);
HttpServerProperties& http_server_properties =
*session_->http_server_properties();
const AlternativeServiceInfoVector alternative_service_info_vector =
http_server_properties.GetAlternativeServiceInfos(
- origin, request_info.network_isolation_key);
+ url::SchemeHostPort(original_url),
+ request_info.network_isolation_key);
if (alternative_service_info_vector.empty())
return AlternativeServiceInfo();
@@ -997,7 +1048,7 @@ HttpStreamFactory::JobController::GetAlternativeServiceInfoInternal(
if (!session_->params().enable_user_alternate_protocol_ports &&
(alternative_service_info.alternative_service().port >=
kUnrestrictedPort &&
- origin.port() < kUnrestrictedPort))
+ original_url.EffectiveIntPort() < kUnrestrictedPort))
continue;
if (alternative_service_info.protocol() == kProtoHTTP2) {
@@ -1032,21 +1083,23 @@ HttpStreamFactory::JobController::GetAlternativeServiceInfoInternal(
continue;
// Check whether there is an existing QUIC session to use for this origin.
- HostPortPair mapped_origin(origin.host(), origin.port());
- ignore_result(ApplyHostMappingRules(original_url, &mapped_origin));
+ GURL mapped_origin = original_url;
+ RewriteUrlWithHostMappingRules(mapped_origin);
QuicSessionKey session_key(
- mapped_origin, request_info.privacy_mode, request_info.socket_tag,
- request_info.network_isolation_key, request_info.secure_dns_policy);
+ HostPortPair::FromURL(mapped_origin), request_info.privacy_mode,
+ request_info.socket_tag, request_info.network_isolation_key,
+ request_info.secure_dns_policy);
- HostPortPair destination(alternative_service_info.host_port_pair());
- if (session_key.host() != destination.host() &&
+ GURL destination = CreateAltSvcUrl(
+ original_url, alternative_service_info.host_port_pair());
+ if (session_key.host() != destination.host_piece() &&
!session_->context().quic_context->params()->allow_remote_alt_svc) {
continue;
}
- ignore_result(ApplyHostMappingRules(original_url, &destination));
+ RewriteUrlWithHostMappingRules(destination);
- if (session_->quic_stream_factory()->CanUseExistingSession(session_key,
- destination))
+ if (session_->quic_stream_factory()->CanUseExistingSession(
+ session_key, url::SchemeHostPort(destination)))
return alternative_service_info;
if (!IsQuicAllowedForHost(destination.host()))
diff --git a/chromium/net/http/http_stream_factory_job_controller.h b/chromium/net/http/http_stream_factory_job_controller.h
index abc7eef325e..53292b72217 100644
--- a/chromium/net/http/http_stream_factory_job_controller.h
+++ b/chromium/net/http/http_stream_factory_job_controller.h
@@ -49,7 +49,7 @@ class HttpStreamFactory::JobController
const Job* main_job() const { return main_job_.get(); }
const Job* alternative_job() const { return alternative_job_.get(); }
- GURL ApplyHostMappingRules(const GURL& url, HostPortPair* endpoint);
+ void RewriteUrlWithHostMappingRules(GURL& url);
// Methods below are called by HttpStreamFactory only.
// Creates request and hands out to HttpStreamFactory, this will also create
diff --git a/chromium/net/http/http_stream_factory_job_controller_unittest.cc b/chromium/net/http/http_stream_factory_job_controller_unittest.cc
index de826bb4bd5..5f2413563d8 100644
--- a/chromium/net/http/http_stream_factory_job_controller_unittest.cc
+++ b/chromium/net/http/http_stream_factory_job_controller_unittest.cc
@@ -58,6 +58,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
using ::testing::_;
using ::testing::Contains;
@@ -199,6 +200,7 @@ class HttpStreamFactoryJobControllerTest : public TestWithTaskEnvironment {
HttpStreamFactoryJobControllerTest()
: TestWithTaskEnvironment(
base::test::TaskEnvironment::TimeSource::MOCK_TIME) {
+ FLAGS_quic_enable_http3_grease_randomness = false;
session_deps_.enable_quic = true;
session_deps_.host_resolver->set_synchronous_mode(true);
}
@@ -236,9 +238,9 @@ class HttpStreamFactoryJobControllerTest : public TestWithTaskEnvironment {
test_proxy_delegate_.get());
session_deps_.net_log = net_log_.bound().net_log();
- HttpNetworkSession::Params params =
+ HttpNetworkSessionParams params =
SpdySessionDependencies::CreateSessionParams(&session_deps_);
- HttpNetworkSession::Context session_context =
+ HttpNetworkSessionContext session_context =
SpdySessionDependencies::CreateSessionContext(&session_deps_);
session_context.quic_crypto_client_stream_factory =
@@ -2449,16 +2451,13 @@ TEST_F(JobControllerLimitMultipleH2Requests,
reinterpret_cast<TransportClientSocketPool*>(session_->GetSocketPool(
HttpNetworkSession::NORMAL_SOCKET_POOL, ProxyServer::Direct()));
ClientSocketPool::GroupId group_id0(
- HostPortPair::FromURL(request_info.url),
- ClientSocketPool::SocketType::kSsl, request_info.privacy_mode,
+ url::SchemeHostPort(request_info.url), request_info.privacy_mode,
NetworkIsolationKey(), SecureDnsPolicy::kAllow);
ClientSocketPool::GroupId group_id1(
- HostPortPair::FromURL(request_info.url),
- ClientSocketPool::SocketType::kSsl, request_info.privacy_mode,
+ url::SchemeHostPort(request_info.url), request_info.privacy_mode,
kNetworkIsolationKey1, SecureDnsPolicy::kAllow);
ClientSocketPool::GroupId group_id2(
- HostPortPair::FromURL(request_info.url),
- ClientSocketPool::SocketType::kSsl, request_info.privacy_mode,
+ url::SchemeHostPort(request_info.url), request_info.privacy_mode,
kNetworkIsolationKey2, SecureDnsPolicy::kAllow);
EXPECT_EQ(static_cast<uint32_t>(kNumRequests),
socket_pool->NumConnectJobsInGroupForTesting(group_id0));
@@ -2936,7 +2935,14 @@ TEST_F(HttpStreamFactoryJobControllerTest, GetAlternativeServiceInfoFor) {
[](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
return a.transport_version < b.transport_version;
});
- EXPECT_EQ(supported_versions, alt_svc_info.advertised_versions());
+ quic::ParsedQuicVersionVector advertised_versions =
+ alt_svc_info.advertised_versions();
+ std::sort(
+ advertised_versions.begin(), advertised_versions.end(),
+ [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
+ return a.transport_version < b.transport_version;
+ });
+ EXPECT_EQ(supported_versions, advertised_versions);
quic::ParsedQuicVersion unsupported_version_1 =
quic::ParsedQuicVersion::Unsupported();
@@ -3109,8 +3115,15 @@ TEST_F(HttpStreamFactoryJobControllerTest, QuicHostAllowlist) {
[](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
return a.transport_version < b.transport_version;
});
+ quic::ParsedQuicVersionVector advertised_versions =
+ alt_svc_info.advertised_versions();
+ std::sort(
+ advertised_versions.begin(), advertised_versions.end(),
+ [](const quic::ParsedQuicVersion& a, const quic::ParsedQuicVersion& b) {
+ return a.transport_version < b.transport_version;
+ });
EXPECT_EQ(kProtoQUIC, alt_svc_info.alternative_service().protocol);
- EXPECT_EQ(supported_versions, alt_svc_info.advertised_versions());
+ EXPECT_EQ(supported_versions, advertised_versions);
session_->http_server_properties()->SetQuicAlternativeService(
server, NetworkIsolationKey(),
diff --git a/chromium/net/http/http_stream_factory_test_util.cc b/chromium/net/http/http_stream_factory_test_util.cc
index 95c0ab0cae4..3da68eec0e6 100644
--- a/chromium/net/http/http_stream_factory_test_util.cc
+++ b/chromium/net/http/http_stream_factory_test_util.cc
@@ -7,6 +7,7 @@
#include <utility>
#include "net/proxy_resolution/proxy_info.h"
+#include "url/scheme_host_port.h"
using ::testing::_;
@@ -24,7 +25,7 @@ MockHttpStreamFactoryJob::MockHttpStreamFactoryJob(
ProxyInfo proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -39,7 +40,7 @@ MockHttpStreamFactoryJob::MockHttpStreamFactoryJob(
proxy_info,
server_ssl_config,
proxy_ssl_config,
- destination,
+ std::move(destination),
origin_url,
alternative_protocol,
quic_version,
@@ -67,7 +68,7 @@ std::unique_ptr<HttpStreamFactory::Job> TestJobFactory::CreateMainJob(
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
bool is_websocket,
bool enable_ip_based_pooling,
@@ -77,8 +78,8 @@ std::unique_ptr<HttpStreamFactory::Job> TestJobFactory::CreateMainJob(
auto main_job = std::make_unique<MockHttpStreamFactoryJob>(
delegate, job_type, session, request_info, priority, proxy_info,
- SSLConfig(), SSLConfig(), destination, origin_url, kProtoUnknown,
- quic::ParsedQuicVersion::Unsupported(), is_websocket,
+ SSLConfig(), SSLConfig(), std::move(destination), origin_url,
+ kProtoUnknown, quic::ParsedQuicVersion::Unsupported(), is_websocket,
enable_ip_based_pooling, net_log);
// Keep raw pointer to Job but pass ownership.
@@ -96,7 +97,7 @@ std::unique_ptr<HttpStreamFactory::Job> TestJobFactory::CreateAltSvcJob(
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -105,8 +106,9 @@ std::unique_ptr<HttpStreamFactory::Job> TestJobFactory::CreateAltSvcJob(
NetLog* net_log) {
auto alternative_job = std::make_unique<MockHttpStreamFactoryJob>(
delegate, job_type, session, request_info, priority, proxy_info,
- SSLConfig(), SSLConfig(), destination, origin_url, alternative_protocol,
- quic_version, is_websocket, enable_ip_based_pooling, net_log);
+ SSLConfig(), SSLConfig(), std::move(destination), origin_url,
+ alternative_protocol, quic_version, is_websocket, enable_ip_based_pooling,
+ net_log);
// Keep raw pointer to Job but pass ownership.
alternative_job_ = alternative_job.get();
diff --git a/chromium/net/http/http_stream_factory_test_util.h b/chromium/net/http/http_stream_factory_test_util.h
index e352f36511f..d94b2420756 100644
--- a/chromium/net/http/http_stream_factory_test_util.h
+++ b/chromium/net/http/http_stream_factory_test_util.h
@@ -16,6 +16,7 @@
#include "net/proxy_resolution/proxy_info.h"
#include "net/socket/next_proto.h"
#include "testing/gmock/include/gmock/gmock.h"
+#include "url/scheme_host_port.h"
using testing::_;
using testing::Invoke;
@@ -109,7 +110,7 @@ class MockHttpStreamFactoryJob : public HttpStreamFactory::Job {
ProxyInfo proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
@@ -139,7 +140,7 @@ class TestJobFactory : public HttpStreamFactory::JobFactory {
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
bool is_websocket,
bool enable_ip_based_pooling,
@@ -154,7 +155,7 @@ class TestJobFactory : public HttpStreamFactory::JobFactory {
const ProxyInfo& proxy_info,
const SSLConfig& server_ssl_config,
const SSLConfig& proxy_ssl_config,
- HostPortPair destination,
+ url::SchemeHostPort destination,
GURL origin_url,
NextProto alternative_protocol,
quic::ParsedQuicVersion quic_version,
diff --git a/chromium/net/http/http_stream_factory_unittest.cc b/chromium/net/http/http_stream_factory_unittest.cc
index f8d80d73cca..5486b105ec7 100644
--- a/chromium/net/http/http_stream_factory_unittest.cc
+++ b/chromium/net/http/http_stream_factory_unittest.cc
@@ -14,10 +14,10 @@
#include "base/compiler_specific.h"
#include "base/containers/contains.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_piece.h"
#include "base/test/metrics/histogram_tester.h"
@@ -86,6 +86,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
// This file can be included from net/http even though
// it is in net/websockets because it doesn't
@@ -402,12 +404,12 @@ void PreconnectHelper(const TestCase& test, HttpNetworkSession* session) {
ClientSocketPool::GroupId GetGroupId(const TestCase& test) {
if (test.ssl) {
return ClientSocketPool::GroupId(
- HostPortPair("www.google.com", 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "www.google.com", 443),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
}
return ClientSocketPool::GroupId(
- HostPortPair("www.google.com", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
}
@@ -434,7 +436,8 @@ class CapturePreconnectsTransportSocketPool : public TransportClientSocketPool {
last_num_streams_ = -1;
// Group ID that shouldn't match much.
last_group_id_ = ClientSocketPool::GroupId(
- HostPortPair(), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme,
+ "unexpected.to.conflict.with.anything.test", 9999),
PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
}
@@ -843,10 +846,10 @@ TEST_F(HttpStreamFactoryTest, QuicProxyMarkedAsBad) {
ConfiguredProxyResolutionService::CreateFixedFromPacResult(
"QUIC bad:99; DIRECT", TRAFFIC_ANNOTATION_FOR_TESTS);
- HttpNetworkSession::Params session_params;
+ HttpNetworkSessionParams session_params;
session_params.enable_quic = true;
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
SSLConfigServiceDefaults ssl_config_service;
HttpServerProperties http_server_properties;
MockClientSocketFactory socket_factory;
@@ -987,7 +990,7 @@ TEST_F(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
"http_proxy", TRAFFIC_ANNOTATION_FOR_TESTS));
// Setup params to disable preconnect, but QUIC doesn't 0RTT.
- HttpNetworkSession::Params session_params =
+ HttpNetworkSessionParams session_params =
SpdySessionDependencies::CreateSessionParams(&session_deps);
session_params.enable_quic = true;
@@ -1003,7 +1006,7 @@ TEST_F(HttpStreamFactoryTest, UsePreConnectIfNoZeroRTT) {
server, NetworkIsolationKey(), alternative_service, expiration,
DefaultSupportedQuicVersions());
- HttpNetworkSession::Context session_context =
+ HttpNetworkSessionContext session_context =
SpdySessionDependencies::CreateSessionContext(&session_deps);
session_context.http_server_properties = &http_server_properties;
@@ -1763,7 +1766,7 @@ TEST_F(HttpStreamFactoryTest, NewSpdySessionCloseIdleH2Sockets) {
std::unique_ptr<HttpNetworkSession> session(
SpdySessionDependencies::SpdyCreateSession(&session_deps));
- HostPortPair host_port_pair("www.google.com", 443);
+ url::SchemeHostPort destination(url::kHttpsScheme, "www.google.com", 443);
// Create some HTTP/2 sockets.
std::vector<std::unique_ptr<ClientSocketHandle>> handles;
@@ -1776,8 +1779,7 @@ TEST_F(HttpStreamFactoryTest, NewSpdySessionCloseIdleH2Sockets) {
std::make_unique<SSLConfig>() /* ssl_config_for_origin */,
nullptr /* ssl_config_for_proxy */);
ClientSocketPool::GroupId group_id(
- host_port_pair, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ destination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
int rv = connection->Init(
group_id, socket_params, absl::nullopt /* proxy_annotation_tag */,
@@ -2014,7 +2016,7 @@ class HttpStreamFactoryBidirectionalQuicTest
quic_context_.params()->headers_include_h2_stream_dependency =
client_headers_include_h2_stream_dependency_;
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.http_server_properties = &http_server_properties_;
session_context.quic_context = &quic_context_;
@@ -2096,7 +2098,7 @@ class HttpStreamFactoryBidirectionalQuicTest
MockHostResolver host_resolver_;
std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<SSLConfigServiceDefaults> ssl_config_service_;
- HttpNetworkSession::Params params_;
+ HttpNetworkSessionParams params_;
};
INSTANTIATE_TEST_SUITE_P(VersionIncludeStreamDependencySequence,
@@ -3519,8 +3521,8 @@ class ProcessAlternativeServicesTest : public TestWithTaskEnvironment {
}
protected:
- HttpNetworkSession::Params session_params_;
- HttpNetworkSession::Context session_context_;
+ HttpNetworkSessionParams session_params_;
+ HttpNetworkSessionContext session_context_;
std::unique_ptr<HttpNetworkSession> session_;
HttpServerProperties http_server_properties_;
QuicContext quic_context_;
diff --git a/chromium/net/http/http_stream_parser_unittest.cc b/chromium/net/http/http_stream_parser_unittest.cc
index 8c234b97698..545b9f11b43 100644
--- a/chromium/net/http/http_stream_parser_unittest.cc
+++ b/chromium/net/http/http_stream_parser_unittest.cc
@@ -13,12 +13,12 @@
#include <vector>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -1361,7 +1361,7 @@ TEST(HttpStreamParser, Http09PortTests) {
get_runner.response_info()->headers->GetStatusLine());
EXPECT_EQ(0, get_runner.parser()->received_bytes());
- int read_lengths[] = {kResponse.size(), 0};
+ int read_lengths[] = {static_cast<int>(kResponse.size()), 0};
get_runner.ReadBody(kResponse.size(), read_lengths);
EXPECT_EQ(kResponse.size(),
static_cast<size_t>(get_runner.parser()->received_bytes()));
@@ -1386,7 +1386,7 @@ TEST(HttpStreamParser, Http09PortTests) {
get_runner.response_info()->headers->GetStatusLine());
EXPECT_EQ(0, get_runner.parser()->received_bytes());
- int read_lengths[] = {kShoutcastResponse.size(), 0};
+ int read_lengths[] = {static_cast<int>(kShoutcastResponse.size()), 0};
get_runner.ReadBody(kShoutcastResponse.size(), read_lengths);
EXPECT_EQ(kShoutcastResponse.size(),
static_cast<size_t>(get_runner.parser()->received_bytes()));
diff --git a/chromium/net/http/http_stream_request.cc b/chromium/net/http/http_stream_request.cc
index 3a38169db6e..980bc740455 100644
--- a/chromium/net/http/http_stream_request.cc
+++ b/chromium/net/http/http_stream_request.cc
@@ -8,7 +8,6 @@
#include "base/callback.h"
#include "base/check.h"
-#include "base/stl_util.h"
#include "net/http/bidirectional_stream_impl.h"
#include "net/log/net_log_event_type.h"
#include "net/spdy/bidirectional_stream_spdy_impl.h"
diff --git a/chromium/net/http/http_transaction_test_util.cc b/chromium/net/http/http_transaction_test_util.cc
index e81ccf0fd26..45f8e4263f2 100644
--- a/chromium/net/http/http_transaction_test_util.cc
+++ b/chromium/net/http/http_transaction_test_util.cc
@@ -10,10 +10,10 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/clock.h"
diff --git a/chromium/net/http/http_util.cc b/chromium/net/http/http_util.cc
index 1fc95492ab8..8a32b3075dd 100644
--- a/chromium/net/http/http_util.cc
+++ b/chromium/net/http/http_util.cc
@@ -10,7 +10,7 @@
#include <algorithm>
#include "base/check_op.h"
-#include "base/stl_util.h"
+#include "base/containers/cxx20_erase.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@@ -418,10 +418,6 @@ bool HttpUtil::IsToken(base::StringPiece string) {
return true;
}
-bool HttpUtil::IsControlChar(char c) {
- return (c >= 0x00 && c <= 0x1F) || c == 0x7F;
-}
-
// See RFC 5987 Sec 3.2.1 for the definition of |parmname|.
bool HttpUtil::IsParmName(base::StringPiece str) {
if (str.empty())
diff --git a/chromium/net/http/http_util.h b/chromium/net/http/http_util.h
index 202ff638f08..1b1208fa31b 100644
--- a/chromium/net/http/http_util.h
+++ b/chromium/net/http/http_util.h
@@ -130,7 +130,9 @@ class NET_EXPORT HttpUtil {
// Whether the character is a control character (CTL) as defined in RFC 5234
// Appendix B.1.
- static bool IsControlChar(char c);
+ static inline bool IsControlChar(char c) {
+ return (c >= 0x00 && c <= 0x1F) || c == 0x7F;
+ }
// Whether the string is a valid |parmname| as defined in RFC 5987 Sec 3.2.1.
static bool IsParmName(base::StringPiece str);
diff --git a/chromium/net/http/http_util_unittest.cc b/chromium/net/http/http_util_unittest.cc
index 255ed4bbd21..5b7b6a189cf 100644
--- a/chromium/net/http/http_util_unittest.cc
+++ b/chromium/net/http/http_util_unittest.cc
@@ -5,7 +5,7 @@
#include <algorithm>
#include <limits>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "net/http/http_util.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/http/http_vary_data_unittest.cc b/chromium/net/http/http_vary_data_unittest.cc
index 7442d0174a2..491454b9361 100644
--- a/chromium/net/http/http_vary_data_unittest.cc
+++ b/chromium/net/http/http_vary_data_unittest.cc
@@ -4,7 +4,7 @@
#include <algorithm>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/http/http_request_info.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_vary_data.h"
diff --git a/chromium/net/http/mock_http_cache.cc b/chromium/net/http/mock_http_cache.cc
index e6ea9bcedaf..728a36da34f 100644
--- a/chromium/net/http/mock_http_cache.cc
+++ b/chromium/net/http/mock_http_cache.cc
@@ -72,8 +72,7 @@ int GetTestModeForEntry(const std::string& key) {
struct MockDiskEntry::CallbackInfo {
scoped_refptr<MockDiskEntry> entry;
- net::CompletionOnceCallback callback;
- int result;
+ base::OnceClosure callback;
};
MockDiskEntry::MockDiskEntry(const std::string& key)
@@ -268,44 +267,47 @@ int MockDiskEntry::WriteSparseData(int64_t offset,
return ERR_IO_PENDING;
}
-int MockDiskEntry::GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) {
+disk_cache::RangeResult MockDiskEntry::GetAvailableRange(
+ int64_t offset,
+ int len,
+ RangeResultCallback callback) {
DCHECK(!callback.is_null());
if (!sparse_ || busy_ || cancel_)
- return ERR_CACHE_OPERATION_NOT_SUPPORTED;
+ return RangeResult(ERR_CACHE_OPERATION_NOT_SUPPORTED);
if (offset < 0)
- return ERR_FAILED;
+ return RangeResult(ERR_FAILED);
if (fail_requests_ & FAIL_GET_AVAILABLE_RANGE)
- return ERR_CACHE_READ_FAILURE;
+ return RangeResult(ERR_CACHE_READ_FAILURE);
- *start = offset;
+ RangeResult result;
+ result.net_error = OK;
+ result.start = offset;
+ result.available_len = 0;
DCHECK(offset < std::numeric_limits<int32_t>::max());
int real_offset = static_cast<int>(offset);
if (static_cast<int>(data_[1].size()) < real_offset)
- return 0;
+ return result;
int num = std::min(static_cast<int>(data_[1].size()) - real_offset, len);
- int count = 0;
for (; num > 0; num--, real_offset++) {
- if (!count) {
+ if (!result.available_len) {
if (data_[1][real_offset]) {
- count++;
- *start = real_offset;
+ result.available_len++;
+ result.start = real_offset;
}
} else {
if (!data_[1][real_offset])
break;
- count++;
+ result.available_len++;
}
}
- if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE)
- return count;
+ if (MockHttpCache::GetTestMode(test_mode_) & TEST_MODE_SYNC_CACHE_WRITE) {
+ return result;
+ }
- CallbackLater(std::move(callback), count);
- return ERR_IO_PENDING;
+ CallbackLater(base::BindOnce(std::move(callback), result));
+ return RangeResult(ERR_IO_PENDING);
}
bool MockDiskEntry::CouldBeSparse() const {
@@ -348,7 +350,7 @@ void MockDiskEntry::IgnoreCallbacks(bool value) {
return;
ignore_callbacks_ = value;
if (!value)
- StoreAndDeliverCallbacks(false, nullptr, CompletionOnceCallback(), 0);
+ StoreAndDeliverCallbacks(false, nullptr, base::OnceClosure());
}
MockDiskEntry::~MockDiskEntry() = default;
@@ -356,15 +358,19 @@ MockDiskEntry::~MockDiskEntry() = default;
// Unlike the callbacks for MockHttpTransaction, we want this one to run even
// if the consumer called Close on the MockDiskEntry. We achieve that by
// leveraging the fact that this class is reference counted.
-void MockDiskEntry::CallbackLater(CompletionOnceCallback callback, int result) {
+void MockDiskEntry::CallbackLater(base::OnceClosure callback) {
if (ignore_callbacks_)
- return StoreAndDeliverCallbacks(true, this, std::move(callback), result);
+ return StoreAndDeliverCallbacks(true, this, std::move(callback));
base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&MockDiskEntry::RunCallback, this,
- std::move(callback), result));
+ FROM_HERE,
+ base::BindOnce(&MockDiskEntry::RunCallback, this, std::move(callback)));
+}
+
+void MockDiskEntry::CallbackLater(CompletionOnceCallback callback, int result) {
+ CallbackLater(base::BindOnce(std::move(callback), result));
}
-void MockDiskEntry::RunCallback(CompletionOnceCallback callback, int result) {
+void MockDiskEntry::RunCallback(base::OnceClosure callback) {
if (busy_) {
// This is kind of hacky, but controlling the behavior of just this entry
// from a test is sort of complicated. What we really want to do is
@@ -376,11 +382,11 @@ void MockDiskEntry::RunCallback(CompletionOnceCallback callback, int result) {
// trips through the message loop instead of one).
if (!delayed_) {
delayed_ = true;
- return CallbackLater(std::move(callback), result);
+ return CallbackLater(std::move(callback));
}
}
busy_ = false;
- std::move(callback).Run(result);
+ std::move(callback).Run();
}
// When |store| is true, stores the callback to be delivered later; otherwise
@@ -388,16 +394,15 @@ void MockDiskEntry::RunCallback(CompletionOnceCallback callback, int result) {
// Static.
void MockDiskEntry::StoreAndDeliverCallbacks(bool store,
MockDiskEntry* entry,
- CompletionOnceCallback callback,
- int result) {
+ base::OnceClosure callback) {
static std::vector<CallbackInfo> callback_list;
if (store) {
- CallbackInfo c = {entry, std::move(callback), result};
+ CallbackInfo c = {entry, std::move(callback)};
callback_list.push_back(std::move(c));
} else {
for (size_t i = 0; i < callback_list.size(); i++) {
CallbackInfo& c = callback_list[i];
- c.entry->CallbackLater(std::move(c.callback), c.result);
+ c.entry->CallbackLater(std::move(c.callback));
}
callback_list.clear();
}
diff --git a/chromium/net/http/mock_http_cache.h b/chromium/net/http/mock_http_cache.h
index f0736c17e69..7d9731926c0 100644
--- a/chromium/net/http/mock_http_cache.h
+++ b/chromium/net/http/mock_http_cache.h
@@ -79,10 +79,9 @@ class MockDiskEntry : public disk_cache::Entry,
IOBuffer* buf,
int buf_len,
CompletionOnceCallback callback) override;
- int GetAvailableRange(int64_t offset,
- int len,
- int64_t* start,
- CompletionOnceCallback callback) override;
+ RangeResult GetAvailableRange(int64_t offset,
+ int len,
+ RangeResultCallback callback) override;
bool CouldBeSparse() const override;
void CancelSparseIO() override;
net::Error ReadyForSparseIO(
@@ -123,15 +122,15 @@ class MockDiskEntry : public disk_cache::Entry,
// if the consumer called Close on the MockDiskEntry. We achieve that by
// leveraging the fact that this class is reference counted.
void CallbackLater(CompletionOnceCallback callback, int result);
+ void CallbackLater(base::OnceClosure callback);
- void RunCallback(CompletionOnceCallback callback, int result);
+ void RunCallback(base::OnceClosure callback);
// When |store| is true, stores the callback to be delivered later; otherwise
// delivers any callback previously stored.
static void StoreAndDeliverCallbacks(bool store,
MockDiskEntry* entry,
- CompletionOnceCallback callback,
- int result);
+ base::OnceClosure callback);
static const int kNumCacheEntryDataIndices = 3;
diff --git a/chromium/net/http/partial_data.cc b/chromium/net/http/partial_data.cc
index 79f71ab662b..3f76d090e79 100644
--- a/chromium/net/http/partial_data.cc
+++ b/chromium/net/http/partial_data.cc
@@ -107,22 +107,18 @@ int PartialData::ShouldValidateCache(disk_cache::Entry* entry,
if (sparse_entry_) {
DCHECK(callback_.is_null());
- // |start| will be deleted later in this method if GetAvailableRange()
- // returns synchronously, or by GetAvailableRangeCompleted() if it returns
- // asynchronously.
- int64_t* start = new int64_t;
- CompletionOnceCallback cb =
- base::BindOnce(&PartialData::GetAvailableRangeCompleted,
- weak_factory_.GetWeakPtr(), start);
- cached_min_len_ = entry->GetAvailableRange(current_range_start_, len, start,
- std::move(cb));
+ disk_cache::RangeResultCallback cb = base::BindOnce(
+ &PartialData::GetAvailableRangeCompleted, weak_factory_.GetWeakPtr());
+ disk_cache::RangeResult range =
+ entry->GetAvailableRange(current_range_start_, len, std::move(cb));
+ cached_min_len_ =
+ range.net_error == OK ? range.available_len : range.net_error;
if (cached_min_len_ == ERR_IO_PENDING) {
callback_ = std::move(callback);
return ERR_IO_PENDING;
} else {
- cached_start_ = *start;
- delete start;
+ cached_start_ = range.start;
}
} else if (!truncated_) {
if (byte_range_.HasFirstBytePosition() &&
@@ -456,17 +452,20 @@ int PartialData::GetNextRangeLen() {
return static_cast<int32_t>(range_len);
}
-void PartialData::GetAvailableRangeCompleted(int64_t* start, int result) {
+void PartialData::GetAvailableRangeCompleted(
+ const disk_cache::RangeResult& result) {
DCHECK(!callback_.is_null());
- DCHECK_NE(ERR_IO_PENDING, result);
+ DCHECK_NE(ERR_IO_PENDING, result.net_error);
- cached_start_ = *start;
- delete start;
- cached_min_len_ = result;
- if (result >= 0)
- result = 1; // Return success, go ahead and validate the entry.
+ int len_or_error =
+ result.net_error == OK ? result.available_len : result.net_error;
+ cached_start_ = result.start;
+ cached_min_len_ = len_or_error;
- std::move(callback_).Run(result);
+ // ShouldValidateCache has an unusual convention where 0 denotes EOF,
+ // so convert end of range to success (since there may be things that need
+ // fetching from network or other ranges).
+ std::move(callback_).Run(len_or_error >= 0 ? 1 : len_or_error);
}
} // namespace net
diff --git a/chromium/net/http/partial_data.h b/chromium/net/http/partial_data.h
index 3e8b1a406dc..134c32e333e 100644
--- a/chromium/net/http/partial_data.h
+++ b/chromium/net/http/partial_data.h
@@ -10,12 +10,10 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "net/base/completion_once_callback.h"
+#include "net/disk_cache/disk_cache.h"
#include "net/http/http_byte_range.h"
#include "net/http/http_request_headers.h"
-namespace disk_cache {
-class Entry;
-}
namespace net {
@@ -131,8 +129,8 @@ class PartialData {
// Returns the length to use when scanning the cache.
int GetNextRangeLen();
- // Completion routine for our callback. Deletes |start|.
- void GetAvailableRangeCompleted(int64_t* start, int result);
+ // Completion routine for our callback.
+ void GetAvailableRangeCompleted(const disk_cache::RangeResult& result);
// The portion we're trying to get, either from cache or network.
int64_t current_range_start_;
@@ -143,7 +141,8 @@ class PartialData {
// succeeds.
//
// |cached_start_| represents the beginning of the range, while
- // |cached_min_len_| the data not yet read (possibly overestimated).
+ // |cached_min_len_| the data not yet read (possibly overestimated). It may
+ // also have an error code latched into it.
int64_t cached_start_;
int cached_min_len_;
diff --git a/chromium/net/http/transport_security_persister.cc b/chromium/net/http/transport_security_persister.cc
index 9603507a520..e4e4a156668 100644
--- a/chromium/net/http/transport_security_persister.cc
+++ b/chromium/net/http/transport_security_persister.cc
@@ -15,7 +15,6 @@
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
-#include "base/metrics/histogram_macros.h"
#include "base/sequenced_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -296,10 +295,10 @@ void OnWriteFinishedTask(scoped_refptr<base::SequencedTaskRunner> task_runner,
TransportSecurityPersister::TransportSecurityPersister(
TransportSecurityState* state,
- const base::FilePath& profile_path,
- const scoped_refptr<base::SequencedTaskRunner>& background_runner)
+ const scoped_refptr<base::SequencedTaskRunner>& background_runner,
+ const base::FilePath& data_path)
: transport_security_state_(state),
- writer_(profile_path.AppendASCII("TransportSecurity"), background_runner),
+ writer_(data_path, background_runner),
foreground_runner_(base::ThreadTaskRunnerHandle::Get()),
background_runner_(background_runner) {
transport_security_state_->SetDelegate(this);
@@ -388,10 +387,6 @@ void TransportSecurityPersister::Deserialize(const std::string& serialized,
base::Value* expect_ct_value = value->FindKey(kExpectCTKey);
if (expect_ct_value)
DeserializeExpectCTData(*expect_ct_value, state);
-
- UMA_HISTOGRAM_CUSTOM_COUNTS("Net.ExpectCT.EntriesOnLoad",
- state->num_expect_ct_entries(), 1 /* min */,
- 2000 /* max */, 40 /* buckets */);
}
void TransportSecurityPersister::CompleteLoad(const std::string& state) {
diff --git a/chromium/net/http/transport_security_persister.h b/chromium/net/http/transport_security_persister.h
index aa30cbbe0dd..7a5c5a37196 100644
--- a/chromium/net/http/transport_security_persister.h
+++ b/chromium/net/http/transport_security_persister.h
@@ -58,10 +58,13 @@ class NET_EXPORT TransportSecurityPersister
: public TransportSecurityState::Delegate,
public base::ImportantFileWriter::DataSerializer {
public:
+ // Create a TransportSecurityPersister with state |state| on background runner
+ // |background_runner|. |data_path| points to the file to hold the transport
+ // security state data on disk.
TransportSecurityPersister(
TransportSecurityState* state,
- const base::FilePath& profile_path,
- const scoped_refptr<base::SequencedTaskRunner>& background_runner);
+ const scoped_refptr<base::SequencedTaskRunner>& background_runner,
+ const base::FilePath& data_path);
~TransportSecurityPersister() override;
// Called by the TransportSecurityState when it changes its state.
diff --git a/chromium/net/http/transport_security_persister_unittest.cc b/chromium/net/http/transport_security_persister_unittest.cc
index 530e98ff7be..a1f2ec3edfb 100644
--- a/chromium/net/http/transport_security_persister_unittest.cc
+++ b/chromium/net/http/transport_security_persister_unittest.cc
@@ -54,6 +54,8 @@ class TransportSecurityPersisterTest : public ::testing::TestWithParam<bool>,
void SetUp() override {
ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ transport_security_file_path_ =
+ temp_dir_.GetPath().AppendASCII("TransportSecurity");
ASSERT_TRUE(base::CurrentIOThread::IsSet());
scoped_refptr<base::SequencedTaskRunner> background_runner(
base::ThreadPool::CreateSequencedTaskRunner(
@@ -69,12 +71,14 @@ class TransportSecurityPersisterTest : public ::testing::TestWithParam<bool>,
}
state_ = std::make_unique<TransportSecurityState>();
persister_ = std::make_unique<TransportSecurityPersister>(
- state_.get(), temp_dir_.GetPath(), std::move(background_runner));
+ state_.get(), std::move(background_runner),
+ transport_security_file_path_);
}
bool partition_expect_ct_state() const { return GetParam(); }
protected:
+ base::FilePath transport_security_file_path_;
base::ScopedTempDir temp_dir_;
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<TransportSecurityState> state_;
@@ -198,9 +202,9 @@ TEST_P(TransportSecurityPersisterTest, SerializeData3) {
run_loop.Run();
// Read the data back.
- base::FilePath path = temp_dir_.GetPath().AppendASCII("TransportSecurity");
std::string persisted;
- EXPECT_TRUE(base::ReadFileToString(path, &persisted));
+ EXPECT_TRUE(
+ base::ReadFileToString(transport_security_file_path_, &persisted));
EXPECT_EQ(persisted, serialized);
persister_->LoadEntries(persisted);
@@ -226,23 +230,23 @@ TEST_P(TransportSecurityPersisterTest, SerializeData3) {
// entries being added to the transport security state.
TEST_P(TransportSecurityPersisterTest, DeserializeBadData) {
persister_->LoadEntries("");
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
persister_->LoadEntries("Foopy");
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
persister_->LoadEntries("15");
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
persister_->LoadEntries("[15]");
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
persister_->LoadEntries("{\"version\":1}");
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
}
@@ -258,7 +262,7 @@ TEST_P(TransportSecurityPersisterTest, DeserializeDataOldWithoutCreationDate) {
"}"
"}";
persister_->LoadEntries(kInput);
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
}
@@ -300,7 +304,7 @@ TEST_P(TransportSecurityPersisterTest, DeserializeDataOldMergedDictionary) {
"}";
persister_->LoadEntries(kInput);
- EXPECT_EQ(0u, state_->num_expect_ct_entries());
+ EXPECT_EQ(0u, state_->num_expect_ct_entries_for_testing());
EXPECT_EQ(0u, state_->num_sts_entries());
}
@@ -441,10 +445,11 @@ TEST_P(TransportSecurityPersisterTest, ExpectCTWithNetworkIsolationKey) {
features::kPartitionExpectCTStateByNetworkIsolationKey);
TransportSecurityState state2;
TransportSecurityPersister persister2(
- &state2, temp_dir_.GetPath(),
+ &state2,
std::move(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN})));
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ transport_security_file_path_);
TransportSecurityState::ExpectCTState expect_ct_state;
state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
empty_network_isolation_key);
@@ -521,10 +526,11 @@ TEST_P(TransportSecurityPersisterTest,
std::string serialized;
TransportSecurityState state2;
TransportSecurityPersister persister2(
- &state2, temp_dir_.GetPath(),
+ &state2,
std::move(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN})));
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN})),
+ transport_security_file_path_);
TransportSecurityState::ExpectCTState expect_ct_state;
state2.AddExpectCT(kTestDomain, expiry1, true /* enforce */, GURL(),
empty_network_isolation_key);
diff --git a/chromium/net/http/transport_security_state.cc b/chromium/net/http/transport_security_state.cc
index 857a7b4d0cb..2e9761fb621 100644
--- a/chromium/net/http/transport_security_state.cc
+++ b/chromium/net/http/transport_security_state.cc
@@ -393,7 +393,12 @@ void SetTransportSecurityStateSourceForTesting(
}
TransportSecurityState::TransportSecurityState()
- : TransportSecurityState(std::vector<std::string>()) {}
+ : TransportSecurityState(std::vector<std::string>()) {
+ // By default the CT log list is treated as last updated at build time (since
+ // a compiled-in list is used), this is overridden if the list is dynamically
+ // updated.
+ ct_log_list_last_update_time_ = base::GetBuildTime();
+}
TransportSecurityState::TransportSecurityState(
std::vector<std::string> hsts_host_bypass_list)
@@ -482,6 +487,10 @@ TransportSecurityState::CheckCTRequirements(
using CTRequirementLevel = RequireCTDelegate::CTRequirementLevel;
std::string hostname = host_port_pair.host();
+ // If CT emergency disable flag is set, we don't require CT for any host.
+ if (ct_emergency_disable_)
+ return CT_NOT_REQUIRED;
+
// CT is not required if the certificate does not chain to a publicly
// trusted root certificate. Testing can override this, as certain tests
// rely on using a non-publicly-trusted root.
@@ -603,6 +612,10 @@ void TransportSecurityState::SetRequireCTDelegate(RequireCTDelegate* delegate) {
require_ct_delegate_ = delegate;
}
+void TransportSecurityState::SetCTLogListUpdateTime(base::Time update_time) {
+ ct_log_list_last_update_time_ = update_time;
+}
+
void TransportSecurityState::AddHSTSInternal(
const std::string& host,
TransportSecurityState::STSState::UpgradeMode upgrade_mode,
@@ -769,7 +782,7 @@ bool TransportSecurityState::GetStaticExpectCTState(
ExpectCTState* expect_ct_state) const {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (!IsBuildTimely())
+ if (!IsCTLogListTimely())
return false;
PreloadResult result;
@@ -1068,7 +1081,7 @@ void TransportSecurityState::ClearReportCachesForTesting() {
sent_expect_ct_reports_cache_.Clear();
}
-size_t TransportSecurityState::num_expect_ct_entries() const {
+size_t TransportSecurityState::num_expect_ct_entries_for_testing() const {
return enabled_expect_ct_hosts_.size();
}
@@ -1527,4 +1540,16 @@ bool TransportSecurityState::ExpectCTPruningSorter(
it2->second.last_observed);
}
+bool TransportSecurityState::IsCTLogListTimely() const {
+ // Preloaded Expect-CT is enforced if the CT log list is timely. Note that
+ // unlike HSTS and HPKP, the date of the preloaded list itself (i.e.
+ // base::GetBuildTime()) is not directly consulted. Consulting the
+ // build time would allow sites that have subsequently disabled Expect-CT
+ // to opt-out. However, because as of June 2021, all unexpired certificates
+ // are already expected to comply with the policies expressed by Expect-CT,
+ // there's no need to offer an opt-out.
+ return (base::Time::Now() - ct_log_list_last_update_time_).InDays() <
+ 70 /* 10 weeks */;
+}
+
} // namespace net
diff --git a/chromium/net/http/transport_security_state.h b/chromium/net/http/transport_security_state.h
index aa1c8372b3c..7e24b4cb49b 100644
--- a/chromium/net/http/transport_security_state.h
+++ b/chromium/net/http/transport_security_state.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include <map>
+#include <set>
#include <string>
#include "base/callback.h"
@@ -433,6 +434,15 @@ class NET_EXPORT TransportSecurityState {
// occurs first.
void SetRequireCTDelegate(RequireCTDelegate* delegate);
+ // If |emergency_disable| is set to true, will stop requiring CT
+ // compliance on any further requests regardless of host or certificate
+ // status.
+ void SetCTEmergencyDisabled(bool emergency_disable) {
+ ct_emergency_disable_ = emergency_disable;
+ }
+
+ void SetCTLogListUpdateTime(base::Time update_time);
+
// Clears all dynamic data (e.g. HSTS and HPKP data).
//
// Does NOT persist changes using the Delegate, as this function is only
@@ -574,7 +584,7 @@ class NET_EXPORT TransportSecurityState {
bool has_dynamic_pkp_state() const { return !enabled_pkp_hosts_.empty(); }
// The number of cached ExpectCTState entries.
- size_t num_expect_ct_entries() const;
+ size_t num_expect_ct_entries_for_testing() const;
// The number of cached STSState entries.
size_t num_sts_entries() const;
@@ -684,6 +694,9 @@ class NET_EXPORT TransportSecurityState {
static bool ExpectCTPruningSorter(const ExpectCTStateMap::iterator& it1,
const ExpectCTStateMap::iterator& it2);
+ // Returns true if the CT log list has been updated in the last 10 weeks.
+ bool IsCTLogListTimely() const;
+
// The sets of hosts that have enabled TransportSecurity. |domain| will always
// be empty for a STSState, PKPState, or ExpectCTState in these maps; the
// domain comes from the map keys instead. In addition, |upgrade_mode| in the
@@ -727,6 +740,10 @@ class NET_EXPORT TransportSecurityState {
std::set<std::string> hsts_host_bypass_list_;
+ bool ct_emergency_disable_ = false;
+
+ base::Time ct_log_list_last_update_time_;
+
THREAD_CHECKER(thread_checker_);
DISALLOW_COPY_AND_ASSIGN(TransportSecurityState);
diff --git a/chromium/net/http/transport_security_state_static.json.gz b/chromium/net/http/transport_security_state_static.json.gz
index d2557b61e55..7bdf030ecd5 100644
--- a/chromium/net/http/transport_security_state_static.json.gz
+++ b/chromium/net/http/transport_security_state_static.json.gz
Binary files differ
diff --git a/chromium/net/http/transport_security_state_static.template b/chromium/net/http/transport_security_state_static.template
index ceb400a0834..21542f9b7ce 100644
--- a/chromium/net/http/transport_security_state_static.template
+++ b/chromium/net/http/transport_security_state_static.template
@@ -9,7 +9,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/http/transport_security_state_source.h"
// These are SubjectPublicKeyInfo hashes for public key pinning. The
diff --git a/chromium/net/http/transport_security_state_static_unittest.template b/chromium/net/http/transport_security_state_static_unittest.template
index 08b21164872..0c4f5966f11 100644
--- a/chromium/net/http/transport_security_state_static_unittest.template
+++ b/chromium/net/http/transport_security_state_static_unittest.template
@@ -8,7 +8,7 @@
#include <stdint.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/http/transport_security_state_source.h"
[[SPKI_HASHES]]
diff --git a/chromium/net/http/transport_security_state_test_util.cc b/chromium/net/http/transport_security_state_test_util.cc
index d66bfacb66f..d0d05bb4d33 100644
--- a/chromium/net/http/transport_security_state_test_util.cc
+++ b/chromium/net/http/transport_security_state_test_util.cc
@@ -4,6 +4,7 @@
#include "net/http/transport_security_state_test_util.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/http/transport_security_state.h"
#include "url/gurl.h"
diff --git a/chromium/net/http/transport_security_state_unittest.cc b/chromium/net/http/transport_security_state_unittest.cc
index 6d6cff5ee82..ed9d676f571 100644
--- a/chromium/net/http/transport_security_state_unittest.cc
+++ b/chromium/net/http/transport_security_state_unittest.cc
@@ -16,6 +16,7 @@
#include "base/metrics/field_trial.h"
#include "base/metrics/field_trial_param_associator.h"
#include "base/rand_util.h"
+#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
@@ -1739,6 +1740,99 @@ TEST_F(TransportSecurityStateTest, RequireCTConsultsDelegate) {
}
}
+// Tests that the emergency disable flag causes CT to stop being required
+// regardless of host or delegate status.
+TEST_F(TransportSecurityStateTest, CTEmergencyDisable) {
+ using ::testing::_;
+ using ::testing::Return;
+ using CTRequirementLevel =
+ TransportSecurityState::RequireCTDelegate::CTRequirementLevel;
+
+ // Dummy cert to use as the validation chain. The contents do not matter.
+ scoped_refptr<X509Certificate> cert =
+ ImportCertFromFile(GetTestCertsDirectory(), "expired_cert.pem");
+ ASSERT_TRUE(cert);
+
+ HashValueVector hashes;
+ hashes.push_back(
+ HashValue(X509Certificate::CalculateFingerprint256(cert->cert_buffer())));
+
+ TransportSecurityState state;
+
+ // Set CT emergency disable flag.
+ state.SetCTEmergencyDisabled(true);
+
+ MockRequireCTDelegate always_require_delegate;
+ EXPECT_CALL(always_require_delegate, IsCTRequiredForHost(_, _, _))
+ .WillRepeatedly(Return(CTRequirementLevel::REQUIRED));
+ state.SetRequireCTDelegate(&always_require_delegate);
+ EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+ state.CheckCTRequirements(
+ HostPortPair("www.example.com", 443), true, hashes, cert.get(),
+ cert.get(), SignedCertificateTimestampAndStatusList(),
+ TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
+ NetworkIsolationKey()));
+ EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+ state.CheckCTRequirements(
+ HostPortPair("www.example.com", 443), true, hashes, cert.get(),
+ cert.get(), SignedCertificateTimestampAndStatusList(),
+ TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct::CTPolicyCompliance::CT_POLICY_NOT_DIVERSE_SCTS,
+ NetworkIsolationKey()));
+ EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+ state.CheckCTRequirements(
+ HostPortPair("www.example.com", 443), true, hashes, cert.get(),
+ cert.get(), SignedCertificateTimestampAndStatusList(),
+ TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct::CTPolicyCompliance::CT_POLICY_COMPLIES_VIA_SCTS,
+ NetworkIsolationKey()));
+ EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+ state.CheckCTRequirements(
+ HostPortPair("www.example.com", 443), true, hashes, cert.get(),
+ cert.get(), SignedCertificateTimestampAndStatusList(),
+ TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct::CTPolicyCompliance::CT_POLICY_BUILD_NOT_TIMELY,
+ NetworkIsolationKey()));
+
+ state.SetRequireCTDelegate(nullptr);
+ EXPECT_EQ(TransportSecurityState::CT_NOT_REQUIRED,
+ state.CheckCTRequirements(
+ HostPortPair("www.example.com", 443), true, hashes, cert.get(),
+ cert.get(), SignedCertificateTimestampAndStatusList(),
+ TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
+ ct::CTPolicyCompliance::CT_POLICY_NOT_ENOUGH_SCTS,
+ NetworkIsolationKey()));
+}
+
+// Tests that the if the CT log list last update time is set, it is used for
+// enforcement decisions.
+TEST_F(TransportSecurityStateTest, CTTimestampUpdate) {
+ TransportSecurityState state;
+ TransportSecurityStateTest::EnableStaticExpectCT(&state);
+ TransportSecurityState::ExpectCTState expect_ct_state;
+ // Initially the preloaded host should require CT.
+ EXPECT_TRUE(
+ GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
+
+ // Change the last updated time to a value greater than 10 weeks.
+ // We use a close value (70 days + 1 hour ago) to ensure rounding behavior is
+ // working properly.
+ state.SetCTLogListUpdateTime(
+ base::Time::Now() -
+ (base::TimeDelta::FromDays(70) + base::TimeDelta::FromHours(1)));
+ // CT should no longer be required.
+ EXPECT_FALSE(
+ GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
+
+ // CT should once again be required after the log list is newer than 70 days.
+ state.SetCTLogListUpdateTime(
+ base::Time::Now() -
+ (base::TimeDelta::FromDays(70) - base::TimeDelta::FromHours(1)));
+ EXPECT_TRUE(
+ GetExpectCTState(&state, kExpectCTStaticHostname, &expect_ct_state));
+}
+
// Tests that Certificate Transparency is required for Symantec-issued
// certificates, unless the certificate was issued prior to 1 June 2016
// or the issuing CA is permitted as independently operated.
@@ -3697,7 +3791,7 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTDelay) {
// Should have removed enough entries to get down to kExpectCTPruneMin
// entries.
EXPECT_EQ(features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// Add more prunable entries, but pruning should not be triggered, due to the
// delay between subsequent pruning tasks.
@@ -3708,14 +3802,14 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTDelay) {
}
EXPECT_EQ(
features::kExpectCTPruneMax.Get() + features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// Time passes, which does not trigger pruning.
FastForwardBy(
base::TimeDelta::FromSeconds(features::kExpectCTPruneDelaySecs.Get()));
EXPECT_EQ(
features::kExpectCTPruneMax.Get() + features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// Another entry is added, which triggers pruning, now that enough time has
// passed.
@@ -3723,13 +3817,13 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTDelay) {
report_uri,
CreateUniqueNetworkIsolationKey(true /* is_transient */));
EXPECT_EQ(features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// More time passes.
FastForwardBy(base::TimeDelta::FromSeconds(
10 * features::kExpectCTPruneDelaySecs.Get()));
EXPECT_EQ(features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// When enough entries are added to trigger pruning, it runs immediately,
// since enough time has passed.
@@ -3741,7 +3835,7 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTDelay) {
CreateUniqueNetworkIsolationKey(true /* is_transient */));
}
EXPECT_EQ(features::kExpectCTPruneMin.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
}
// Test that Expect-CT pruning respects kExpectCTMaxEntriesPerNik, which is only
@@ -3773,7 +3867,7 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTNetworkIsolationKeyLimit) {
CreateUniqueNetworkIsolationKey(false /* is_transient */));
}
EXPECT_EQ(features::kExpectCTPruneMax.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// Add kExpectCTMaxEntriesPerNik non-prunable entries with a single NIK,
// allowing pruning to run each time. No entries should be deleted.
@@ -3785,7 +3879,7 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTNetworkIsolationKeyLimit) {
state.AddExpectCT(CreateUniqueHostName(), expiry2, true /* enforce */,
report_uri, network_isolation_key);
EXPECT_EQ(features::kExpectCTPruneMax.Get() + i + 1,
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
}
// Add kExpectCTMaxEntriesPerNik non-prunable entries with the same NIK as
@@ -3798,7 +3892,7 @@ TEST_F(TransportSecurityStateTest, PruneExpectCTNetworkIsolationKeyLimit) {
report_uri, network_isolation_key);
EXPECT_EQ(features::kExpectCTPruneMax.Get() +
features::kExpectCTMaxEntriesPerNik.Get(),
- static_cast<int>(state.num_expect_ct_entries()));
+ static_cast<int>(state.num_expect_ct_entries_for_testing()));
// Count entries with |expiry2| and |expiry3|. For each loop iteration, an
// entry with |expiry2| should be replaced by one with |expiry3|.
diff --git a/chromium/net/http/url_security_manager_unittest.cc b/chromium/net/http/url_security_manager_unittest.cc
index 93f31186037..f4e16e73f6a 100644
--- a/chromium/net/http/url_security_manager_unittest.cc
+++ b/chromium/net/http/url_security_manager_unittest.cc
@@ -6,7 +6,7 @@
#include <utility>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/net_errors.h"
#include "net/http/http_auth_filter.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/http2/platform/impl/http2_string_utils_impl.h b/chromium/net/http2/platform/impl/http2_string_utils_impl.h
deleted file mode 100644
index e39261e361a..00000000000
--- a/chromium/net/http2/platform/impl/http2_string_utils_impl.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_
-#define NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_
-
-#include <sstream>
-#include <utility>
-
-#include "base/strings/abseil_string_conversions.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "net/base/escape.h"
-#include "net/base/hex_utils.h"
-#include "net/third_party/quiche/src/common/quiche_text_utils.h"
-
-namespace http2 {
-
-inline std::string Http2HexDumpImpl(absl::string_view data) {
- return quiche::QuicheTextUtils::HexDump(data);
-}
-
-} // namespace http2
-
-#endif // NET_HTTP2_PLATFORM_IMPL_HTTP2_STRING_UTILS_IMPL_H_
diff --git a/chromium/net/log/net_log_event_type_list.h b/chromium/net/log/net_log_event_type_list.h
index 69d9b86806d..5446ad7b69e 100644
--- a/chromium/net/log/net_log_event_type_list.h
+++ b/chromium/net/log/net_log_event_type_list.h
@@ -2647,6 +2647,9 @@ EVENT_TYPE(AUTH_BOUND_TO_CONTROLLER)
// "scheme": <scheme>
// "net_error": <Net Error. Only present in case of error.>
// "challenge": <challenge string, if NetLogCaptureIncludesSensitive>
+// "origin": <the origin of the server or proxy which issued the challenge>
+// "allows_default_credentials": <whether the default credentials may be
+// used for the origin>
// }
EVENT_TYPE(AUTH_HANDLER_CREATE_RESULT)
@@ -2862,6 +2865,10 @@ EVENT_TYPE(SPECIFIC_NETWORK_SOON_TO_DISCONNECT)
// }
EVENT_TYPE(SPECIFIC_NETWORK_MADE_DEFAULT)
+// This event is emitted whenever CertDatabase determines that the certificate
+// database has changed.
+EVENT_TYPE(CERTIFICATE_DATABASE_CHANGED)
+
// ------------------------------------------------------------------------
// Exponential back-off throttling events
// ------------------------------------------------------------------------
diff --git a/chromium/net/log/net_log_source_type_list.h b/chromium/net/log/net_log_source_type_list.h
index 15f1cdd6eb4..50d0e3b9f4a 100644
--- a/chromium/net/log/net_log_source_type_list.h
+++ b/chromium/net/log/net_log_source_type_list.h
@@ -45,3 +45,4 @@ SOURCE_TYPE(COOKIE_STORE)
SOURCE_TYPE(HTTP_AUTH_CONTROLLER)
SOURCE_TYPE(HTTP3_SESSION)
SOURCE_TYPE(QUIC_TRANSPORT_CLIENT)
+SOURCE_TYPE(NETWORK_SERVICE_HOST_RESOLVER)
diff --git a/chromium/net/log/net_log_unittest.cc b/chromium/net/log/net_log_unittest.cc
index f83b334c298..2d028b367db 100644
--- a/chromium/net/log/net_log_unittest.cc
+++ b/chromium/net/log/net_log_unittest.cc
@@ -4,7 +4,7 @@
#include "net/log/net_log.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/task_environment.h"
#include "base/threading/simple_thread.h"
diff --git a/chromium/net/log/test_net_log.h b/chromium/net/log/test_net_log.h
index 2aebd279e6c..f59e23acbb6 100644
--- a/chromium/net/log/test_net_log.h
+++ b/chromium/net/log/test_net_log.h
@@ -7,7 +7,6 @@
#include <stddef.h>
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/net/log/trace_net_log_observer_unittest.cc b/chromium/net/log/trace_net_log_observer_unittest.cc
index 13eb16bf507..7bdc5a75c49 100644
--- a/chromium/net/log/trace_net_log_observer_unittest.cc
+++ b/chromium/net/log/trace_net_log_observer_unittest.cc
@@ -120,7 +120,7 @@ class TraceNetLogObserverTest : public TestWithTaskEnvironment {
base::RunLoop* run_loop,
const scoped_refptr<base::RefCountedString>& events_str,
bool has_more_events) {
- DCHECK(trace_events_->empty());
+ DCHECK(trace_events_->GetList().empty());
trace_buffer_.Start();
trace_buffer_.AddFragment(events_str->data());
trace_buffer_.Finish();
diff --git a/chromium/net/network_error_logging/OWNERS b/chromium/net/network_error_logging/OWNERS
index 7117a80a72b..acbf93af41e 100644
--- a/chromium/net/network_error_logging/OWNERS
+++ b/chromium/net/network_error_logging/OWNERS
@@ -1 +1 @@
-chlily@chromium.org
+yhirano@chromium.org
diff --git a/chromium/net/network_error_logging/mock_persistent_nel_store.h b/chromium/net/network_error_logging/mock_persistent_nel_store.h
index a5a646da609..15af5fa1684 100644
--- a/chromium/net/network_error_logging/mock_persistent_nel_store.h
+++ b/chromium/net/network_error_logging/mock_persistent_nel_store.h
@@ -5,7 +5,6 @@
#ifndef NET_NETWORK_ERROR_LOGGING_MOCK_PERSISTENT_NEL_STORE_H_
#define NET_NETWORK_ERROR_LOGGING_MOCK_PERSISTENT_NEL_STORE_H_
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/net/network_error_logging/network_error_logging_service.cc b/chromium/net/network_error_logging/network_error_logging_service.cc
index b2faaaa72b1..afc786921aa 100644
--- a/chromium/net/network_error_logging/network_error_logging_service.cc
+++ b/chromium/net/network_error_logging/network_error_logging_service.cc
@@ -10,12 +10,12 @@
#include <vector>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/json/json_reader.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/time/clock.h"
#include "base/time/default_clock.h"
#include "base/time/time.h"
diff --git a/chromium/net/nqe/network_qualities_prefs_manager.cc b/chromium/net/nqe/network_qualities_prefs_manager.cc
index f960ad9a96e..6c4ad458c83 100644
--- a/chromium/net/nqe/network_qualities_prefs_manager.cc
+++ b/chromium/net/nqe/network_qualities_prefs_manager.cc
@@ -35,7 +35,7 @@ ParsedPrefs ConvertDictionaryValueToMap(const base::DictionaryValue* value) {
DCHECK_GE(kMaxCacheSize, value->DictSize());
ParsedPrefs read_prefs;
- for (const auto& it : value->DictItems()) {
+ for (auto it : value->DictItems()) {
nqe::internal::NetworkID network_id =
nqe::internal::NetworkID::FromString(it.first);
@@ -135,7 +135,7 @@ void NetworkQualitiesPrefsManager::OnChangeInCachedNetworkQuality(
// |kMaxCacheSize|.
int index_to_delete = base::RandInt(0, kMaxCacheSize - 1);
- for (const auto& it : prefs_->DictItems()) {
+ for (auto it : prefs_->DictItems()) {
// Delete the kth element in the dictionary, not including the element
// that represents the current network. k == |index_to_delete|.
if (nqe::internal::NetworkID::FromString(it.first) == network_id)
diff --git a/chromium/net/nqe/network_quality_estimator.cc b/chromium/net/nqe/network_quality_estimator.cc
index 1ebb0b78061..13787418ff7 100644
--- a/chromium/net/nqe/network_quality_estimator.cc
+++ b/chromium/net/nqe/network_quality_estimator.cc
@@ -13,6 +13,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/metrics/field_trial_params.h"
#include "base/metrics/histogram.h"
@@ -22,7 +23,6 @@
#include "base/metrics/histogram_macros_local.h"
#include "base/notreached.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/task/lazy_thread_pool_task_runner.h"
@@ -89,49 +89,11 @@ bool RequestSchemeIsHTTPOrHTTPS(const URLRequest& request) {
nqe::internal::NetworkID DoGetCurrentNetworkID(
NetworkQualityEstimatorParams* params) {
- // It is possible that the connection type changed between when
- // GetConnectionType() was called and when the API to determine the
- // network name was called. Check if that happened and retry until the
- // connection type stabilizes. This is an imperfect solution but should
- // capture majority of cases, and should not significantly affect estimates
- // (that are approximate to begin with).
- while (true) {
nqe::internal::NetworkID network_id(
NetworkChangeNotifier::GetConnectionType(), std::string(), INT32_MIN);
- if (!params || !params->get_signal_strength_and_detailed_network_id())
- return network_id;
-
- switch (network_id.type) {
- case NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_NONE:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET:
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI:
-#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
- defined(OS_WIN)
- network_id.id = GetWifiSSID();
-#endif
- break;
- case NetworkChangeNotifier::ConnectionType::CONNECTION_2G:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_3G:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_4G:
- case NetworkChangeNotifier::ConnectionType::CONNECTION_5G:
-#if defined(OS_ANDROID)
- network_id.id = android::GetTelephonyNetworkOperator();
-#endif
- break;
- default:
- NOTREACHED() << "Unexpected connection type = " << network_id.type;
- break;
- }
-
- if (network_id.type == NetworkChangeNotifier::GetConnectionType())
return network_id;
}
- NOTREACHED();
-}
} // namespace
@@ -152,23 +114,23 @@ NetworkQualityEstimator::NetworkQualityEstimator(
params_.get(),
tick_clock_,
params_->weight_multiplier_per_second(),
- params_->weight_multiplier_per_signal_strength_level()),
+ 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
rtt_ms_observations_{
ObservationBuffer(
params_.get(),
tick_clock_,
params_->weight_multiplier_per_second(),
- params_->weight_multiplier_per_signal_strength_level()),
+ 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
ObservationBuffer(
params_.get(),
tick_clock_,
params_->weight_multiplier_per_second(),
- params_->weight_multiplier_per_signal_strength_level()),
+ 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/),
ObservationBuffer(
params_.get(),
tick_clock_,
params_->weight_multiplier_per_second(),
- params_->weight_multiplier_per_signal_strength_level())},
+ 1.0 /*params_->weight_multiplier_per_signal_strength_level()*/)},
effective_connection_type_at_last_main_frame_(
EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
effective_connection_type_recomputation_interval_(
@@ -507,7 +469,7 @@ bool NetworkQualityEstimator::RequestProvidesRTTObservation(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool private_network_request =
- nqe::internal::IsRequestForPrivateHost(request);
+ nqe::internal::IsRequestForPrivateHost(request, net_log_);
return (use_localhost_requests_ || !private_network_request) &&
// Verify that response headers are received, so it can be ensured that
@@ -540,29 +502,7 @@ void NetworkQualityEstimator::OnConnectionTypeChanged(
for (int i = 0; i < nqe::internal::OBSERVATION_CATEGORY_COUNT; ++i)
rtt_ms_observations_[i].Clear();
-#if defined(OS_ANDROID)
-
- bool is_cell_connection =
- NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type);
- bool is_wifi_connection =
- (current_network_id_.type == NetworkChangeNotifier::CONNECTION_WIFI);
-
- if (params_->weight_multiplier_per_signal_strength_level() < 1.0 &&
- (is_cell_connection || is_wifi_connection)) {
- bool signal_strength_available =
- min_signal_strength_since_connection_change_ &&
- max_signal_strength_since_connection_change_;
-
- std::string histogram_name =
- is_cell_connection ? "NQE.CellularSignalStrength.LevelAvailable"
- : "NQE.WifiSignalStrength.LevelAvailable";
-
- base::UmaHistogramBoolean(histogram_name, signal_strength_available);
- }
-#endif // OS_ANDROID
current_network_id_.signal_strength = INT32_MIN;
- min_signal_strength_since_connection_change_.reset();
- max_signal_strength_since_connection_change_.reset();
network_quality_ = nqe::internal::NetworkQuality();
end_to_end_rtt_ = absl::nullopt;
effective_connection_type_ = EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
@@ -627,91 +567,6 @@ void NetworkQualityEstimator::ContinueGatherEstimatesForNextConnectionType(
ComputeEffectiveConnectionType();
}
-absl::optional<int32_t>
-NetworkQualityEstimator::GetCurrentSignalStrengthWithThrottling() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- if (!params_->get_signal_strength_and_detailed_network_id())
- return absl::nullopt;
-
- if (params_->weight_multiplier_per_signal_strength_level() >= 1.0)
- return absl::nullopt;
-
- if ((current_network_id_.type != NetworkChangeNotifier::CONNECTION_WIFI) &&
- !NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) {
- return absl::nullopt;
- }
-
- // Do not call more than once per |wifi_signal_strength_query_interval|
- // duration.
- if (last_signal_strength_check_timestamp_.has_value() &&
- (tick_clock_->NowTicks() - last_signal_strength_check_timestamp_.value() <
- params_->wifi_signal_strength_query_interval()) &&
- (last_signal_strength_check_timestamp_.value() >
- last_connection_change_)) {
- return absl::nullopt;
- }
-
- last_signal_strength_check_timestamp_ = tick_clock_->NowTicks();
-
- if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_WIFI) {
- UMA_HISTOGRAM_BOOLEAN("NQE.SignalStrengthQueried.WiFi", true);
-
-#if defined(OS_ANDROID)
- return android::GetWifiSignalLevel();
-#endif // OS_ANDROID
- }
-
- if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) {
- UMA_HISTOGRAM_BOOLEAN("NQE.SignalStrengthQueried.Cellular", true);
-#if defined(OS_ANDROID)
- return android::cellular_signal_strength::GetSignalStrengthLevel();
-#endif // OS_ANDROID
- }
-
- return absl::nullopt;
-}
-
-void NetworkQualityEstimator::UpdateSignalStrength() {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- int32_t past_signal_strength = current_network_id_.signal_strength;
- absl::optional<int32_t> new_signal_strength =
- GetCurrentSignalStrengthWithThrottling();
-
- // A fresh value is unavailable. So, return early.
- if (!new_signal_strength)
- return;
-
- // Check if there is no change in the signal strength.
- if (past_signal_strength == new_signal_strength.value())
- return;
-
- // Check if the signal strength is unavailable.
- if (new_signal_strength.value() == INT32_MIN)
- return;
-
- DCHECK(new_signal_strength.value() >= 0 && new_signal_strength.value() <= 4);
-
- // Record the network quality we experienced for the previous signal strength
- // (for when we return to that signal strength).
- network_quality_store_->Add(current_network_id_,
- nqe::internal::CachedNetworkQuality(
- tick_clock_->NowTicks(), network_quality_,
- effective_connection_type_));
-
- current_network_id_.signal_strength = new_signal_strength.value();
- // Update network quality from cached value for new signal strength.
- ReadCachedNetworkQualityEstimate();
-
- min_signal_strength_since_connection_change_ =
- std::min(min_signal_strength_since_connection_change_.value_or(INT32_MAX),
- current_network_id_.signal_strength);
- max_signal_strength_since_connection_change_ =
- std::max(max_signal_strength_since_connection_change_.value_or(INT32_MIN),
- current_network_id_.signal_strength);
-}
-
void NetworkQualityEstimator::RecordNetworkIDAvailability() const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (current_network_id_.type ==
@@ -756,8 +611,6 @@ void NetworkQualityEstimator::RecordMetricsOnMainFrameRequest() const {
void NetworkQualityEstimator::ComputeEffectiveConnectionType() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- UpdateSignalStrength();
-
const base::TimeTicks now = tick_clock_->NowTicks();
const EffectiveConnectionType past_type = effective_connection_type_;
@@ -775,27 +628,6 @@ void NetworkQualityEstimator::ComputeEffectiveConnectionType() {
network_quality_ = nqe::internal::NetworkQuality(http_rtt, transport_rtt,
downstream_throughput_kbps);
- net::EffectiveConnectionType signal_strength_capped_ect =
- GetCappedECTBasedOnSignalStrength();
-
- if (signal_strength_capped_ect != effective_connection_type_) {
- DCHECK_LE(signal_strength_capped_ect, effective_connection_type_);
- UMA_HISTOGRAM_EXACT_LINEAR(
- "NQE.CellularSignalStrength.ECTReduction",
- effective_connection_type_ - signal_strength_capped_ect,
- static_cast<int>(EFFECTIVE_CONNECTION_TYPE_LAST));
-
- effective_connection_type_ = signal_strength_capped_ect;
-
- // Reset |network_quality_| based on the updated effective connection type.
- network_quality_ = nqe::internal::NetworkQuality(
- params_->TypicalNetworkQuality(effective_connection_type_).http_rtt(),
- params_->TypicalNetworkQuality(effective_connection_type_)
- .transport_rtt(),
- params_->TypicalNetworkQuality(effective_connection_type_)
- .downstream_throughput_kbps());
- }
-
ClampKbpsBasedOnEct();
UMA_HISTOGRAM_ENUMERATION("NQE.EffectiveConnectionType.OnECTComputation",
@@ -930,85 +762,6 @@ void NetworkQualityEstimator::AdjustHttpRttBasedOnRTTCounts(
*http_rtt = upper_bound_http_rtt;
}
-EffectiveConnectionType
-NetworkQualityEstimator::GetCappedECTBasedOnSignalStrength() const {
- if (!params_->cap_ect_based_on_signal_strength())
- return effective_connection_type_;
-
- // Check if signal strength is available.
- if (current_network_id_.signal_strength == INT32_MIN)
- return effective_connection_type_;
-
- if (effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_UNKNOWN ||
- effective_connection_type_ == EFFECTIVE_CONNECTION_TYPE_OFFLINE) {
- return effective_connection_type_;
- }
-
- // Do not cap ECT if the signal strength is high.
- if (current_network_id_.signal_strength > 2)
- return effective_connection_type_;
-
- DCHECK_LE(0, current_network_id_.signal_strength);
-
- // When signal strength is 0, the device is almost offline.
- if (current_network_id_.signal_strength == 0) {
- switch (current_network_id_.type) {
- case NetworkChangeNotifier::CONNECTION_2G:
- case NetworkChangeNotifier::CONNECTION_3G:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
- case NetworkChangeNotifier::CONNECTION_4G:
- case NetworkChangeNotifier::CONNECTION_5G:
- case NetworkChangeNotifier::CONNECTION_WIFI:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_2G);
- default:
- NOTREACHED();
- return effective_connection_type_;
- }
- }
-
- if (current_network_id_.signal_strength == 1) {
- switch (current_network_id_.type) {
- case NetworkChangeNotifier::CONNECTION_2G:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_SLOW_2G);
- case NetworkChangeNotifier::CONNECTION_3G:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_2G);
- case NetworkChangeNotifier::CONNECTION_4G:
- case NetworkChangeNotifier::CONNECTION_5G:
- case NetworkChangeNotifier::CONNECTION_WIFI:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_3G);
- default:
- NOTREACHED();
- return effective_connection_type_;
- }
- }
-
- if (current_network_id_.signal_strength == 2) {
- switch (current_network_id_.type) {
- case NetworkChangeNotifier::CONNECTION_2G:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_2G);
- case NetworkChangeNotifier::CONNECTION_3G:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_3G);
- case NetworkChangeNotifier::CONNECTION_4G:
- case NetworkChangeNotifier::CONNECTION_5G:
- case NetworkChangeNotifier::CONNECTION_WIFI:
- return std::min(effective_connection_type_,
- EFFECTIVE_CONNECTION_TYPE_4G);
- default:
- NOTREACHED();
- return effective_connection_type_;
- }
- }
- NOTREACHED();
- return effective_connection_type_;
-}
-
EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType()
const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromium/net/nqe/network_quality_estimator.h b/chromium/net/nqe/network_quality_estimator.h
index 4c8d636b75d..176ac2d2f45 100644
--- a/chromium/net/nqe/network_quality_estimator.h
+++ b/chromium/net/nqe/network_quality_estimator.h
@@ -9,7 +9,6 @@
#include <map>
#include <memory>
-#include <string>
#include <vector>
#include "base/compiler_specific.h"
@@ -384,16 +383,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// |observed_http_rtt| with the expected HTTP and transport RTT.
bool IsHangingRequest(base::TimeDelta observed_http_rtt) const;
- // Returns the current network signal strength by querying the platform APIs.
- // Set to INT32_MIN when the value is unavailable. Otherwise, must be between
- // 0 and 4 (both inclusive). This may take into account many different radio
- // technology inputs. 0 represents very poor signal strength while 4
- // represents a very strong signal strength. The range is capped between 0 and
- // 4 to ensure that a change in the value indicates a non-negligible change in
- // the signal quality. To reduce the number of Android API calls, it returns
- // a null value if the signal strength was recently obtained.
- virtual absl::optional<int32_t> GetCurrentSignalStrengthWithThrottling();
-
// Forces computation of effective connection type, and notifies observers
// if there is a change in its value.
void ComputeEffectiveConnectionType();
@@ -497,11 +486,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// main frame request is observed.
void RecordAccuracyAfterMainFrame(base::TimeDelta measuring_duration) const;
- // Obtains the current cellular signal strength value and updates
- // |min_signal_strength_since_connection_change_| and
- // |max_signal_strength_since_connection_change_|.
- void UpdateSignalStrength();
-
// Updates the provided |http_rtt| based on all provided RTT values.
void UpdateHttpRttUsingAllRttValues(
base::TimeDelta* http_rtt,
@@ -536,11 +520,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// observations.
bool ShouldSocketWatcherNotifyRTT(base::TimeTicks now);
- // Caps and returns the current value of effective connection type based on
- // the current signal strength. If the signal strength is reported as low, a
- // value lower than |effective_connection_type_| may be returned.
- EffectiveConnectionType GetCappedECTBasedOnSignalStrength() const;
-
// When RTT counts are low, it may be impossible to predict accurate ECT. In
// that case, we just give the highest value.
void AdjustHttpRttBasedOnRTTCounts(base::TimeDelta* http_rtt) const;
@@ -637,11 +616,6 @@ class NET_EXPORT_PRIVATE NetworkQualityEstimator
// |effective_connection_type_recomputation_interval_| ago).
EffectiveConnectionType effective_connection_type_;
- // Minimum and maximum signal strength level observed since last connection
- // change. Updated on connection change and main frame requests.
- absl::optional<int32_t> min_signal_strength_since_connection_change_;
- absl::optional<int32_t> max_signal_strength_since_connection_change_;
-
// Stores the qualities of different networks.
std::unique_ptr<nqe::internal::NetworkQualityStore> network_quality_store_;
diff --git a/chromium/net/nqe/network_quality_estimator_params.cc b/chromium/net/nqe/network_quality_estimator_params.cc
index 0940489c366..c9d17826fba 100644
--- a/chromium/net/nqe/network_quality_estimator_params.cc
+++ b/chromium/net/nqe/network_quality_estimator_params.cc
@@ -436,7 +436,6 @@ NetworkQualityEstimatorParams::NetworkQualityEstimatorParams(
"throughput_hanging_requests_cwnd_size_multiplier",
1)),
weight_multiplier_per_second_(GetWeightMultiplierPerSecond(params_)),
- weight_multiplier_per_signal_strength_level_(0.8),
forced_effective_connection_type_(
GetInitForcedEffectiveConnectionType(params_)),
forced_effective_connection_type_on_cellular_only_(
@@ -499,29 +498,12 @@ NetworkQualityEstimatorParams::NetworkQualityEstimatorParams(
"socket_watchers_min_notification_interval_msec",
200))),
use_end_to_end_rtt_(true),
- cap_ect_based_on_signal_strength_(
- GetStringValueForVariationParamWithDefaultValue(
- params_,
- "cap_ect_based_on_signal_strength",
- "true") != "false"),
upper_bound_typical_kbps_multiplier_(
GetDoubleValueForVariationParamWithDefaultValue(
params_,
"upper_bound_typical_kbps_multiplier",
3.5)),
- // |get_signal_strength_and_detailed_network_id_| is false by default.
- get_signal_strength_and_detailed_network_id_(
- GetStringValueForVariationParamWithDefaultValue(
- params_,
- "get_signal_strength_and_detailed_network_id",
- "false") == "true"),
- // Default 30 minutes.
- wifi_signal_strength_query_interval_(
- base::TimeDelta::FromSeconds(GetValueForVariationParam(
- params_,
- "wifi_signal_strength_query_interval_seconds",
- 30 * 60))),
adjust_rtt_based_on_rtt_counts_(
GetStringValueForVariationParamWithDefaultValue(
params_,
@@ -537,9 +519,6 @@ NetworkQualityEstimatorParams::NetworkQualityEstimatorParams(
hanging_request_http_rtt_upper_bound_transport_rtt_multiplier_ >=
hanging_request_http_rtt_upper_bound_http_rtt_multiplier_);
- DCHECK_GE(1.0, weight_multiplier_per_signal_strength_level_);
- DCHECK_LE(0.0, weight_multiplier_per_signal_strength_level_);
-
DCHECK_LT(0, hanging_request_duration_http_rtt_multiplier());
DCHECK_LT(0, hanging_request_http_rtt_upper_bound_http_rtt_multiplier());
DCHECK_LT(0, hanging_request_http_rtt_upper_bound_transport_rtt_multiplier());
diff --git a/chromium/net/nqe/network_quality_estimator_params.h b/chromium/net/nqe/network_quality_estimator_params.h
index 185d2174137..dc830f82069 100644
--- a/chromium/net/nqe/network_quality_estimator_params.h
+++ b/chromium/net/nqe/network_quality_estimator_params.h
@@ -68,13 +68,6 @@ class NET_EXPORT NetworkQualityEstimatorParams {
return weight_multiplier_per_second_;
}
- // Returns the factor by which the weight of an observation reduces for every
- // signal strength level difference between the current signal strength, and
- // the signal strength at the time when the observation was taken.
- double weight_multiplier_per_signal_strength_level() const {
- return weight_multiplier_per_signal_strength_level_;
- }
-
// Returns an unset value if the effective connection type has not been forced
// via the |params| provided to this class. Otherwise, returns a value set to
// the effective connection type that has been forced. Forced ECT can be
@@ -240,12 +233,6 @@ class NET_EXPORT NetworkQualityEstimatorParams {
// quality estimate.
bool use_end_to_end_rtt() const { return use_end_to_end_rtt_; }
- // Return true if ECT value should be capped based on the current signal
- // strength.
- bool cap_ect_based_on_signal_strength() const {
- return cap_ect_based_on_signal_strength_;
- }
-
// Returns a multiplier which is used to clamp Kbps on slow connections. For
// a given ECT, the upper bound on Kbps is computed based on this returned
// multiplier and the typical Kbps for the given ECT. If
@@ -255,18 +242,6 @@ class NET_EXPORT NetworkQualityEstimatorParams {
return upper_bound_typical_kbps_multiplier_;
}
- // Returns true if the signal strength or detailed network ID should be
- // queried.
- bool get_signal_strength_and_detailed_network_id() const {
- return get_signal_strength_and_detailed_network_id_;
- }
-
- // Returns the minimum duration between two consecutuve calls for querying the
- // current WiFi network's signal strength.
- base::TimeDelta wifi_signal_strength_query_interval() const {
- return wifi_signal_strength_query_interval_;
- }
-
// Returns true if RTTs should be adjusted based on RTT counts.
// If there are not enough transport RTT samples, end-to-end RTT samples and
// the cached estimates are unavailble/too stale, then the computed value of
@@ -289,7 +264,6 @@ class NET_EXPORT NetworkQualityEstimatorParams {
const int throughput_min_transfer_size_kilobytes_;
const double throughput_hanging_requests_cwnd_size_multiplier_;
const double weight_multiplier_per_second_;
- const double weight_multiplier_per_signal_strength_level_;
absl::optional<EffectiveConnectionType> forced_effective_connection_type_;
const bool forced_effective_connection_type_on_cellular_only_;
bool persistent_cache_reading_enabled_;
@@ -308,10 +282,7 @@ class NET_EXPORT NetworkQualityEstimatorParams {
const bool add_default_platform_observations_;
const base::TimeDelta socket_watchers_min_notification_interval_;
const bool use_end_to_end_rtt_;
- const bool cap_ect_based_on_signal_strength_;
const double upper_bound_typical_kbps_multiplier_;
- const bool get_signal_strength_and_detailed_network_id_;
- const base::TimeDelta wifi_signal_strength_query_interval_;
const bool adjust_rtt_based_on_rtt_counts_;
bool use_small_responses_;
diff --git a/chromium/net/nqe/network_quality_estimator_test_util.cc b/chromium/net/nqe/network_quality_estimator_test_util.cc
index 11f4f5fadc9..8bced216f80 100644
--- a/chromium/net/nqe/network_quality_estimator_test_util.cc
+++ b/chromium/net/nqe/network_quality_estimator_test_util.cc
@@ -327,19 +327,6 @@ nqe::internal::NetworkID TestNetworkQualityEstimator::GetCurrentNetworkID()
INT32_MIN);
}
-absl::optional<int32_t>
-TestNetworkQualityEstimator::GetCurrentSignalStrengthWithThrottling() {
- if (current_cellular_signal_strength_) {
- return current_cellular_signal_strength_;
- }
- return NetworkQualityEstimator::GetCurrentSignalStrengthWithThrottling();
-}
-
-void TestNetworkQualityEstimator::SetCurrentSignalStrength(
- int32_t signal_strength) {
- current_cellular_signal_strength_ = signal_strength;
-}
-
TestNetworkQualityEstimator::LocalHttpTestServer::LocalHttpTestServer(
const base::FilePath& document_root) {
AddDefaultHandlers(document_root);
diff --git a/chromium/net/nqe/network_quality_estimator_test_util.h b/chromium/net/nqe/network_quality_estimator_test_util.h
index 1b2cc87c06c..dae3df73d8b 100644
--- a/chromium/net/nqe/network_quality_estimator_test_util.h
+++ b/chromium/net/nqe/network_quality_estimator_test_util.h
@@ -211,8 +211,6 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
transport_rtt_observation_count_last_ect_computation_ = count;
}
- void SetCurrentSignalStrength(int32_t signal_strength);
-
// Returns count of ping RTTs received from H2/spdy connections.
size_t ping_rtt_received_count() const { return ping_rtt_received_count_; }
@@ -228,10 +226,6 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
using NetworkQualityEstimator::AddAndNotifyObserversOfThroughput;
using NetworkQualityEstimator::IsHangingRequest;
- // NetworkQualityEstimator implementation that returns the overridden
- // network id and signal strength (instead of invoking platform APIs).
- absl::optional<int32_t> GetCurrentSignalStrengthWithThrottling() override;
-
private:
class LocalHttpTestServer : public EmbeddedTestServer {
public:
@@ -284,8 +278,6 @@ class TestNetworkQualityEstimator : public NetworkQualityEstimator {
// If set, GetRTTEstimateInternal() would return the set value.
absl::optional<base::TimeDelta> start_time_null_end_to_end_rtt_;
- absl::optional<int32_t> current_cellular_signal_strength_;
-
LocalHttpTestServer embedded_test_server_;
// If true, notifications are not sent to any of the observers.
diff --git a/chromium/net/nqe/network_quality_estimator_unittest.cc b/chromium/net/nqe/network_quality_estimator_unittest.cc
index 52a598124cd..e87a9f4afcc 100644
--- a/chromium/net/nqe/network_quality_estimator_unittest.cc
+++ b/chromium/net/nqe/network_quality_estimator_unittest.cc
@@ -17,6 +17,7 @@
#include "base/check_op.h"
#include "base/macros.h"
#include "base/metrics/histogram_samples.h"
+#include "base/numerics/safe_conversions.h"
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/task/thread_pool/thread_pool_instance.h"
@@ -69,20 +70,6 @@ void ExpectBucketCountAtLeast(base::HistogramTester* histogram_tester,
<< " expected_min_count_samples=" << expected_min_count_samples;
}
-size_t GetHistogramCount(base::HistogramTester* histogram_tester,
- const std::string& histogram_name) {
- base::ThreadPoolInstance::Get()->FlushForTesting();
- base::RunLoop().RunUntilIdle();
-
- const std::vector<base::Bucket> buckets =
- histogram_tester->GetAllSamples(histogram_name);
- size_t total_count = 0;
- for (const auto& bucket : buckets) {
- total_count += bucket.count;
- }
- return total_count;
-}
-
} // namespace
namespace net {
@@ -1028,9 +1015,9 @@ TEST_F(NetworkQualityEstimatorTest, ClampKbpsBasedOnEct) {
} tests[] = {
// Clamping multiplier set to 3.5 by default.
{"", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G,
- kTypicalDownlinkKbpsEffectiveConnectionType
- [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
- 3.5},
+ base::ClampFloor(kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] *
+ 3.5)},
// Clamping disabled.
{"-1", 3000, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_SLOW_2G, INT32_MAX},
// Clamping multiplier overridden to 1000.
@@ -1050,9 +1037,9 @@ TEST_F(NetworkQualityEstimatorTest, ClampKbpsBasedOnEct) {
1000},
// Clamping multiplier set to 3.5 by default.
{"", 500, INT32_MAX, EFFECTIVE_CONNECTION_TYPE_3G,
- kTypicalDownlinkKbpsEffectiveConnectionType
- [EFFECTIVE_CONNECTION_TYPE_3G] *
- 3.5},
+ base::ClampFloor(kTypicalDownlinkKbpsEffectiveConnectionType
+ [EFFECTIVE_CONNECTION_TYPE_3G] *
+ 3.5)},
// Clamping ineffective when the observed throughput is lower than the
// clamped throughput.
{"", 500, 100, EFFECTIVE_CONNECTION_TYPE_3G, 100},
@@ -1140,83 +1127,6 @@ TEST_F(NetworkQualityEstimatorTest, DefaultHttpRTTBasedThresholds) {
}
}
-// Tests that the ECT and other network quality metrics are capped based on
-// signal strength.
-TEST_F(NetworkQualityEstimatorTest, SignalStrengthBasedCapping) {
- const struct {
- bool enable_signal_strength_capping_experiment;
- NetworkChangeNotifier::ConnectionType device_connection_type;
- int32_t signal_strength_level;
- int32_t http_rtt_msec;
- EffectiveConnectionType expected_ect;
- bool expected_http_rtt_overridden;
- } tests[] = {
- // Signal strength is unavailable.
- {true, NetworkChangeNotifier::CONNECTION_4G, INT32_MIN, 20,
- EFFECTIVE_CONNECTION_TYPE_4G, false},
-
- // 4G device connection type: Signal strength is too low. Even though RTT
- // is reported as low,
- // ECT is expected to be capped to 2G.
- {true, NetworkChangeNotifier::CONNECTION_4G, 0, 20,
- EFFECTIVE_CONNECTION_TYPE_2G, true},
-
- // WiFi device connection type: Signal strength is too low. Even though
- // RTT is reported as low, ECT is expected to be capped to 2G.
- {true, NetworkChangeNotifier::CONNECTION_WIFI, 0, 20,
- EFFECTIVE_CONNECTION_TYPE_2G, true},
-
- // When the signal strength based capping experiment is not enabled,
- // ECT should be computed only on the based of |http_rtt_msec|.
- {false, NetworkChangeNotifier::CONNECTION_4G, INT32_MIN, 20,
- EFFECTIVE_CONNECTION_TYPE_4G, false},
- {false, NetworkChangeNotifier::CONNECTION_4G, 0, 20,
- EFFECTIVE_CONNECTION_TYPE_4G, false},
- };
-
- for (const auto& test : tests) {
- base::HistogramTester histogram_tester;
- std::map<std::string, std::string> variation_params;
- variation_params["cap_ect_based_on_signal_strength"] =
- test.enable_signal_strength_capping_experiment ? "true" : "false";
-
- TestNetworkQualityEstimator estimator(variation_params);
-
- // Simulate the connection type so that GetEffectiveConnectionType
- // does not return Offline if the device is offline.
- estimator.SetCurrentSignalStrength(test.signal_strength_level);
-
- estimator.SimulateNetworkChange(test.device_connection_type, "test");
-
- estimator.SetStartTimeNullHttpRtt(
- base::TimeDelta::FromMilliseconds(test.http_rtt_msec));
- estimator.set_recent_http_rtt(
- base::TimeDelta::FromMilliseconds(test.http_rtt_msec));
- estimator.set_start_time_null_downlink_throughput_kbps(INT32_MAX);
- estimator.set_recent_downlink_throughput_kbps(INT32_MAX);
- estimator.RunOneRequest();
- EXPECT_EQ(test.expected_ect, estimator.GetEffectiveConnectionType());
-
- if (!test.expected_http_rtt_overridden) {
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(test.http_rtt_msec),
- estimator.GetHttpRTT());
- } else {
- EXPECT_EQ(estimator.params()
- ->TypicalNetworkQuality(EFFECTIVE_CONNECTION_TYPE_2G)
- .http_rtt(),
- estimator.GetHttpRTT());
- }
-
- if (!test.expected_http_rtt_overridden) {
- histogram_tester.ExpectTotalCount(
- "NQE.CellularSignalStrength.ECTReduction", 0);
- } else {
- ExpectBucketCountAtLeast(&histogram_tester,
- "NQE.CellularSignalStrength.ECTReduction", 2, 1);
- }
- }
-}
-
// Tests that |GetEffectiveConnectionType| returns correct connection type when
// both HTTP RTT and throughput thresholds are specified in the variation
// params.
@@ -2133,8 +2043,7 @@ TEST_F(NetworkQualityEstimatorTest, MAYBE_TestTCPSocketRTT) {
TestURLRequestContext context(true);
context.set_network_quality_estimator(&estimator);
- std::unique_ptr<HttpNetworkSession::Context> session_context(
- new HttpNetworkSession::Context);
+ auto session_context = std::make_unique<HttpNetworkSessionContext>();
// |estimator| should be notified of TCP RTT observations.
session_context->socket_performance_watcher_factory =
estimator.GetSocketPerformanceWatcherFactory();
@@ -3047,121 +2956,6 @@ TEST_F(NetworkQualityEstimatorTest, TestPeerToPeerConnectionsCountObserver) {
EXPECT_EQ(3u, observer.count());
}
-// Fails only for Android. https://crbug.com/1130720
-#if defined(OS_ANDROID)
-#define MAYBE_CheckSignalStrength DISABLED_CheckSignalStrength
-#else
-#define MAYBE_CheckSignalStrength CheckSignalStrength
-#endif
-
-// Tests that the signal strength API is not called too frequently.
-TEST_F(NetworkQualityEstimatorTest, MAYBE_CheckSignalStrength) {
- constexpr char histogram_name[] = "NQE.SignalStrengthQueried.WiFi";
- constexpr int kWiFiSignalStrengthQueryIntervalSeconds = 30 * 60;
-
- std::map<std::string, std::string> variation_params;
- variation_params["get_signal_strength_and_detailed_network_id"] = "true";
- TestNetworkQualityEstimator estimator(variation_params);
-
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
-
- base::SimpleTestTickClock tick_clock;
- // SimulateNetworkChange() above can produce entries in the histogram bucket
- // if the test system has real wifi or cellular connections, and can also
- // leave the NQE inside its timeout. To avoid that, fastforward fake time for
- // more than the query interval.
- tick_clock.SetNowTicks(base::TimeTicks::Now() +
- base::TimeDelta::FromSeconds(
- kWiFiSignalStrengthQueryIntervalSeconds * 2));
-
- estimator.SetTickClockForTesting(&tick_clock);
-
- base::HistogramTester histogram_tester;
- absl::optional<int32_t> signal_strength =
- estimator.GetCurrentSignalStrengthWithThrottling();
-
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, 1);
-
- // Advance clock by |kWiFiSignalStrengthQueryIntervalSeconds|. The signal
- // strength API should now be called.
- tick_clock.Advance(
- base::TimeDelta::FromSeconds(kWiFiSignalStrengthQueryIntervalSeconds));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, 2);
-
- // Calling it again should return no value.
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
-
- tick_clock.Advance(base::TimeDelta::FromSeconds(
- kWiFiSignalStrengthQueryIntervalSeconds - 3));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, 2);
-
- // Move the clock by another 4 seconds. Since it's more than 30 seconds since
- // the strength was last available, it should be available again.
- tick_clock.Advance(base::TimeDelta::FromSeconds(3));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, 3);
-
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, 3);
-
- // Changing the connection type should make the signal strength available
- // again. Verify that the signal strength is not queried too frequently
- // (currently, the threshold is set to 5). This is partially indeterminsitic
- // due to the indeterminism at the connection change.
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI, "test");
- size_t samples_count = GetHistogramCount(&histogram_tester, histogram_name);
- EXPECT_LE(4u, samples_count);
- EXPECT_GE(8u, samples_count);
-
- tick_clock.Advance(base::TimeDelta::FromMilliseconds(2));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, samples_count + 1);
-
- tick_clock.Advance(base::TimeDelta::FromMilliseconds(2));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- histogram_tester.ExpectTotalCount(histogram_name, samples_count + 1);
-}
-
-TEST_F(NetworkQualityEstimatorTest, CheckSignalStrengthDisabledByDefault) {
- TestNetworkQualityEstimator estimator;
-
- base::SimpleTestTickClock tick_clock;
- tick_clock.SetNowTicks(base::TimeTicks::Now());
-
- estimator.SetTickClockForTesting(&tick_clock);
-
- absl::optional<int32_t> signal_strength =
- estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-
- // Advance clock by 60 seconds. The signal strength API should NOT be called.
- tick_clock.Advance(base::TimeDelta::FromSeconds(60));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-
- // Changing the connection type should NOT make the signal strength available
- // again.
- estimator.SimulateNetworkChange(
- NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, "test");
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-
- tick_clock.Advance(base::TimeDelta::FromMilliseconds(2));
- signal_strength = estimator.GetCurrentSignalStrengthWithThrottling();
- EXPECT_FALSE(signal_strength);
-}
-
// Tests that the HTTP RTT and ECT are adjusted when the count of transport RTTs
// is low. The test adds only HTTP RTT observations and does not add any
// transport RTT observations. Absence of transport RTT observations should
diff --git a/chromium/net/nqe/network_quality_estimator_util.cc b/chromium/net/nqe/network_quality_estimator_util.cc
index 245e01d19c9..4364060f022 100644
--- a/chromium/net/nqe/network_quality_estimator_util.cc
+++ b/chromium/net/nqe/network_quality_estimator_util.cc
@@ -14,8 +14,7 @@
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/dns/host_resolver.h"
-#include "net/dns/host_resolver_source.h"
-#include "net/log/net_log_with_source.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -27,13 +26,14 @@ namespace {
bool IsPrivateHost(HostResolver* host_resolver,
const HostPortPair& host_port_pair,
- const NetworkIsolationKey& network_isolation_key) {
+ const NetworkIsolationKey& network_isolation_key,
+ NetLogWithSource net_log) {
// Try resolving |host_port_pair.host()| synchronously.
HostResolver::ResolveHostParameters parameters;
parameters.source = HostResolverSource::LOCAL_ONLY;
std::unique_ptr<HostResolver::ResolveHostRequest> request =
host_resolver->CreateRequest(host_port_pair, network_isolation_key,
- NetLogWithSource(), parameters);
+ net_log, parameters);
int rv = request->Start(base::BindOnce([](int error) { NOTREACHED(); }));
DCHECK_NE(rv, ERR_IO_PENDING);
@@ -54,18 +54,20 @@ bool IsPrivateHost(HostResolver* host_resolver,
namespace internal {
-bool IsRequestForPrivateHost(const URLRequest& request) {
+bool IsRequestForPrivateHost(const URLRequest& request,
+ NetLogWithSource net_log) {
// Using the request's NetworkIsolationKey isn't necessary for privacy
// reasons, but is needed to maximize the chances of a cache hit.
- return IsPrivateHost(request.context()->host_resolver(),
- HostPortPair::FromURL(request.url()),
- request.isolation_info().network_isolation_key());
+ return IsPrivateHost(
+ request.context()->host_resolver(), HostPortPair::FromURL(request.url()),
+ request.isolation_info().network_isolation_key(), net_log);
}
bool IsPrivateHostForTesting(HostResolver* host_resolver,
const HostPortPair& host_port_pair,
const NetworkIsolationKey& network_isolation_key) {
- return IsPrivateHost(host_resolver, host_port_pair, network_isolation_key);
+ return IsPrivateHost(host_resolver, host_port_pair, network_isolation_key,
+ NetLogWithSource());
}
} // namespace internal
diff --git a/chromium/net/nqe/network_quality_estimator_util.h b/chromium/net/nqe/network_quality_estimator_util.h
index 41e15d08380..67d2099db2b 100644
--- a/chromium/net/nqe/network_quality_estimator_util.h
+++ b/chromium/net/nqe/network_quality_estimator_util.h
@@ -8,6 +8,7 @@
#include <stdint.h>
#include "net/base/net_export.h"
+#include "net/log/net_log_with_source.h"
namespace net {
@@ -32,7 +33,8 @@ typedef uint64_t IPHash;
// To make this determination, this method makes the best effort estimate
// including trying to resolve the host from the HostResolver's cache. This
// method is synchronous.
-NET_EXPORT_PRIVATE bool IsRequestForPrivateHost(const URLRequest& request);
+NET_EXPORT_PRIVATE bool IsRequestForPrivateHost(const URLRequest& request,
+ NetLogWithSource net_log);
// Provides access to the method used internally by IsRequestForPrivateHost(),
// for testing.
diff --git a/chromium/net/nqe/observation_buffer.cc b/chromium/net/nqe/observation_buffer.cc
index 0b99d81dbc3..de645b20635 100644
--- a/chromium/net/nqe/observation_buffer.cc
+++ b/chromium/net/nqe/observation_buffer.cc
@@ -9,9 +9,9 @@
#include <algorithm>
#include <utility>
+#include "base/containers/cxx20_erase.h"
+#include "base/cxx17_backports.h"
#include "base/macros.h"
-#include "base/numerics/ranges.h"
-#include "base/stl_util.h"
#include "base/time/default_tick_clock.h"
#include "base/time/time.h"
#include "net/nqe/network_quality_estimator_params.h"
@@ -150,7 +150,7 @@ void ObservationBuffer::ComputeWeightedObservations(
}
double weight = time_weight * signal_strength_weight;
- weight = base::ClampToRange(weight, DBL_MIN, 1.0);
+ weight = base::clamp(weight, DBL_MIN, 1.0);
weighted_observations->push_back(
WeightedObservation(observation.value(), weight));
diff --git a/chromium/net/nqe/throughput_analyzer.cc b/chromium/net/nqe/throughput_analyzer.cc
index 34503232ac0..b2853e20489 100644
--- a/chromium/net/nqe/throughput_analyzer.cc
+++ b/chromium/net/nqe/throughput_analyzer.cc
@@ -403,7 +403,7 @@ bool ThroughputAnalyzer::DegradesAccuracy(const URLRequest& request) const {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool private_network_request =
- nqe::internal::IsRequestForPrivateHost(request);
+ nqe::internal::IsRequestForPrivateHost(request, net_log_);
return !(use_localhost_requests_for_tests_ || !private_network_request) ||
request.creation_time() < last_connection_change_;
diff --git a/chromium/net/nqe/throughput_analyzer.h b/chromium/net/nqe/throughput_analyzer.h
index a243b370da9..c6ec2438ef5 100644
--- a/chromium/net/nqe/throughput_analyzer.h
+++ b/chromium/net/nqe/throughput_analyzer.h
@@ -17,7 +17,6 @@
#include "base/time/time.h"
#include "net/base/net_export.h"
#include "net/log/net_log_with_source.h"
-#include "third_party/abseil-cpp/absl/types/optional.h"
namespace {
typedef base::RepeatingCallback<void(int32_t)> ThroughputObservationCallback;
diff --git a/chromium/net/ntlm/ntlm_buffer_reader.h b/chromium/net/ntlm/ntlm_buffer_reader.h
index d0149347822..d6cb7d7e5cf 100644
--- a/chromium/net/ntlm/ntlm_buffer_reader.h
+++ b/chromium/net/ntlm/ntlm_buffer_reader.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <stdint.h>
-#include <string>
#include <vector>
#include "base/containers/span.h"
diff --git a/chromium/net/ntlm/ntlm_buffer_reader_unittest.cc b/chromium/net/ntlm/ntlm_buffer_reader_unittest.cc
index ba25da9ccd4..bbeeecacde2 100644
--- a/chromium/net/ntlm/ntlm_buffer_reader_unittest.cc
+++ b/chromium/net/ntlm/ntlm_buffer_reader_unittest.cc
@@ -4,7 +4,7 @@
#include "net/ntlm/ntlm_buffer_reader.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/ntlm/ntlm_buffer_writer_unittest.cc b/chromium/net/ntlm/ntlm_buffer_writer_unittest.cc
index d2b9aeef5b0..8a385682b05 100644
--- a/chromium/net/ntlm/ntlm_buffer_writer_unittest.cc
+++ b/chromium/net/ntlm/ntlm_buffer_writer_unittest.cc
@@ -4,7 +4,7 @@
#include "net/ntlm/ntlm_buffer_writer.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/ntlm/ntlm_client_unittest.cc b/chromium/net/ntlm/ntlm_client_unittest.cc
index a67f397db39..33ede581aba 100644
--- a/chromium/net/ntlm/ntlm_client_unittest.cc
+++ b/chromium/net/ntlm/ntlm_client_unittest.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/containers/span.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "net/ntlm/ntlm.h"
@@ -25,8 +25,8 @@ std::vector<uint8_t> GenerateAuthMsg(const NtlmClient& client,
base::span<const uint8_t> challenge_msg) {
return client.GenerateAuthenticateMessage(
test::kNtlmDomain, test::kUser, test::kPassword, test::kHostnameAscii,
- test::kChannelBindings, test::kNtlmSpn, test::kClientTimestamp,
- test::kClientChallenge, challenge_msg);
+ reinterpret_cast<const char*>(test::kChannelBindings), test::kNtlmSpn,
+ test::kClientTimestamp, test::kClientChallenge, challenge_msg);
}
std::vector<uint8_t> GenerateAuthMsg(const NtlmClient& client,
diff --git a/chromium/net/ntlm/ntlm_constants.h b/chromium/net/ntlm/ntlm_constants.h
index 3a3c26336d9..d1163babaf7 100644
--- a/chromium/net/ntlm/ntlm_constants.h
+++ b/chromium/net/ntlm/ntlm_constants.h
@@ -10,7 +10,7 @@
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/net_export.h"
namespace net {
diff --git a/chromium/net/ntlm/ntlm_test_data.h b/chromium/net/ntlm/ntlm_test_data.h
index 2c3d1e5f9ff..cc44939367e 100644
--- a/chromium/net/ntlm/ntlm_test_data.h
+++ b/chromium/net/ntlm/ntlm_test_data.h
@@ -41,7 +41,7 @@ constexpr char kUserAscii[] = "User";
constexpr char kHostnameAscii[] = "COMPUTER";
// Test data obtained from [2].
-constexpr char kChannelBindings[] = {
+constexpr uint8_t kChannelBindings[] = {
't', 'l', 's', '-', 's', 'e', 'r', 'v', 'e', 'r', '-',
'e', 'n', 'd', '-', 'p', 'o', 'i', 'n', 't', ':', 0xea,
0x05, 0xfe, 0xfe, 0xcc, 0x6b, 0x0b, 0xd5, 0x71, 0xdb, 0xbc, 0x5b,
diff --git a/chromium/net/ntlm/ntlm_unittest.cc b/chromium/net/ntlm/ntlm_unittest.cc
index ad3ab5bbdda..9342152334c 100644
--- a/chromium/net/ntlm/ntlm_unittest.cc
+++ b/chromium/net/ntlm/ntlm_unittest.cc
@@ -17,7 +17,7 @@
#include <iterator>
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/utf_string_conversions.h"
#include "net/ntlm/ntlm_test_data.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -256,7 +256,9 @@ TEST(NtlmTest, GenerateSessionBaseKeyWithClientTimestampV2SpecTests) {
TEST(NtlmTest, GenerateChannelBindingHashV2SpecTests) {
uint8_t v2_channel_binding_hash[kChannelBindingsHashLen];
- GenerateChannelBindingHashV2(test::kChannelBindings, v2_channel_binding_hash);
+ GenerateChannelBindingHashV2(
+ reinterpret_cast<const char*>(test::kChannelBindings),
+ v2_channel_binding_hash);
ASSERT_EQ(0, memcmp(test::kExpectedChannelBindingHashV2,
v2_channel_binding_hash, kChannelBindingsHashLen));
@@ -306,8 +308,8 @@ TEST(NtlmTest, GenerateUpdatedTargetInfo) {
uint64_t server_timestamp = UINT64_MAX;
std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
- true, true, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
- &server_timestamp);
+ true, true, reinterpret_cast<const char*>(test::kChannelBindings),
+ test::kNtlmSpn, server_av_pairs, &server_timestamp);
// With MIC and EPA enabled 3 additional AvPairs will be added.
// 1) A flags AVPair with the MIC_PRESENT bit set.
@@ -331,8 +333,8 @@ TEST(NtlmTest, GenerateUpdatedTargetInfoNoEpaOrMic) {
// When both EPA and MIC are false the target info does not get modified by
// the client.
std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
- false, false, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
- &server_timestamp);
+ false, false, reinterpret_cast<const char*>(test::kChannelBindings),
+ test::kNtlmSpn, server_av_pairs, &server_timestamp);
ASSERT_EQ(base::size(test::kExpectedTargetInfoFromSpecV2),
updated_target_info.size());
ASSERT_EQ(0, memcmp(test::kExpectedTargetInfoFromSpecV2,
@@ -356,8 +358,8 @@ TEST(NtlmTest, GenerateUpdatedTargetInfoWithServerTimestamp) {
// When both EPA and MIC are false the target info does not get modified by
// the client.
std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
- false, false, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
- &server_timestamp);
+ false, false, reinterpret_cast<const char*>(test::kChannelBindings),
+ test::kNtlmSpn, server_av_pairs, &server_timestamp);
// Verify that the server timestamp was read from the target info.
ASSERT_EQ(test::kServerTimestamp, server_timestamp);
ASSERT_EQ(base::size(test::kExpectedTargetInfoFromSpecPlusServerTimestampV2),
@@ -373,8 +375,8 @@ TEST(NtlmTest, GenerateUpdatedTargetInfoWhenServerSendsNoTargetInfo) {
uint64_t server_timestamp = UINT64_MAX;
std::vector<uint8_t> updated_target_info = GenerateUpdatedTargetInfo(
- true, true, test::kChannelBindings, test::kNtlmSpn, server_av_pairs,
- &server_timestamp);
+ true, true, reinterpret_cast<const char*>(test::kChannelBindings),
+ test::kNtlmSpn, server_av_pairs, &server_timestamp);
// With MIC and EPA enabled 3 additional AvPairs will be added.
// 1) A flags AVPair with the MIC_PRESENT bit set.
diff --git a/chromium/net/proxy_resolution/multi_threaded_proxy_resolver.cc b/chromium/net/proxy_resolution/multi_threaded_proxy_resolver.cc
index e121741d323..a64a29841da 100644
--- a/chromium/net/proxy_resolution/multi_threaded_proxy_resolver.cc
+++ b/chromium/net/proxy_resolution/multi_threaded_proxy_resolver.cc
@@ -13,7 +13,6 @@
#include "base/containers/circular_deque.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread.h"
diff --git a/chromium/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc b/chromium/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
index b92df79f877..0c36dad03c3 100644
--- a/chromium/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
+++ b/chromium/net/proxy_resolution/multi_threaded_proxy_resolver_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/proxy_resolution/network_delegate_error_observer_unittest.cc b/chromium/net/proxy_resolution/network_delegate_error_observer_unittest.cc
index 57439a3d409..c7117336fb4 100644
--- a/chromium/net/proxy_resolution/network_delegate_error_observer_unittest.cc
+++ b/chromium/net/proxy_resolution/network_delegate_error_observer_unittest.cc
@@ -30,44 +30,9 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
private:
// NetworkDelegate implementation.
- int OnBeforeURLRequest(URLRequest* request,
- CompletionOnceCallback callback,
- GURL* new_url) override {
- return OK;
- }
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
- return OK;
- }
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const net::IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override {
- return OK;
- }
- void OnBeforeRedirect(URLRequest* request,
- const GURL& new_location) override {}
- void OnResponseStarted(URLRequest* request, int net_error) override {}
- void OnCompleted(URLRequest* request, bool started, int net_error) override {}
- void OnURLRequestDestroyed(URLRequest* request) override {}
-
void OnPACScriptError(int line_number, const std::u16string& error) override {
got_pac_error_ = true;
}
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
- bool OnCanSetCookie(const URLRequest& request,
- const net::CanonicalCookie& cookie,
- CookieOptions* options,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
bool got_pac_error_;
};
diff --git a/chromium/net/proxy_resolution/pac_file_decider.cc b/chromium/net/proxy_resolution/pac_file_decider.cc
index 73711b345e8..4a4bfbdc4d8 100644
--- a/chromium/net/proxy_resolution/pac_file_decider.cc
+++ b/chromium/net/proxy_resolution/pac_file_decider.cc
@@ -18,8 +18,8 @@
#include "base/values.h"
#include "net/base/completion_repeating_callback.h"
#include "net/base/host_port_pair.h"
+#include "net/base/isolation_info.h"
#include "net/base/net_errors.h"
-#include "net/base/network_isolation_key.h"
#include "net/base/request_priority.h"
#include "net/log/net_log_capture_mode.h"
#include "net/log/net_log_event_type.h"
@@ -286,12 +286,10 @@ int PacFileDecider::DoQuickCheck() {
HostResolver* host_resolver =
pac_file_fetcher_->GetRequestContext()->host_resolver();
- // It's safe to use an empty NetworkIsolationKey() here, since this is only
- // for fetching the PAC script, so can't usefully leak data to web-initiated
- // requests (Which can't use an empty NIK for resolving IPs other than that of
- // the proxy).
resolve_request_ = host_resolver->CreateRequest(
- HostPortPair(host, 80), NetworkIsolationKey(), net_log_, parameters);
+ HostPortPair(host, 80),
+ pac_file_fetcher_->isolation_info().network_isolation_key(), net_log_,
+ parameters);
CompletionRepeatingCallback callback = base::BindRepeating(
&PacFileDecider::OnIOCompletion, base::Unretained(this));
diff --git a/chromium/net/proxy_resolution/pac_file_decider_unittest.cc b/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
index 8f273116cf7..621ebfa72e5 100644
--- a/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
+++ b/chromium/net/proxy_resolution/pac_file_decider_unittest.cc
@@ -93,15 +93,6 @@ class Rules {
return rules_[0];
}
- const Rule& GetRuleByText(const std::u16string& text) const {
- for (auto it = rules_.begin(); it != rules_.end(); ++it) {
- if (it->text() == text)
- return *it;
- }
- LOG(FATAL) << "Rule not found for " << text;
- return rules_[0];
- }
-
private:
typedef std::vector<Rule> RuleList;
RuleList rules_;
@@ -393,6 +384,14 @@ TEST_F(PacFileDeciderQuickCheckTest, AsyncSuccess) {
EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
ASSERT_TRUE(resolver_.has_pending_requests());
+
+ // The DNS lookup should be pending, and be using the same NetworkIsolationKey
+ // as the PacFileFetcher, so wpad fetches can reuse the DNS lookup result from
+ // the wpad quick check, if it succeeds.
+ ASSERT_EQ(1u, resolver_.last_id());
+ EXPECT_EQ(fetcher_.isolation_info().network_isolation_key(),
+ resolver_.request_network_isolation_key(1));
+
resolver_.ResolveAllPending();
callback_.WaitForResult();
EXPECT_FALSE(resolver_.has_pending_requests());
@@ -410,6 +409,14 @@ TEST_F(PacFileDeciderQuickCheckTest, AsyncFail) {
"wpad", HOST_RESOLVER_AVOID_MULTICAST);
EXPECT_THAT(StartDecider(), IsError(ERR_IO_PENDING));
ASSERT_TRUE(resolver_.has_pending_requests());
+
+ // The DNS lookup should be pending, and be using the same NetworkIsolationKey
+ // as the PacFileFetcher, so wpad fetches can reuse the DNS lookup result from
+ // the wpad quick check, if it succeeds.
+ ASSERT_EQ(1u, resolver_.last_id());
+ EXPECT_EQ(fetcher_.isolation_info().network_isolation_key(),
+ resolver_.request_network_isolation_key(1));
+
resolver_.ResolveAllPending();
callback_.WaitForResult();
EXPECT_FALSE(decider_->effective_config().value().has_pac_url());
diff --git a/chromium/net/proxy_resolution/pac_file_fetcher.cc b/chromium/net/proxy_resolution/pac_file_fetcher.cc
new file mode 100644
index 00000000000..d21e48defb4
--- /dev/null
+++ b/chromium/net/proxy_resolution/pac_file_fetcher.cc
@@ -0,0 +1,12 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/proxy_resolution/pac_file_fetcher.h"
+
+namespace net {
+
+PacFileFetcher::PacFileFetcher() = default;
+PacFileFetcher::~PacFileFetcher() = default;
+
+} // namespace net
diff --git a/chromium/net/proxy_resolution/pac_file_fetcher.h b/chromium/net/proxy_resolution/pac_file_fetcher.h
index 6aa91aa76d7..6faf8d75969 100644
--- a/chromium/net/proxy_resolution/pac_file_fetcher.h
+++ b/chromium/net/proxy_resolution/pac_file_fetcher.h
@@ -12,6 +12,7 @@
#include <string>
#include "net/base/completion_once_callback.h"
+#include "net/base/isolation_info.h"
#include "net/base/net_export.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -25,8 +26,12 @@ class URLRequestContext;
// timeouts, maximum size constraints, content encoding, etc..
class NET_EXPORT_PRIVATE PacFileFetcher {
public:
+ PacFileFetcher();
+ PacFileFetcher(const PacFileFetcher&) = delete;
+ PacFileFetcher& operator=(const PacFileFetcher&) = delete;
+
// Destruction should cancel any outstanding requests.
- virtual ~PacFileFetcher() {}
+ virtual ~PacFileFetcher();
// Downloads the given PAC URL, and invokes |callback| on completion.
// Returns OK on success, otherwise the error code. If the return code is
@@ -63,6 +68,15 @@ class NET_EXPORT_PRIVATE PacFileFetcher {
// called. Must be called before the URLRequestContext the fetcher was
// created with is torn down.
virtual void OnShutdown() = 0;
+
+ const IsolationInfo& isolation_info() const { return isolation_info_; }
+
+ private:
+ // Transient IsolationInfo used to fetch PAC scripts and resolve hostnames.
+ // Safe to reuse because delays for WPAD fetches don't provide information
+ // to the web platform useful to attackers, and WPAD fetches uniformly
+ // block all network requests.
+ const IsolationInfo isolation_info_ = IsolationInfo::CreateTransient();
};
} // namespace net
diff --git a/chromium/net/proxy_resolution/pac_file_fetcher_impl.cc b/chromium/net/proxy_resolution/pac_file_fetcher_impl.cc
index a44cc6bb06c..821a5fd1d5c 100644
--- a/chromium/net/proxy_resolution/pac_file_fetcher_impl.cc
+++ b/chromium/net/proxy_resolution/pac_file_fetcher_impl.cc
@@ -6,12 +6,12 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/data_url.h"
@@ -175,7 +175,7 @@ int PacFileFetcherImpl::Fetch(
cur_request_ = url_request_context_->CreateRequest(url, MAXIMUM_PRIORITY,
this, traffic_annotation);
- cur_request_->set_isolation_info(isolation_info_);
+ cur_request_->set_isolation_info(isolation_info());
// Make sure that the PAC script is downloaded using a direct connection,
// to avoid circular dependencies (fetching is a part of proxy resolution).
@@ -318,7 +318,6 @@ void PacFileFetcherImpl::OnReadCompleted(URLRequest* request, int num_bytes) {
PacFileFetcherImpl::PacFileFetcherImpl(URLRequestContext* url_request_context)
: url_request_context_(url_request_context),
- isolation_info_(IsolationInfo::CreateTransient()),
buf_(base::MakeRefCounted<IOBuffer>(kBufSize)),
next_id_(0),
cur_request_id_(0),
diff --git a/chromium/net/proxy_resolution/pac_file_fetcher_impl.h b/chromium/net/proxy_resolution/pac_file_fetcher_impl.h
index 1b306a16183..f11c4af2b8c 100644
--- a/chromium/net/proxy_resolution/pac_file_fetcher_impl.h
+++ b/chromium/net/proxy_resolution/pac_file_fetcher_impl.h
@@ -16,7 +16,6 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "net/base/completion_once_callback.h"
-#include "net/base/isolation_info.h"
#include "net/base/net_export.h"
#include "net/proxy_resolution/pac_file_fetcher.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -80,8 +79,6 @@ class NET_EXPORT PacFileFetcherImpl : public PacFileFetcher,
void OnResponseStarted(URLRequest* request, int net_error) override;
void OnReadCompleted(URLRequest* request, int num_bytes) override;
- const IsolationInfo& isolation_info_for_testing() { return isolation_info_; }
-
private:
enum { kBufSize = 4096 };
@@ -112,9 +109,6 @@ class NET_EXPORT PacFileFetcherImpl : public PacFileFetcher,
// OnShutdown.
URLRequestContext* url_request_context_;
- // Transient IsolationInfo used to fetch PAC scripts.
- const IsolationInfo isolation_info_;
-
// Buffer that URLRequest writes into.
scoped_refptr<IOBuffer> buf_;
diff --git a/chromium/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc b/chromium/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
index 41b4d0cffb7..72113d09e5a 100644
--- a/chromium/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
+++ b/chromium/net/proxy_resolution/pac_file_fetcher_impl_unittest.cc
@@ -15,7 +15,6 @@
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
@@ -95,7 +94,7 @@ class RequestContext : public URLRequestContext {
std::make_unique<HttpServerProperties>());
storage_.set_quic_context(std::make_unique<QuicContext>());
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.host_resolver = host_resolver();
session_context.cert_verifier = cert_verifier();
session_context.transport_security_state = transport_security_state();
@@ -105,7 +104,7 @@ class RequestContext : public URLRequestContext {
session_context.http_server_properties = http_server_properties();
session_context.quic_context = quic_context();
storage_.set_http_network_session(std::make_unique<HttpNetworkSession>(
- HttpNetworkSession::Params(), session_context));
+ HttpNetworkSessionParams(), session_context));
storage_.set_http_transaction_factory(std::make_unique<HttpCache>(
storage_.http_network_session(), HttpCache::DefaultBackend::InMemory(0),
false));
@@ -146,46 +145,6 @@ class BasicNetworkDelegate : public NetworkDelegateImpl {
return OK;
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
- return OK;
- }
-
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const net::IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override {
- return OK;
- }
-
- void OnBeforeRedirect(URLRequest* request,
- const GURL& new_location) override {}
-
- void OnResponseStarted(URLRequest* request, int net_error) override {}
-
- void OnCompleted(URLRequest* request, bool started, int net_error) override {}
-
- void OnURLRequestDestroyed(URLRequest* request) override {}
-
- void OnPACScriptError(int line_number, const std::u16string& error) override {
- }
-
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
-
- bool OnCanSetCookie(const URLRequest& request,
- const net::CanonicalCookie& cookie,
- CookieOptions* options,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
-
DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
};
@@ -348,8 +307,7 @@ TEST_F(PacFileFetcherImplTest, IsolationInfo) {
params.source = net::HostResolverSource::LOCAL_ONLY;
std::unique_ptr<net::HostResolver::ResolveHostRequest> host_request =
context_.host_resolver()->CreateRequest(
- kHostPortPair,
- pac_fetcher->isolation_info_for_testing().network_isolation_key(),
+ kHostPortPair, pac_fetcher->isolation_info().network_isolation_key(),
net::NetLogWithSource(), params);
net::TestCompletionCallback callback2;
result = host_request->Start(callback2.callback());
diff --git a/chromium/net/proxy_resolution/proxy_bypass_rules_unittest.cc b/chromium/net/proxy_resolution/proxy_bypass_rules_unittest.cc
index b1327117200..126c9b8c77d 100644
--- a/chromium/net/proxy_resolution/proxy_bypass_rules_unittest.cc
+++ b/chromium/net/proxy_resolution/proxy_bypass_rules_unittest.cc
@@ -4,7 +4,7 @@
#include "net/proxy_resolution/proxy_bypass_rules.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "net/proxy_resolution/proxy_config_service_common_unittest.h"
diff --git a/chromium/net/proxy_resolution/proxy_config_service_linux.cc b/chromium/net/proxy_resolution/proxy_config_service_linux.cc
index baf86b81960..afa3eb0c4c1 100644
--- a/chromium/net/proxy_resolution/proxy_config_service_linux.cc
+++ b/chromium/net/proxy_resolution/proxy_config_service_linux.cc
@@ -826,6 +826,7 @@ class SettingGetterImplKDE : public ProxyConfigServiceLinux::SettingGetter {
ResolveIndirect(PROXY_HTTP_HOST);
ResolveIndirect(PROXY_HTTPS_HOST);
ResolveIndirect(PROXY_FTP_HOST);
+ ResolveIndirect(PROXY_SOCKS_HOST);
ResolveIndirectList(PROXY_IGNORE_HOSTS);
}
if (auto_no_pac_) {
diff --git a/chromium/net/proxy_resolution/proxy_config_service_linux_unittest.cc b/chromium/net/proxy_resolution/proxy_config_service_linux_unittest.cc
index 7a2fde9fb5c..26c4aff3b23 100644
--- a/chromium/net/proxy_resolution/proxy_config_service_linux_unittest.cc
+++ b/chromium/net/proxy_resolution/proxy_config_service_linux_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/format_macros.h"
@@ -18,7 +19,6 @@
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/lock.h"
@@ -1661,32 +1661,34 @@ TEST_F(ProxyConfigServiceLinuxTest, KDEConfigParser) {
// Input.
"[Proxy Settings]\nProxyType=4\nhttpProxy=http_proxy\n"
- "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n",
+ "httpsProxy=https_proxy\nftpProxy=ftp_proxy\nNoProxyFor=no_proxy\n"
+ "socksProxy=SOCKS_SERVER\n",
{
// env_values
- nullptr, // DESKTOP_SESSION
- nullptr, // HOME
- nullptr, // KDEHOME
- nullptr, // KDE_SESSION_VERSION
- nullptr, // XDG_CURRENT_DESKTOP
- nullptr, // auto_proxy
- nullptr, // all_proxy
- "www.normal.com", // http_proxy
- "www.secure.com", // https_proxy
- "ftp.foo.com", // ftp_proxy
- nullptr, nullptr, // SOCKS
- ".google.com, .kde.org", // no_proxy
+ nullptr, // DESKTOP_SESSION
+ nullptr, // HOME
+ nullptr, // KDEHOME
+ nullptr, // KDE_SESSION_VERSION
+ nullptr, // XDG_CURRENT_DESKTOP
+ nullptr, // auto_proxy
+ nullptr, // all_proxy
+ "www.normal.com", // http_proxy
+ "www.secure.com", // https_proxy
+ "ftp.foo.com", // ftp_proxy
+ "socks.comfy.com:1234", nullptr, // SOCKS
+ ".google.com, .kde.org", // no_proxy
},
// Expected result.
ProxyConfigService::CONFIG_VALID,
false, // auto_detect
GURL(), // pac_url
- ProxyRulesExpectation::PerScheme(
- "www.normal.com:80", // http
- "www.secure.com:80", // https
- "ftp.foo.com:80", // ftp
- "*.google.com,*.kde.org"), // bypass rules
+ ProxyRulesExpectation::PerSchemeWithSocks(
+ "www.normal.com:80", // http
+ "www.secure.com:80", // https
+ "ftp.foo.com:80", // ftp
+ "socks5://socks.comfy.com:1234", // socks
+ "*.google.com,*.kde.org"), // bypass rules
},
};
diff --git a/chromium/net/proxy_resolution/proxy_config_unittest.cc b/chromium/net/proxy_resolution/proxy_config_unittest.cc
index cffcfa14695..ff1a7d7799b 100644
--- a/chromium/net/proxy_resolution/proxy_config_unittest.cc
+++ b/chromium/net/proxy_resolution/proxy_config_unittest.cc
@@ -3,8 +3,8 @@
// found in the LICENSE file.
#include "net/proxy_resolution/proxy_config.h"
+#include "base/cxx17_backports.h"
#include "base/json/json_writer.h"
-#include "base/stl_util.h"
#include "base/values.h"
#include "net/proxy_resolution/proxy_config_service_common_unittest.h"
#include "net/proxy_resolution/proxy_info.h"
diff --git a/chromium/net/proxy_resolution/proxy_list_unittest.cc b/chromium/net/proxy_resolution/proxy_list_unittest.cc
index 50cbc59b402..c00db6d12d2 100644
--- a/chromium/net/proxy_resolution/proxy_list_unittest.cc
+++ b/chromium/net/proxy_resolution/proxy_list_unittest.cc
@@ -6,7 +6,7 @@
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
#include "net/log/net_log_with_source.h"
diff --git a/chromium/net/proxy_resolution/proxy_resolver.h b/chromium/net/proxy_resolution/proxy_resolver.h
index ed59ffcc6cf..7b54e570962 100644
--- a/chromium/net/proxy_resolution/proxy_resolver.h
+++ b/chromium/net/proxy_resolution/proxy_resolver.h
@@ -5,8 +5,6 @@
#ifndef NET_PROXY_RESOLUTION_PROXY_RESOLVER_H_
#define NET_PROXY_RESOLUTION_PROXY_RESOLVER_H_
-#include <string>
-
#include "base/callback_forward.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
diff --git a/chromium/net/proxy_resolution/proxy_resolver_mac.cc b/chromium/net/proxy_resolution/proxy_resolver_mac.cc
index 08d034d05a5..7ef110e8999 100644
--- a/chromium/net/proxy_resolution/proxy_resolver_mac.cc
+++ b/chromium/net/proxy_resolution/proxy_resolver_mac.cc
@@ -19,6 +19,7 @@
#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
#include "net/proxy_resolution/proxy_info.h"
+#include "net/proxy_resolution/proxy_list.h"
#include "net/proxy_resolution/proxy_resolver.h"
#include "url/gurl.h"
@@ -308,11 +309,7 @@ int ProxyResolverMac::GetProxyForURL(
base::mac::CFCastStrict<CFArrayRef>(result));
DCHECK(proxy_array_ref != NULL);
- // This string will be an ordered list of <proxy-uri> entries, separated by
- // semi-colons. It is the format that ProxyInfo::UseNamedProxy() expects.
- // proxy-uri = [<proxy-scheme>"://"]<proxy-host>":"<proxy-port>
- // (This also includes entries for direct connection, as "direct://").
- std::string proxy_uri_list;
+ ProxyList proxy_list;
CFIndex proxy_array_count = CFArrayGetCount(proxy_array_ref.get());
for (CFIndex i = 0; i < proxy_array_count; ++i) {
@@ -344,13 +341,11 @@ int ProxyResolverMac::GetProxyForURL(
if (!proxy_server.is_valid())
continue;
- if (!proxy_uri_list.empty())
- proxy_uri_list += ";";
- proxy_uri_list += proxy_server.ToURI();
+ proxy_list.AddProxyServer(proxy_server);
}
- if (!proxy_uri_list.empty())
- results->UseNamedProxy(proxy_uri_list);
+ if (!proxy_list.IsEmpty())
+ results->UseProxyList(proxy_list);
// Else do nothing (results is already guaranteed to be in the default state).
return OK;
diff --git a/chromium/net/proxy_resolution/win/proxy_config_service_win.h b/chromium/net/proxy_resolution/win/proxy_config_service_win.h
index b9ed0162c4a..886ebfc10cd 100644
--- a/chromium/net/proxy_resolution/win/proxy_config_service_win.h
+++ b/chromium/net/proxy_resolution/win/proxy_config_service_win.h
@@ -9,7 +9,6 @@
#include <winhttp.h>
#include <memory>
-#include <string>
#include <vector>
#include "base/compiler_specific.h"
diff --git a/chromium/net/proxy_resolution/win/proxy_config_service_win_unittest.cc b/chromium/net/proxy_resolution/win/proxy_config_service_win_unittest.cc
index 2f41f457105..b5b7740bce4 100644
--- a/chromium/net/proxy_resolution/win/proxy_config_service_win_unittest.cc
+++ b/chromium/net/proxy_resolution/win/proxy_config_service_win_unittest.cc
@@ -4,7 +4,7 @@
#include "net/proxy_resolution/win/proxy_config_service_win.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/net_errors.h"
#include "net/proxy_resolution/proxy_config.h"
#include "net/proxy_resolution/proxy_config_service_common_unittest.h"
diff --git a/chromium/net/proxy_resolution/win/windows_system_proxy_resolver_unittest.cc b/chromium/net/proxy_resolution/win/windows_system_proxy_resolver_unittest.cc
index 72a8dda68f7..61a794dd7ba 100644
--- a/chromium/net/proxy_resolution/win/windows_system_proxy_resolver_unittest.cc
+++ b/chromium/net/proxy_resolution/win/windows_system_proxy_resolver_unittest.cc
@@ -260,65 +260,30 @@ class MockWinHttpAPIWrapper : public WinHttpAPIWrapper {
callback_info_ = std::make_unique<WINHTTP_ASYNC_RESULT>();
callback_info_->dwError = info_error;
}
- void AddToProxyResults(const ProxyServer& proxy_server,
- bool bypass = false,
- bool skip_port = false) {
+ void AddBypassToProxyResults() {
EXPECT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
+ proxy_result_.pEntries[proxy_result_.cEntries].fBypass = TRUE;
+ proxy_result_.cEntries++;
+ }
+ void AddDirectToProxyResults() {
+ EXPECT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
+ proxy_result_.cEntries++;
+ }
+ void AddToProxyResults(INTERNET_SCHEME scheme,
+ std::wstring proxy_host,
+ INTERNET_PORT port) {
+ EXPECT_LT(proxy_result_.cEntries, kMaxProxyEntryLimit - 1);
+ AllocateProxyResultEntriesIfNeeded();
- // Assign memory as needed.
- if (proxy_result_.cEntries == 0) {
- proxy_result_.pEntries =
- new WINHTTP_PROXY_RESULT_ENTRY[kMaxProxyEntryLimit];
- std::memset(proxy_result_.pEntries, 0,
- kMaxProxyEntryLimit * sizeof(WINHTTP_PROXY_RESULT_ENTRY));
-
- // The memory of the strings above will be backed by a vector of strings.
- proxy_list_.reserve(kMaxProxyEntryLimit);
- }
+ proxy_list_.push_back(std::move(proxy_host));
+ wchar_t* proxy_host_raw = const_cast<wchar_t*>(proxy_list_.back().data());
- if (bypass) {
- proxy_result_.pEntries[proxy_result_.cEntries].fBypass = TRUE;
- } else if (!proxy_server.is_direct()) {
- // Now translate the ProxyServer into a WINHTTP_PROXY_RESULT_ENTRY and
- // assign.
- proxy_result_.pEntries[proxy_result_.cEntries].fProxy = TRUE;
-
- switch (proxy_server.scheme()) {
- case ProxyServer::Scheme::SCHEME_HTTP:
- proxy_result_.pEntries[proxy_result_.cEntries].ProxyScheme =
- INTERNET_SCHEME_HTTP;
- break;
- case ProxyServer::Scheme::SCHEME_HTTPS:
- proxy_result_.pEntries[proxy_result_.cEntries].ProxyScheme =
- INTERNET_SCHEME_HTTPS;
- break;
- case ProxyServer::Scheme::SCHEME_SOCKS4:
- proxy_result_.pEntries[proxy_result_.cEntries].ProxyScheme =
- INTERNET_SCHEME_SOCKS;
- break;
- default:
- ADD_FAILURE()
- << "Of the possible proxy schemes returned by WinHttp, Chrome "
- "supports HTTP(S) and SOCKS4. The ProxyServer::Scheme that "
- "triggered this message is: "
- << proxy_server.scheme();
- break;
- }
-
- std::wstring proxy_host(proxy_server.host_port_pair().host().begin(),
- proxy_server.host_port_pair().host().end());
- proxy_list_.push_back(proxy_host);
-
- wchar_t* proxy_host_raw = const_cast<wchar_t*>(proxy_list_.back().data());
- proxy_result_.pEntries[proxy_result_.cEntries].pwszProxy = proxy_host_raw;
-
- if (skip_port)
- proxy_result_.pEntries[proxy_result_.cEntries].ProxyPort =
- INTERNET_DEFAULT_PORT;
- else
- proxy_result_.pEntries[proxy_result_.cEntries].ProxyPort =
- proxy_server.host_port_pair().port();
- }
+ proxy_result_.pEntries[proxy_result_.cEntries].fProxy = TRUE;
+ proxy_result_.pEntries[proxy_result_.cEntries].ProxyScheme = scheme;
+ proxy_result_.pEntries[proxy_result_.cEntries].pwszProxy = proxy_host_raw;
+ proxy_result_.pEntries[proxy_result_.cEntries].ProxyPort = port;
proxy_result_.cEntries++;
}
@@ -372,6 +337,19 @@ class MockWinHttpAPIWrapper : public WinHttpAPIWrapper {
callback_info_.reset();
}
+ void AllocateProxyResultEntriesIfNeeded() {
+ if (proxy_result_.cEntries != 0)
+ return;
+
+ proxy_result_.pEntries =
+ new WINHTTP_PROXY_RESULT_ENTRY[kMaxProxyEntryLimit];
+ std::memset(proxy_result_.pEntries, 0,
+ kMaxProxyEntryLimit * sizeof(WINHTTP_PROXY_RESULT_ENTRY));
+
+ // The memory of the strings above will be backed by a vector of strings.
+ proxy_list_.reserve(kMaxProxyEntryLimit);
+ }
+
// Data configurable by tests to simulate errors and results from WinHttp.
bool open_success_ = true;
bool set_timeouts_success_ = true;
@@ -442,55 +420,6 @@ class WindowsSystemProxyResolverTest : public TestWithTaskEnvironment {
bool InitializeResolver() { return proxy_resolver_->Initialize(); }
- void AddNoPortProxyToResults() {
- const ProxyServer proxy_result =
- ProxyServer::FromPacString("PROXY foopy:8080");
- winhttp_api_wrapper_->AddToProxyResults(proxy_result, /*bypass=*/false,
- /*skip_port=*/true);
- }
-
- void AddDirectProxyToResults(ProxyList* out_proxy_list) {
- winhttp_api_wrapper_->AddToProxyResults(ProxyServer::Direct());
- out_proxy_list->AddProxyServer(ProxyServer::Direct());
- }
-
- void AddBypassedProxyToResults(ProxyList* out_proxy_list) {
- winhttp_api_wrapper_->AddToProxyResults(ProxyServer::Direct(),
- /*bypass=*/true);
- out_proxy_list->AddProxyServer(ProxyServer::Direct());
- }
-
- void AddHTTPProxyToResults(ProxyList* out_proxy_list) {
- const ProxyServer proxy_result =
- ProxyServer::FromPacString("PROXY foopy:8080");
- winhttp_api_wrapper_->AddToProxyResults(proxy_result);
- out_proxy_list->AddProxyServer(proxy_result);
- }
-
- void AddHTTPSProxyToResults(ProxyList* out_proxy_list) {
- const ProxyServer proxy_result =
- ProxyServer::FromPacString("HTTPS foopy:8443");
- winhttp_api_wrapper_->AddToProxyResults(proxy_result);
- out_proxy_list->AddProxyServer(proxy_result);
- }
-
- void AddSOCKSProxyToResults(ProxyList* out_proxy_list) {
- const ProxyServer proxy_result =
- ProxyServer::FromPacString("SOCKS4 foopy:8080");
- winhttp_api_wrapper_->AddToProxyResults(proxy_result);
- out_proxy_list->AddProxyServer(proxy_result);
- }
-
- void AddIDNProxyToResults(ProxyList* out_proxy_list) {
- const ProxyServer proxy_result =
- ProxyServer::FromPacString("HTTPS föopy:8080");
- winhttp_api_wrapper_->AddToProxyResults(proxy_result);
-
- const ProxyServer expected_proxy_result =
- ProxyServer::FromPacString("HTTPS xn--fopy-5jr83a:8080");
- out_proxy_list->AddProxyServer(expected_proxy_result);
- }
-
void PerformGetProxyForUrlAndValidateResult(const ProxyList& proxy_list,
int net_error,
int windows_error) {
@@ -517,8 +446,10 @@ class WindowsSystemProxyResolverTest : public TestWithTaskEnvironment {
}
void DoProxyConfigTest(const ProxyConfig& proxy_config) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
ProxyList proxy_list;
- AddHTTPSProxyToResults(&proxy_list);
+ proxy_list.AddProxyServer(ProxyServer::FromPacString("HTTPS foopy:8443"));
std::wstring pac_url;
if (proxy_config.has_pac_url())
@@ -626,7 +557,8 @@ TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlFailOnGetProxyResult) {
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlFailOnDefaultPort) {
- AddNoPortProxyToResults();
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTP, L"foopy",
+ INTERNET_DEFAULT_PORT);
DoFailedGetProxyForUrlTest(ERR_FAILED, 0);
}
@@ -660,8 +592,11 @@ TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlCancellation) {
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlCancelAndRestart) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
ProxyList expected_proxy_list;
- AddHTTPSProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS foopy:8443"));
ASSERT_TRUE(InitializeResolver());
TestCompletionCallback unused_callback;
@@ -738,52 +673,81 @@ TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlConfigMultipleSettings) {
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlDirect) {
+ winhttp_api_wrapper()->AddDirectToProxyResults();
ProxyList expected_proxy_list;
- AddDirectProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(ProxyServer::Direct());
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlBypass) {
+ winhttp_api_wrapper()->AddBypassToProxyResults();
ProxyList expected_proxy_list;
- AddBypassedProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(ProxyServer::Direct());
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlHTTP) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTP, L"foopy",
+ 8080);
ProxyList expected_proxy_list;
- AddHTTPProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("PROXY foopy:8080"));
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlHTTPS) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
ProxyList expected_proxy_list;
- AddHTTPSProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS foopy:8443"));
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlSOCKS) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_SOCKS, L"foopy",
+ 8080);
ProxyList expected_proxy_list;
- AddSOCKSProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("SOCKS4 foopy:8080"));
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlIDNProxy) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"föopy",
+ 8080);
+
+ // Expect L"föopy" to be ascii-encoded as "xn--fopy-5qa".
ProxyList expected_proxy_list;
- AddIDNProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS xn--fopy-5qa:8080"));
+
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, GetProxyForUrlMultipleResults) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+
ProxyList expected_proxy_list;
- AddHTTPSProxyToResults(&expected_proxy_list);
- AddDirectProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS foopy:8443"));
+ expected_proxy_list.AddProxyServer(ProxyServer::Direct());
+
DoGetProxyForUrlTest(expected_proxy_list);
}
TEST_F(WindowsSystemProxyResolverTest, MultipleCallsToGetProxyForUrl) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+
ProxyList expected_proxy_list;
- AddHTTPSProxyToResults(&expected_proxy_list);
- AddDirectProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS foopy:8443"));
+ expected_proxy_list.AddProxyServer(ProxyServer::Direct());
+
ASSERT_TRUE(InitializeResolver());
TestCompletionCallback unused_callback;
@@ -818,9 +782,15 @@ TEST_F(WindowsSystemProxyResolverTest, MultipleCallsToGetProxyForUrl) {
TEST_F(WindowsSystemProxyResolverTest,
MultipleCallsToGetProxyForUrlWithOneCancellation) {
+ winhttp_api_wrapper()->AddToProxyResults(INTERNET_SCHEME_HTTPS, L"foopy",
+ 8443);
+ winhttp_api_wrapper()->AddDirectToProxyResults();
+
ProxyList expected_proxy_list;
- AddHTTPSProxyToResults(&expected_proxy_list);
- AddDirectProxyToResults(&expected_proxy_list);
+ expected_proxy_list.AddProxyServer(
+ ProxyServer::FromPacString("HTTPS foopy:8443"));
+ expected_proxy_list.AddProxyServer(ProxyServer::Direct());
+
ASSERT_TRUE(InitializeResolver());
// This extra scope is needed so that the MockProxyResolutionRequests destruct
diff --git a/chromium/net/quic/address_utils.h b/chromium/net/quic/address_utils.h
index 3c8d096257d..056c428ebe7 100644
--- a/chromium/net/quic/address_utils.h
+++ b/chromium/net/quic/address_utils.h
@@ -57,9 +57,9 @@ inline quic::QuicSocketAddress ToQuicSocketAddress(IPEndPoint address) {
sockaddr_storage result;
socklen_t size = sizeof(result);
- bool success =
- address.ToSockAddr(reinterpret_cast<sockaddr*>(&result), &size);
- DCHECK(success);
+ if (!address.ToSockAddr(reinterpret_cast<sockaddr*>(&result), &size)) {
+ return quic::QuicSocketAddress();
+ }
return quic::QuicSocketAddress(result);
}
diff --git a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
index aca69072cae..83cedfda0fa 100644
--- a/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
+++ b/chromium/net/quic/bidirectional_stream_quic_impl_unittest.cc
@@ -62,6 +62,8 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
@@ -463,7 +465,9 @@ class BidirectionalStreamQuicImplTest
false),
random_generator_(0),
printer_(version_),
- destination_(kDefaultServerHostName, kDefaultServerPort) {
+ destination_(url::kHttpsScheme,
+ kDefaultServerHostName,
+ kDefaultServerPort) {
quic::QuicEnableVersion(version_);
FLAGS_quic_enable_http3_grease_randomness = false;
IPAddress ip(192, 0, 2, 33);
@@ -810,10 +814,9 @@ class BidirectionalStreamQuicImplTest
if (!version_.UsesHttp3()) {
return "";
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
- return std::string(buffer.get(), header_length);
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body_len, quic::SimpleBufferAllocator::Get());
+ return std::string(buffer.data(), buffer.size());
}
protected:
@@ -846,7 +849,7 @@ class BidirectionalStreamQuicImplTest
MockCryptoClientStreamFactory crypto_client_stream_factory_;
std::unique_ptr<StaticSocketDataProvider> socket_data_;
std::vector<PacketToWrite> writes_;
- HostPortPair destination_;
+ url::SchemeHostPort destination_;
quic::test::NoopQpackStreamSenderDelegate noop_qpack_stream_sender_delegate_;
};
diff --git a/chromium/net/quic/crypto/proof_source_chromium.cc b/chromium/net/quic/crypto/proof_source_chromium.cc
index b923516b9c6..5c7a79f61b9 100644
--- a/chromium/net/quic/crypto/proof_source_chromium.cc
+++ b/chromium/net/quic/crypto/proof_source_chromium.cc
@@ -33,7 +33,8 @@ bool ProofSourceChromium::Initialize(const base::FilePath& cert_path,
CertificateList certs_in_file =
X509Certificate::CreateCertificateListFromBytes(
- cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
+ base::as_bytes(base::make_span(cert_data)),
+ X509Certificate::FORMAT_AUTO);
if (certs_in_file.empty()) {
DLOG(FATAL) << "No certificates.";
@@ -191,6 +192,12 @@ void ProofSourceChromium::ComputeTlsSignature(
callback->Run(true, sig, nullptr);
}
+absl::InlinedVector<uint16_t, 8>
+ProofSourceChromium::SupportedTlsSignatureAlgorithms() const {
+ // Allow all signature algorithms that BoringSSL allows.
+ return {};
+}
+
quic::ProofSource::TicketCrypter* ProofSourceChromium::GetTicketCrypter() {
return ticket_crypter_.get();
}
diff --git a/chromium/net/quic/crypto/proof_source_chromium.h b/chromium/net/quic/crypto/proof_source_chromium.h
index 0addbc7de11..873720e58b3 100644
--- a/chromium/net/quic/crypto/proof_source_chromium.h
+++ b/chromium/net/quic/crypto/proof_source_chromium.h
@@ -54,6 +54,9 @@ class NET_EXPORT_PRIVATE ProofSourceChromium : public quic::ProofSource {
absl::string_view in,
std::unique_ptr<SignatureCallback> callback) override;
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override;
+
TicketCrypter* GetTicketCrypter() override;
void SetTicketCrypter(std::unique_ptr<TicketCrypter> ticket_crypter);
diff --git a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
index e62a0387d39..3030ab82e61 100644
--- a/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
+++ b/chromium/net/quic/crypto/proof_verifier_chromium_test.cc
@@ -203,7 +203,7 @@ class ProofVerifierChromiumTest : public ::testing::Test {
void GetSCTTestCertificates(std::vector<std::string>* certs) {
std::string der_test_cert(ct::GetDerEncodedX509Cert());
scoped_refptr<X509Certificate> test_cert = X509Certificate::CreateFromBytes(
- der_test_cert.data(), der_test_cert.length());
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(test_cert.get());
certs->clear();
@@ -300,6 +300,12 @@ TEST_F(ProofVerifierChromiumTest, FailsIfCertFails) {
ASSERT_EQ(quic::QUIC_FAILURE, status);
}
+class DoNothingLogNotifier : public MultiLogCTVerifier::CTLogProvider {
+ public:
+ DoNothingLogNotifier() = default;
+ ~DoNothingLogNotifier() = default;
+};
+
// Valid SCT and cert
TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
// Use different certificates for SCT tests.
@@ -307,7 +313,7 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
std::string der_test_cert(ct::GetDerEncodedX509Cert());
scoped_refptr<X509Certificate> test_cert = X509Certificate::CreateFromBytes(
- der_test_cert.data(), der_test_cert.length());
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(test_cert);
CertVerifyResult dummy_result;
dummy_result.verified_cert = test_cert;
@@ -322,8 +328,9 @@ TEST_F(ProofVerifierChromiumTest, ValidSCTList) {
CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
ASSERT_TRUE(log);
log_verifiers.push_back(log);
- auto ct_verifier = std::make_unique<MultiLogCTVerifier>();
- ct_verifier->AddLogs(log_verifiers);
+ DoNothingLogNotifier notifier;
+ auto ct_verifier = std::make_unique<MultiLogCTVerifier>(&notifier);
+ ct_verifier->SetLogs(log_verifiers);
CertAndCTVerifier cert_verifier(std::move(dummy_verifier),
std::move(ct_verifier));
@@ -349,7 +356,7 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
std::string der_test_cert(ct::GetDerEncodedX509Cert());
scoped_refptr<X509Certificate> test_cert = X509Certificate::CreateFromBytes(
- der_test_cert.data(), der_test_cert.length());
+ base::as_bytes(base::make_span(der_test_cert)));
ASSERT_TRUE(test_cert);
CertVerifyResult dummy_result;
dummy_result.verified_cert = test_cert;
@@ -364,8 +371,9 @@ TEST_F(ProofVerifierChromiumTest, InvalidSCTList) {
CTLogVerifier::Create(ct::GetTestPublicKey(), kLogDescription));
ASSERT_TRUE(log);
log_verifiers.push_back(log);
- auto ct_verifier = std::make_unique<MultiLogCTVerifier>();
- ct_verifier->AddLogs(log_verifiers);
+ DoNothingLogNotifier notifier;
+ auto ct_verifier = std::make_unique<MultiLogCTVerifier>(&notifier);
+ ct_verifier->SetLogs(log_verifiers);
CertAndCTVerifier cert_verifier(std::move(dummy_verifier),
std::move(ct_verifier));
diff --git a/chromium/net/quic/crypto_test_utils_chromium.cc b/chromium/net/quic/crypto_test_utils_chromium.cc
index d6d4dbb3e77..0b2dd8234d7 100644
--- a/chromium/net/quic/crypto_test_utils_chromium.cc
+++ b/chromium/net/quic/crypto_test_utils_chromium.cc
@@ -8,7 +8,6 @@
#include "base/check.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
diff --git a/chromium/net/quic/dedicated_web_transport_http3_client.cc b/chromium/net/quic/dedicated_web_transport_http3_client.cc
index aa10bb1ae3e..a9723753516 100644
--- a/chromium/net/quic/dedicated_web_transport_http3_client.cc
+++ b/chromium/net/quic/dedicated_web_transport_http3_client.cc
@@ -5,8 +5,8 @@
#include "net/quic/dedicated_web_transport_http3_client.h"
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
#include "base/strings/abseil_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/url_util.h"
@@ -19,6 +19,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/url_request/url_request_context.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -287,6 +288,9 @@ int DedicatedWebTransportHttp3Client::DoInit() {
if (url_.scheme_piece() != url::kHttpsScheme)
return ERR_DISALLOWED_URL_SCHEME;
+ if (!IsPortAllowedForScheme(url_.EffectiveIntPort(), url_.scheme_piece()))
+ return ERR_UNSAFE_PORT;
+
// TODO(vasilvv): check if QUIC is disabled by policy.
// Ensure that for the duration of the origin trial, a fixed QUIC transport
@@ -336,7 +340,7 @@ int DedicatedWebTransportHttp3Client::DoResolveHost() {
next_connect_state_ = CONNECT_STATE_RESOLVE_HOST_COMPLETE;
HostResolver::ResolveHostParameters parameters;
resolve_host_request_ = context_->host_resolver()->CreateRequest(
- HostPortPair::FromURL(url_), isolation_key_, net_log_, absl::nullopt);
+ url::SchemeHostPort(url_), isolation_key_, net_log_, absl::nullopt);
return resolve_host_request_->Start(base::BindOnce(
&DedicatedWebTransportHttp3Client::DoLoop, base::Unretained(this)));
}
diff --git a/chromium/net/quic/mock_crypto_client_stream.cc b/chromium/net/quic/mock_crypto_client_stream.cc
index 97738cb3e9f..c545c697d52 100644
--- a/chromium/net/quic/mock_crypto_client_stream.cc
+++ b/chromium/net/quic/mock_crypto_client_stream.cc
@@ -142,9 +142,6 @@ bool MockCryptoClientStream::CryptoConnect() {
std::make_unique<MockDecrypter>(Perspective::IS_CLIENT));
}
session()->connection()->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
- session()->connection()->SetEncrypter(
ENCRYPTION_ZERO_RTT,
std::make_unique<MockEncrypter>(Perspective::IS_CLIENT));
} else {
@@ -160,13 +157,13 @@ bool MockCryptoClientStream::CryptoConnect() {
if (session()->version().UsesHttp3()) {
SetConfigNegotiated();
}
- session()->connection()->SetEncrypter(
- ENCRYPTION_FORWARD_SECURE,
- std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
session()->OnNewEncryptionKeyAvailable(
ENCRYPTION_ZERO_RTT,
std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
}
+ if (!session()->connection()->connected()) {
+ break;
+ }
if (session()->version().UsesQuicCrypto()) {
session()->SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
} else {
@@ -223,6 +220,9 @@ bool MockCryptoClientStream::CryptoConnect() {
session()->OnNewEncryptionKeyAvailable(
ENCRYPTION_FORWARD_SECURE,
std::make_unique<NullEncrypter>(Perspective::IS_CLIENT));
+ if (!session()->connection()->connected()) {
+ break;
+ }
if (session()->version().UsesTls()) {
session()->OnTlsHandshakeComplete();
} else {
diff --git a/chromium/net/quic/mock_crypto_client_stream.h b/chromium/net/quic/mock_crypto_client_stream.h
index 9cb0cfdbc25..68e5ad9fc52 100644
--- a/chromium/net/quic/mock_crypto_client_stream.h
+++ b/chromium/net/quic/mock_crypto_client_stream.h
@@ -5,8 +5,6 @@
#ifndef NET_QUIC_MOCK_CRYPTO_CLIENT_STREAM_H_
#define NET_QUIC_MOCK_CRYPTO_CLIENT_STREAM_H_
-#include <string>
-
#include "base/macros.h"
#include "net/quic/crypto/proof_verifier_chromium.h"
#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
diff --git a/chromium/net/quic/mock_crypto_client_stream_factory.h b/chromium/net/quic/mock_crypto_client_stream_factory.h
index b5e89f05278..b0f8193e64a 100644
--- a/chromium/net/quic/mock_crypto_client_stream_factory.h
+++ b/chromium/net/quic/mock_crypto_client_stream_factory.h
@@ -6,7 +6,6 @@
#define NET_QUIC_MOCK_CRYPTO_CLIENT_STREAM_FACTORY_H_
#include <memory>
-#include <string>
#include "base/containers/queue.h"
#include "base/macros.h"
diff --git a/chromium/net/quic/platform/impl/DEPS b/chromium/net/quic/platform/impl/DEPS
index fbe38244fb1..2c12fec5f33 100644
--- a/chromium/net/quic/platform/impl/DEPS
+++ b/chromium/net/quic/platform/impl/DEPS
@@ -1,8 +1,4 @@
include_rules = [
- # This is a temporary rule to simplify migrating QUICHE to using Abseil
- # directly.
- # TODO(b/166325009): remove this rule.
- "+third_party/abseil-cpp/absl/base",
- "+third_party/abseil-cpp/absl/container",
+ # Allow string_view.h since absl::string_view is widely used in QUICHE API.
"+third_party/abseil-cpp/absl/strings",
]
diff --git a/chromium/net/quic/platform/impl/quic_chromium_clock.cc b/chromium/net/quic/platform/impl/quic_chromium_clock.cc
index f6be6b29448..92c1860105b 100644
--- a/chromium/net/quic/platform/impl/quic_chromium_clock.cc
+++ b/chromium/net/quic/platform/impl/quic_chromium_clock.cc
@@ -13,9 +13,10 @@ QuicChromiumClock* QuicChromiumClock::GetInstance() {
static base::NoDestructor<QuicChromiumClock> instance;
return instance.get();
}
-QuicChromiumClock::QuicChromiumClock() {}
-QuicChromiumClock::~QuicChromiumClock() {}
+QuicChromiumClock::QuicChromiumClock() = default;
+
+QuicChromiumClock::~QuicChromiumClock() = default;
QuicTime QuicChromiumClock::ApproximateNow() const {
// At the moment, Chrome does not have a distinct notion of ApproximateNow().
@@ -37,4 +38,14 @@ QuicWallTime QuicChromiumClock::WallNow() const {
return QuicWallTime::FromUNIXMicroseconds(time_since_unix_epoch_micro);
}
+// static
+base::TimeTicks QuicChromiumClock::QuicTimeToTimeTicks(QuicTime quic_time) {
+ // QuicChromiumClock defines base::TimeTicks() as equal to
+ // quic::QuicTime::Zero(). See QuicChromiumClock::Now() above.
+ QuicTime::Delta offset_from_zero = quic_time - QuicTime::Zero();
+ int64_t offset_from_zero_us = offset_from_zero.ToMicroseconds();
+ return base::TimeTicks() +
+ base::TimeDelta::FromMicroseconds(offset_from_zero_us);
+}
+
} // namespace quic
diff --git a/chromium/net/quic/platform/impl/quic_chromium_clock.h b/chromium/net/quic/platform/impl/quic_chromium_clock.h
index 30c83e45e08..29012d49999 100644
--- a/chromium/net/quic/platform/impl/quic_chromium_clock.h
+++ b/chromium/net/quic/platform/impl/quic_chromium_clock.h
@@ -6,6 +6,7 @@
#define NET_QUIC_PLATFORM_IMPL_QUIC_CHROMIUM_CLOCK_H_
#include "base/macros.h"
+#include "base/time/time.h"
#include "net/third_party/quiche/src/quic/core/quic_clock.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
@@ -25,6 +26,10 @@ class QUIC_EXPORT_PRIVATE QuicChromiumClock : public QuicClock {
QuicTime Now() const override;
QuicWallTime WallNow() const override;
+ // Converts a QuicTime returned by QuicChromiumClock to base::TimeTicks.
+ // Helper functions to safely convert between QuicTime and TimeTicks.
+ static base::TimeTicks QuicTimeToTimeTicks(QuicTime quic_time);
+
private:
DISALLOW_COPY_AND_ASSIGN(QuicChromiumClock);
};
diff --git a/chromium/net/quic/platform/impl/quic_containers_impl.h b/chromium/net/quic/platform/impl/quic_containers_impl.h
index e4e950c7051..05ea22166cc 100644
--- a/chromium/net/quic/platform/impl/quic_containers_impl.h
+++ b/chromium/net/quic/platform/impl/quic_containers_impl.h
@@ -5,27 +5,18 @@
#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_CONTAINERS_IMPL_H_
#define NET_QUIC_PLATFORM_IMPL_QUIC_CONTAINERS_IMPL_H_
-#include <memory>
#include <vector>
-#include "net/third_party/quiche/src/common/quiche_linked_hash_map.h"
-#include "third_party/abseil-cpp/absl/container/btree_set.h"
+#include "base/containers/flat_set.h"
namespace quic {
-// The default hasher used by hash tables.
-template <typename Key>
-using QuicDefaultHasherImpl = absl::Hash<Key>;
-
-template <typename Key, typename Value, typename Hash>
-using QuicLinkedHashMapImpl = quiche::QuicheLinkedHashMap<Key, Value, Hash>;
-
// TODO(wub): Switch to absl::InlinedVector once it is allowed.
template <typename T, size_t N, typename A = std::allocator<T>>
using QuicInlinedVectorImpl = std::vector<T, A>;
-template <typename Key, typename Compare, typename Rep>
-using QuicOrderedSetImpl = absl::btree_set<Key, Compare>;
+template <typename Key, typename Compare>
+using QuicSmallOrderedSetImpl = base::flat_set<Key, Compare>;
} // namespace quic
diff --git a/chromium/net/quic/platform/impl/quic_flags_impl.cc b/chromium/net/quic/platform/impl/quic_flags_impl.cc
index 3491e055739..9cc59b5eedf 100644
--- a/chromium/net/quic/platform/impl/quic_flags_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_flags_impl.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <initializer_list>
#include <iostream>
+#include <limits>
#include <set>
#include <string>
@@ -192,6 +193,18 @@ bool TypedQuicFlagHelper<bool>::SetFlag(const std::string& s) const {
}
template <>
+bool TypedQuicFlagHelper<uint16_t>::SetFlag(const std::string& s) const {
+ int value;
+ if (!base::StringToInt(s, &value) ||
+ value < std::numeric_limits<uint16_t>::min() ||
+ value > std::numeric_limits<uint16_t>::max()) {
+ return false;
+ }
+ *flag_ = static_cast<uint16_t>(value);
+ return true;
+}
+
+template <>
bool TypedQuicFlagHelper<int32_t>::SetFlag(const std::string& s) const {
int32_t value;
if (!base::StringToInt(s, &value)) {
@@ -210,6 +223,8 @@ bool TypedQuicFlagHelper<std::string>::SetFlag(const std::string& s) const {
template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<bool>;
template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
+ TypedQuicFlagHelper<uint16_t>;
+template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<int32_t>;
template class EXPORT_TEMPLATE_DEFINE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<std::string>;
diff --git a/chromium/net/quic/platform/impl/quic_flags_impl.h b/chromium/net/quic/platform/impl/quic_flags_impl.h
index dab7dd05275..5553084db31 100644
--- a/chromium/net/quic/platform/impl/quic_flags_impl.h
+++ b/chromium/net/quic/platform/impl/quic_flags_impl.h
@@ -11,7 +11,9 @@
#include <string>
#include <vector>
+#include "base/command_line.h"
#include "base/export_template.h"
+#include "base/no_destructor.h"
#include "net/third_party/quiche/src/common/platform/api/quiche_flags.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
@@ -21,12 +23,6 @@
#include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
#undef QUIC_PROTOCOL_FLAG
-namespace base {
-class CommandLine;
-template <typename T>
-class NoDestructor;
-} // namespace base
-
// Sets the flag named |flag_name| to the value of |value| after converting
// it from a string to the appropriate type. If |value| is invalid or out of
// range, the flag will be unchanged.
@@ -72,6 +68,9 @@ template <>
QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<bool>::SetFlag(
const std::string&) const;
template <>
+QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<uint16_t>::SetFlag(
+ const std::string&) const;
+template <>
QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<int32_t>::SetFlag(
const std::string&) const;
template <>
@@ -82,6 +81,8 @@ QUIC_EXPORT_PRIVATE bool TypedQuicFlagHelper<std::string>::SetFlag(
extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<bool>;
extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
+ TypedQuicFlagHelper<uint16_t>;
+extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<int32_t>;
extern template class EXPORT_TEMPLATE_DECLARE(QUIC_EXPORT_PRIVATE)
TypedQuicFlagHelper<std::string>;
diff --git a/chromium/net/quic/platform/impl/quic_flags_test.cc b/chromium/net/quic/platform/impl/quic_flags_test.cc
index f8fa493ac1d..d78187283c7 100644
--- a/chromium/net/quic/platform/impl/quic_flags_test.cc
+++ b/chromium/net/quic/platform/impl/quic_flags_test.cc
@@ -7,7 +7,7 @@
#include <string>
#include "base/command_line.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/strcat.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/quic/platform/impl/quic_hostname_utils_impl.cc b/chromium/net/quic/platform/impl/quic_hostname_utils_impl.cc
index 36b752118d0..2fdf09fbbbd 100644
--- a/chromium/net/quic/platform/impl/quic_hostname_utils_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_hostname_utils_impl.cc
@@ -23,9 +23,7 @@ bool QuicHostnameUtilsImpl::IsValidSNI(absl::string_view sni) {
std::string canonicalized_host(
net::CanonicalizeHost(base::StringViewToStringPiece(sni), &host_info));
return !host_info.IsIPAddress() &&
- net::IsCanonicalizedHostCompliant(canonicalized_host) &&
- (GetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots) ||
- sni.find_last_of('.') != std::string::npos);
+ net::IsCanonicalizedHostCompliant(canonicalized_host);
}
// static
diff --git a/chromium/net/quic/platform/impl/quic_map_util_impl.h b/chromium/net/quic/platform/impl/quic_map_util_impl.h
deleted file mode 100644
index 006877a9cfa..00000000000
--- a/chromium/net/quic/platform/impl/quic_map_util_impl.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_MAP_UTIL_IMPL_H_
-#define NET_QUIC_PLATFORM_IMPL_QUIC_MAP_UTIL_IMPL_H_
-
-#include "base/containers/contains.h"
-
-namespace quic {
-
-template <class Collection, class Key>
-bool QuicContainsKeyImpl(const Collection& collection, const Key& key) {
- return base::Contains(collection, key);
-}
-
-template <typename Collection, typename Value>
-bool QuicContainsValueImpl(const Collection& collection, const Value& value) {
- return base::Contains(collection, value);
-}
-
-} // namespace quic
-
-#endif // NET_QUIC_PLATFORM_IMPL_QUIC_MAP_UTIL_IMPL_H_
diff --git a/chromium/net/quic/platform/impl/quic_test_flags_utils.cc b/chromium/net/quic/platform/impl/quic_test_flags_utils.cc
new file mode 100644
index 00000000000..0e5b8ab5d9e
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_test_flags_utils.cc
@@ -0,0 +1,64 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <cstdint>
+#include <iostream>
+
+#include "net/quic/platform/impl/quic_test_flags_utils.h"
+
+#include "base/check_op.h"
+#include "net/quic/platform/impl/quic_flags_impl.h"
+
+QuicFlagSaverImpl::QuicFlagSaverImpl() {
+#define QUIC_FLAG(flag, value) saved_##flag##_ = flag;
+#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+#define QUIC_PROTOCOL_FLAG(type, flag, ...) saved_##flag##_ = FLAGS_##flag;
+#include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
+#undef QUIC_PROTOCOL_FLAG
+}
+
+QuicFlagSaverImpl::~QuicFlagSaverImpl() {
+#define QUIC_FLAG(flag, value) flag = saved_##flag##_;
+#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+#define QUIC_PROTOCOL_FLAG(type, flag, ...) FLAGS_##flag = saved_##flag##_;
+#include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
+#undef QUIC_PROTOCOL_FLAG
+}
+
+QuicFlagChecker::QuicFlagChecker() {
+#define QUIC_FLAG(flag, value) \
+ CHECK_EQ(value, flag) \
+ << "Flag set to an unexpected value. A prior test is likely " \
+ << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \
+ "avoid this issue.";
+#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+
+#define QUIC_PROTOCOL_FLAG_CHECK(type, flag, value) \
+ CHECK_EQ((type)value, FLAGS_##flag) \
+ << "Flag set to an unexpected value. A prior test is likely " \
+ << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \
+ "avoid this issue.";
+#define DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE(type, flag, value, doc) \
+ QUIC_PROTOCOL_FLAG_CHECK(type, flag, value);
+
+#define DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES(type, flag, internal_value, \
+ external_value, doc) \
+ QUIC_PROTOCOL_FLAG_CHECK(type, flag, external_value);
+#define GET_6TH_ARG(arg1, arg2, arg3, arg4, arg5, arg6, ...) arg6
+#define QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(...) \
+ GET_6TH_ARG(__VA_ARGS__, DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES, \
+ DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE)
+#define QUIC_PROTOCOL_FLAG(...) \
+ QUIC_PROTOCOL_FLAG_MACRO_CHOOSER(__VA_ARGS__)(__VA_ARGS__)
+#include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
+#undef QUIC_PROTOCOL_FLAG
+#undef QUIC_PROTOCOL_FLAG_MACRO_CHOOSER
+#undef GET_6TH_ARG
+#undef DEFINE_QUIC_PROTOCOL_FLAG_TWO_VALUES
+#undef DEFINE_QUIC_PROTOCOL_FLAG_SINGLE_VALUE
+#undef QUIC_PROTOCOL_FLAG_CHECK
+}
diff --git a/chromium/net/quic/platform/impl/quic_test_flags_utils.h b/chromium/net/quic/platform/impl/quic_test_flags_utils.h
new file mode 100644
index 00000000000..ff11a3ab9b9
--- /dev/null
+++ b/chromium/net/quic/platform/impl/quic_test_flags_utils.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_QUIC_PLATFORM_IMPL_QUIC_TEST_FLAGS_UTILS_H_
+#define NET_QUIC_PLATFORM_IMPL_QUIC_TEST_FLAGS_UTILS_H_
+
+// When constructed, saves the current values of all QUIC flags. When
+// destructed, restores all QUIC flags to the saved values.
+class QuicFlagSaverImpl {
+ public:
+ QuicFlagSaverImpl();
+ ~QuicFlagSaverImpl();
+
+ private:
+#define QUIC_FLAG(flag, value) bool saved_##flag##_;
+#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
+#undef QUIC_FLAG
+#define QUIC_PROTOCOL_FLAG(type, flag, ...) type saved_##flag##_;
+#include "net/third_party/quiche/src/quic/core/quic_protocol_flags_list.h"
+#undef QUIC_PROTOCOL_FLAG
+};
+
+//// Checks if all QUIC flags are on their default values on construction.
+class QuicFlagChecker {
+ public:
+ QuicFlagChecker();
+};
+
+#endif // NET_QUIC_PLATFORM_IMPL_QUIC_TEST_FLAGS_UTILS_H_
diff --git a/chromium/net/quic/platform/impl/quic_test_impl.cc b/chromium/net/quic/platform/impl/quic_test_impl.cc
index 859012ff614..efad1fbfba1 100644
--- a/chromium/net/quic/platform/impl/quic_test_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_test_impl.cc
@@ -7,18 +7,6 @@
#include "base/files/file_path.h"
#include "base/path_service.h"
-QuicFlagSaverImpl::QuicFlagSaverImpl() {
-#define QUIC_FLAG(flag, value) saved_##flag##_ = flag;
-#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
-#undef QUIC_FLAG
-}
-
-QuicFlagSaverImpl::~QuicFlagSaverImpl() {
-#define QUIC_FLAG(flag, value) flag = saved_##flag##_;
-#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
-#undef QUIC_FLAG
-}
-
std::string QuicGetTestMemoryCachePathImpl() {
base::FilePath path;
base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
diff --git a/chromium/net/quic/platform/impl/quic_test_impl.h b/chromium/net/quic/platform/impl/quic_test_impl.h
index 0d9825fbae7..34a293977de 100644
--- a/chromium/net/quic/platform/impl/quic_test_impl.h
+++ b/chromium/net/quic/platform/impl/quic_test_impl.h
@@ -6,6 +6,7 @@
#define NET_QUIC_PLATFORM_IMPL_QUIC_TEST_IMPL_H_
#include "base/check_op.h"
+#include "net/quic/platform/impl/quic_test_flags_utils.h"
#include "net/test/test_with_task_environment.h"
#include "net/third_party/quiche/src/quic/core/quic_versions.h"
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
@@ -13,32 +14,6 @@
#include "testing/gtest/include/gtest/gtest-spi.h" // IWYU pragma: export
#include "testing/gtest/include/gtest/gtest.h" // IWYU pragma: export
-// When constructed, saves the current values of all QUIC flags. When
-// destructed, restores all QUIC flags to the saved values.
-class QuicFlagSaverImpl {
- public:
- QuicFlagSaverImpl();
- ~QuicFlagSaverImpl();
-
- private:
-#define QUIC_FLAG(flag, value) bool saved_##flag##_;
-#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
-#undef QUIC_FLAG
-};
-
-// Checks if all QUIC flags are on their default values on construction.
-class QuicFlagChecker {
- public:
- QuicFlagChecker() {
-#define QUIC_FLAG(flag, value) \
- CHECK_EQ(value, flag) \
- << "Flag set to an unexpected value. A prior test is likely " \
- << "setting a flag without using a QuicFlagSaver. Use QuicTest to " \
- "avoid this issue.";
-#include "net/third_party/quiche/src/quic/core/quic_flags_list.h"
-#undef QUIC_FLAG
- }
-};
class QuicTestImpl : public ::testing::Test {
private:
diff --git a/chromium/net/quic/platform/impl/quic_test_loopback_impl.cc b/chromium/net/quic/platform/impl/quic_test_loopback_impl.cc
index f339bf1a12c..92cea5409a2 100644
--- a/chromium/net/quic/platform/impl/quic_test_loopback_impl.cc
+++ b/chromium/net/quic/platform/impl/quic_test_loopback_impl.cc
@@ -23,7 +23,7 @@ QuicIpAddress TestLoopbackImpl() {
}
QuicIpAddress TestLoopbackImpl(int index) {
- const char kLocalhostIPv4[] = {127, 0, 0, index};
+ const char kLocalhostIPv4[] = {127, 0, 0, static_cast<char>(index)};
QuicIpAddress address;
address.FromPackedString(kLocalhostIPv4, 4);
return address;
diff --git a/chromium/net/quic/quic_chromium_alarm_factory.cc b/chromium/net/quic/quic_chromium_alarm_factory.cc
index d3102e958a1..8b63b75bc15 100644
--- a/chromium/net/quic/quic_chromium_alarm_factory.cc
+++ b/chromium/net/quic/quic_chromium_alarm_factory.cc
@@ -7,89 +7,74 @@
#include "base/bind.h"
#include "base/check.h"
#include "base/location.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/task_runner.h"
+#include "base/time/tick_clock.h"
#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "net/quic/platform/impl/quic_chromium_clock.h"
namespace net {
namespace {
-class QuicChromeAlarm : public quic::QuicAlarm {
+class QuicChromeAlarm : public quic::QuicAlarm, public base::TickClock {
public:
QuicChromeAlarm(const quic::QuicClock* clock,
- base::TaskRunner* task_runner,
+ base::SequencedTaskRunner* task_runner,
quic::QuicArenaScopedPtr<quic::QuicAlarm::Delegate> delegate)
: quic::QuicAlarm(std::move(delegate)),
clock_(clock),
- task_runner_(task_runner),
- task_deadline_(quic::QuicTime::Zero()) {}
+ // Unretained is safe because base::OneShotTimer never runs its task
+ // after being deleted.
+ on_alarm_callback_(base::BindRepeating(&QuicChromeAlarm::OnAlarm,
+ base::Unretained(this))),
+ timer_(std::make_unique<base::OneShotTimer>(this)) {
+ timer_->SetTaskRunner(task_runner);
+ }
protected:
void SetImpl() override {
DCHECK(deadline().IsInitialized());
- if (task_deadline_.IsInitialized()) {
- if (task_deadline_ <= deadline()) {
- // Since tasks can not be un-posted, OnAlarm will be invoked which
- // will notice that deadline has not yet been reached, and will set
- // the alarm for the new deadline.
- return;
- }
- // The scheduled task is after new deadline. Invalidate the weak ptrs
- // so that task does not execute when we're not expecting it.
- weak_factory_.InvalidateWeakPtrs();
- }
-
- int64_t delay_us = (deadline() - (clock_->Now())).ToMicroseconds();
- if (delay_us < 0) {
- delay_us = 0;
- }
- task_runner_->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&QuicChromeAlarm::OnAlarm, weak_factory_.GetWeakPtr()),
- base::TimeDelta::FromMicroseconds(delay_us));
- task_deadline_ = deadline();
+ const int64_t delay_us = (deadline() - clock_->Now()).ToMicroseconds();
+ timer_->Start(FROM_HERE, base::TimeDelta::FromMicroseconds(delay_us),
+ on_alarm_callback_);
}
void CancelImpl() override {
DCHECK(!deadline().IsInitialized());
- // Since tasks can not be un-posted, OnAlarm will be invoked which
- // will notice that deadline is not Initialized and will do nothing.
+ timer_->Stop();
}
private:
void OnAlarm() {
- DCHECK(task_deadline_.IsInitialized());
- task_deadline_ = quic::QuicTime::Zero();
- // The alarm may have been cancelled.
- if (!deadline().IsInitialized()) {
- return;
- }
+ DCHECK(deadline().IsInitialized());
- // The alarm may have been re-set to a later time.
+ // In tests, the time source used by the scheduler may not be in sync with
+ // |clock_|. Because of this, the scheduler may run this task when
+ // |clock->Now()| is smaller than |deadline()|. In that case, retry later.
+ // This shouldn't happen in production.
if (clock_->Now() < deadline()) {
SetImpl();
return;
}
+ DCHECK_LE(deadline(), clock_->Now());
Fire();
}
- const quic::QuicClock* clock_;
- base::TaskRunner* task_runner_;
- // If a task has been posted to the message loop, this is the time it
- // was scheduled to fire. Tracking this allows us to avoid posting a
- // new tast if the new deadline is in the future, but permits us to
- // post a new task when the new deadline now earlier than when
- // previously posted.
- quic::QuicTime task_deadline_;
- base::WeakPtrFactory<QuicChromeAlarm> weak_factory_{this};
+ // base::TickClock:
+ base::TimeTicks NowTicks() const override {
+ return quic::QuicChromiumClock::QuicTimeToTimeTicks(clock_->Now());
+ }
+
+ const quic::QuicClock* const clock_;
+ base::RepeatingClosure on_alarm_callback_;
+ const std::unique_ptr<base::OneShotTimer> timer_;
};
} // namespace
QuicChromiumAlarmFactory::QuicChromiumAlarmFactory(
- base::TaskRunner* task_runner,
+ base::SequencedTaskRunner* task_runner,
const quic::QuicClock* clock)
: task_runner_(task_runner), clock_(clock) {}
diff --git a/chromium/net/quic/quic_chromium_alarm_factory.h b/chromium/net/quic/quic_chromium_alarm_factory.h
index 330eea83566..6082aff8cba 100644
--- a/chromium/net/quic/quic_chromium_alarm_factory.h
+++ b/chromium/net/quic/quic_chromium_alarm_factory.h
@@ -9,7 +9,6 @@
#define NET_QUIC_QUIC_CHROMIUM_ALARM_FACTORY_H_
#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
#include "net/base/net_export.h"
#include "net/third_party/quiche/src/quic/core/quic_alarm_factory.h"
#include "net/third_party/quiche/src/quic/core/quic_clock.h"
@@ -17,7 +16,7 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
namespace base {
-class TaskRunner;
+class SequencedTaskRunner;
} // namespace base
namespace net {
@@ -25,7 +24,7 @@ namespace net {
class NET_EXPORT_PRIVATE QuicChromiumAlarmFactory
: public quic::QuicAlarmFactory {
public:
- QuicChromiumAlarmFactory(base::TaskRunner* task_runner,
+ QuicChromiumAlarmFactory(base::SequencedTaskRunner* task_runner,
const quic::QuicClock* clock);
~QuicChromiumAlarmFactory() override;
@@ -36,9 +35,8 @@ class NET_EXPORT_PRIVATE QuicChromiumAlarmFactory
quic::QuicConnectionArena* arena) override;
private:
- base::TaskRunner* task_runner_;
- const quic::QuicClock* clock_;
- base::WeakPtrFactory<QuicChromiumAlarmFactory> weak_factory_{this};
+ base::SequencedTaskRunner* task_runner_;
+ const quic::QuicClock* const clock_;
DISALLOW_COPY_AND_ASSIGN(QuicChromiumAlarmFactory);
};
diff --git a/chromium/net/quic/quic_chromium_alarm_factory_test.cc b/chromium/net/quic/quic_chromium_alarm_factory_test.cc
index 0058bebf9c6..e6c0854e315 100644
--- a/chromium/net/quic/quic_chromium_alarm_factory_test.cc
+++ b/chromium/net/quic/quic_chromium_alarm_factory_test.cc
@@ -40,16 +40,19 @@ TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarm) {
TestDelegate* delegate = new TestDelegate();
std::unique_ptr<quic::QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
- quic::QuicTime::Delta delta = quic::QuicTime::Delta::FromMicroseconds(1);
- alarm->Set(clock_.Now() + delta);
+ // Set the deadline 1µs in the future.
+ constexpr quic::QuicTime::Delta kDelta =
+ quic::QuicTime::Delta::FromMicroseconds(1);
+ quic::QuicTime deadline = clock_.Now() + kDelta;
+ alarm->Set(deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), deadline);
+ EXPECT_FALSE(delegate->fired());
- // Verify that the alarm task has been posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[0].delay);
+ runner_->FastForwardBy(kDelta);
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_TRUE(delegate->fired());
}
@@ -57,17 +60,24 @@ TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndCancel) {
TestDelegate* delegate = new TestDelegate();
std::unique_ptr<quic::QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
- quic::QuicTime::Delta delta = quic::QuicTime::Delta::FromMicroseconds(1);
- alarm->Set(clock_.Now() + delta);
+ constexpr quic::QuicTime::Delta kDelta =
+ quic::QuicTime::Delta::FromMicroseconds(1);
+ quic::QuicTime deadline = clock_.Now() + kDelta;
+ alarm->Set(deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), deadline);
+ EXPECT_FALSE(delegate->fired());
+
alarm->Cancel();
- // The alarm task should still be posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[0].delay);
+ EXPECT_FALSE(alarm->IsSet());
+ EXPECT_FALSE(delegate->fired());
+
+ // Advancing time should not cause the alarm to fire.
+ runner_->FastForwardBy(kDelta);
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_FALSE(delegate->fired());
}
@@ -75,26 +85,41 @@ TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndReset) {
TestDelegate* delegate = new TestDelegate();
std::unique_ptr<quic::QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
- quic::QuicTime::Delta delta = quic::QuicTime::Delta::FromMicroseconds(1);
- alarm->Set(clock_.Now() + delta);
+ // Set the deadline 1µs in the future.
+ constexpr quic::QuicTime::Delta kDelta =
+ quic::QuicTime::Delta::FromMicroseconds(1);
+ quic::QuicTime deadline = clock_.Now() + kDelta;
+ alarm->Set(deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), deadline);
+ EXPECT_FALSE(delegate->fired());
+
alarm->Cancel();
- quic::QuicTime::Delta new_delta = quic::QuicTime::Delta::FromMicroseconds(3);
- alarm->Set(clock_.Now() + new_delta);
- // The alarm task should still be posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[0].delay);
+ EXPECT_FALSE(alarm->IsSet());
+ EXPECT_FALSE(delegate->fired());
+
+ // Set the timer with a longer delta.
+ constexpr quic::QuicTime::Delta kNewDelta =
+ quic::QuicTime::Delta::FromMicroseconds(3);
+ quic::QuicTime new_deadline = clock_.Now() + kNewDelta;
+ alarm->Set(new_deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), new_deadline);
+ EXPECT_FALSE(delegate->fired());
+
+ // Advancing time for the first delay should not cause the alarm to fire.
+ runner_->FastForwardBy(kDelta);
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kDelta, clock_.Now());
+ EXPECT_TRUE(alarm->IsSet());
EXPECT_FALSE(delegate->fired());
- // The alarm task should be posted again.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+ // Advancing time for the remaining of the new delay will fire the alarm.
+ runner_->FastForwardBy(kNewDelta - kDelta);
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + new_delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kNewDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_TRUE(delegate->fired());
}
@@ -102,28 +127,45 @@ TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndResetEarlier) {
TestDelegate* delegate = new TestDelegate();
std::unique_ptr<quic::QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
- quic::QuicTime::Delta delta = quic::QuicTime::Delta::FromMicroseconds(3);
- alarm->Set(clock_.Now() + delta);
+ // Set the deadline 3µs in the future.
+ constexpr quic::QuicTime::Delta kDelta =
+ quic::QuicTime::Delta::FromMicroseconds(3);
+ quic::QuicTime deadline = clock_.Now() + kDelta;
+ alarm->Set(deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), deadline);
+ EXPECT_FALSE(delegate->fired());
+
alarm->Cancel();
- quic::QuicTime::Delta new_delta = quic::QuicTime::Delta::FromMicroseconds(1);
- alarm->Set(clock_.Now() + new_delta);
- // Both alarm tasks will be posted.
- ASSERT_EQ(2u, runner_->GetPostedTasks().size());
+ EXPECT_FALSE(alarm->IsSet());
+ EXPECT_FALSE(delegate->fired());
+
+ // Set the timer with a shorter delta.
+ constexpr quic::QuicTime::Delta kNewDelta =
+ quic::QuicTime::Delta::FromMicroseconds(1);
+ quic::QuicTime new_deadline = clock_.Now() + kNewDelta;
+ alarm->Set(new_deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), new_deadline);
+ EXPECT_FALSE(delegate->fired());
+
+ // Advancing time for the shorter delay will fire the alarm.
+ runner_->FastForwardBy(kNewDelta);
- // The earlier task will execute and will fire the alarm->
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + new_delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kNewDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_TRUE(delegate->fired());
+
delegate->Clear();
+ EXPECT_FALSE(delegate->fired());
- // The latter task is still posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
+ // Advancing time for the remaining of the new original delay should not cause
+ // the alarm to fire again.
+ runner_->FastForwardBy(kDelta - kNewDelta);
- // When the latter task is executed, the weak ptr will be invalid and
- // the alarm will not fire.
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_FALSE(delegate->fired());
}
@@ -131,39 +173,51 @@ TEST_F(QuicChromiumAlarmFactoryTest, CreateAlarmAndUpdate) {
TestDelegate* delegate = new TestDelegate();
std::unique_ptr<quic::QuicAlarm> alarm(alarm_factory_.CreateAlarm(delegate));
- quic::QuicTime start = clock_.Now();
- quic::QuicTime::Delta delta = quic::QuicTime::Delta::FromMicroseconds(1);
- alarm->Set(clock_.Now() + delta);
- quic::QuicTime::Delta new_delta = quic::QuicTime::Delta::FromMicroseconds(3);
- alarm->Update(clock_.Now() + new_delta,
- quic::QuicTime::Delta::FromMicroseconds(1));
-
- // The alarm task should still be posted.
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(base::TimeDelta::FromMicroseconds(delta.ToMicroseconds()),
- runner_->GetPostedTasks()[0].delay);
+ // Set the deadline 1µs in the future.
+ constexpr quic::QuicTime::Delta kDelta =
+ quic::QuicTime::Delta::FromMicroseconds(1);
+ quic::QuicTime deadline = clock_.Now() + kDelta;
+ alarm->Set(deadline);
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), deadline);
+ EXPECT_FALSE(delegate->fired());
- runner_->RunNextTask();
- EXPECT_EQ(quic::QuicTime::Zero() + delta, clock_.Now());
+ // Update the deadline.
+ constexpr quic::QuicTime::Delta kNewDelta =
+ quic::QuicTime::Delta::FromMicroseconds(3);
+ quic::QuicTime new_deadline = clock_.Now() + kNewDelta;
+ alarm->Update(new_deadline, quic::QuicTime::Delta::FromMicroseconds(1));
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), new_deadline);
EXPECT_FALSE(delegate->fired());
- // Move the alarm forward 1us and ensure it doesn't move forward.
- alarm->Update(clock_.Now() + new_delta,
+ // Update the alarm with another delta that is not further away from the
+ // current deadline than the granularity. The deadline should not change.
+ alarm->Update(new_deadline + quic::QuicTime::Delta::FromMicroseconds(1),
quic::QuicTime::Delta::FromMicroseconds(2));
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), new_deadline);
+ EXPECT_FALSE(delegate->fired());
+
+ // Advancing time for the first delay should not cause the alarm to fire.
+ runner_->FastForwardBy(kDelta);
- ASSERT_EQ(1u, runner_->GetPostedTasks().size());
- EXPECT_EQ(
- base::TimeDelta::FromMicroseconds((new_delta - delta).ToMicroseconds()),
- runner_->GetPostedTasks()[0].delay);
- runner_->RunNextTask();
- EXPECT_EQ(start + new_delta, clock_.Now());
+ EXPECT_EQ(quic::QuicTime::Zero() + kDelta, clock_.Now());
+ EXPECT_TRUE(alarm->IsSet());
+ EXPECT_FALSE(delegate->fired());
+
+ // Advancing time for the remaining of the new delay will fire the alarm.
+ runner_->FastForwardBy(kNewDelta - kDelta);
+
+ EXPECT_EQ(quic::QuicTime::Zero() + kNewDelta, clock_.Now());
+ EXPECT_FALSE(alarm->IsSet());
EXPECT_TRUE(delegate->fired());
// Set the alarm via an update call.
- new_delta = quic::QuicTime::Delta::FromMicroseconds(5);
- alarm->Update(clock_.Now() + new_delta,
- quic::QuicTime::Delta::FromMicroseconds(1));
+ new_deadline = clock_.Now() + quic::QuicTime::Delta::FromMicroseconds(5);
+ alarm->Update(new_deadline, quic::QuicTime::Delta::FromMicroseconds(1));
EXPECT_TRUE(alarm->IsSet());
+ EXPECT_EQ(alarm->deadline(), new_deadline);
// Update it with an uninitialized time and ensure it's cancelled.
alarm->Update(quic::QuicTime::Zero(),
diff --git a/chromium/net/quic/quic_chromium_client_session.cc b/chromium/net/quic/quic_chromium_client_session.cc
index ce53c752c70..15f25429fb2 100644
--- a/chromium/net/quic/quic_chromium_client_session.cc
+++ b/chromium/net/quic/quic_chromium_client_session.cc
@@ -56,6 +56,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "url/origin.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -358,10 +359,10 @@ class QuicServerPushHelper : public ServerPushDelegate::ServerPushHelper {
QuicChromiumClientSession::Handle::Handle(
const base::WeakPtr<QuicChromiumClientSession>& session,
- const HostPortPair& destination)
+ url::SchemeHostPort destination)
: MultiplexedSessionHandle(session),
session_(session),
- destination_(destination),
+ destination_(std::move(destination)),
net_log_(session_->net_log()),
was_handshake_confirmed_(session->OneRttKeysAvailable()),
net_error_(OK),
@@ -817,6 +818,7 @@ void QuicChromiumClientSession::ConnectionMigrationValidationResultDelegate::
void QuicChromiumClientSession::ConnectionMigrationValidationResultDelegate::
OnPathValidationFailure(
std::unique_ptr<quic::QuicPathValidationContext> context) {
+ session_->connection()->OnPathValidationFailureAtClient();
// Note that socket, packet writer, and packet reader in |context| will be
// discarded.
auto* chrome_context =
@@ -843,6 +845,7 @@ void QuicChromiumClientSession::PortMigrationValidationResultDelegate::
void QuicChromiumClientSession::PortMigrationValidationResultDelegate::
OnPathValidationFailure(
std::unique_ptr<quic::QuicPathValidationContext> context) {
+ session_->connection()->OnPathValidationFailureAtClient();
// Note that socket, packet writer, and packet reader in |context| will be
// discarded.
auto* chrome_context =
@@ -1705,10 +1708,17 @@ void QuicChromiumClientSession::OnCanCreateNewOutgoingStream(
void QuicChromiumClientSession::OnConfigNegotiated() {
quic::QuicSpdyClientSessionBase::OnConfigNegotiated();
- if (!stream_factory_ || !stream_factory_->allow_server_migration() ||
- (!config()->HasReceivedIPv6AlternateServerAddress() &&
- !config()->HasReceivedIPv4AlternateServerAddress())) {
- return;
+ if (!stream_factory_ || !stream_factory_->allow_server_migration()) {
+ if (connection()->connection_migration_use_new_cid()) {
+ if (!config()->HasReceivedPreferredAddressConnectionIdAndToken()) {
+ return;
+ }
+ } else {
+ if (!config()->HasReceivedIPv6AlternateServerAddress() &&
+ !config()->HasReceivedIPv4AlternateServerAddress()) {
+ return;
+ }
+ }
}
// Server has sent an alternate address to connect to.
@@ -1721,8 +1731,7 @@ void QuicChromiumClientSession::OnConfigNegotiated() {
if (!config()->HasReceivedIPv6AlternateServerAddress()) {
return;
}
- new_address =
- ToIPEndPoint(config()->ReceivedIPv6AlternateServerAddress());
+ new_address = ToIPEndPoint(config()->ReceivedIPv6AlternateServerAddress());
} else if (old_address.GetFamily() == ADDRESS_FAMILY_IPV4) {
if (!config()->HasReceivedIPv4AlternateServerAddress()) {
return;
@@ -2183,9 +2192,13 @@ int QuicChromiumClientSession::HandleWriteError(
weak_factory_.GetWeakPtr(), error_code,
connection()->writer()));
- // Store packet in the session since the actual migration and packet rewrite
- // can happen via this posted task or via an async network notification.
- packet_ = std::move(packet);
+ // Only save packet from the old path for retransmission on the new path when
+ // the connection ID does not change.
+ if (!connection()->connection_migration_use_new_cid()) {
+ // Store packet in the session since the actual migration and packet rewrite
+ // can happen via this posted task or via an async network notification.
+ packet_ = std::move(packet);
+ }
ignore_read_error_ = true;
// Cause the packet writer to return ERR_IO_PENDING and block so
@@ -2501,7 +2514,7 @@ void QuicChromiumClientSession::OnProbeFailed(
/*is_success=*/false);
});
- if (version().HasIetfQuicFrames() && connection()->use_path_validator()) {
+ if (connection()->connection_migration_use_new_cid()) {
auto* context = static_cast<QuicChromiumPathValidationContext*>(
connection()->GetPathValidationContext());
@@ -2580,7 +2593,7 @@ void QuicChromiumClientSession::OnNetworkDisconnectedV2(
"disconnected_network", disconnected_network);
// Stop probing the disconnected network if there is one.
- if (version().HasIetfQuicFrames() && connection()->use_path_validator()) {
+ if (connection()->connection_migration_use_new_cid()) {
auto* context = static_cast<QuicChromiumPathValidationContext*>(
connection()->GetPathValidationContext());
if (context && context->network() == disconnected_network &&
@@ -2706,7 +2719,7 @@ void QuicChromiumClientSession::MigrateNetworkImmediately(
}
// Cancel probing on |network| if there is any.
- if (version().HasIetfQuicFrames() && connection()->use_path_validator()) {
+ if (connection()->connection_migration_use_new_cid()) {
auto* context = static_cast<QuicChromiumPathValidationContext*>(
connection()->GetPathValidationContext());
if (context && context->network() == network &&
@@ -3041,7 +3054,8 @@ ProbingResult QuicChromiumClientSession::MaybeStartProbing(
// Abort probing if connection migration is disabled by config.
if (config()->DisableConnectionMigration() ||
- (version().HasIetfQuicFrames() && !connection()->use_path_validator())) {
+ (version().HasIetfQuicFrames() &&
+ !connection()->connection_migration_use_new_cid())) {
DVLOG(1) << "Client disables probing network with connection migration "
<< "disabled by config";
HistogramAndLogMigrationFailure(MIGRATION_STATUS_DISABLED_BY_CONFIG,
@@ -3057,7 +3071,7 @@ ProbingResult QuicChromiumClientSession::StartProbing(
NetworkChangeNotifier::NetworkHandle network,
const quic::QuicSocketAddress& peer_address) {
// Check if probing manager is probing the same path.
- if (version().HasIetfQuicFrames() && connection()->use_path_validator()) {
+ if (connection()->connection_migration_use_new_cid()) {
auto* context = static_cast<QuicChromiumPathValidationContext*>(
connection()->GetPathValidationContext());
if (context && context->network() == network &&
@@ -3097,7 +3111,8 @@ ProbingResult QuicChromiumClientSession::StartProbing(
rtt_ms = kDefaultRTTMilliSecs;
int timeout_ms = rtt_ms * 2;
- if (connection()->use_path_validator() && version().HasIetfQuicFrames()) {
+ if (connection()->connection_migration_use_new_cid() &&
+ version().HasIetfQuicFrames()) {
probing_reader->StartReading();
path_validation_writer_delegate_.set_network(network);
path_validation_writer_delegate_.set_peer_address(peer_address);
@@ -3406,9 +3421,9 @@ bool QuicChromiumClientSession::gquic_zero_rtt_disabled() const {
}
std::unique_ptr<QuicChromiumClientSession::Handle>
-QuicChromiumClientSession::CreateHandle(const HostPortPair& destination) {
+QuicChromiumClientSession::CreateHandle(url::SchemeHostPort destination) {
return std::make_unique<QuicChromiumClientSession::Handle>(
- weak_factory_.GetWeakPtr(), destination);
+ weak_factory_.GetWeakPtr(), std::move(destination));
}
bool QuicChromiumClientSession::OnReadError(
@@ -3586,8 +3601,6 @@ MigrationResult QuicChromiumClientSession::Migrate(
if (!MigrateToSocket(ToQuicSocketAddress(self_address),
ToQuicSocketAddress(peer_address), std::move(socket),
std::move(new_reader), std::move(new_writer))) {
- HistogramAndLogMigrationFailure(MIGRATION_STATUS_TOO_MANY_CHANGES,
- connection_id(), "Too many changes");
if (close_session_on_error) {
if (migrate_session_on_network_change_v2_) {
CloseSessionOnErrorLater(
@@ -3619,6 +3632,8 @@ bool QuicChromiumClientSession::MigrateToSocket(
// write error events, and path degrading on original network.
if (!migrate_session_on_network_change_v2_ &&
sockets_.size() >= kMaxReadersPerQuicSession) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_TOO_MANY_CHANGES,
+ connection_id(), "Too many changes");
return false;
}
@@ -3628,8 +3643,14 @@ bool QuicChromiumClientSession::MigrateToSocket(
// WriteToNewSocket completes.
DVLOG(1) << "Force blocking the packet writer";
writer->set_force_write_blocked(true);
- MigratePath(self_address, peer_address, writer.release(),
- /*owns_writer=*/true);
+ if (!MigratePath(self_address, peer_address, writer.release(),
+ /*owns_writer=*/true)) {
+ HistogramAndLogMigrationFailure(MIGRATION_STATUS_NO_UNUSED_CONNECTION_ID,
+ connection_id(),
+ "No unused server connection ID");
+ DVLOG(1) << "MigratePath fails as there is no CID available";
+ return false;
+ }
// Post task to write the pending packet or a PING packet to the new
// socket. This avoids reentrancy issues if there is a write error
diff --git a/chromium/net/quic/quic_chromium_client_session.h b/chromium/net/quic/quic_chromium_client_session.h
index 538ffda7779..6ee1230a337 100644
--- a/chromium/net/quic/quic_chromium_client_session.h
+++ b/chromium/net/quic/quic_chromium_client_session.h
@@ -53,6 +53,7 @@
#include "net/third_party/quiche/src/quic/core/quic_time.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "url/origin.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -121,6 +122,7 @@ enum QuicConnectionMigrationStatus {
MIGRATION_STATUS_ON_WRITE_ERROR_DISABLED,
MIGRATION_STATUS_PATH_DEGRADING_BEFORE_HANDSHAKE_CONFIRMED,
MIGRATION_STATUS_IDLE_MIGRATION_TIMEOUT,
+ MIGRATION_STATUS_NO_UNUSED_CONNECTION_ID,
MIGRATION_STATUS_MAX
};
@@ -195,7 +197,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Constructs a handle to |session| which was created via the alternative
// server |destination|.
Handle(const base::WeakPtr<QuicChromiumClientSession>& session,
- const HostPortPair& destination);
+ url::SchemeHostPort destination);
Handle(const Handle& other) = delete;
~Handle() override;
@@ -266,7 +268,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
quic::QuicServerId server_id() const { return server_id_; }
// Returns the alternative server used for this session.
- HostPortPair destination() const { return destination_; }
+ const url::SchemeHostPort& destination() const { return destination_; }
// Returns the session's net log.
const NetLogWithSource& net_log() const { return net_log_; }
@@ -322,7 +324,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Underlying session which may be destroyed before this handle.
base::WeakPtr<QuicChromiumClientSession> session_;
- HostPortPair destination_;
+ url::SchemeHostPort destination_;
// Stream request created by |RequestStream()|.
std::unique_ptr<StreamRequest> stream_request_;
@@ -743,7 +745,7 @@ class NET_EXPORT_PRIVATE QuicChromiumClientSession
// Returns a Handle to this session.
std::unique_ptr<QuicChromiumClientSession::Handle> CreateHandle(
- const HostPortPair& destination);
+ url::SchemeHostPort destination);
// Returns the number of client hello messages that have been sent on the
// crypto stream. If the handshake has completed then this is one greater
diff --git a/chromium/net/quic/quic_chromium_client_session_test.cc b/chromium/net/quic/quic_chromium_client_session_test.cc
index 58906e65c96..3f925d90121 100644
--- a/chromium/net/quic/quic_chromium_client_session_test.cc
+++ b/chromium/net/quic/quic_chromium_client_session_test.cc
@@ -9,7 +9,6 @@
#include "base/files/file_path.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -71,6 +70,8 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using testing::_;
@@ -129,6 +130,7 @@ class QuicChromiumClientSessionTest
: version_(GetParam().version),
client_headers_include_h2_stream_dependency_(
GetParam().client_headers_include_h2_stream_dependency),
+ config_(quic::test::DefaultQuicConfig()),
crypto_config_(
quic::test::crypto_test_utils::ProofVerifierForTesting()),
default_read_(new MockRead(SYNCHRONOUS, ERR_IO_PENDING, 0)),
@@ -144,7 +146,7 @@ class QuicChromiumClientSessionTest
SocketTag(),
NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
- destination_(kServerHostname, kServerPort),
+ destination_(url::kHttpsScheme, kServerHostname, kServerPort),
default_network_(NetworkChangeNotifier::kInvalidNetworkHandle),
client_maker_(version_,
quic::QuicUtils::CreateRandomConnectionId(&random_),
@@ -161,6 +163,7 @@ class QuicChromiumClientSessionTest
migrate_session_early_v2_(false),
go_away_on_path_degrading_(false) {
FLAGS_quic_enable_http3_grease_randomness = false;
+ FLAGS_quic_reloadable_flag_quic_ack_cid_frames = true;
quic::QuicEnableVersion(version_);
// Advance the time, because timers do not like uninitialized times.
clock_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
@@ -206,7 +209,7 @@ class QuicChromiumClientSessionTest
kQuicYieldAfterDurationMilliseconds),
go_away_on_path_degrading_,
client_headers_include_h2_stream_dependency_,
- /*cert_verify_flags=*/0, quic::test::DefaultQuicConfig(),
+ /*cert_verify_flags=*/0, config_,
std::make_unique<TestQuicCryptoClientConfigHandle>(&crypto_config_),
"CONNECTION_UNKNOWN", base::TimeTicks::Now(), base::TimeTicks::Now(),
std::make_unique<quic::QuicClientPushPromiseIndex>(),
@@ -242,6 +245,17 @@ class QuicChromiumClientSessionTest
}
}
+ void SetIetfConnectionMigrationFlagsAndConnectionOptions() {
+ FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
+ FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3 = true;
+ FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer =
+ true;
+ FLAGS_quic_reloadable_flag_quic_drop_unsent_path_response = true;
+ FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2 = true;
+ config_.SetConnectionOptionsToSend({quic::kRVCM});
+ }
+
void CompleteCryptoHandshake() {
ASSERT_THAT(session_->CryptoConnect(callback_.callback()), IsOk());
}
@@ -283,6 +297,7 @@ class QuicChromiumClientSessionTest
const quic::ParsedQuicVersion version_;
const bool client_headers_include_h2_stream_dependency_;
QuicFlagSaver flags_; // Save/restore all QUIC flag values.
+ quic::QuicConfig config_;
quic::QuicCryptoClientConfig crypto_config_;
RecordingTestNetLog net_log_;
RecordingBoundTestNetLog bound_test_net_log_;
@@ -296,7 +311,7 @@ class QuicChromiumClientSessionTest
std::unique_ptr<TransportSecurityState> transport_security_state_;
MockCryptoClientStreamFactory crypto_client_stream_factory_;
QuicSessionKey session_key_;
- HostPortPair destination_;
+ url::SchemeHostPort destination_;
std::unique_ptr<TestingQuicChromiumClientSession> session_;
NetworkChangeNotifier::NetworkHandle default_network_;
std::unique_ptr<QuicConnectivityMonitor> connectivity_monitor_;
@@ -1877,12 +1892,25 @@ TEST_P(QuicChromiumClientSessionTest, ConnectionPooledWithMatchingPin) {
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ }
+
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
MockQuicData quic_data(version_);
int packet_num = 1;
+ int peer_packet_num = 1;
socket_data_.reset();
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data.AddWrite(SYNCHRONOUS,
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data.AddWrite(ASYNC,
client_maker_.MakeInitialSettingsPacket(packet_num++));
+ quic_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false,
+ cid_on_new_path,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
}
quic_data.AddRead(ASYNC, ERR_IO_PENDING);
quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
@@ -1890,14 +1918,24 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
Initialize();
CompleteCryptoHandshake();
+ if (VersionUsesHttp3(version_.transport_version)) {
+ // Make new connection ID available after handshake completion.
+ quic_data.Resume();
+ base::RunLoop().RunUntilIdle();
+ }
+
char data[] = "ABCD";
MockQuicData quic_data2(version_);
- quic_data2.AddRead(
- SYNCHRONOUS, server_maker_.MakePingPacket(1, /*include_version=*/false));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- if (version_.UsesHttp3() || version_.HasIetfInvariantHeader()) {
- quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
- packet_num++, false, 1, 1));
+ if (version_.UsesHttp3()) {
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndPingPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1));
} else {
quic_data2.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, true));
@@ -1945,33 +1983,77 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocket) {
quic::test::QuicStreamPeer::SendBuffer(stream).SaveStreamData(iov, 1, 0, 4);
quic::test::QuicStreamPeer::SetStreamBytesWritten(4, stream);
session_->WritevData(stream->id(), 4, 0, quic::NO_FIN,
- quic::NOT_RETRANSMISSION, absl::nullopt);
+ quic::NOT_RETRANSMISSION,
+ quic::ENCRYPTION_FORWARD_SECURE);
EXPECT_TRUE(quic_data2.AllReadDataConsumed());
EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ }
MockQuicData quic_data(version_);
socket_data_.reset();
int packet_num = 1;
+ int peer_packet_num = 1;
+ quic::QuicConnectionId next_cid =
+ quic::QuicUtils::CreateReplacementConnectionId(
+ quic::QuicUtils::CreateRandomConnectionId(&random_));
+ uint64_t next_cid_sequence_number = 1u;
if (VersionUsesHttp3(version_.transport_version)) {
quic_data.AddWrite(SYNCHRONOUS,
client_maker_.MakeInitialSettingsPacket(packet_num++));
}
quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, next_cid,
+ next_cid_sequence_number,
+ /*retire_prior_to=*/next_cid_sequence_number - 1));
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
+ }
quic_data.AddRead(ASYNC, ERR_CONNECTION_CLOSED);
quic_data.AddSocketDataToFactory(&socket_factory_);
Initialize();
CompleteCryptoHandshake();
- for (size_t i = 0; i < kMaxReadersPerQuicSession; ++i) {
- MockQuicData quic_data2(version_);
- quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- quic_data2.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ // Make connection ID available for the first migration.
+ quic_data.Resume();
+ }
+ /* Migration succeeds when maximum number of readers is not reached.*/
+ for (size_t i = 0; i < kMaxReadersPerQuicSession - 1; ++i) {
+ MockQuicData quic_data2(version_);
+ if (!VersionUsesHttp3(version_.transport_version)) {
+ quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
+ } else {
+ client_maker_.set_connection_id(next_cid);
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndPingPacket(
+ packet_num++, /*include_version=*/true,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1));
+ quic_data2.AddRead(ASYNC, ERR_IO_PENDING);
+ quic_data2.AddWrite(
+ ASYNC, client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/next_cid_sequence_number - 1));
+ next_cid = quic::QuicUtils::CreateReplacementConnectionId(next_cid);
+ ++next_cid_sequence_number;
+ quic_data2.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, next_cid,
+ next_cid_sequence_number,
+ /*retire_prior_to=*/next_cid_sequence_number - 1));
+ quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
+ }
quic_data2.AddSocketDataToFactory(&socket_factory_);
// Create connected socket.
@@ -1996,33 +2078,76 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketMaxReaders) {
IPEndPoint peer_address;
new_socket->GetPeerAddress(&peer_address);
// Migrate session.
- if (i < kMaxReadersPerQuicSession - 1) {
- EXPECT_TRUE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- // Spin message loop to complete migration.
+ EXPECT_TRUE(session_->MigrateToSocket(
+ ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+ // Spin message loop to complete migration.
+ base::RunLoop().RunUntilIdle();
+ if (VersionUsesHttp3(version_.transport_version)) {
+ alarm_factory_.FireAlarm(
+ quic::test::QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(
+ session_->connection()));
+ // Make new connection ID available for subsequent migration.
+ quic_data2.Resume();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
- } else {
- // Max readers exceeded.
- EXPECT_FALSE(session_->MigrateToSocket(
- ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
- std::move(new_socket), std::move(new_reader), std::move(new_writer)));
- EXPECT_TRUE(quic_data2.AllReadDataConsumed());
- EXPECT_FALSE(quic_data2.AllWriteDataConsumed());
}
+ EXPECT_TRUE(quic_data2.AllReadDataConsumed());
+ EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
}
+
+ /* Migration fails when maximum number of readers is reached.*/
+ MockQuicData quic_data2(version_);
+ quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
+ quic_data2.AddSocketDataToFactory(&socket_factory_);
+ // Create connected socket.
+ std::unique_ptr<DatagramClientSocket> new_socket =
+ socket_factory_.CreateDatagramClientSocket(DatagramSocket::RANDOM_BIND,
+ &net_log_, NetLogSource());
+ EXPECT_THAT(new_socket->Connect(kIpEndPoint), IsOk());
+
+ // Create reader and writer.
+ std::unique_ptr<QuicChromiumPacketReader> new_reader(
+ new QuicChromiumPacketReader(new_socket.get(), &clock_, session_.get(),
+ kQuicYieldAfterPacketsRead,
+ quic::QuicTime::Delta::FromMilliseconds(
+ kQuicYieldAfterDurationMilliseconds),
+ bound_test_net_log_.bound()));
+ new_reader->StartReading();
+ std::unique_ptr<QuicChromiumPacketWriter> new_writer(
+ CreateQuicChromiumPacketWriter(new_socket.get(), session_.get()));
+
+ IPEndPoint local_address;
+ new_socket->GetLocalAddress(&local_address);
+ IPEndPoint peer_address;
+ new_socket->GetPeerAddress(&peer_address);
+ EXPECT_FALSE(session_->MigrateToSocket(
+ ToQuicSocketAddress(local_address), ToQuicSocketAddress(peer_address),
+ std::move(new_socket), std::move(new_reader), std::move(new_writer)));
+ EXPECT_TRUE(quic_data2.AllReadDataConsumed());
+ EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
}
TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ }
+
MockQuicData quic_data(version_);
socket_data_.reset();
int packet_num = 1;
+ int peer_packet_num = 1;
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING);
quic_data.AddWrite(ASYNC,
client_maker_.MakeInitialSettingsPacket(packet_num++));
+ quic_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false,
+ cid_on_new_path,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
} else {
quic_data.AddWrite(ASYNC, client_maker_.MakePingPacket(packet_num++, true));
}
@@ -2033,14 +2158,30 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
Initialize();
CompleteCryptoHandshake();
- if (!VersionUsesHttp3(version_.transport_version))
+ if (!VersionUsesHttp3(version_.transport_version)) {
session_->connection()->SendPing();
+ } else {
+ // Make new connection ID available after handshake completion.
+ quic_data.Resume();
+ base::RunLoop().RunUntilIdle();
+ }
MockQuicData quic_data2(version_);
- quic_data2.AddRead(
- SYNCHRONOUS, server_maker_.MakePingPacket(1, /*include_version=*/false));
- quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeAckAndPingPacket(
- packet_num++, false, 1, 1));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndPingPacket(
+ packet_num++,
+ /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1));
+ } else {
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
+ }
quic_data2.AddRead(ASYNC, ERR_IO_PENDING);
quic_data2.AddRead(
ASYNC, server_maker_.MakePingPacket(1, /*include_version=*/false));
@@ -2075,6 +2216,12 @@ TEST_P(QuicChromiumClientSessionTest, MigrateToSocketReadError) {
std::move(new_socket), std::move(new_reader), std::move(new_writer)));
// Spin message loop to complete migration.
base::RunLoop().RunUntilIdle();
+ if (VersionUsesHttp3(version_.transport_version)) {
+ EXPECT_TRUE(
+ quic::test::QuicConnectionPeer::GetRetirePeerIssuedConnectionIdAlarm(
+ session_->connection())
+ ->IsSet());
+ }
// Read error on old socket does not impact session.
quic_data.Resume();
diff --git a/chromium/net/quic/quic_chromium_client_stream_test.cc b/chromium/net/quic/quic_chromium_client_stream_test.cc
index 6509df58d4c..dd035c054aa 100644
--- a/chromium/net/quic/quic_chromium_client_stream_test.cc
+++ b/chromium/net/quic/quic_chromium_client_stream_test.cc
@@ -8,9 +8,9 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
@@ -18,6 +18,7 @@
#include "net/quic/quic_chromium_client_session.h"
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
+#include "net/third_party/quiche/src/quic/core/crypto/null_encrypter.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_session_base.h"
#include "net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream.h"
#include "net/third_party/quiche/src/quic/core/http/spdy_utils.h"
@@ -61,14 +62,15 @@ class MockQuicClientSessionBase : public quic::QuicSpdyClientSessionBase {
quic::QuicSpdyStream*(quic::PendingStream* pending));
MOCK_METHOD0(CreateOutgoingBidirectionalStream, QuicChromiumClientStream*());
MOCK_METHOD0(CreateOutgoingUnidirectionalStream, QuicChromiumClientStream*());
- MOCK_METHOD6(
- WritevData,
- quic::QuicConsumedData(quic::QuicStreamId id,
- size_t write_length,
- quic::QuicStreamOffset offset,
- quic::StreamSendingState state,
- quic::TransmissionType type,
- absl::optional<quic::EncryptionLevel> level));
+ MOCK_METHOD6(WritevData,
+ quic::QuicConsumedData(quic::QuicStreamId id,
+ size_t write_length,
+ quic::QuicStreamOffset offset,
+ quic::StreamSendingState state,
+ quic::TransmissionType type,
+ quic::EncryptionLevel level));
+ MOCK_METHOD2(WriteControlFrame,
+ bool(const quic::QuicFrame&, quic::TransmissionType));
MOCK_METHOD4(SendRstStream,
void(quic::QuicStreamId stream_id,
quic::QuicRstStreamErrorCode error,
@@ -185,6 +187,9 @@ class QuicChromiumClientStreamTest
session_.ActivateStream(base::WrapUnique(stream_));
handle_ = stream_->CreateHandle();
helper_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
+ session_.connection()->SetEncrypter(
+ quic::ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<quic::NullEncrypter>(quic::Perspective::IS_CLIENT));
}
void InitializeHeaders() {
@@ -274,10 +279,9 @@ class QuicChromiumClientStreamTest
if (!version_.HasIetfQuicFrames()) {
return "";
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
- return std::string(buffer.get(), header_length);
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body_len, quic::SimpleBufferAllocator::Get());
+ return std::string(buffer.data(), buffer.size());
}
const quic::ParsedQuicVersion version_;
@@ -973,10 +977,6 @@ TEST_P(QuicChromiumClientStreamTest, InvalidStatus) {
version_.transport_version, 0),
quic::QUIC_BAD_APPLICATION_PAYLOAD));
- EXPECT_CALL(
- *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
- SendControlFrame(_));
-
ProcessHeaders(headers);
EXPECT_FALSE(handle_->IsOpen());
EXPECT_EQ(quic::QUIC_BAD_APPLICATION_PAYLOAD, handle_->stream_error());
@@ -992,10 +992,6 @@ TEST_P(QuicChromiumClientStreamTest, SwitchingProtocolsResponse) {
version_.transport_version, 0),
quic::QUIC_BAD_APPLICATION_PAYLOAD));
- EXPECT_CALL(
- *static_cast<quic::test::MockQuicConnection*>(session_.connection()),
- SendControlFrame(_));
-
ProcessHeaders(informational_headers);
EXPECT_FALSE(handle_->IsOpen());
EXPECT_EQ(quic::QUIC_BAD_APPLICATION_PAYLOAD, handle_->stream_error());
diff --git a/chromium/net/quic/quic_client_session_cache.h b/chromium/net/quic/quic_client_session_cache.h
index cf1a90f8924..d566fca721a 100644
--- a/chromium/net/quic/quic_client_session_cache.h
+++ b/chromium/net/quic/quic_client_session_cache.h
@@ -9,7 +9,6 @@
#include <time.h>
#include <memory>
-#include <string>
#include "base/bind.h"
#include "base/containers/mru_cache.h"
diff --git a/chromium/net/quic/quic_connection_logger.h b/chromium/net/quic/quic_connection_logger.h
index 823497969b5..6e41cb2fcbb 100644
--- a/chromium/net/quic/quic_connection_logger.h
+++ b/chromium/net/quic/quic_connection_logger.h
@@ -8,7 +8,6 @@
#include <stddef.h>
#include <bitset>
-#include <string>
#include "base/macros.h"
#include "net/base/ip_endpoint.h"
diff --git a/chromium/net/quic/quic_connectivity_monitor.h b/chromium/net/quic/quic_connectivity_monitor.h
index bc458bfd8b0..4d0aabc1a61 100644
--- a/chromium/net/quic/quic_connectivity_monitor.h
+++ b/chromium/net/quic/quic_connectivity_monitor.h
@@ -7,7 +7,6 @@
#include <set>
-#include "base/containers/flat_set.h"
#include "base/numerics/clamped_math.h"
#include "net/base/network_change_notifier.h"
#include "net/quic/quic_chromium_client_session.h"
diff --git a/chromium/net/quic/quic_connectivity_probing_manager_test.cc b/chromium/net/quic/quic_connectivity_probing_manager_test.cc
index 1bf53d6c6ae..307fef0070b 100644
--- a/chromium/net/quic/quic_connectivity_probing_manager_test.cc
+++ b/chromium/net/quic/quic_connectivity_probing_manager_test.cc
@@ -6,7 +6,6 @@
#include <memory>
-#include "base/stl_util.h"
#include "base/test/test_mock_time_task_runner.h"
#include "net/log/test_net_log.h"
#include "net/quic/address_utils.h"
@@ -169,24 +168,22 @@ TEST_F(QuicConnectivityProbingManagerTest, ReceiveProbingResponseOnSamePath) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
// 2 * initial_timeout_ms.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.WillOnce(Return(true));
-
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
EXPECT_FALSE(session_.is_successfully_probed());
// Notify the manager a connectivity probing packet is received from
@@ -199,14 +196,14 @@ TEST_F(QuicConnectivityProbingManagerTest, ReceiveProbingResponseOnSamePath) {
EXPECT_TRUE(session_.is_successfully_probed());
EXPECT_TRUE(session_.IsProbedPathMatching(testNetworkHandle, testPeerAddress,
self_address_));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Verify there's nothing to send.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest,
@@ -223,7 +220,6 @@ TEST_F(QuicConnectivityProbingManagerTest,
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -232,14 +228,14 @@ TEST_F(QuicConnectivityProbingManagerTest,
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Notify the manager a connectivity probing packet is received from
// testPeerAddress to a different self address, manager should ignore the
@@ -249,7 +245,7 @@ TEST_F(QuicConnectivityProbingManagerTest,
probing_manager_.OnPacketReceived(quic::QuicSocketAddress(), testPeerAddress,
true);
EXPECT_FALSE(session_.is_successfully_probed());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward another initial_timeout_ms, another probing packet will be
// sent.
@@ -257,7 +253,7 @@ TEST_F(QuicConnectivityProbingManagerTest,
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Finally receive the probing response on the same path.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
@@ -266,12 +262,13 @@ TEST_F(QuicConnectivityProbingManagerTest,
EXPECT_TRUE(session_.is_successfully_probed());
EXPECT_TRUE(session_.IsProbedPathMatching(testNetworkHandle, testPeerAddress,
self_address_));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Verify there's nothing to send.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest,
@@ -289,7 +286,6 @@ TEST_F(QuicConnectivityProbingManagerTest,
std::move(socket_), std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -298,14 +294,14 @@ TEST_F(QuicConnectivityProbingManagerTest,
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Notify the manager a connectivity probing packet is received from
// testPeerAddress to a different self address (which only differs in the
@@ -317,7 +313,7 @@ TEST_F(QuicConnectivityProbingManagerTest,
different_port);
probing_manager_.OnPacketReceived(different_self_address, testPeerAddress,
true);
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Verify that session's probed network is still not valid.
EXPECT_FALSE(session_.is_successfully_probed());
@@ -327,7 +323,7 @@ TEST_F(QuicConnectivityProbingManagerTest,
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Finally receive the probing response on the same self address and peer
// address.
@@ -339,12 +335,13 @@ TEST_F(QuicConnectivityProbingManagerTest,
EXPECT_TRUE(session_.IsProbedPathMatching(
NetworkChangeNotifier::kInvalidNetworkHandle, testPeerAddress,
self_address_));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Verify there's nothing to send.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, RetryProbingWithExponentailBackoff) {
@@ -357,7 +354,6 @@ TEST_F(QuicConnectivityProbingManagerTest, RetryProbingWithExponentailBackoff) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// For expential backoff, this will try to resend: 100ms, 200ms, 400ms, 800ms,
// 1600ms.
@@ -367,7 +363,7 @@ TEST_F(QuicConnectivityProbingManagerTest, RetryProbingWithExponentailBackoff) {
int timeout_ms = (1 << retry_count) * initial_timeout_ms;
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
// Move forward another 1600ms, expect probing manager will no longer send any
@@ -377,7 +373,7 @@ TEST_F(QuicConnectivityProbingManagerTest, RetryProbingWithExponentailBackoff) {
int timeout_ms = (1 << 4) * initial_timeout_ms;
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, ProbingReceivedStatelessReset) {
@@ -389,7 +385,6 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingReceivedStatelessReset) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -398,14 +393,14 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingReceivedStatelessReset) {
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
EXPECT_CALL(session_, OnProbeFailed(testNetworkHandle, testPeerAddress))
.Times(1);
@@ -415,6 +410,7 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingReceivedStatelessReset) {
EXPECT_FALSE(
probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
test_task_runner_->RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest,
@@ -428,7 +424,6 @@ TEST_F(QuicConnectivityProbingManagerTest,
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -437,14 +432,14 @@ TEST_F(QuicConnectivityProbingManagerTest,
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Request cancel probing, manager will no longer send connectivity probes.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, _)).Times(0);
@@ -461,6 +456,7 @@ TEST_F(QuicConnectivityProbingManagerTest,
EXPECT_FALSE(
probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
test_task_runner_->RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, CancelProbing) {
@@ -473,7 +469,6 @@ TEST_F(QuicConnectivityProbingManagerTest, CancelProbing) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -482,14 +477,14 @@ TEST_F(QuicConnectivityProbingManagerTest, CancelProbing) {
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Request cancel probing, manager will no longer send connectivity probes.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, _)).Times(0);
@@ -499,6 +494,7 @@ TEST_F(QuicConnectivityProbingManagerTest, CancelProbing) {
probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
test_task_runner_->RunUntilIdle();
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, DoNotCancelProbing) {
@@ -512,14 +508,12 @@ TEST_F(QuicConnectivityProbingManagerTest, DoNotCancelProbing) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Request cancel probing for |newPeerAddress| on |testNetworkHandle| doesn't
- // affect the exisiting probing.
+ // affect the existing probing.
probing_manager_.CancelProbing(testNetworkHandle, newPeerAddress);
EXPECT_TRUE(
probing_manager_.IsUnderProbing(testNetworkHandle, testPeerAddress));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
for (int retry_count = 0; retry_count < 4; retry_count++) {
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
@@ -527,7 +521,7 @@ TEST_F(QuicConnectivityProbingManagerTest, DoNotCancelProbing) {
int timeout_ms = (1 << retry_count) * initial_timeout_ms;
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
EXPECT_CALL(session_, OnProbeFailed(testNetworkHandle, testPeerAddress))
@@ -536,7 +530,7 @@ TEST_F(QuicConnectivityProbingManagerTest, DoNotCancelProbing) {
int timeout_ms = (1 << 4) * initial_timeout_ms;
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, ProbingWriterError) {
@@ -550,7 +544,6 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingWriterError) {
std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
// Fast forward initial_timeout_ms, timeout the first connectivity probing
// packet, cause another probing packet to be sent with timeout set to
@@ -559,14 +552,14 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingWriterError) {
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Probing packet writer received an write error, notifies manager to handle
// write error. Manager will notify session of the probe failure, cancel
@@ -577,7 +570,7 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbingWriterError) {
writer_ptr->OnWriteComplete(ERR_CONNECTION_CLOSED);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest,
@@ -593,24 +586,22 @@ TEST_F(QuicConnectivityProbingManagerTest,
std::move(socket_), std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
-
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Notify the manager a connectivity probing packet is received from
- // testPeerAddress to |self_address_|, manager should decalre probing as
+ // testPeerAddress to |self_address_|, manager should declare probing as
// successful, notify delegate and will no longer send connectivity probes.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
@@ -622,13 +613,13 @@ TEST_F(QuicConnectivityProbingManagerTest,
EXPECT_TRUE(session_.IsProbedPathMatching(
NetworkChangeNotifier::kInvalidNetworkHandle, testPeerAddress,
self_address_));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
TEST_F(QuicConnectivityProbingManagerTest, ProbeServerPreferredAddressFailed) {
@@ -644,20 +635,19 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbeServerPreferredAddressFailed) {
std::move(socket_), std::move(writer_), std::move(reader_),
base::TimeDelta::FromMilliseconds(initial_timeout_ms),
bound_test_net_log_.bound());
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.WillOnce(Return(true));
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Fast forward initial_timeout_ms, should be no-op.
EXPECT_CALL(session_, OnSendConnectivityProbingPacket(_, testPeerAddress))
.Times(0);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(1u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
// Probing packet writer received an write error, notifies manager to handle
// write error. Manager will notify session of the probe failure, cancel
@@ -670,7 +660,7 @@ TEST_F(QuicConnectivityProbingManagerTest, ProbeServerPreferredAddressFailed) {
writer_ptr->OnWriteComplete(ERR_CONNECTION_CLOSED);
test_task_runner_->FastForwardBy(
base::TimeDelta::FromMilliseconds(initial_timeout_ms));
- EXPECT_EQ(0u, test_task_runner_->GetPendingTaskCount());
+ testing::Mock::VerifyAndClearExpectations(&session_);
}
} // namespace test
diff --git a/chromium/net/quic/quic_context.h b/chromium/net/quic/quic_context.h
index 8c055b263b3..736440f8e5e 100644
--- a/chromium/net/quic/quic_context.h
+++ b/chromium/net/quic/quic_context.h
@@ -7,6 +7,7 @@
#include <memory>
+#include "base/time/time.h"
#include "net/base/host_port_pair.h"
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
@@ -19,12 +20,10 @@ DefaultSupportedQuicVersions() {
// The ordering of this list does not matter for Chrome because it respects
// the ordering received from the server via Alt-Svc. However, cronet offers
// an addQuicHint() API which uses the first version from this list until
- // it receives Alt-Svc from the server. We therefore list Q050 first here
- // because there are some cronet applications which communicate with servers
- // that speak Q050 but not Draft29.
- // TODO(dschinazi) Move Draft29 first once those servers support it.
- return quic::ParsedQuicVersionVector{quic::ParsedQuicVersion::Q050(),
- quic::ParsedQuicVersion::Draft29()};
+ // it receives Alt-Svc from the server.
+ return quic::ParsedQuicVersionVector{quic::ParsedQuicVersion::RFCv1(),
+ quic::ParsedQuicVersion::Draft29(),
+ quic::ParsedQuicVersion::Q050()};
}
// Obsolete QUIC supported versions are versions that are supported by the
diff --git a/chromium/net/quic/quic_crypto_client_stream_factory.h b/chromium/net/quic/quic_crypto_client_stream_factory.h
index a010b7f39de..33ddde2b9da 100644
--- a/chromium/net/quic/quic_crypto_client_stream_factory.h
+++ b/chromium/net/quic/quic_crypto_client_stream_factory.h
@@ -6,7 +6,6 @@
#define NET_QUIC_QUIC_CRYPTO_CLIENT_STREAM_FACTORY_H_
#include <memory>
-#include <string>
#include "net/base/net_export.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
diff --git a/chromium/net/quic/quic_end_to_end_unittest.cc b/chromium/net/quic/quic_end_to_end_unittest.cc
index a8adcfb07b1..650a1eb108f 100644
--- a/chromium/net/quic/quic_end_to_end_unittest.cc
+++ b/chromium/net/quic/quic_end_to_end_unittest.cc
@@ -59,9 +59,10 @@ const char kResponseBody[] = "some arbitrary response body";
class TestTransactionFactory : public HttpTransactionFactory {
public:
explicit TestTransactionFactory(
- const HttpNetworkSession::Params& session_params,
- const HttpNetworkSession::Context& session_context)
- : session_(new HttpNetworkSession(session_params, session_context)) {}
+ const HttpNetworkSessionParams& session_params,
+ const HttpNetworkSessionContext& session_context)
+ : session_(std::make_unique<HttpNetworkSession>(session_params,
+ session_context)) {}
~TestTransactionFactory() override {}
@@ -219,8 +220,8 @@ class QuicEndToEndTest : public ::testing::Test, public WithTaskEnvironment {
std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
HttpServerProperties http_server_properties_;
- HttpNetworkSession::Params session_params_;
- HttpNetworkSession::Context session_context_;
+ HttpNetworkSessionParams session_params_;
+ HttpNetworkSessionContext session_context_;
std::unique_ptr<TestTransactionFactory> transaction_factory_;
HttpRequestInfo request_;
std::string request_body_;
diff --git a/chromium/net/quic/quic_event_logger.cc b/chromium/net/quic/quic_event_logger.cc
index e2844ba3fb8..83bfa463b63 100644
--- a/chromium/net/quic/quic_event_logger.cc
+++ b/chromium/net/quic/quic_event_logger.cc
@@ -274,60 +274,14 @@ base::Value NetLogQuicTransportParametersParams(
base::Value NetLogQuicZeroRttRejectReason(int reason) {
base::Value dict(base::Value::Type::DICTIONARY);
- std::string reason_detail = "";
- switch (reason) {
- case ssl_early_data_unknown:
- reason_detail = "The handshake has not progressed far enough";
- break;
- case ssl_early_data_disabled:
- reason_detail = "0-RTT is disabled for this connection.";
- break;
- case ssl_early_data_accepted:
- reason_detail = "0-RTT was accepted";
- break;
- case ssl_early_data_protocol_version:
- reason_detail = "The negotiated protocol doesn't support 0-RTT.";
- break;
- case ssl_early_data_peer_declined:
- reason_detail =
- "The peer declined to offer or accept 0-RTT for an unknown reason.";
- break;
- case ssl_early_data_no_session_offered:
- reason_detail = "The client did not offer a session.";
- break;
- case ssl_early_data_session_not_resumed:
- reason_detail = "The server declined to resume the session.";
- break;
- case ssl_early_data_unsupported_for_session:
- reason_detail = "The session does not support 0-RTT.";
- break;
- case ssl_early_data_hello_retry_request:
- reason_detail = "The server sent a HelloRetryRequest.";
- break;
- case ssl_early_data_alpn_mismatch:
- reason_detail = "The negotiated ALPN protocol did not match the session.";
- break;
- case ssl_early_data_channel_id:
- reason_detail =
- "The connection negotiated Channel ID, which is incompatible with "
- "0-RTT.";
- break;
- case ssl_early_data_token_binding:
- reason_detail =
- "The connection negotiated token binding, which is incompatible with "
- "0-RTT.";
- break;
- case ssl_early_data_ticket_age_skew:
- reason_detail = "The client and server ticket age were too far apart.";
- break;
- case ssl_early_data_quic_parameter_mismatch:
- reason_detail =
- "QUIC parameters differ between this connection and the original.";
- break;
- default:
- reason_detail = "Unknown reason " + base::NumberToString(reason);
+ const char* reason_detail = SSL_early_data_reason_string(
+ static_cast<ssl_early_data_reason_t>(reason));
+ if (reason_detail) {
+ dict.SetStringKey("reason", reason_detail);
+ } else {
+ dict.SetStringKey("reason",
+ "Unknown reason " + base::NumberToString(reason));
}
- dict.SetStringKey("reason", reason_detail);
return dict;
}
diff --git a/chromium/net/quic/quic_http3_logger.cc b/chromium/net/quic/quic_http3_logger.cc
index 14d3c0b968d..4410a373785 100644
--- a/chromium/net/quic/quic_http3_logger.cc
+++ b/chromium/net/quic/quic_http3_logger.cc
@@ -145,15 +145,6 @@ void QuicHttp3Logger::OnPeerQpackDecoderStreamCreated(
stream_id);
}
-void QuicHttp3Logger::OnCancelPushFrameReceived(
- const quic::CancelPushFrame& frame) {
- if (!net_log_.IsCapturing()) {
- return;
- }
- net_log_.AddEventWithIntParams(NetLogEventType::HTTP3_CANCEL_PUSH_RECEIVED,
- "push_id", frame.push_id);
-}
-
void QuicHttp3Logger::OnSettingsFrameReceived(
const quic::SettingsFrame& frame) {
// Increment value by one because empty SETTINGS frames are allowed,
@@ -262,42 +253,6 @@ void QuicHttp3Logger::OnHeadersDecoded(quic::QuicStreamId stream_id,
});
}
-void QuicHttp3Logger::OnPushPromiseFrameReceived(
- quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- quic::QuicByteCount compressed_headers_length) {
- if (!net_log_.IsCapturing()) {
- return;
- }
- net_log_.AddEvent(NetLogEventType::HTTP3_PUSH_PROMISE_RECEIVED,
- [stream_id, push_id, compressed_headers_length] {
- return NetLogThreeIntParams("stream_id", stream_id,
- "push_id", push_id,
- "compressed_headers_length",
- compressed_headers_length);
- });
-}
-
-void QuicHttp3Logger::OnPushPromiseDecoded(quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- quic::QuicHeaderList headers) {
- if (!net_log_.IsCapturing()) {
- return;
- }
- net_log_.AddEvent(
- NetLogEventType::HTTP3_PUSH_PROMISE_DECODED,
- [stream_id, push_id, &headers](NetLogCaptureMode capture_mode) {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id",
- NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers",
- ElideQuicHeaderListForNetLog(headers, capture_mode));
- return dict;
- });
-}
-
void QuicHttp3Logger::OnUnknownFrameReceived(
quic::QuicStreamId stream_id,
uint64_t frame_type,
@@ -382,25 +337,4 @@ void QuicHttp3Logger::OnHeadersFrameSent(
});
}
-void QuicHttp3Logger::OnPushPromiseFrameSent(
- quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- const spdy::Http2HeaderBlock& header_block) {
- if (!net_log_.IsCapturing()) {
- return;
- }
- net_log_.AddEvent(
- NetLogEventType::HTTP3_PUSH_PROMISE_SENT,
- [stream_id, push_id, &header_block](NetLogCaptureMode capture_mode) {
- base::Value dict(base::Value::Type::DICTIONARY);
- dict.SetKey("stream_id",
- NetLogNumberValue(static_cast<uint64_t>(stream_id)));
- dict.SetKey("push_id",
- NetLogNumberValue(static_cast<uint64_t>(push_id)));
- dict.SetKey("headers",
- ElideHttp2HeaderBlockForNetLog(header_block, capture_mode));
- return dict;
- });
-}
-
} // namespace net
diff --git a/chromium/net/quic/quic_http3_logger.h b/chromium/net/quic/quic_http3_logger.h
index 295952a6b87..c22fc79fbee 100644
--- a/chromium/net/quic/quic_http3_logger.h
+++ b/chromium/net/quic/quic_http3_logger.h
@@ -30,7 +30,6 @@ class NET_EXPORT_PRIVATE QuicHttp3Logger : public quic::Http3DebugVisitor {
void OnPeerQpackEncoderStreamCreated(quic::QuicStreamId stream_id) override;
void OnPeerQpackDecoderStreamCreated(quic::QuicStreamId stream_id) override;
- void OnCancelPushFrameReceived(const quic::CancelPushFrame& frame) override;
void OnSettingsFrameReceived(const quic::SettingsFrame& frame) override;
void OnSettingsFrameResumed(const quic::SettingsFrame& frame) override;
void OnGoAwayFrameReceived(const quic::GoAwayFrame& frame) override;
@@ -45,13 +44,6 @@ class NET_EXPORT_PRIVATE QuicHttp3Logger : public quic::Http3DebugVisitor {
quic::QuicByteCount compressed_headers_length) override;
void OnHeadersDecoded(quic::QuicStreamId stream_id,
quic::QuicHeaderList headers) override;
- void OnPushPromiseFrameReceived(
- quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- quic::QuicByteCount compressed_headers_length) override;
- void OnPushPromiseDecoded(quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- quic::QuicHeaderList headers) override;
void OnUnknownFrameReceived(quic::QuicStreamId stream_id,
uint64_t frame_type,
@@ -67,10 +59,6 @@ class NET_EXPORT_PRIVATE QuicHttp3Logger : public quic::Http3DebugVisitor {
quic::QuicByteCount payload_length) override;
void OnHeadersFrameSent(quic::QuicStreamId stream_id,
const spdy::Http2HeaderBlock& header_block) override;
- void OnPushPromiseFrameSent(
- quic::QuicStreamId stream_id,
- quic::QuicStreamId push_id,
- const spdy::Http2HeaderBlock& header_block) override;
private:
NetLogWithSource net_log_;
diff --git a/chromium/net/quic/quic_http_stream.cc b/chromium/net/quic/quic_http_stream.cc
index a3f31f99746..4c24a1be5e8 100644
--- a/chromium/net/quic/quic_http_stream.cc
+++ b/chromium/net/quic/quic_http_stream.cc
@@ -30,6 +30,7 @@
#include "net/third_party/quiche/src/spdy/core/spdy_frame_builder.h"
#include "net/third_party/quiche/src/spdy/core/spdy_framer.h"
#include "url/origin.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -252,7 +253,12 @@ int QuicHttpStream::SendRequest(const HttpRequestHeaders& request_headers,
// Store the response info.
response_info_ = response;
- int rv;
+ // Put the peer's IP address and port into the response.
+ IPEndPoint address;
+ int rv = quic_session()->GetPeerAddress(&address);
+ if (rv != OK)
+ return rv;
+ response_info_->remote_endpoint = address;
if (!found_promise_) {
next_state_ = STATE_SET_REQUEST_PRIORITY;
@@ -403,7 +409,7 @@ bool QuicHttpStream::GetLoadTimingInfo(LoadTimingInfo* load_timing_info) const {
bool QuicHttpStream::GetAlternativeService(
AlternativeService* alternative_service) const {
alternative_service->protocol = kProtoQUIC;
- const HostPortPair& destination = quic_session()->destination();
+ const url::SchemeHostPort& destination = quic_session()->destination();
alternative_service->host = destination.host();
alternative_service->port = destination.port();
return true;
@@ -707,13 +713,6 @@ int QuicHttpStream::ProcessResponseHeaders(
return OK;
}
- // Put the peer's IP address and port into the response.
- IPEndPoint address;
- int rv = quic_session()->GetPeerAddress(&address);
- if (rv != OK)
- return rv;
-
- response_info_->remote_endpoint = address;
response_info_->connection_info =
ConnectionInfoFromQuicVersion(quic_session()->GetQuicVersion());
response_info_->vary_data.Init(*request_info_,
diff --git a/chromium/net/quic/quic_http_stream_test.cc b/chromium/net/quic/quic_http_stream_test.cc
index d3645f3e982..ae180464925 100644
--- a/chromium/net/quic/quic_http_stream_test.cc
+++ b/chromium/net/quic/quic_http_stream_test.cc
@@ -12,7 +12,6 @@
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -79,6 +78,8 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using std::string;
using testing::_;
@@ -434,10 +435,12 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
TestCompletionCallback callback;
session_->CryptoConnect(callback.callback());
stream_ = std::make_unique<QuicHttpStream>(
- session_->CreateHandle(HostPortPair("www.example.org", 443)),
+ session_->CreateHandle(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
std::vector<std::string>() /* dns_aliases */);
promised_stream_ = std::make_unique<QuicHttpStream>(
- session_->CreateHandle(HostPortPair("www.example.org", 443)),
+ session_->CreateHandle(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443)),
std::vector<std::string>() /* dns_aliases */);
push_promise_[":path"] = "/bar";
push_promise_[":authority"] = "www.example.org";
@@ -618,10 +621,9 @@ class QuicHttpStreamTest : public ::testing::TestWithParam<TestParams>,
if (!version_.HasIetfQuicFrames()) {
return "";
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
- return std::string(buffer.get(), header_length);
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body_len, quic::SimpleBufferAllocator::Get());
+ return std::string(buffer.data(), buffer.size());
}
void ReceivePromise(quic::QuicStreamId id) {
@@ -829,9 +831,9 @@ TEST_P(QuicHttpStreamTest, LoadTimingTwoRequests) {
stream_->SendRequest(headers_, &response_, callback_.callback()));
// Start a second request.
- QuicHttpStream stream2(
- session_->CreateHandle(HostPortPair("www.example.org", 443)),
- {} /* dns_aliases */);
+ QuicHttpStream stream2(session_->CreateHandle(url::SchemeHostPort(
+ url::kHttpsScheme, "www.example.org", 443)),
+ {} /* dns_aliases */);
TestCompletionCallback callback2;
EXPECT_EQ(OK,
stream2.InitializeStream(&request_, true, DEFAULT_PRIORITY,
@@ -1042,7 +1044,8 @@ TEST_P(QuicHttpStreamTest, ElideHeadersInNetLog) {
DEFAULT_PRIORITY, &spdy_request_header_frame_length));
auto stream = std::make_unique<QuicHttpStream>(
- session_->CreateHandle(HostPortPair("www.example.org/foo", 443)),
+ session_->CreateHandle(
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org/foo", 443)),
std::vector<std::string>() /* dns_aliases */);
EXPECT_THAT(stream->InitializeStream(&request_, true, DEFAULT_PRIORITY,
net_log_.bound(), callback_.callback()),
@@ -1750,8 +1753,8 @@ TEST_P(QuicHttpStreamTest, SendChunkedPostRequestAbortedByResetStream) {
kIncludeVersion, !kFin, DEFAULT_PRIORITY, 0,
&spdy_request_headers_frame_length, {header, kUploadData}));
AddWrite(ConstructClientAckPacket(packet_number++, 3, 1));
- AddWrite(client_maker_.MakeRstPacket(
- packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR,
+ AddWrite(client_maker_.MakeAckAndRstPacket(
+ packet_number++, true, stream_id_, quic::QUIC_STREAM_NO_ERROR, 4, 1,
/* include_stop_sending_if_v99 = */ false));
} else {
AddWrite(ConstructRequestHeadersAndDataFramesPacket(
diff --git a/chromium/net/quic/quic_network_transaction_unittest.cc b/chromium/net/quic/quic_network_transaction_unittest.cc
index 5dd509d7e77..c56fb53dc48 100644
--- a/chromium/net/quic/quic_network_transaction_unittest.cc
+++ b/chromium/net/quic/quic_network_transaction_unittest.cc
@@ -12,7 +12,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
@@ -217,10 +216,9 @@ std::string ConstructDataFrameForVersion(base::StringPiece body,
if (!version.HasIetfQuicFrames()) {
return std::string(body);
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body.size(), &buffer);
- return base::StrCat({base::StringPiece(buffer.get(), header_length), body});
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body.size(), quic::SimpleBufferAllocator::Get());
+ return base::StrCat({base::StringPiece(buffer.data(), buffer.size()), body});
}
} // namespace
@@ -899,6 +897,7 @@ class QuicNetworkTransactionTest
true, true, ConvertRequestPriorityToQuicPriority(DEFAULT_PRIORITY),
GetRequestHeaders("GET", "https", "/", &client_maker), 0, nullptr));
client_maker.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
quic_data.AddRead(
ASYNC, server_maker.MakeResponseHeadersPacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false,
@@ -912,7 +911,23 @@ class QuicNetworkTransactionTest
// No more data to read.
quic_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
quic_data.AddSocketDataToFactory(&socket_factory_);
- SendRequestAndExpectQuicResponse("quic used");
+
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ int rv = trans.Start(&request_, callback.callback(), net_log_.bound());
+ EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
+
+ // Pump the message loop to get the request started.
+ base::RunLoop().RunUntilIdle();
+ // Explicitly confirm the handshake.
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+
+ ASSERT_FALSE(quic_data.AllReadDataConsumed());
+ quic_data.Resume();
+
+ // Run the QUIC session to completion.
+ base::RunLoop().RunUntilIdle();
EXPECT_TRUE(quic_data.AllReadDataConsumed());
}
@@ -943,11 +958,11 @@ class QuicNetworkTransactionTest
GetNthClientInitiatedBidirectionalStreamId(n);
EXPECT_LT(cancelled_stream_id, 63u);
- const unsigned char opcode = 0x40;
+ const char opcode = 0x40;
if (create_stream) {
- return {0x03, opcode | static_cast<unsigned char>(cancelled_stream_id)};
+ return {0x03, static_cast<char>(opcode | cancelled_stream_id)};
} else {
- return {opcode | static_cast<unsigned char>(cancelled_stream_id)};
+ return {static_cast<char>(opcode | cancelled_stream_id)};
}
}
@@ -999,8 +1014,8 @@ class QuicNetworkTransactionTest
std::unique_ptr<ProxyResolutionService> proxy_resolution_service_;
std::unique_ptr<HttpAuthHandlerFactory> auth_handler_factory_;
std::unique_ptr<HttpServerProperties> http_server_properties_;
- HttpNetworkSession::Params session_params_;
- HttpNetworkSession::Context session_context_;
+ HttpNetworkSessionParams session_params_;
+ HttpNetworkSessionContext session_context_;
HttpRequestInfo request_;
RecordingBoundTestNetLog net_log_;
std::vector<std::unique_ptr<StaticSocketDataProvider>> hanging_data_;
@@ -3782,7 +3797,7 @@ TEST_P(QuicNetworkTransactionTest, ResetAfterHandshakeConfirmedThenBroken) {
if (VersionUsesHttp3(version_.transport_version)) {
quic_data.AddWrite(
SYNCHRONOUS,
- client_maker_->MakeRstAckAndDataPacket(
+ client_maker_->MakeAckRstAndDataPacket(
packet_num++, true, GetNthClientInitiatedBidirectionalStreamId(0),
quic::QUIC_HEADERS_TOO_LARGE, 1, 1, GetQpackDecoderStreamId(),
false, StreamCancellationQpackDecoderInstruction(0)));
@@ -4051,7 +4066,7 @@ TEST_P(QuicNetworkTransactionTest,
if (VersionUsesHttp3(version_.transport_version)) {
mock_quic_data.AddWrite(
SYNCHRONOUS,
- client_maker_->MakeRstAckAndDataPacket(
+ client_maker_->MakeAckRstAndDataPacket(
packet_num++, /*include_version=*/true,
GetNthClientInitiatedBidirectionalStreamId(1),
quic::QUIC_HEADERS_TOO_LARGE, 3, 2, GetQpackDecoderStreamId(),
@@ -4812,6 +4827,8 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
ConstructClientRequestHeadersPacket(
packet_num++, GetNthClientInitiatedBidirectionalStreamId(0), true,
true, GetRequestHeaders("GET", "https", "/")));
+ client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4820,9 +4837,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
ASYNC, ConstructServerDataPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
ConstructDataFrame("hello!")));
- if (version_.UsesTls()) {
- client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
- }
mock_quic_data.AddWrite(SYNCHRONOUS,
ConstructClientAckPacket(packet_num++, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
@@ -4836,7 +4850,27 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithHttpRace) {
CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
- SendRequestAndExpectQuicResponse("hello!");
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ EXPECT_THAT(trans.Start(&request_, callback.callback(), net_log_.bound()),
+ IsError(ERR_IO_PENDING));
+ // Complete host resolution in next message loop so that QUIC job could
+ // proceed.
+ base::RunLoop().RunUntilIdle();
+ // Explicitly confirm the handshake.
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+
+ ASSERT_FALSE(mock_quic_data.AllReadDataConsumed());
+ mock_quic_data.Resume();
+
+ // Run the QUIC session to completion.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_THAT(callback.WaitForResult(), IsOk());
+
+ CheckWasQuicResponse(&trans);
+ CheckResponseData(&trans, "hello!");
EXPECT_EQ(nullptr, http_server_properties_->GetServerNetworkStats(
url::SchemeHostPort("https", request_.url.host(), 443),
@@ -4856,6 +4890,8 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
ConstructClientRequestHeadersPacket(
packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true,
true, GetRequestHeaders("GET", "https", "/")));
+ client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -4864,9 +4900,6 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
ASYNC, ConstructServerDataPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
ConstructDataFrame("hello!")));
- if (version_.UsesTls()) {
- client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
- }
mock_quic_data.AddWrite(SYNCHRONOUS,
ConstructClientAckPacket(packet_number++, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
@@ -4883,7 +4916,27 @@ TEST_P(QuicNetworkTransactionTest, ZeroRTTWithNoHttpRace) {
AddHangingNonAlternateProtocolSocketData();
CreateSession();
AddQuicAlternateProtocolMapping(MockCryptoClientStream::ZERO_RTT);
- SendRequestAndExpectQuicResponse("hello!");
+ HttpNetworkTransaction trans(DEFAULT_PRIORITY, session_.get());
+ TestCompletionCallback callback;
+ EXPECT_THAT(trans.Start(&request_, callback.callback(), net_log_.bound()),
+ IsError(ERR_IO_PENDING));
+ // Complete host resolution in next message loop so that QUIC job could
+ // proceed.
+ base::RunLoop().RunUntilIdle();
+ // Explicitly confirm the handshake.
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+
+ ASSERT_FALSE(mock_quic_data.AllReadDataConsumed());
+ mock_quic_data.Resume();
+
+ // Run the QUIC session to completion.
+ base::RunLoop().RunUntilIdle();
+
+ EXPECT_THAT(callback.WaitForResult(), IsOk());
+
+ CheckWasQuicResponse(&trans);
+ CheckResponseData(&trans, "hello!");
}
TEST_P(QuicNetworkTransactionTest, ZeroRTTWithProxy) {
@@ -5411,7 +5464,7 @@ TEST_P(QuicNetworkTransactionTest, RstStreamBeforeHeaders) {
if (VersionUsesHttp3(version_.transport_version)) {
mock_quic_data.AddWrite(
SYNCHRONOUS,
- client_maker_->MakeRstAckAndDataPacket(
+ client_maker_->MakeAckRstAndDataPacket(
packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
quic::QUIC_STREAM_CANCELLED, 1, 1, GetQpackDecoderStreamId(), false,
StreamCancellationQpackDecoderInstruction(0)));
@@ -5606,6 +5659,8 @@ TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {
ConstructClientRequestHeadersPacket(
packet_number++, GetNthClientInitiatedBidirectionalStreamId(0), true,
true, GetRequestHeaders("GET", "https", "/")));
+ client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
+ mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
mock_quic_data.AddRead(
ASYNC, ConstructServerResponseHeadersPacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
@@ -5614,9 +5669,6 @@ TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {
ASYNC, ConstructServerDataPacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, true,
ConstructDataFrame("hello!")));
- if (version_.UsesTls()) {
- client_maker_->SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
- }
mock_quic_data.AddWrite(SYNCHRONOUS,
ConstructClientAckPacket(packet_number++, 2, 1));
mock_quic_data.AddRead(ASYNC, ERR_IO_PENDING); // No more data to read
@@ -5645,6 +5697,15 @@ TEST_P(QuicNetworkTransactionTest, DelayTCPOnStartWithQuicSupportOnSameIP) {
// Complete host resolution in next message loop so that QUIC job could
// proceed.
base::RunLoop().RunUntilIdle();
+ // Explicitly confirm the handshake.
+ crypto_client_stream_factory_.last_stream()
+ ->NotifySessionOneRttKeyAvailable();
+
+ ASSERT_FALSE(mock_quic_data.AllReadDataConsumed());
+ mock_quic_data.Resume();
+
+ // Run the QUIC session to completion.
+ base::RunLoop().RunUntilIdle();
EXPECT_THAT(callback.WaitForResult(), IsOk());
CheckWasQuicResponse(&trans);
@@ -6882,14 +6943,14 @@ class QuicNetworkTransactionWithDestinationTest
NetworkChangeNotifier::NotifyObserversOfIPAddressChangeForTests();
base::RunLoop().RunUntilIdle();
- HttpNetworkSession::Params session_params;
+ HttpNetworkSessionParams session_params;
session_params.enable_quic = true;
context_.params()->allow_remote_alt_svc = true;
context_.params()->supported_versions = supported_versions_;
context_.params()->headers_include_h2_stream_dependency =
client_headers_include_h2_stream_dependency_;
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(20));
diff --git a/chromium/net/quic/quic_proxy_client_socket_unittest.cc b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
index 6bcc5404851..b232fff4763 100644
--- a/chromium/net/quic/quic_proxy_client_socket_unittest.cc
+++ b/chromium/net/quic/quic_proxy_client_socket_unittest.cc
@@ -56,6 +56,8 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using testing::_;
using testing::AnyNumber;
@@ -179,8 +181,8 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
false),
random_generator_(0),
user_agent_(kUserAgent),
- proxy_host_port_(kProxyHost, kProxyPort),
- endpoint_host_port_(kOriginHost, kOriginPort),
+ proxy_endpoint_(url::kHttpsScheme, kProxyHost, kProxyPort),
+ destination_endpoint_(url::kHttpsScheme, kOriginHost, kOriginPort),
http_auth_cache_(
false /* key_server_entries_by_network_isolation_key */),
host_resolver_(new MockCachingHostResolver()),
@@ -283,8 +285,8 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
writer->set_delegate(session_.get());
- session_handle_ =
- session_->CreateHandle(HostPortPair("mail.example.org", 80));
+ session_handle_ = session_->CreateHandle(
+ url::SchemeHostPort(url::kHttpsScheme, "mail.example.org", 80));
session_->Initialize();
@@ -307,10 +309,16 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
sock_ = std::make_unique<QuicProxyClientSocket>(
std::move(stream_handle), std::move(session_handle_),
- ProxyServer(ProxyServer::SCHEME_HTTPS, proxy_host_port_), user_agent_,
- endpoint_host_port_, net_log_.bound(),
- new HttpAuthController(HttpAuth::AUTH_PROXY,
- GURL("https://" + proxy_host_port_.ToString()),
+ // TODO(crbug.com/1206799) Construct `ProxyServer` with plain
+ // `proxy_endpoint_` once it supports `url::SchemeHostPort`.
+ ProxyServer(ProxyServer::SCHEME_HTTPS,
+ HostPortPair::FromSchemeHostPort(proxy_endpoint_)),
+ user_agent_,
+ // TODO(crbug.com/1206799) Construct `QuicProxyClientSocket` with plain
+ // `proxy_endpoint_` once it supports `url::SchemeHostPort`.
+ HostPortPair::FromSchemeHostPort(destination_endpoint_),
+ net_log_.bound(),
+ new HttpAuthController(HttpAuth::AUTH_PROXY, proxy_endpoint_.GetURL(),
NetworkIsolationKey(), &http_auth_cache_,
http_auth_handler_factory_.get(),
host_resolver_.get()),
@@ -321,7 +329,8 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
void PopulateConnectRequestIR(spdy::Http2HeaderBlock* block) {
(*block)[":method"] = "CONNECT";
- (*block)[":authority"] = endpoint_host_port_.ToString();
+ (*block)[":authority"] =
+ HostPortPair::FromSchemeHostPort(destination_endpoint_).ToString();
(*block)["user-agent"] = kUserAgent;
}
@@ -380,7 +389,8 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
RequestPriority request_priority = LOWEST) {
spdy::Http2HeaderBlock block;
block[":method"] = "CONNECT";
- block[":authority"] = endpoint_host_port_.ToString();
+ block[":authority"] =
+ HostPortPair::FromSchemeHostPort(destination_endpoint_).ToString();
for (const auto& header : extra_headers) {
block[header.first] = header.second;
}
@@ -588,10 +598,9 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
if (!version_.HasIetfQuicFrames()) {
return "";
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
- return std::string(buffer.get(), header_length);
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body_len, quic::SimpleBufferAllocator::Get());
+ return std::string(buffer.data(), buffer.size());
}
RecordingBoundTestNetLog net_log_;
@@ -626,8 +635,8 @@ class QuicProxyClientSocketTest : public ::testing::TestWithParam<TestParams>,
MockCryptoClientStreamFactory crypto_client_stream_factory_;
std::string user_agent_;
- HostPortPair proxy_host_port_;
- HostPortPair endpoint_host_port_;
+ url::SchemeHostPort proxy_endpoint_;
+ url::SchemeHostPort destination_endpoint_;
HttpAuthCache http_auth_cache_;
std::unique_ptr<MockHostResolverBase> host_resolver_;
std::unique_ptr<HttpAuthHandlerRegistryFactory> http_auth_handler_factory_;
@@ -669,7 +678,10 @@ TEST_P(QuicProxyClientSocketTest, ConnectSendsCorrectRequest) {
TEST_P(QuicProxyClientSocketTest, ProxyDelegateExtraHeaders) {
proxy_delegate_ = std::make_unique<TestProxyDelegate>();
- ProxyServer proxy_server(ProxyServer::SCHEME_HTTPS, proxy_host_port_);
+ // TODO(crbug.com/1206799) Construct `ProxyServer` with plain
+ // `proxy_endpoint_` once it supports `url::SchemeHostPort`.
+ ProxyServer proxy_server(ProxyServer::SCHEME_HTTPS,
+ HostPortPair::FromSchemeHostPort(proxy_endpoint_));
const char kResponseHeaderName[] = "foo";
const char kResponseHeaderValue[] = "testing";
@@ -1268,29 +1280,23 @@ TEST_P(QuicProxyClientSocketTest, MultipleShortReadsThenMoreRead) {
mock_quic_data_.AddRead(ASYNC, ConstructServerConnectReplyPacket(1, !kFin));
mock_quic_data_.AddRead(ASYNC, ERR_IO_PENDING); // Pause
- int offset = 0;
-
std::string header = ConstructDataHeader(kLen1);
mock_quic_data_.AddRead(
ASYNC, ConstructServerDataPacket(2, header + std::string(kMsg1, kLen1)));
- offset += kLen1 + header.length();
mock_quic_data_.AddWrite(SYNCHRONOUS,
ConstructAckPacket(packet_number++, 2, 1));
std::string header2 = ConstructDataHeader(kLen3);
mock_quic_data_.AddRead(
ASYNC, ConstructServerDataPacket(3, header2 + std::string(kMsg3, kLen3)));
- offset += kLen3 + header2.length();
mock_quic_data_.AddRead(
ASYNC, ConstructServerDataPacket(4, header2 + std::string(kMsg3, kLen3)));
- offset += kLen3 + header2.length();
mock_quic_data_.AddWrite(SYNCHRONOUS,
ConstructAckPacket(packet_number++, 4, 3));
std::string header3 = ConstructDataHeader(kLen2);
mock_quic_data_.AddRead(
ASYNC, ConstructServerDataPacket(5, header3 + std::string(kMsg2, kLen2)));
- offset += kLen2 + header3.length();
mock_quic_data_.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
mock_quic_data_.AddWrite(
diff --git a/chromium/net/quic/quic_stream_factory.cc b/chromium/net/quic/quic_stream_factory.cc
index dd06a3085a0..2ce8734149b 100644
--- a/chromium/net/quic/quic_stream_factory.cc
+++ b/chromium/net/quic/quic_stream_factory.cc
@@ -17,6 +17,7 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/no_destructor.h"
+#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -71,6 +72,7 @@
#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
#include "third_party/boringssl/src/include/openssl/aead.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
#include "url/url_constants.h"
using NetworkHandle = net::NetworkChangeNotifier::NetworkHandle;
@@ -187,7 +189,8 @@ void SetInitialRttEstimate(base::TimeDelta estimate,
UMA_HISTOGRAM_ENUMERATION("Net.QuicSession.InitialRttEsitmateSource", source,
INITIAL_RTT_SOURCE_MAX);
if (estimate != base::TimeDelta())
- config->SetInitialRoundTripTimeUsToSend(estimate.InMicroseconds());
+ config->SetInitialRoundTripTimeUsToSend(
+ base::checked_cast<uint64_t>(estimate.InMicroseconds()));
}
// An implementation of quic::QuicCryptoClientConfig::ServerIdFilter that wraps
@@ -971,7 +974,7 @@ QuicStreamRequest::~QuicStreamRequest() {
}
int QuicStreamRequest::Request(
- const HostPortPair& destination,
+ url::SchemeHostPort destination,
quic::ParsedQuicVersion quic_version,
PrivacyMode privacy_mode,
RequestPriority priority,
@@ -998,9 +1001,9 @@ int QuicStreamRequest::Request(
QuicSessionKey(HostPortPair::FromURL(url), privacy_mode, socket_tag,
network_isolation_key, secure_dns_policy);
- int rv =
- factory_->Create(session_key_, destination, quic_version, priority,
- use_dns_aliases, cert_verify_flags, url, net_log, this);
+ int rv = factory_->Create(session_key_, std::move(destination), quic_version,
+ priority, use_dns_aliases, cert_verify_flags, url,
+ net_log, this);
if (rv == ERR_IO_PENDING) {
net_log_ = net_log;
callback_ = std::move(callback);
@@ -1069,9 +1072,10 @@ void QuicStreamRequest::SetSession(
}
QuicStreamFactory::QuicSessionAliasKey::QuicSessionAliasKey(
- const HostPortPair& destination,
- const QuicSessionKey& session_key)
- : destination_(destination), session_key_(session_key) {}
+ url::SchemeHostPort destination,
+ QuicSessionKey session_key)
+ : destination_(std::move(destination)),
+ session_key_(std::move(session_key)) {}
bool QuicStreamFactory::QuicSessionAliasKey::operator<(
const QuicSessionAliasKey& other) const {
@@ -1081,7 +1085,7 @@ bool QuicStreamFactory::QuicSessionAliasKey::operator<(
bool QuicStreamFactory::QuicSessionAliasKey::operator==(
const QuicSessionAliasKey& other) const {
- return destination_.Equals(other.destination_) &&
+ return destination_ == other.destination_ &&
session_key_ == other.session_key_;
}
@@ -1170,14 +1174,15 @@ QuicStreamFactory::~QuicStreamFactory() {
}
}
-bool QuicStreamFactory::CanUseExistingSession(const QuicSessionKey& session_key,
- const HostPortPair& destination) {
+bool QuicStreamFactory::CanUseExistingSession(
+ const QuicSessionKey& session_key,
+ const url::SchemeHostPort& destination) {
if (base::Contains(active_sessions_, session_key))
return true;
for (const auto& key_value : active_sessions_) {
QuicChromiumClientSession* session = key_value.second;
- if (destination.Equals(all_sessions_[session].destination()) &&
+ if (destination == all_sessions_[session].destination() &&
session->CanPool(session_key.host(), session_key)) {
return true;
}
@@ -1187,7 +1192,7 @@ bool QuicStreamFactory::CanUseExistingSession(const QuicSessionKey& session_key,
}
int QuicStreamFactory::Create(const QuicSessionKey& session_key,
- const HostPortPair& destination,
+ url::SchemeHostPort destination,
quic::ParsedQuicVersion quic_version,
RequestPriority priority,
bool use_dns_aliases,
@@ -1210,7 +1215,7 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key,
if (!promised)
continue;
DCHECK_EQ(promised->session(), session.second);
- request->SetSession(session.second->CreateHandle(destination));
+ request->SetSession(session.second->CreateHandle(std::move(destination)));
++num_push_streams_created_;
return OK;
}
@@ -1219,7 +1224,7 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key,
auto active_session = active_sessions_.find(session_key);
if (active_session != active_sessions_.end()) {
QuicChromiumClientSession* session = active_session->second;
- request->SetSession(session->CreateHandle(destination));
+ request->SetSession(session->CreateHandle(std::move(destination)));
return OK;
}
@@ -1241,9 +1246,9 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key,
if (!active_sessions_.empty()) {
for (const auto& key_value : active_sessions_) {
QuicChromiumClientSession* session = key_value.second;
- if (destination.Equals(all_sessions_[session].destination()) &&
+ if (destination == all_sessions_[session].destination() &&
session->CanPool(session_key.server_id().host(), session_key)) {
- request->SetSession(session->CreateHandle(destination));
+ request->SetSession(session->CreateHandle(std::move(destination)));
return OK;
}
}
@@ -1278,7 +1283,7 @@ int QuicStreamFactory::Create(const QuicSessionKey& session_key,
if (it == active_sessions_.end())
return ERR_QUIC_PROTOCOL_ERROR;
QuicChromiumClientSession* session = it->second;
- request->SetSession(session->CreateHandle(destination));
+ request->SetSession(session->CreateHandle(std::move(destination)));
}
return rv;
}
@@ -1905,7 +1910,10 @@ void QuicStreamFactory::ConfigureInitialRttEstimate(
quic::QuicConfig* config) {
const base::TimeDelta* srtt =
GetServerNetworkStatsSmoothedRtt(server_id, network_isolation_key);
- if (srtt != nullptr) {
+ // Sometimes *srtt is negative. See https://crbug.com/1225616.
+ // TODO(ricea): When the root cause of the negative value is fixed, change the
+ // non-negative assertion to a DCHECK.
+ if (srtt != nullptr && *srtt > base::TimeDelta()) {
SetInitialRttEstimate(*srtt, INITIAL_RTT_CACHED, config);
return;
}
diff --git a/chromium/net/quic/quic_stream_factory.h b/chromium/net/quic/quic_stream_factory.h
index d825a1f1220..975f1264dbb 100644
--- a/chromium/net/quic/quic_stream_factory.h
+++ b/chromium/net/quic/quic_stream_factory.h
@@ -45,6 +45,7 @@
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
+#include "url/scheme_host_port.h"
namespace base {
class Value;
@@ -122,7 +123,7 @@ class NET_EXPORT_PRIVATE QuicStreamRequest {
// When |use_dns_aliases| is true, any DNS aliases found in host resolution
// are stored in the |dns_aliases_by_session_key_| map. |use_dns_aliases|
// should be false in the case of a proxy.
- int Request(const HostPortPair& destination,
+ int Request(url::SchemeHostPort destination,
quic::ParsedQuicVersion quic_version,
PrivacyMode privacy_mode,
RequestPriority priority,
@@ -214,15 +215,15 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
class NET_EXPORT_PRIVATE QuicSessionAliasKey {
public:
QuicSessionAliasKey() = default;
- QuicSessionAliasKey(const HostPortPair& destination,
- const QuicSessionKey& session_key);
+ QuicSessionAliasKey(url::SchemeHostPort destination,
+ QuicSessionKey session_key);
~QuicSessionAliasKey() = default;
// Needed to be an element of std::set.
bool operator<(const QuicSessionAliasKey& other) const;
bool operator==(const QuicSessionAliasKey& other) const;
- const HostPortPair& destination() const { return destination_; }
+ const url::SchemeHostPort& destination() const { return destination_; }
const quic::QuicServerId& server_id() const {
return session_key_.server_id();
}
@@ -231,7 +232,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// Returns the estimate of dynamically allocated memory in bytes.
private:
- HostPortPair destination_;
+ url::SchemeHostPort destination_;
QuicSessionKey session_key_;
};
@@ -254,7 +255,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// request can be pooled to an existing session to the IP address of
// |destination|.
bool CanUseExistingSession(const QuicSessionKey& session_key,
- const HostPortPair& destination);
+ const url::SchemeHostPort& destination);
// Fetches a QuicChromiumClientSession to |host_port_pair| which will be
// owned by |request|.
@@ -265,7 +266,7 @@ class NET_EXPORT_PRIVATE QuicStreamFactory
// are stored in the |dns_aliases_by_session_key_| map. |use_dns_aliases|
// should be false in the case of a proxy.
int Create(const QuicSessionKey& session_key,
- const HostPortPair& destination,
+ url::SchemeHostPort destination,
quic::ParsedQuicVersion quic_version,
RequestPriority priority,
bool use_dns_aliases,
diff --git a/chromium/net/quic/quic_stream_factory_fuzzer.cc b/chromium/net/quic/quic_stream_factory_fuzzer.cc
index 67e583c377d..3fce1d5beb9 100644
--- a/chromium/net/quic/quic_stream_factory_fuzzer.cc
+++ b/chromium/net/quic/quic_stream_factory_fuzzer.cc
@@ -6,7 +6,7 @@
#include <fuzzer/FuzzedDataProvider.h>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/ct_policy_enforcer.h"
@@ -28,12 +28,14 @@
#include "net/ssl/ssl_config_service_defaults.h"
#include "net/test/gtest_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
namespace {
-const char kCertData[] = {
+const uint8_t kCertData[] = {
#include "net/data/ssl/certificates/wildcard.inc"
};
@@ -53,13 +55,13 @@ const int kCertVerifyFlags = 0;
// Static initialization for persistent factory data
struct Env {
- Env() : host_port_pair(kServerHostName, kServerPort) {
+ Env() : scheme_host_port(url::kHttpsScheme, kServerHostName, kServerPort) {
quic_context.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
ssl_config_service = std::make_unique<SSLConfigServiceDefaults>();
crypto_client_stream_factory.set_use_mock_crypter(true);
cert_verifier = std::make_unique<MockCertVerifier>();
verify_details.cert_verify_result.verified_cert =
- X509Certificate::CreateFromBytes(kCertData, base::size(kCertData));
+ X509Certificate::CreateFromBytes(kCertData);
CHECK(verify_details.cert_verify_result.verified_cert);
verify_details.cert_verify_result.is_issued_by_known_root = true;
}
@@ -67,7 +69,7 @@ struct Env {
std::unique_ptr<SSLConfigService> ssl_config_service;
ProofVerifyDetailsChromium verify_details;
MockCryptoClientStreamFactory crypto_client_stream_factory;
- HostPortPair host_port_pair;
+ url::SchemeHostPort scheme_host_port;
NetLogWithSource net_log;
std::unique_ptr<CertVerifier> cert_verifier;
TransportSecurityState transport_security_state;
@@ -147,7 +149,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
quic::QuicEnableVersion(version);
request.Request(
- env->host_port_pair, version, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY,
+ env->scheme_host_port, version, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */, kCertVerifyFlags, GURL(kUrl), env->net_log,
&net_error_details,
diff --git a/chromium/net/quic/quic_stream_factory_peer.cc b/chromium/net/quic/quic_stream_factory_peer.cc
index 0770124b44b..c03d1320446 100644
--- a/chromium/net/quic/quic_stream_factory_peer.cc
+++ b/chromium/net/quic/quic_stream_factory_peer.cc
@@ -17,6 +17,7 @@
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h"
+#include "url/scheme_host_port.h"
using std::string;
@@ -53,10 +54,11 @@ bool QuicStreamFactoryPeer::HasActiveJob(QuicStreamFactory* factory,
QuicChromiumClientSession* QuicStreamFactoryPeer::GetPendingSession(
QuicStreamFactory* factory,
const quic::QuicServerId& server_id,
- const HostPortPair& destination) {
+ url::SchemeHostPort destination) {
QuicSessionKey session_key(server_id, SocketTag(), NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
- QuicStreamFactory::QuicSessionAliasKey key(destination, session_key);
+ QuicStreamFactory::QuicSessionAliasKey key(std::move(destination),
+ session_key);
DCHECK(factory->HasActiveJob(session_key));
DCHECK_EQ(factory->all_sessions_.size(), 1u);
DCHECK(key == factory->all_sessions_.begin()->second);
@@ -75,12 +77,12 @@ QuicChromiumClientSession* QuicStreamFactoryPeer::GetActiveSession(
bool QuicStreamFactoryPeer::HasLiveSession(
QuicStreamFactory* factory,
- const HostPortPair& destination,
+ url::SchemeHostPort destination,
const quic::QuicServerId& server_id) {
QuicSessionKey session_key = QuicSessionKey(
server_id, SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow);
- QuicStreamFactory::QuicSessionAliasKey alias_key =
- QuicStreamFactory::QuicSessionAliasKey(destination, session_key);
+ QuicStreamFactory::QuicSessionAliasKey alias_key(std::move(destination),
+ session_key);
for (auto it = factory->all_sessions_.begin();
it != factory->all_sessions_.end(); ++it) {
if (it->second == alias_key)
diff --git a/chromium/net/quic/quic_stream_factory_peer.h b/chromium/net/quic/quic_stream_factory_peer.h
index 0e25bad8f76..adc782fe3e5 100644
--- a/chromium/net/quic/quic_stream_factory_peer.h
+++ b/chromium/net/quic/quic_stream_factory_peer.h
@@ -19,6 +19,7 @@
#include "net/third_party/quiche/src/quic/core/quic_packets.h"
#include "net/third_party/quiche/src/quic/core/quic_server_id.h"
#include "net/third_party/quiche/src/quic/core/quic_time.h"
+#include "url/scheme_host_port.h"
namespace quic {
class QuicAlarmFactory;
@@ -53,7 +54,7 @@ class QuicStreamFactoryPeer {
static QuicChromiumClientSession* GetPendingSession(
QuicStreamFactory* factory,
const quic::QuicServerId& server_id,
- const HostPortPair& destination);
+ url::SchemeHostPort destination);
static QuicChromiumClientSession* GetActiveSession(
QuicStreamFactory* factory,
@@ -61,7 +62,7 @@ class QuicStreamFactoryPeer {
const NetworkIsolationKey& network_isolation_key = NetworkIsolationKey());
static bool HasLiveSession(QuicStreamFactory* factory,
- const HostPortPair& destination,
+ url::SchemeHostPort destination,
const quic::QuicServerId& server_id);
static bool IsLiveSession(QuicStreamFactory* factory,
diff --git a/chromium/net/quic/quic_stream_factory_test.cc b/chromium/net/quic/quic_stream_factory_test.cc
index 6e5ea81c35c..c5f83a440cc 100644
--- a/chromium/net/quic/quic_stream_factory_test.cc
+++ b/chromium/net/quic/quic_stream_factory_test.cc
@@ -27,9 +27,9 @@
#include "net/base/schemeful_site.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/mock_cert_verifier.h"
-#include "net/dns/host_resolver_source.h"
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/dns_query_type.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_response_headers.h"
#include "net/http/http_response_info.h"
@@ -82,6 +82,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using std::string;
@@ -112,6 +114,7 @@ const size_t kMinRetryTimeForDefaultNetworkSecs = 1;
const size_t kWaitTimeForNewNetworkSecs = 10;
const IPAddress kCachedIPAddress = IPAddress(192, 168, 0, 2);
const char kNonCachedIPAddress[] = "192.168.0.1";
+const quic::QuicConnectionId kNewCID = quic::test::TestConnectionId(12345678);
// Run QuicStreamFactoryTest instances with all value combinations of version
// and enable_connection_racting.
@@ -216,7 +219,9 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
cert_verifier_(std::make_unique<MockCertVerifier>()),
scoped_mock_network_change_notifier_(nullptr),
factory_(nullptr),
- host_port_pair_(kDefaultServerHostName, kDefaultServerPort),
+ scheme_host_port_(url::kHttpsScheme,
+ kDefaultServerHostName,
+ kDefaultServerPort),
url_(kDefaultUrl),
url2_(kServer2Url),
url3_(kServer3Url),
@@ -228,6 +233,7 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
failed_on_default_network_(false),
quic_params_(context_.params()) {
FLAGS_quic_enable_http3_grease_randomness = false;
+ FLAGS_quic_reloadable_flag_quic_ack_cid_frames = true;
quic_params_->headers_include_h2_stream_dependency =
client_headers_include_h2_stream_dependency;
context_.AdvanceTime(quic::QuicTime::Delta::FromSeconds(1));
@@ -244,6 +250,17 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
&crypto_client_stream_factory_, &context_);
}
+ void SetIetfConnectionMigrationFlagsAndConnectionOptions() {
+ FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
+ FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3 = true;
+ FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer =
+ true;
+ FLAGS_quic_reloadable_flag_quic_drop_unsent_path_response = true;
+ FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2 = true;
+ quic_params_->connection_options.push_back(quic::kRVCM);
+ }
+
void InitializeConnectionMigrationV2Test(
NetworkChangeNotifier::NetworkList connected_networks) {
scoped_mock_network_change_notifier_ =
@@ -256,11 +273,31 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
quic_params_->migrate_sessions_early_v2 = true;
quic_params_->allow_port_migration = false;
socket_factory_ = std::make_unique<TestConnectionMigrationSocketFactory>();
- FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
- FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
Initialize();
}
+ // For IETF QUIC, make a NEW_CONNECTION_ID frame available for client such
+ // that connection migration can begin with a new connection ID. A side
+ // effect of calling this function is that ACK_FRAME that should have been
+ // sent for the first packet read might be skipped in the unit test. If the
+ // order of ACKing is important for a test, use
+ // QuicTestPacketMaker::MakeNewConnectionIdPacket instead.
+ void MaybeMakeNewConnectionIdAvailableToSession(
+ const quic::QuicConnectionId& new_cid,
+ quic::QuicSession* session) {
+ if (version_.HasIetfQuicFrames()) {
+ quic::QuicNewConnectionIdFrame new_cid_frame;
+ new_cid_frame.connection_id = new_cid;
+ new_cid_frame.sequence_number = 1u;
+ new_cid_frame.retire_prior_to = 0u;
+ new_cid_frame.stateless_reset_token =
+ quic::QuicUtils::GenerateStatelessResetToken(
+ new_cid_frame.connection_id);
+ session->connection()->OnNewConnectionIdFrame(new_cid_frame);
+ }
+ }
+
std::unique_ptr<HttpStream> CreateStream(QuicStreamRequest* request) {
std::unique_ptr<QuicChromiumClientSession::Handle> session =
request->ReleaseSessionHandle();
@@ -273,57 +310,59 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
std::move(dns_aliases));
}
- bool HasActiveSession(const HostPortPair& host_port_pair,
+ bool HasActiveSession(const url::SchemeHostPort& scheme_host_port,
const NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey()) {
- quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(),
- false);
+ quic::QuicServerId server_id(scheme_host_port.host(),
+ scheme_host_port.port(), false);
return QuicStreamFactoryPeer::HasActiveSession(factory_.get(), server_id,
network_isolation_key);
}
- bool HasLiveSession(const HostPortPair& host_port_pair) {
- quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(),
- false);
- return QuicStreamFactoryPeer::HasLiveSession(factory_.get(), host_port_pair,
- server_id);
+ bool HasLiveSession(const url::SchemeHostPort& scheme_host_port) {
+ quic::QuicServerId server_id(scheme_host_port.host(),
+ scheme_host_port.port(), false);
+ return QuicStreamFactoryPeer::HasLiveSession(factory_.get(),
+ scheme_host_port, server_id);
}
- bool HasActiveJob(const HostPortPair& host_port_pair,
+ bool HasActiveJob(const url::SchemeHostPort& scheme_host_port,
const PrivacyMode privacy_mode) {
- quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(),
+ quic::QuicServerId server_id(scheme_host_port.host(),
+ scheme_host_port.port(),
privacy_mode == PRIVACY_MODE_ENABLED);
return QuicStreamFactoryPeer::HasActiveJob(factory_.get(), server_id);
}
// Get the pending, not activated session, if there is only one session alive.
QuicChromiumClientSession* GetPendingSession(
- const HostPortPair& host_port_pair) {
- quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(),
- false);
+ const url::SchemeHostPort& scheme_host_port) {
+ quic::QuicServerId server_id(scheme_host_port.host(),
+ scheme_host_port.port(), false);
return QuicStreamFactoryPeer::GetPendingSession(factory_.get(), server_id,
- host_port_pair);
+ scheme_host_port);
}
QuicChromiumClientSession* GetActiveSession(
- const HostPortPair& host_port_pair,
+ const url::SchemeHostPort& scheme_host_port,
const NetworkIsolationKey& network_isolation_key =
NetworkIsolationKey()) {
- quic::QuicServerId server_id(host_port_pair.host(), host_port_pair.port(),
- false);
+ quic::QuicServerId server_id(scheme_host_port.host(),
+ scheme_host_port.port(), false);
return QuicStreamFactoryPeer::GetActiveSession(factory_.get(), server_id,
network_isolation_key);
}
- int GetSourcePortForNewSession(const HostPortPair& destination) {
+ int GetSourcePortForNewSession(const url::SchemeHostPort& destination) {
return GetSourcePortForNewSessionInner(destination, false);
}
- int GetSourcePortForNewSessionAndGoAway(const HostPortPair& destination) {
+ int GetSourcePortForNewSessionAndGoAway(
+ const url::SchemeHostPort& destination) {
return GetSourcePortForNewSessionInner(destination, true);
}
- int GetSourcePortForNewSessionInner(const HostPortPair& destination,
+ int GetSourcePortForNewSessionInner(const url::SchemeHostPort& destination,
bool goaway_received) {
// Should only be called if there is no active session for this destination.
EXPECT_FALSE(HasActiveSession(destination));
@@ -472,6 +511,9 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
// Set up second socket data provider that is used after
// migration.
MockQuicData socket_data2(version_);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(kNewCID);
+ }
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
int packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
@@ -482,6 +524,10 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
if (VersionUsesHttp3(version_.transport_version)) {
+ socket_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
socket_data2.AddWrite(
SYNCHRONOUS, client_maker_.MakeDataPacket(
packet_num++, GetQpackDecoderStreamId(), true, false,
@@ -498,11 +544,12 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
+
EXPECT_EQ(OK, callback_.WaitForResult());
// Run QuicChromiumClientSession::WriteToNewSocket()
@@ -522,9 +569,9 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
stream->InitializeStream(&request_info, true, DEFAULT_PRIORITY,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
IPEndPoint actual_address;
session->GetDefaultSocket()->GetPeerAddress(&actual_address);
@@ -580,7 +627,7 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
const AlternativeService alternative_service1(
- kProtoQUIC, host_port_pair_.host(), host_port_pair_.port());
+ kProtoQUIC, scheme_host_port_.host(), scheme_host_port_.port());
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
@@ -698,7 +745,7 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
++quic_server_info_map_it;
EXPECT_EQ(quic_server_info_map_it->first.server_id, quic_server_id1);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
// Create a session and verify that the cached state is loaded.
@@ -712,7 +759,8 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- HostPortPair(quic_server_id1.host(), quic_server_id1.port()),
+ url::SchemeHostPort(url::kHttpsScheme, quic_server_id1.host(),
+ quic_server_id1.port()),
version_, privacy_mode_, DEFAULT_PRIORITY, SocketTag(),
network_isolation_key1, SecureDnsPolicy::kAllow,
true /* use_dns_aliases */, /*cert_verify_flags=*/0, url_,
@@ -748,14 +796,15 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data2.AddSocketDataToFactory(socket_factory_.get());
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.2", "");
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(
ERR_IO_PENDING,
request2.Request(
- HostPortPair(quic_server_id2.host(), quic_server_id2.port()),
+ url::SchemeHostPort(url::kHttpsScheme, quic_server_id2.host(),
+ quic_server_id2.port()),
version_, privacy_mode_, DEFAULT_PRIORITY, SocketTag(),
network_isolation_key2, SecureDnsPolicy::kAllow,
true /* use_dns_aliases */, /*cert_verify_flags=*/0,
@@ -809,11 +858,11 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
GetNthClientInitiatedBidirectionalStreamId(n);
EXPECT_LT(cancelled_stream_id, 63u);
- const unsigned char opcode = 0x40;
+ const char opcode = 0x40;
if (create_stream) {
- return {0x03, opcode | static_cast<unsigned char>(cancelled_stream_id)};
+ return {0x03, static_cast<char>(opcode | cancelled_stream_id)};
} else {
- return {opcode | static_cast<unsigned char>(cancelled_stream_id)};
+ return {static_cast<char>(opcode | cancelled_stream_id)};
}
}
@@ -821,10 +870,9 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
if (!version_.HasIetfQuicFrames()) {
return "";
}
- std::unique_ptr<char[]> buffer;
- auto header_length =
- quic::HttpEncoder::SerializeDataFrameHeader(body_len, &buffer);
- return std::string(buffer.get(), header_length);
+ quic::QuicBuffer buffer = quic::HttpEncoder::SerializeDataFrameHeader(
+ body_len, quic::SimpleBufferAllocator::Get());
+ return std::string(buffer.data(), buffer.size());
}
std::unique_ptr<quic::QuicEncryptedPacket> ConstructServerDataPacket(
@@ -899,7 +947,7 @@ class QuicStreamFactoryTestBase : public WithTaskEnvironment {
std::unique_ptr<ScopedMockNetworkChangeNotifier>
scoped_mock_network_change_notifier_;
std::unique_ptr<QuicStreamFactory> factory_;
- HostPortPair host_port_pair_;
+ url::SchemeHostPort scheme_host_port_;
GURL url_;
GURL url2_;
GURL url3_;
@@ -943,7 +991,7 @@ TEST_P(QuicStreamFactoryTest, Create) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -958,7 +1006,7 @@ TEST_P(QuicStreamFactoryTest, Create) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -973,7 +1021,7 @@ TEST_P(QuicStreamFactoryTest, Create) {
QuicStreamRequest request3(factory_.get());
EXPECT_EQ(OK,
request3.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1001,13 +1049,13 @@ TEST_P(QuicStreamFactoryTest, CreateZeroRtt) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1040,22 +1088,22 @@ TEST_P(QuicStreamFactoryTest, AsyncZeroRtt) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ASYNC_ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(nullptr, CreateStream(&request));
crypto_client_stream_factory_.last_stream()->NotifySessionZeroRttComplete();
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_THAT(callback_.WaitForResult(), IsOk());
@@ -1079,7 +1127,7 @@ TEST_P(QuicStreamFactoryTest, DefaultInitialRtt) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1089,7 +1137,7 @@ TEST_P(QuicStreamFactoryTest, DefaultInitialRtt) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(session->require_confirmation());
EXPECT_EQ(100000u, session->connection()->GetStats().srtt_us);
ASSERT_FALSE(session->config()->HasInitialRoundTripTimeUsToSend());
@@ -1109,13 +1157,13 @@ TEST_P(QuicStreamFactoryTest, FactoryDestroyedWhenJobPending) {
auto request = std::make_unique<QuicStreamRequest>(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request->Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
request.reset();
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Tearing down a QuicStreamFactory with a pending Job should not cause any
// crash. crbug.com/768343.
factory_.reset();
@@ -1125,7 +1173,7 @@ TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(false);
@@ -1142,7 +1190,7 @@ TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1159,7 +1207,7 @@ TEST_P(QuicStreamFactoryTest, RequireConfirmation) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(session->require_confirmation());
}
@@ -1167,7 +1215,7 @@ TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
Initialize();
factory_->set_is_quic_known_to_work_on_current_network(false);
@@ -1186,7 +1234,7 @@ TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) {
QuicStreamRequest request(factory_.get());
EXPECT_THAT(request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1198,7 +1246,7 @@ TEST_P(QuicStreamFactoryTest, DontRequireConfirmationFromSameIP) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_FALSE(session->require_confirmation());
crypto_client_stream_factory_.last_stream()
@@ -1227,7 +1275,7 @@ TEST_P(QuicStreamFactoryTest, CachedInitialRtt) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1237,7 +1285,7 @@ TEST_P(QuicStreamFactoryTest, CachedInitialRtt) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(10000u, session->connection()->GetStats().srtt_us);
ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend());
EXPECT_EQ(10000u, session->config()->GetInitialRoundTripTimeUsToSend());
@@ -1295,7 +1343,7 @@ TEST_P(QuicStreamFactoryTest, CachedInitialRttWithNetworkIsolationKey) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), network_isolation_key, SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1306,7 +1354,7 @@ TEST_P(QuicStreamFactoryTest, CachedInitialRttWithNetworkIsolationKey) {
EXPECT_TRUE(stream.get());
QuicChromiumClientSession* session =
- GetActiveSession(host_port_pair_, network_isolation_key);
+ GetActiveSession(scheme_host_port_, network_isolation_key);
if (network_isolation_key == kNetworkIsolationKey1) {
EXPECT_EQ(10000, session->connection()->GetStats().srtt_us);
ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend());
@@ -1338,7 +1386,7 @@ TEST_P(QuicStreamFactoryTest, 2gInitialRtt) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1348,7 +1396,7 @@ TEST_P(QuicStreamFactoryTest, 2gInitialRtt) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(1000000u, session->connection()->GetStats().srtt_us);
ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend());
EXPECT_EQ(1200000u, session->config()->GetInitialRoundTripTimeUsToSend());
@@ -1373,7 +1421,7 @@ TEST_P(QuicStreamFactoryTest, 3gInitialRtt) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1383,7 +1431,7 @@ TEST_P(QuicStreamFactoryTest, 3gInitialRtt) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(400000u, session->connection()->GetStats().srtt_us);
ASSERT_TRUE(session->config()->HasInitialRoundTripTimeUsToSend());
EXPECT_EQ(400000u, session->config()->GetInitialRoundTripTimeUsToSend());
@@ -1403,7 +1451,7 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1413,7 +1461,7 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
if (version_.UsesHttp3()) {
session->OnHttp3GoAway(0);
@@ -1421,7 +1469,7 @@ TEST_P(QuicStreamFactoryTest, GoAway) {
session->OnGoAway(quic::QuicGoAwayFrame());
}
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -1446,7 +1494,7 @@ TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1456,7 +1504,7 @@ TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
session->OnGoAway(quic::QuicGoAwayFrame(
quic::kInvalidControlFrameId, quic::QUIC_ERROR_MIGRATING_PORT, 0,
@@ -1469,7 +1517,7 @@ TEST_P(QuicStreamFactoryTest, GoAwayForConnectionMigrationWithPortOnly) {
stream->PopulateNetErrorDetails(&details);
EXPECT_TRUE(details.quic_port_migration_detected);
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -1526,7 +1574,7 @@ TEST_P(QuicStreamFactoryTest, ServerNetworkStatsWithNetworkIsolationKey) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), kNetworkIsolationKeys[i],
SecureDnsPolicy::kAllow, true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1537,7 +1585,7 @@ TEST_P(QuicStreamFactoryTest, ServerNetworkStatsWithNetworkIsolationKey) {
EXPECT_TRUE(stream.get());
QuicChromiumClientSession* session =
- GetActiveSession(host_port_pair_, kNetworkIsolationKeys[i]);
+ GetActiveSession(scheme_host_port_, kNetworkIsolationKeys[i]);
if (version_.UsesHttp3()) {
session->OnHttp3GoAway(0);
@@ -1545,7 +1593,7 @@ TEST_P(QuicStreamFactoryTest, ServerNetworkStatsWithNetworkIsolationKey) {
session->OnGoAway(quic::QuicGoAwayFrame());
}
- EXPECT_FALSE(HasActiveSession(host_port_pair_, kNetworkIsolationKeys[i]));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_, kNetworkIsolationKeys[i]));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -1583,7 +1631,7 @@ TEST_P(QuicStreamFactoryTest, ServerNetworkStatsWithNetworkIsolationKey) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), kNetworkIsolationKeys[i],
SecureDnsPolicy::kAllow, true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1591,7 +1639,7 @@ TEST_P(QuicStreamFactoryTest, ServerNetworkStatsWithNetworkIsolationKey) {
EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_QUIC_HANDSHAKE_FAILED));
- EXPECT_FALSE(HasActiveSession(host_port_pair_, kNetworkIsolationKeys[i]));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_, kNetworkIsolationKeys[i]));
for (size_t j = 0; j < base::size(kNetworkIsolationKeys); ++j) {
// Stats up to kNetworkIsolationKeys[j] should have been deleted, all
@@ -1618,16 +1666,17 @@ TEST_P(QuicStreamFactoryTest, Pooling) {
socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server2(kServer2HostName, kDefaultServerPort);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName,
+ kDefaultServerPort);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1646,35 +1695,48 @@ TEST_P(QuicStreamFactoryTest, Pooling) {
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2.get());
- EXPECT_EQ(GetActiveSession(host_port_pair_), GetActiveSession(server2));
+ EXPECT_EQ(GetActiveSession(scheme_host_port_), GetActiveSession(server2));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
+// Regression test for https://crbug.com/639916.
TEST_P(QuicStreamFactoryTest, PoolingWithServerMigration) {
// Set up session to migrate.
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 443);
quic::QuicConfig config;
- config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address));
-
+ if (version_.UsesHttp3()) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ config.SetIPv4AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address), kNewCID,
+ quic::QuicUtils::GenerateStatelessResetToken(kNewCID));
+ } else {
+ config.SetIPv4AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address));
+ }
+ quic::QuicConnectionId cid_on_old_path =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
VerifyServerMigration(config, alt_address);
// Close server-migrated session.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
session->CloseSessionOnError(0u, quic::QUIC_NO_ERROR,
quic::ConnectionCloseBehavior::SILENT_CLOSE);
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
client_maker_.Reset();
// Set up server IP, socket, proof, and config for new session.
- HostPortPair server2(kServer2HostName, kDefaultServerPort);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName,
+ kDefaultServerPort);
host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
MockQuicData socket_data1(version_);
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_old_path);
socket_data1.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
}
socket_data1.AddSocketDataToFactory(socket_factory_.get());
@@ -1700,7 +1762,11 @@ TEST_P(QuicStreamFactoryTest, PoolingWithServerMigration) {
EXPECT_TRUE(socket_data1.AllReadDataConsumed());
EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
- // EXPECT_EQ(GetActiveSession(host_port_pair_), GetActiveSession(server2));
+
+ EXPECT_TRUE(HasActiveSession(server2));
+
+ // No zombie entry in session map.
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
}
TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
@@ -1721,16 +1787,17 @@ TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data2.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server2(kServer2HostName, kDefaultServerPort);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName,
+ kDefaultServerPort);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1749,8 +1816,8 @@ TEST_P(QuicStreamFactoryTest, NoPoolingAfterGoAway) {
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2.get());
- factory_->OnSessionGoingAway(GetActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ factory_->OnSessionGoingAway(GetActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_FALSE(HasActiveSession(server2));
TestCompletionCallback callback3;
@@ -1781,8 +1848,8 @@ TEST_P(QuicStreamFactoryTest, HttpsPooling) {
socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server1(kDefaultServerHostName, 443);
- HostPortPair server2(kServer2HostName, 443);
+ url::SchemeHostPort server1(url::kHttpsScheme, kDefaultServerHostName, 443);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName, 443);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -1826,8 +1893,8 @@ TEST_P(QuicStreamFactoryTest, HttpsPoolingWithMatchingPins) {
socket_data.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server1(kDefaultServerHostName, 443);
- HostPortPair server2(kServer2HostName, 443);
+ url::SchemeHostPort server1(url::kHttpsScheme, kDefaultServerHostName, 443);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName, 443);
transport_security_state_.EnableStaticPinsForTesting();
ScopedTransportSecurityStateSource scoped_security_state_source;
@@ -1884,8 +1951,8 @@ TEST_P(QuicStreamFactoryTest, NoHttpsPoolingWithDifferentPins) {
socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data2.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server1(kDefaultServerHostName, 443);
- HostPortPair server2(kServer2HostName, 443);
+ url::SchemeHostPort server1(url::kHttpsScheme, kDefaultServerHostName, 443);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName, 443);
transport_security_state_.EnableStaticPinsForTesting();
ScopedTransportSecurityStateSource scoped_security_state_source;
@@ -1956,7 +2023,7 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1968,18 +2035,18 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
// Mark the session as going away. Ensure that while it is still alive
// that it is no longer active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
factory_->OnSessionGoingAway(session);
EXPECT_EQ(true,
QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
// Create a new request for the same destination and verify that a
// new session is created.
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -1988,8 +2055,8 @@ TEST_P(QuicStreamFactoryTest, Goaway) {
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2.get());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_NE(session, GetActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_NE(session, GetActiveSession(scheme_host_port_));
EXPECT_EQ(true,
QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
@@ -2027,8 +2094,11 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
ASYNC, server_maker_.MakeRstPacket(1, false, stream_id,
quic::QUIC_STREAM_CANCELLED));
socket_data.AddRead(
- ASYNC, server_maker_.MakeMaxStreamsPacket(4, true, 52,
+ ASYNC, server_maker_.MakeMaxStreamsPacket(2, true, 52,
/*unidirectional=*/false));
+ socket_data.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckPacket(packet_num++, 2, 1));
+
} else {
socket_data.AddWrite(
SYNCHRONOUS, client_maker_.MakeRstPacket(1, true, stream_id,
@@ -2050,8 +2120,8 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
for (size_t i = 0; i < quic::kDefaultMaxStreamsPerConnection / 2; i++) {
QuicStreamRequest request(factory_.get());
int rv = request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, SocketTag(),
- NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback());
@@ -2072,7 +2142,7 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2096,7 +2166,7 @@ TEST_P(QuicStreamFactoryTest, MaxOpenStream) {
// Force close of the connection to suppress the generation of RST
// packets when streams are torn down, which wouldn't be relevant to
// this test anyway.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
session->connection()->CloseConnection(
quic::QUIC_PUBLIC_RESET, "test",
quic::ConnectionCloseBehavior::SILENT_CLOSE);
@@ -2112,7 +2182,7 @@ TEST_P(QuicStreamFactoryTest, ResolutionErrorInCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2134,7 +2204,7 @@ TEST_P(QuicStreamFactoryTest, ConnectErrorInCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2157,7 +2227,7 @@ TEST_P(QuicStreamFactoryTest, CancelCreate) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2169,7 +2239,7 @@ TEST_P(QuicStreamFactoryTest, CancelCreate) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2212,7 +2282,7 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2238,7 +2308,7 @@ TEST_P(QuicStreamFactoryTest, CloseAllSessions) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2275,14 +2345,14 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult());
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Verify new requests can be sent normally without hanging.
crypto_client_stream_factory_.set_handshake_mode(
@@ -2299,13 +2369,13 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Run the message loop to complete host resolution.
base::RunLoop().RunUntilIdle();
@@ -2313,8 +2383,8 @@ TEST_P(QuicStreamFactoryTest,
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Create QuicHttpStream.
std::unique_ptr<HttpStream> stream = CreateStream(&request2);
@@ -2332,7 +2402,7 @@ TEST_P(QuicStreamFactoryTest, WriteErrorInCryptoConnectWithSyncHostResolution) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::COLD_START_WITH_CHLO_SENT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
MockQuicData socket_data(version_);
@@ -2345,14 +2415,14 @@ TEST_P(QuicStreamFactoryTest, WriteErrorInCryptoConnectWithSyncHostResolution) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check no active session, or active jobs left for this server.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Verify new requests can be sent normally without hanging.
crypto_client_stream_factory_.set_handshake_mode(
@@ -2369,20 +2439,20 @@ TEST_P(QuicStreamFactoryTest, WriteErrorInCryptoConnectWithSyncHostResolution) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Complete handshake.
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Create QuicHttpStream.
std::unique_ptr<HttpStream> stream = CreateStream(&request2);
@@ -2424,7 +2494,7 @@ TEST_P(QuicStreamFactoryTest, CloseSessionsOnIPAddressChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2439,8 +2509,8 @@ TEST_P(QuicStreamFactoryTest, CloseSessionsOnIPAddressChanged) {
net_log_, CompletionOnceCallback()));
// Check an active session exists for the destination.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(http_server_properties_->HasLastLocalAddressWhenQuicWorked());
@@ -2452,14 +2522,14 @@ TEST_P(QuicStreamFactoryTest, CloseSessionsOnIPAddressChanged) {
EXPECT_FALSE(factory_->is_quic_known_to_work_on_current_network());
EXPECT_FALSE(http_server_properties_->HasLastLocalAddressWhenQuicWorked());
// Check no active session exists for the destination.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
// Now attempting to request a stream to the same origin should create
// a new session.
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2468,10 +2538,10 @@ TEST_P(QuicStreamFactoryTest, CloseSessionsOnIPAddressChanged) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
stream = CreateStream(&request2);
- // Check a new active session exisits for the destination and the old session
+ // Check a new active session exists for the destination and the old session
// is no longer live.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- QuicChromiumClientSession* session2 = GetActiveSession(host_port_pair_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session2));
stream.reset(); // Will reset stream 3.
@@ -2521,7 +2591,7 @@ TEST_P(QuicStreamFactoryTest, GoAwaySessionsOnIPAddressChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2540,9 +2610,9 @@ TEST_P(QuicStreamFactoryTest, GoAwaySessionsOnIPAddressChanged) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -2554,7 +2624,7 @@ TEST_P(QuicStreamFactoryTest, GoAwaySessionsOnIPAddressChanged) {
NotifyIPAddressChanged();
// The connection should still be alive, but marked as going away.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(1u, session->GetNumActiveStreams());
@@ -2568,7 +2638,7 @@ TEST_P(QuicStreamFactoryTest, GoAwaySessionsOnIPAddressChanged) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2577,10 +2647,10 @@ TEST_P(QuicStreamFactoryTest, GoAwaySessionsOnIPAddressChanged) {
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2.get());
- // Check an active session exisits for the destination.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ // Check an active session exists for the destination.
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- QuicChromiumClientSession* session2 = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session2));
stream.reset();
@@ -2617,7 +2687,7 @@ TEST_P(QuicStreamFactoryTest, OnIPAddressChangedWithConnectionMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2642,7 +2712,7 @@ TEST_P(QuicStreamFactoryTest, OnIPAddressChangedWithConnectionMigration) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2697,6 +2767,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
// Set up the second socket data provider that is used after migration.
// The response to the earlier request is read on the new socket.
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
MockQuicData quic_data2(version_);
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
@@ -2708,8 +2783,10 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
if (version_.UsesHttp3()) {
// in-flight SETTINGS and requests will be retransmitted. Since data is
// already sent on the new address, ping will no longer be sent.
- quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_num++, 1, 1, 1, {1, 2}));
+ quic_data2.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
} else {
// Ping packet to send after migration is completed.
quic_data2.AddWrite(
@@ -2743,7 +2820,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2762,9 +2839,10 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -2782,35 +2860,15 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
// Cause the connection to report path degrading to the session.
// Due to lack of alternate network, session will not migrate connection.
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
- // A task will be posted to migrate to the new default network.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- EXPECT_EQ(base::TimeDelta(), task_runner->NextPendingTaskDelay());
-
- // Execute the posted task to migrate back to the default network.
+ // A task was posted to migrate to the new default network. Execute that task.
task_runner->RunUntilIdle();
- base::TimeDelta next_task_delay;
- // IETF QUIC's PATH_CHALLENGE is managed by a timer set in the core QUIC code.
- if (!version_.HasIetfQuicFrames()) {
- // Another task to try send a new connectivity probe is posted. And a task
- // to retry migrate back to default network is scheduled.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- // Next connectivity probe is scheduled to be sent in 2 *
- // kDefaultRTTMilliSecs.
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- } else {
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- }
-
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -2820,47 +2878,19 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkMadeDefault(
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
- // There should be three pending tasks for gQUIC and 2 for IETF QUIC, the
- // nearest one will complete migration to the new network.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ // There should be a task that will complete the migration to the new network.
+ task_runner->RunUntilIdle();
// Response headers are received over the new network.
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
- base::TimeDelta time_advanced;
- if (!version_.HasIetfQuicFrames()) {
- // Now there are two pending tasks, the nearest one was to send connectivity
- // probe and has been cancelled due to successful migration.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- time_advanced = next_task_delay;
- task_runner->FastForwardBy(next_task_delay);
- }
-
- // There's one more task to mgirate back to the default network in 0.4s, which
- // is also cancelled due to the success migration on the previous trial.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- base::TimeDelta expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- time_advanced;
- EXPECT_EQ(expected_delay, next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
-
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -2909,6 +2939,11 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
// Set up the second socket data provider that is used after migration.
// The response to the earlier request is read on the new socket.
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
MockQuicData quic_data2(version_);
// First connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
@@ -2928,12 +2963,17 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_num++, 1, 1, 1, {1, 2}));
+ quic_data2.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, true, 2, 1, 0u));
quic_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 2, 2,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS, client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(), false, false,
+ StreamCancellationQpackDecoderInstruction(0)));
quic_data2.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -2956,7 +2996,7 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -2975,9 +3015,10 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -2995,32 +3036,22 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
// Cause the connection to report path degrading to the session.
// Due to lack of alternate network, session will not mgirate connection.
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
- // A task will be posted to migrate to the new default network.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- EXPECT_EQ(base::TimeDelta(), task_runner->NextPendingTaskDelay());
-
- // Execute the posted task to migrate back to the default network.
+ // A task was posted to migrate to the new default network. Execute that task.
task_runner->RunUntilIdle();
- base::TimeDelta next_task_delay;
- base::TimeDelta expected_delay;
if (!version_.HasIetfQuicFrames()) {
// Another task to resend a new connectivity probe is posted. And a task to
// retry migrate back to default network is scheduled.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
// Next connectivity probe is scheduled to be sent in 2 *
// kDefaultRTTMilliSecs.
- next_task_delay = task_runner->NextPendingTaskDelay();
- expected_delay =
+ base::TimeDelta retry_connectivity_probe_delay =
base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs);
- EXPECT_EQ(expected_delay, next_task_delay);
// Fast forward to send the second connectivity probe. The write will be
// asynchronous and complete after the read completes.
- task_runner->FastForwardBy(next_task_delay);
+ task_runner->FastForwardBy(retry_connectivity_probe_delay);
} else {
// Manually trigger retransmission of PATH_CHALLENGE.
auto* path_validator =
@@ -3035,17 +3066,11 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
- // There should be three pending tasks, the nearest one will complete
- // migration to the new network. Second task will retry migrate back to
- // default but cancelled, and the third task will retry send connectivity
- // probe but also cancelled.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- EXPECT_EQ(base::TimeDelta(), task_runner->NextPendingTaskDelay());
+ // There should be a task that will complete the migration to the new network.
task_runner->RunUntilIdle();
// Response headers are received over the new network.
@@ -3055,33 +3080,9 @@ TEST_P(QuicStreamFactoryTest, MigratedToBlockedSocketAfterProbing) {
// Run the message loop to complete the asynchronous write of ack and ping.
base::RunLoop().RunUntilIdle();
- // Now there are two pending tasks, the nearest one was to retry migrate back
- // to default network and has been cancelled due to successful migration.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 1u : 2u,
- task_runner->GetPendingTaskCount());
- expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- expected_delay;
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(expected_delay, next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
-
- if (!version_.HasIetfQuicFrames()) {
- // There's one more task to retry sending connectivity probe in 0.4s and has
- // also been cancelled due to the successful probing.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- expected_delay =
- base::TimeDelta::FromMilliseconds(3 * 2 * kDefaultRTTMilliSecs) -
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs);
- EXPECT_EQ(expected_delay, next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
- }
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
-
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -3116,7 +3117,7 @@ TEST_P(QuicStreamFactoryTest, MigrationTimeoutWithNoNewNetwork) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3133,9 +3134,9 @@ TEST_P(QuicStreamFactoryTest, MigrationTimeoutWithNoNewNetwork) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Trigger connection migration. Since there are no networks
// to migrate to, this should cause the session to wait for a new network.
@@ -3144,22 +3145,19 @@ TEST_P(QuicStreamFactoryTest, MigrationTimeoutWithNoNewNetwork) {
// The migration will not fail until the migration alarm timeout.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
EXPECT_EQ(true, session->connection()->writer()->IsWriteBlocked());
// Migration will be timed out after kWaitTimeForNewNetwokSecs.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromSeconds(kWaitTimeForNewNetworkSecs),
- next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ task_runner->FastForwardBy(
+ base::TimeDelta::FromSeconds(kWaitTimeForNewNetworkSecs));
// The connection should now be closed. A request for response
// headers should fail.
EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(ERR_INTERNET_DISCONNECTED, callback_.WaitForResult());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -3201,6 +3199,13 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
}
// Set up the second socket data provider that is used for probing.
+ quic::QuicConnectionId cid_on_old_path =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
MockQuicData quic_data1(version_);
// Connectivity probe to be sent on the new path.
quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
@@ -3214,14 +3219,15 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
// A RESET will be sent to the peer to cancel the non-migratable stream.
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeDataRstAndAckPacket(
- packet_num++, true, GetQpackDecoderStreamId(),
- StreamCancellationQpackDecoderInstruction(0),
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 1, 1));
- quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
- 1, packet_num++, false));
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeDataAndRstPacket(
+ packet_num++, /*include_version=*/false,
+ GetQpackDecoderStreamId(),
+ StreamCancellationQpackDecoderInstruction(0),
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
+ quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
+ 1, packet_num++, false));
} else {
quic_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeAckAndRstPacket(
@@ -3232,7 +3238,15 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
// Ping packet to send after migration is completed.
quic_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, false));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_num++, false, 0u));
+ }
} else {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_old_path);
+ }
if (version_.UsesTls()) {
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(
@@ -3285,7 +3299,7 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3303,9 +3317,10 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Trigger connection migration. Session will start to probe the alternative
// network. Although there is a non-migratable stream, session will still be
@@ -3314,14 +3329,14 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNonMigratableStream(
->NotifyNetworkMadeDefault(kNewNetworkForTests);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Resume data to read a connectivity probing response, which will cause
// non-migtable streams to be closed.
quic_data1.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
EXPECT_EQ(0u, session->GetNumActiveStreams());
base::RunLoop().RunUntilIdle();
@@ -3360,7 +3375,7 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultConnectionMigrationDisabled) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3377,9 +3392,9 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultConnectionMigrationDisabled) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Set session config to have connection migration disabled.
quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration(
@@ -3392,7 +3407,7 @@ TEST_P(QuicStreamFactoryTest, OnNetworkMadeDefaultConnectionMigrationDisabled) {
->NotifyNetworkMadeDefault(kNewNetworkForTests);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -3421,6 +3436,10 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNonMigratableStream(
client_maker_.set_save_packet_frames(true);
MockQuicData failed_socket_data(version_);
+ quic::QuicConnectionId cid_on_old_path =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
MockQuicData socket_data(version_);
if (migrate_idle_sessions) {
failed_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -3444,16 +3463,27 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNonMigratableStream(
failed_socket_data.AddSocketDataToFactory(socket_factory_.get());
// Set up second socket data provider that is used after migration.
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
if (version_.UsesHttp3()) {
socket_data.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
{3, 1, 2}, packet_num++, true));
+ // Ping packet to send after migration.
+ socket_data.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++,
+ /*include_version=*/false));
+ socket_data.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, 0u));
+ } else {
+ // Ping packet to send after migration.
+ socket_data.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- // Ping packet to send after migration.
- socket_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
socket_data.AddSocketDataToFactory(socket_factory_.get());
} else {
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
@@ -3478,7 +3508,7 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNonMigratableStream(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3496,21 +3526,22 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNonMigratableStream(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Trigger connection migration. Since there is a non-migratable stream,
// this should cause a RST_STREAM frame to be emitted with
// quic::QUIC_STREAM_CANCELLED error code.
- // If migate idle session, the connection will then be migrated to the
+ // If migrate idle session, the connection will then be migrated to the
// alternate network. Otherwise, the connection will be closed.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
EXPECT_EQ(migrate_idle_sessions,
QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
if (migrate_idle_sessions) {
EXPECT_EQ(0u, session->GetNumActiveStreams());
@@ -3543,7 +3574,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3560,9 +3591,9 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Set session config to have connection migration disabled.
quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration(
@@ -3574,7 +3605,7 @@ TEST_P(QuicStreamFactoryTest,
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -3615,8 +3646,13 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNoOpenStreams(
}
socket_data.AddSocketDataToFactory(socket_factory_.get());
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
MockQuicData quic_data1(version_);
if (migrate_idle_sessions) {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Set up the second socket data provider that is used for probing.
// Connectivity probe to be sent on the new path.
quic_data1.AddWrite(
@@ -3630,8 +3666,12 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNoOpenStreams(
if (version_.UsesHttp3()) {
// in-flight SETTINGS and requests will be retransmitted. Since data is
// already sent on the new address, ping will no longer be sent.
- quic_data1.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_num++, 1, 1, 1, {1}));
+ quic_data1.AddWrite(ASYNC, client_maker_.MakeRetransmissionPacket(
+ /*original_packet_number=*/1, packet_num++,
+ /*should_include_version=*/false));
+ quic_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_num++, false, 0u));
} else {
// Ping packet to send after migration is completed.
quic_data1.AddWrite(
@@ -3644,7 +3684,7 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNoOpenStreams(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3654,15 +3694,16 @@ void QuicStreamFactoryTestBase::TestOnNetworkMadeDefaultNoOpenStreams(
EXPECT_TRUE(stream.get());
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_FALSE(session->HasActiveRequestStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Trigger connection migration.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
if (migrate_idle_sessions) {
quic_data1.Resume();
@@ -3703,7 +3744,12 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNoOpenStreams(
default_socket_data.AddSocketDataToFactory(socket_factory_.get());
MockQuicData alternate_socket_data(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
if (migrate_idle_sessions) {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Set up second socket data provider that is used after migration.
alternate_socket_data.AddRead(SYNCHRONOUS,
ERR_IO_PENDING); // Hanging read.
@@ -3711,11 +3757,19 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNoOpenStreams(
alternate_socket_data.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRetransmissionPacket(1, packet_num++, true));
+ // Ping packet to send after migration.
+ alternate_socket_data.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++,
+ /*include_version=*/false));
+ alternate_socket_data.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_num++, true, 0u));
+ } else {
+ // Ping packet to send after migration.
+ alternate_socket_data.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- // Ping packet to send after migration.
- alternate_socket_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
}
@@ -3723,7 +3777,7 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNoOpenStreams(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3733,14 +3787,15 @@ void QuicStreamFactoryTestBase::TestOnNetworkDisconnectedNoOpenStreams(
EXPECT_TRUE(stream.get());
// Ensure that session is active.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ auto* session = GetActiveSession(scheme_host_port_);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Trigger connection migration. Since there are no active streams,
// the session will be closed.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
EXPECT_TRUE(default_socket_data.AllReadDataConsumed());
EXPECT_TRUE(default_socket_data.AllWriteDataConsumed());
@@ -3798,7 +3853,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3817,9 +3872,12 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -3833,14 +3891,24 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
// Set up second socket data provider that is used after migration.
// The response to the earlier request is read on this new socket.
MockQuicData socket_data1(version_);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
if (version_.UsesHttp3()) {
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
{1, 2}, packet_number++, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_number++,
+ /*include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_number++, false, 0u));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_number++,
+ /*include_version=*/true));
}
- socket_data1.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_number++, /*include_version=*/true));
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -3849,9 +3917,10 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
SYNCHRONOUS,
- client_maker_.MakeAckAndDataPacket(
- packet_number++, false, GetQpackDecoderStreamId(), 1, 1, false,
- StreamCancellationQpackDecoderInstruction(0)));
+ client_maker_.MakeDataPacket(
+ packet_number++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, false,
@@ -3872,13 +3941,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
// The connection should still be alive, not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
// Ensure that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Run the message loop so that data queued in the new socket is read by the
@@ -3891,7 +3960,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnNetworkDisconnected(
// Check that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// There should be posted tasks not executed, which is to migrate back to
// default network.
@@ -3940,7 +4009,7 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -3959,9 +4028,12 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -3976,21 +4048,31 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
// The connection should still be alive, not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
// Set up second socket data provider that is used after migration.
// The response to the earlier request is read on this new socket.
MockQuicData socket_data1(version_);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
if (version_.UsesHttp3()) {
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
{1, 2}, packet_num++, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_num++, false, 0u));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- socket_data1.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -3998,9 +4080,10 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(), /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -4024,7 +4107,7 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
// Ensure that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Run the message loop so that data queued in the new socket is read by the
@@ -4037,7 +4120,7 @@ TEST_P(QuicStreamFactoryTest, NewNetworkConnectedAfterNoNetwork) {
// Check that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// There should posted tasks not executed, which is to migrate back to default
// network.
@@ -4092,6 +4175,11 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
// Set up the second socket data provider that is used for probing on the
// alternate network.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_number++, true));
@@ -4110,6 +4198,9 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
if (version_.UsesHttp3()) {
quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
packet_number++, 1, 4, 1, {1, 2}));
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false, 0u));
} else {
quic_data2.AddWrite(ASYNC,
client_maker_.MakeAckPacket(packet_number++, 4, 1));
@@ -4143,7 +4234,7 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4162,9 +4253,10 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -4178,19 +4270,9 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
session->connection()->OnPathDegradingDetected();
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- base::TimeDelta next_task_delay;
- if (!version_.HasIetfQuicFrames()) {
- // Next connectivity probe is scheduled to be sent in 2 *
- // kDefaultRTTMilliSecs.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- }
-
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -4199,16 +4281,11 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
- // There should be three pending tasks, the nearest one will complete
- // migration to the new network.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ // There should be a task that will complete the migration to the new network.
+ task_runner->RunUntilIdle();
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
@@ -4216,39 +4293,19 @@ TEST_P(QuicStreamFactoryTest, MigrateToProbingSocket) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
- base::TimeDelta time_advanced;
- if (!version_.HasIetfQuicFrames()) {
- // Now there are two pending tasks, the nearest one was to send connectivity
- // probe and has been cancelled due to successful migration.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- time_advanced = next_task_delay;
- task_runner->FastForwardBy(next_task_delay);
- }
-
- // There's one more task to mgirate back to the default network in 0.4s.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- base::TimeDelta expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- time_advanced;
- EXPECT_EQ(expected_delay, next_task_delay);
-
// Deliver a signal that the alternate network now becomes default to session,
- // this will cancel mgirate back to default network timer.
+ // this will cancel migrate back to default network timer.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- task_runner->FastForwardBy(next_task_delay);
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ task_runner->FastForwardBy(
+ base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs));
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -4308,6 +4365,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
// Set up the second socket data provider that is used after migration.
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_number++, true));
@@ -4318,8 +4380,12 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
if (version_.UsesHttp3()) {
// in-flight SETTINGS and requests will be retransmitted. Since data is
// already sent on the new address, ping will no longer be sent.
- quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_number++, 1, 1, 1, {1, 2}));
+ quic_data2.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_number++,
+ /*should_include_version=*/false));
+ quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, true, 0u));
} else {
// Ping packet to send after migration is completed.
quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndPingPacket(
@@ -4354,7 +4420,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4373,9 +4439,10 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -4406,7 +4473,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -4415,17 +4482,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
- // There should be three pending tasks, the nearest one will complete
- // migration to the new network.
- // IETF QUIC has no task for probe retransmission, thus only having 2 tasks.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ // There should be a task that will complete the migration to the new network.
+ task_runner->RunUntilIdle();
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
@@ -4435,28 +4496,6 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- // Now there are two pending tasks, the nearest one was to send connectivity
- // probe and has been cancelled due to successful migration.
- base::TimeDelta advanced_time;
- if (!version_.HasIetfQuicFrames()) {
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
- advanced_time = next_task_delay;
- }
-
- // There's one more task to migrate back to the default network in 0.4s.
- // For IETF QUIC, since we didn't advance time for cancelling probing, the
- // delay for migrating back is 1s.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- base::TimeDelta expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- advanced_time;
- EXPECT_EQ(expected_delay, next_task_delay);
-
// Deliver a signal that the alternate network now becomes default to session,
// this will cancel mgirate back to default network timer.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -4464,12 +4503,12 @@ void QuicStreamFactoryTestBase::TestMigrationOnPathDegrading(
EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- task_runner->FastForwardBy(next_task_delay);
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ task_runner->FastForwardBy(
+ base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs));
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -4509,22 +4548,40 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyProbingWriterError) {
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, true));
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- quic_data1.AddSocketDataToFactory(socket_factory_.get());
// Set up the second socket data provider that is used for path validation.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_old_path =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
+ ++packet_number; // Account for the packet encountering write error.
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
quic_data2.AddRead(ASYNC,
server_maker_.MakeConnectivityProbingPacket(1, false));
+
+ // Connection ID is retired on the old path.
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_old_path);
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false,
+ /*sequence_number=*/1u));
+ }
+
+ quic_data1.AddSocketDataToFactory(socket_factory_.get());
quic_data2.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4543,9 +4600,10 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyProbingWriterError) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -4563,7 +4621,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyProbingWriterError) {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -4588,7 +4646,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyProbingWriterError) {
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -4615,6 +4673,10 @@ TEST_P(QuicStreamFactoryTest,
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->QueueNetworkMadeDefault(kDefaultNetworkForTests);
+ quic::QuicConnectionId cid_on_path1 =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
+ quic::QuicConnectionId cid_on_path2 = quic::test::TestConnectionId(12345678);
+
int packet_number = 1;
MockQuicData quic_data1(version_);
quic_data1.AddWrite(SYNCHRONOUS,
@@ -4630,33 +4692,40 @@ TEST_P(QuicStreamFactoryTest,
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, true));
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- quic_data1.AddSocketDataToFactory(socket_factory_.get());
// Set up the second socket data provider that is used for path validation.
MockQuicData quic_data2(version_);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_path2);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, ERR_ADDRESS_UNREACHABLE);
quic_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause
quic_data2.AddRead(ASYNC,
server_maker_.MakeConnectivityProbingPacket(1, false));
- quic_data2.AddSocketDataToFactory(socket_factory_.get());
+ packet_number++; // Account for packet encountering write error.
- packet_number++;
+ // Connection ID is retired on the old path.
+ client_maker_.set_connection_id(cid_on_path1);
+ quic_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false,
+ /*sequence_number=*/1u));
+ // A socket will be created for a new path, but there would be no write
+ // due to lack of new connection ID.
MockQuicData quic_data3(version_);
- // Connectivity probe to be sent on the new path.
- quic_data3.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
- packet_number++, true));
- quic_data3.AddRead(ASYNC, ERR_IO_PENDING); // Pause
- quic_data3.AddRead(ASYNC,
- server_maker_.MakeConnectivityProbingPacket(1, false));
+ quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Pause
+
+ quic_data1.AddSocketDataToFactory(socket_factory_.get());
+ quic_data2.AddSocketDataToFactory(socket_factory_.get());
quic_data3.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4675,9 +4744,10 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_path2, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -4695,7 +4765,7 @@ TEST_P(QuicStreamFactoryTest,
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -4711,10 +4781,10 @@ TEST_P(QuicStreamFactoryTest,
base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay();
EXPECT_EQ(base::TimeDelta(), next_task_delay);
task_runner->FastForwardBy(next_task_delay);
- // Verify that the task is executed, but since a new path validation is under
- // way, it won't be cancelled.
+ // Verify that the task is executed.
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
- EXPECT_TRUE(session->connection()->HasPendingPathValidation());
+ // No pending path validation as there is no connection ID available.
+ EXPECT_FALSE(session->connection()->HasPendingPathValidation());
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
quic_data1.Resume();
@@ -4724,7 +4794,7 @@ TEST_P(QuicStreamFactoryTest,
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -4739,8 +4809,7 @@ TEST_P(QuicStreamFactoryTest,
return;
}
quic_params_->allow_port_migration = true;
- FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
- FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
socket_factory_ = std::make_unique<TestPortMigrationSocketFactory>();
Initialize();
@@ -4750,6 +4819,11 @@ TEST_P(QuicStreamFactoryTest,
// Verifies that port migration can be attempted and succeed when path degrading
// is detected, even if NetworkHandle is not supported.
TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithoutNetworkHandle) {
+ if (version_.HasIetfQuicFrames()) {
+ // MigratePortOnPathDegrading_WithoutNetworkHandle_PathValidator is the
+ // corresponding IETF QUIC test.
+ return;
+ }
quic_params_->allow_port_migration = true;
FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = false;
FLAGS_quic_reloadable_flag_quic_send_path_response2 = false;
@@ -4825,7 +4899,7 @@ TEST_P(QuicStreamFactoryTest, PortMigrationProbingReceivedStatelessReset) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4844,9 +4918,9 @@ TEST_P(QuicStreamFactoryTest, PortMigrationProbingReceivedStatelessReset) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -4871,7 +4945,7 @@ TEST_P(QuicStreamFactoryTest, PortMigrationProbingReceivedStatelessReset) {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -4882,7 +4956,7 @@ TEST_P(QuicStreamFactoryTest, PortMigrationProbingReceivedStatelessReset) {
// Verify that the session is still active, and the request stream is active.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_FALSE(
QuicChromiumClientSessionPeer::DoesSessionAllowPortMigration(session));
@@ -4905,8 +4979,7 @@ TEST_P(QuicStreamFactoryTest,
return;
}
quic_params_->allow_port_migration = true;
- FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
- FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
socket_factory_ = std::make_unique<TestPortMigrationSocketFactory>();
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -4940,6 +5013,11 @@ TEST_P(QuicStreamFactoryTest,
// Set up the second socket data provider that is used for migration probing.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_number, true));
@@ -4952,7 +5030,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -4971,9 +5049,10 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -4998,7 +5077,7 @@ TEST_P(QuicStreamFactoryTest,
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -5009,7 +5088,7 @@ TEST_P(QuicStreamFactoryTest,
// Verify that the session is still active, and the request stream is active.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -5032,8 +5111,7 @@ TEST_P(QuicStreamFactoryTest,
mock_ncn->ForceNetworkHandlesSupported();
mock_ncn->SetConnectedNetworksList({kDefaultNetworkForTests});
quic_params_->allow_port_migration = true;
- FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
- FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
socket_factory_ = std::make_unique<TestPortMigrationSocketFactory>();
Initialize();
@@ -5046,6 +5124,11 @@ TEST_P(QuicStreamFactoryTest,
// Verifies that port migration can be attempted on the default network and
// succeed when path degrading is detected. NetworkHandle is supported.
TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithNetworkHandle) {
+ if (version_.HasIetfQuicFrames()) {
+ // MigratePortOnPathDegrading_WithNetworkHandle_PathValidator is the
+ // corresponding IETF QUIC test.
+ return;
+ }
scoped_mock_network_change_notifier_ =
std::make_unique<ScopedMockNetworkChangeNotifier>();
MockNetworkChangeNotifier* mock_ncn =
@@ -5069,6 +5152,11 @@ TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithNetworkHandle) {
// NetworkHandle is supported. Migration on network change is also enabled.
// No additional network migration is triggered post port migration.
TEST_P(QuicStreamFactoryTest, MigratePortOnPathDegrading_WithMigration) {
+ if (version_.HasIetfQuicFrames()) {
+ // MigratePortOnPathDegrading_WithMigration_PathValidator is the
+ // corresponding IETF QUIC test.
+ return;
+ }
scoped_mock_network_change_notifier_ =
std::make_unique<ScopedMockNetworkChangeNotifier>();
MockNetworkChangeNotifier* mock_ncn =
@@ -5104,8 +5192,7 @@ TEST_P(QuicStreamFactoryTest,
// Enable migration on network change.
quic_params_->migrate_sessions_on_network_change_v2 = true;
quic_params_->allow_port_migration = true;
- FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator = true;
- FLAGS_quic_reloadable_flag_quic_send_path_response2 = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
socket_factory_ = std::make_unique<TestPortMigrationSocketFactory>();
Initialize();
@@ -5141,6 +5228,12 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
// Set up the second socket data provider that is used after migration.
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version) &&
+ FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_number++, true));
@@ -5149,19 +5242,41 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
quic_data2.AddRead(ASYNC,
server_maker_.MakeConnectivityProbingPacket(1, false));
// Ping packet to send after migration is completed.
- quic_data2.AddWrite(
- ASYNC, client_maker_.MakeAckAndPingPacket(packet_number++, false, 1, 1));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data2.AddWrite(
+ ASYNC, client_maker_.MakePingPacket(packet_number++,
+ /*include_version=*/false));
+ } else {
+ quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndPingPacket(
+ packet_number++, false, 1, 1));
+ }
quic_data2.AddRead(
ASYNC,
ConstructOkResponsePacket(
2, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data2.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeAckAndDataPacket(
- packet_number++, false, GetQpackDecoderStreamId(), 2, 2, false,
- StreamCancellationQpackDecoderInstruction(0)));
+ if (FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2) {
+ quic_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false,
+ /*largest_received=*/2,
+ /*smallest_received=*/1, /*sequence_number=*/0u));
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_number++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
+ } else {
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeAckAndDataPacket(
+ packet_number++, /*include_version=*/false,
+ GetQpackDecoderStreamId(),
+ /*largest_received=*/2, /*smallest_received=*/2, /*fin=*/false,
+ StreamCancellationQpackDecoderInstruction(0)));
+ }
quic_data2.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, false,
@@ -5180,7 +5295,7 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5199,9 +5314,10 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -5247,7 +5363,7 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -5256,7 +5372,7 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Successful port migration causes the path no longer degrading on the same
// network.
@@ -5264,11 +5380,10 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
// There should be pending tasks, the nearest one will complete
// migration to the new port.
- EXPECT_EQ(session->connection()->use_path_validator() ? 1 : 2u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ task_runner->RunUntilIdle();
+
+ // Fire any outstanding quic alarms.
+ base::RunLoop().RunUntilIdle();
// Response headers are received over the new port.
EXPECT_THAT(callback_.WaitForResult(), IsOk());
@@ -5276,22 +5391,14 @@ void QuicStreamFactoryTestBase::TestSimplePortMigrationOnPathDegrading() {
EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- if (!session->connection()->use_path_validator()) {
- // Now there is one pending task to send connectivity probe and has been
- // cancelled due to successful migration.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
- }
-
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ // Now there may be one pending task to send connectivity probe that has been
+ // cancelled due to successful migration.
+ task_runner->FastForwardUntilNoTasksRemain();
// Verify that the session is still alive, and the request stream is still
// alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
chrome_stream = static_cast<QuicChromiumClientStream*>(
quic::test::QuicSessionPeer::GetStream(
session, GetNthClientInitiatedBidirectionalStreamId(0)));
@@ -5338,7 +5445,7 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5357,9 +5464,9 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -5440,7 +5547,7 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Resume quic data and a connectivity probe response will be read on the
@@ -5449,34 +5556,27 @@ TEST_P(QuicStreamFactoryTest, MultiplePortMigrationsExceedsMaxLimit) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
if (i < 4) {
- // There should be pending tasks, the nearest one will complete
- // migration to the new port.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
+ // There's a pending task to complete migration to the new pot.
+ task_runner->RunUntilIdle();
} else {
// Last attempt to migrate will abort due to hitting the limit of max
// number of allowed migrations.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_NE(base::TimeDelta(), next_task_delay);
+ task_runner->FastForwardUntilNoTasksRemain();
}
- task_runner->FastForwardBy(next_task_delay);
+
EXPECT_TRUE(quic_data2.AllWriteDataConsumed());
// The last round of migration will abort upon reading the probing response.
// Future reads in the same socket is ignored.
EXPECT_EQ(i != 4, quic_data2.AllReadDataConsumed());
}
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
-
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -5522,7 +5622,7 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5541,9 +5641,9 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -5562,7 +5662,7 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
EXPECT_EQ(0u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
// The connection should still be alive, but marked as going away.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(1u, session->GetNumActiveStreams());
@@ -5570,7 +5670,7 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5587,9 +5687,9 @@ TEST_P(QuicStreamFactoryTest, GoawayOnPathDegrading) {
EXPECT_EQ(0U, session->GetNumActiveStreams());
// Check an active session exists for the destination.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- QuicChromiumClientSession* session2 = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session2));
EXPECT_NE(session, session2);
@@ -5663,7 +5763,7 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5682,9 +5782,9 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -5700,7 +5800,7 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) {
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -5714,7 +5814,7 @@ TEST_P(QuicStreamFactoryTest, DoNotMigrateToBadSocketOnPathDegrading) {
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data.AllReadDataConsumed());
@@ -5776,6 +5876,11 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
// Set up the second socket data provider that is used after migration.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_number++, false));
@@ -5796,6 +5901,10 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
quic_data2.AddWrite(ASYNC,
client_maker_.MakePingPacket(packet_number++, false));
}
+ if (version_.UsesHttp3()) {
+ quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, false, 0u));
+ }
server_maker_.Reset();
quic_data2.AddRead(
ASYNC,
@@ -5810,7 +5919,7 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -5829,9 +5938,10 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -5848,19 +5958,9 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
// Cause the connection to report path degrading to the session.
// Session should still start to probe the alternate network.
session->connection()->OnPathDegradingDetected();
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- base::TimeDelta next_task_delay;
- if (!version_.HasIetfQuicFrames()) {
- // Next connectivity probe is scheduled to be sent in 2 *
- // kDefaultRTTMilliSecs.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- }
-
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
@@ -5869,51 +5969,24 @@ void QuicStreamFactoryTestBase::TestMigrateSessionWithDrainingStream(
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(0u, session->GetNumActiveStreams());
EXPECT_TRUE(session->HasActiveRequestStreams());
- // There should be three pending tasks, the nearest one will complete
- // migration to the new network.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
-
- base::TimeDelta time_advanced;
- if (!version_.HasIetfQuicFrames()) {
- // Now there are two pending tasks, the nearest one was to send connectivity
- // probe and has been cancelled due to successful migration.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- time_advanced = next_task_delay;
- task_runner->FastForwardBy(next_task_delay);
- }
-
- // There's one more task to mgirate back to the default network in 0.4s.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- base::TimeDelta expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- time_advanced;
- EXPECT_EQ(expected_delay, next_task_delay);
-
- base::RunLoop().RunUntilIdle();
+ // There should be a task that will complete the migration to the new network.
+ task_runner->RunUntilIdle();
// Deliver a signal that the alternate network now becomes default to session,
// this will cancel mgirate back to default network timer.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
- task_runner->FastForwardBy(next_task_delay);
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ task_runner->FastForwardBy(
+ base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs));
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
stream.reset();
@@ -5957,6 +6030,11 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
// Set up the second socket data provider that is used after migration.
// The response to the earlier request is read on the new socket.
MockQuicData quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_num++, true));
@@ -5967,8 +6045,12 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
if (version_.UsesHttp3()) {
// in-flight SETTINGS and requests will be retransmitted. Since data is
// already sent on the new address, ping will no longer be sent.
- quic_data2.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_num++, 1, 1, 1, {1, 2}));
+ quic_data2.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ quic_data2.AddWrite(SYNCHRONOUS, client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, false, 0u));
} else {
// Ping packet to send after migration is completed.
quic_data2.AddWrite(
@@ -6002,7 +6084,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6021,9 +6103,10 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -6051,19 +6134,9 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkConnected(kNewNetworkForTests);
- base::TimeDelta next_task_delay;
- if (!version_.HasIetfQuicFrames()) {
- // Next connectivity probe is scheduled to be sent in 2 *
- // kDefaultRTTMilliSecs.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- base::TimeDelta next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- }
-
// The connection should still be alive, and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -6072,16 +6145,11 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
quic_data2.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
- // There should be three pending tasks, the nearest one will complete
- // migration to the new network.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 2u : 3u,
- task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta(), next_task_delay);
- task_runner->FastForwardBy(next_task_delay);
+ // There should be a task that will complete the migration to the new network.
+ task_runner->RunUntilIdle();
// Although the session successfully migrates, it is still considered
// degrading sessions.
@@ -6091,37 +6159,18 @@ TEST_P(QuicStreamFactoryTest, MigrateOnNewNetworkConnectAfterPathDegrading) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
EXPECT_EQ(200, response.headers->response_code());
- base::TimeDelta time_advanced;
- if (!version_.HasIetfQuicFrames()) {
- // Now there are two pending tasks, the nearest one was to send connectivity
- // probe and has been cancelled due to successful migration.
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(2 * kDefaultRTTMilliSecs),
- next_task_delay);
- time_advanced = next_task_delay;
- task_runner->FastForwardBy(next_task_delay);
- }
-
- // There's one more task to mgirate back to the default network in 0.4s.
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- next_task_delay = task_runner->NextPendingTaskDelay();
- base::TimeDelta expected_delay =
- base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs) -
- time_advanced;
- EXPECT_EQ(expected_delay, next_task_delay);
-
// Deliver a signal that the alternate network now becomes default to session,
// this will cancel mgirate back to default network timer.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
->NotifyNetworkMadeDefault(kNewNetworkForTests);
- task_runner->FastForwardBy(next_task_delay);
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ // There's one more task to mgirate back to the default network in 0.4s.
+ task_runner->FastForwardBy(
+ base::TimeDelta::FromSeconds(kMinRetryTimeForDefaultNetworkSecs));
// Verify that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
stream.reset();
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -6150,8 +6199,8 @@ TEST_P(QuicStreamFactoryTest,
socket_data2.AddWrite(ASYNC, OK);
socket_data2.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server1(kDefaultServerHostName, 443);
- HostPortPair server2(kServer2HostName, 443);
+ url::SchemeHostPort server1(url::kHttpsScheme, kDefaultServerHostName, 443);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName, 443);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -6306,7 +6355,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6325,9 +6374,9 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream.
HttpResponseInfo response;
@@ -6343,7 +6392,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) {
EXPECT_TRUE(session->connection()->IsPathDegrading());
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -6352,7 +6401,7 @@ TEST_P(QuicStreamFactoryTest, MigrateOnPathDegradingWithNoNewNetwork) {
quic_data.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -6392,6 +6441,13 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
// Set up the second socket data provider that is used for probing.
MockQuicData quic_data1(version_);
+ quic::QuicConnectionId cid_on_old_path =
+ quic::QuicUtils::CreateRandomConnectionId(context_.random_generator());
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
// Connectivity probe to be sent on the new path.
quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_num++, true));
@@ -6404,12 +6460,13 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
// A RESET will be sent to the peer to cancel the non-migratable stream.
if (VersionUsesHttp3(version_.transport_version)) {
- quic_data1.AddWrite(SYNCHRONOUS,
- client_maker_.MakeDataRstAndAckPacket(
- packet_num++, true, GetQpackDecoderStreamId(),
- StreamCancellationQpackDecoderInstruction(0),
- GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED, 1, 1));
+ quic_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeDataAndRstPacket(
+ packet_num++, /*include_version=*/true, GetQpackDecoderStreamId(),
+ StreamCancellationQpackDecoderInstruction(0),
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ quic::QUIC_STREAM_CANCELLED));
quic_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
1, packet_num++, false));
} else {
@@ -6422,8 +6479,15 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
// Ping packet to send after migration is completed.
quic_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, false));
-
+ if (VersionUsesHttp3(version_.transport_version)) {
+ quic_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(packet_num++, false, 0u));
+ }
} else {
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_old_path);
+ }
if (version_.UsesTls()) {
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(
@@ -6476,7 +6540,7 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6494,9 +6558,10 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Trigger connection migration. Since there is a non-migratable stream,
// this should cause session to migrate.
@@ -6506,7 +6571,7 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
// packet reader.
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Resume the data to read the connectivity probing response to declare probe
@@ -6515,7 +6580,7 @@ void QuicStreamFactoryTestBase::TestMigrateSessionEarlyNonMigratableStream(
if (migrate_idle_sessions)
base::RunLoop().RunUntilIdle();
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
EXPECT_EQ(0u, session->GetNumActiveStreams());
EXPECT_TRUE(quic_data1.AllReadDataConsumed());
@@ -6554,7 +6619,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6571,9 +6636,9 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Set session config to have connection migration disabled.
quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration(
@@ -6589,7 +6654,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionEarlyConnectionMigrationDisabled) {
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -6630,12 +6695,15 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ }
if (version_.UsesHttp3()) {
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true);
spdy::Http2HeaderBlock headers =
client_maker_.GetRequestHeaders("GET", "https", "/");
spdy::SpdyPriority priority =
@@ -6648,9 +6716,21 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
true, true, priority, std::move(headers),
GetNthClientInitiatedBidirectionalStreamId(0),
&spdy_headers_frame_len));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
} else {
socket_data1.AddWrite(
SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
ConstructGetRequestPacket(
packet_num++, GetNthClientInitiatedBidirectionalStreamId(1),
GetNthClientInitiatedBidirectionalStreamId(0), true, true));
@@ -6662,9 +6742,11 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -6698,7 +6780,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6721,7 +6803,7 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6739,10 +6821,11 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream1. This should cause an async write error.
HttpResponseInfo response;
@@ -6766,10 +6849,12 @@ TEST_P(QuicStreamFactoryTest, MigrateSessionOnAsyncWriteError) {
// Run the task runner so that migration on write error is finally executed.
task_runner->RunUntilIdle();
+ // Fire the retire connection ID alarm.
+ base::RunLoop().RunUntilIdle();
// Verify the session is still alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
// There should be one task posted to migrate back to the default network in
// kMinRetryTimeForDefaultNetworkSecs.
@@ -6814,6 +6899,7 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
MockQuicData socket_data(version_);
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
int packet_num = 1;
+ int peer_packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(SYNCHRONOUS,
ConstructInitialSettingsPacket(packet_num++));
@@ -6825,20 +6911,44 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData quic_data2(version_);
- quic_data2.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
- if (version_.UsesHttp3()) {
+ quic::QuicConnectionId cid1 = quic::test::TestConnectionId(12345678);
+ quic::QuicConnectionId cid2 = quic::test::TestConnectionId(87654321);
+ if (!version_.UsesHttp3()) {
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true,
+ /*fin=*/true));
+ } else {
+ client_maker_.set_connection_id(cid1);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false,
+ /*fin=*/true);
quic_data2.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, true));
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ quic_data2.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ quic_data2.AddRead(ASYNC, server_maker_.MakeAckAndNewConnectionIdPacket(
+ peer_packet_num++, false, packet_num - 1, 1u,
+ cid2, /*sequence_number=*/2u,
+ /*retire_prior_to=*/1u));
}
quic_data2.AddRead(
- ASYNC,
- ConstructOkResponsePacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
+ ASYNC, ConstructOkResponsePacket(
+ peer_packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0), false, false));
quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
quic_data2.AddSocketDataToFactory(socket_factory_.get());
@@ -6846,7 +6956,7 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6865,10 +6975,11 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid1, session);
// Send GET request. This should cause an async write error.
HttpResponseInfo response;
@@ -6885,10 +6996,12 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
// Run the task runner so that migration on write error is finally executed.
task_runner->RunUntilIdle();
+ // Make sure the alarm that retires connection ID on the old path is fired.
+ base::RunLoop().RunUntilIdle();
// Verify the session is still alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// There should be one task posted to migrate back to the default network in
// kMinRetryTimeForDefaultNetworkSecs.
@@ -6904,18 +7017,24 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
// Set up the third socket data provider for migrate back to default network.
MockQuicData quic_data3(version_);
+ if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid2);
+ }
// Connectivity probe to be sent on the new path.
quic_data3.AddWrite(SYNCHRONOUS, client_maker_.MakeConnectivityProbingPacket(
packet_num++, false));
// Connectivity probe to receive from the server.
- quic_data3.AddRead(ASYNC,
- server_maker_.MakeConnectivityProbingPacket(2, false));
+ quic_data3.AddRead(ASYNC, server_maker_.MakeConnectivityProbingPacket(
+ peer_packet_num++, /*include_version=*/false));
quic_data3.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (version_.UsesHttp3()) {
- // Data sent to the old address was in-flight and thus will be
- // retransmistted.
- quic_data3.AddWrite(ASYNC, client_maker_.MakeAckAndRetransmissionPacket(
- packet_num++, 1, 2, 1, {1, 2}));
+ // There is no other data to retransmit as they have been acknowledged by
+ // the packet containing NEW_CONNECTION_ID frame from the server.
+ quic_data3.AddWrite(ASYNC, client_maker_.MakeAckPacket(
+ packet_num++,
+ /*first_received=*/1,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1));
} else {
quic_data3.AddWrite(ASYNC,
client_maker_.MakeAckPacket(packet_num++, 1, 2, 1));
@@ -6940,16 +7059,17 @@ TEST_P(QuicStreamFactoryTest, MigrateBackToDefaultPostMigrationOnWriteError) {
// Verify the session is still alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// There should be one task posted to one will resend a connectivity probe and
// the other will retry migrate back, both are cancelled.
- EXPECT_EQ(version_.HasIetfQuicFrames() ? 1u : 2u,
- task_runner->GetPendingTaskCount());
- task_runner->FastForwardBy(
- base::TimeDelta::FromSeconds(2 * kMinRetryTimeForDefaultNetworkSecs));
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
+ task_runner->FastForwardUntilNoTasksRemain();
+
+ // Verify the session is still alive and not marked as going away.
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
stream1.reset();
EXPECT_TRUE(socket_data.AllReadDataConsumed());
@@ -6985,7 +7105,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -6994,9 +7114,9 @@ TEST_P(QuicStreamFactoryTest,
base::RunLoop().RunUntilIdle();
// Ensure that session is alive but not active.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
- QuicChromiumClientSession* session = GetPendingSession(host_port_pair_);
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
+ QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -7007,8 +7127,8 @@ TEST_P(QuicStreamFactoryTest,
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
@@ -7049,7 +7169,7 @@ void QuicStreamFactoryTestBase::TestNoAlternateNetworkBeforeHandshake(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7058,9 +7178,9 @@ void QuicStreamFactoryTestBase::TestNoAlternateNetworkBeforeHandshake(
base::RunLoop().RunUntilIdle();
// Ensure that session is alive but not active.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
- QuicChromiumClientSession* session = GetPendingSession(host_port_pair_);
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
+ QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
@@ -7070,8 +7190,8 @@ void QuicStreamFactoryTestBase::TestNoAlternateNetworkBeforeHandshake(
session->connection()->OnPathDegradingDetected();
EXPECT_EQ(1u, QuicStreamFactoryPeer::GetNumDegradingSessions(factory_.get()));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Cause the connection to close due to |quic_error| before handshake.
std::string error_details;
@@ -7088,8 +7208,8 @@ void QuicStreamFactoryTestBase::TestNoAlternateNetworkBeforeHandshake(
task_runner->FastForwardUntilNoTasksRemain();
// No new session should be created as there is no alternate network.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
@@ -7147,8 +7267,9 @@ void QuicStreamFactoryTestBase::
socket_data2.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
// Change the encryption level after handshake is confirmed.
client_maker_.SetEncryptionLevel(quic::ENCRYPTION_FORWARD_SECURE);
- if (VersionUsesHttp3(version_.transport_version))
+ if (VersionUsesHttp3(version_.transport_version)) {
socket_data2.AddWrite(ASYNC, ConstructInitialSettingsPacket(packet_num++));
+ }
socket_data2.AddWrite(
ASYNC, ConstructGetRequestPacket(
packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
@@ -7158,14 +7279,17 @@ void QuicStreamFactoryTestBase::
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
-
int probing_packet_num = packet_num++;
-
if (VersionUsesHttp3(version_.transport_version)) {
- socket_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ socket_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/1u));
+ socket_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false, /*fin=*/false,
+ StreamCancellationQpackDecoderInstruction(0)));
socket_data2.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -7182,6 +7306,10 @@ void QuicStreamFactoryTestBase::
// Socket data for probing on the default network.
MockQuicData probing_data(version_);
+ quic::QuicConnectionId cid_on_path1 = quic::test::TestConnectionId(1234567);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_path1);
+ }
probing_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
probing_data.AddWrite(
SYNCHRONOUS,
@@ -7192,7 +7320,7 @@ void QuicStreamFactoryTestBase::
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7201,9 +7329,9 @@ void QuicStreamFactoryTestBase::
base::RunLoop().RunUntilIdle();
// Ensure that session is alive but not active.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
- QuicChromiumClientSession* session = GetPendingSession(host_port_pair_);
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
+ QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
EXPECT_FALSE(failed_on_default_network_);
@@ -7222,9 +7350,9 @@ void QuicStreamFactoryTestBase::
task_runner->FastForwardUntilNoTasksRemain();
// Verify a new session is created on the alternate network.
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- QuicChromiumClientSession* session2 = GetPendingSession(host_port_pair_);
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ QuicChromiumClientSession* session2 = GetPendingSession(scheme_host_port_);
EXPECT_NE(session, session2);
EXPECT_TRUE(failed_on_default_network_);
@@ -7232,7 +7360,8 @@ void QuicStreamFactoryTestBase::
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_path1, session2);
// Resume the data now so that data can be sent and read.
socket_data2.Resume();
@@ -7312,14 +7441,14 @@ TEST_P(QuicStreamFactoryTest, MigrationOnWriteErrorBeforeHandshakeConfirmed) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
EXPECT_EQ(ERR_QUIC_HANDSHAKE_FAILED, callback_.WaitForResult());
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Verify new requests can be sent normally.
crypto_client_stream_factory_.set_handshake_mode(
@@ -7336,13 +7465,13 @@ TEST_P(QuicStreamFactoryTest, MigrationOnWriteErrorBeforeHandshakeConfirmed) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Run the message loop to complete host resolution.
base::RunLoop().RunUntilIdle();
@@ -7350,8 +7479,8 @@ TEST_P(QuicStreamFactoryTest, MigrationOnWriteErrorBeforeHandshakeConfirmed) {
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Create QuicHttpStream.
std::unique_ptr<HttpStream> stream = CreateStream(&request2);
@@ -7425,23 +7554,23 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Ensure that the session is alive but not active.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
base::RunLoop().RunUntilIdle();
- QuicChromiumClientSession* session = GetPendingSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetPendingSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
// Confirm the handshake on the alternate network.
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Resume the data now so that data can be sent and read.
socket_data2.Resume();
@@ -7499,7 +7628,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7518,31 +7647,55 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false,
+ /*fin=*/true);
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ socket_data1.AddWrite(ASYNC, client_maker_.MakePingPacket(
+ packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- socket_data1.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, false));
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -7568,9 +7721,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteError(
// data queued in the new socket is read by the packet reader.
base::RunLoop().RunUntilIdle();
- // Verify that session is alive and not marked as going awya.
+ // Verify that session is alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -7614,7 +7767,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNoNewNetwork(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7633,9 +7786,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNoNewNetwork(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Send GET request on stream. This causes a write error, which triggers
// a connection migration attempt. Since there are no networks
@@ -7655,13 +7808,13 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNoNewNetwork(
// Migration has not yet failed. The session should be alive and active.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_TRUE(session->connection()->writer()->IsWriteBlocked());
// The migration will not fail until the migration alarm timeout.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -7671,7 +7824,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNoNewNetwork(
// The connection should be closed. A request for response headers
// should fail.
EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(ERR_NETWORK_CHANGED, callback_.WaitForResult());
EXPECT_EQ(ERR_NETWORK_CHANGED,
stream->ReadResponseHeaders(callback_.callback()));
@@ -7730,23 +7883,48 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false,
+ /*fin=*/true);
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++,
+ /*include_version=*/false));
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true,
+ /*fin=*/true));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- socket_data1.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, false));
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -7779,7 +7957,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests(
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7802,7 +7980,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests(
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7819,10 +7997,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream. This should cause a write error, which triggers
// a connection migration attempt.
@@ -7837,7 +8016,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorWithMultipleRequests(
// Verify session is still alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -7892,19 +8071,38 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_number++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(1234567);
if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_number++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false,
+ /*fin=*/true);
socket_data1.AddWrite(
SYNCHRONOUS, client_maker_.MakeRetransmissionRstAndDataPacket(
- {1, 2}, packet_number++, true,
+ /*original_packet_numbers=*/{1, 2}, packet_number++,
+ /*include_version=*/false,
GetNthClientInitiatedBidirectionalStreamId(1),
quic::QUIC_STREAM_CANCELLED, GetQpackDecoderStreamId(),
StreamCancellationQpackDecoderInstruction(1)));
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_number++,
+ /*include_version=*/false));
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false,
+ /*sequence_number=*/0u));
} else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_number++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true,
+ /*fin=*/true));
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, true,
@@ -7919,10 +8117,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeAckAndDataPacket(
- packet_number++, false, GetQpackDecoderStreamId(), 1, 1, false,
- StreamCancellationQpackDecoderInstruction(0, false)));
+ SYNCHRONOUS, client_maker_.MakeDataPacket(
+ packet_number++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false,
+ StreamCancellationQpackDecoderInstruction(0, false)));
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, false,
@@ -7941,7 +8140,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7964,7 +8163,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -7983,10 +8182,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream 1. This should cause a write error, which
// triggers a connection migration attempt.
@@ -8002,7 +8202,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams(
// Verify that the session is still alive and not marked as going away.
// Non-migratable stream should be closed due to migration.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -8053,25 +8253,44 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
ERR_ADDRESS_UNREACHABLE); // Write error.
socket_data.AddSocketDataToFactory(socket_factory_.get());
- // Set up second socket data provider that is used after
- // migration. The request is rewritten to this new socket, and the
- // response to the request is read on this new socket.
+ // Set up second socket data provider that is used after migration. The
+ // request is rewritten to this new socket, and the response to the request is
+ // read on this new socket.
MockQuicData socket_data1(version_);
- // The packet triggered writer error will be sent anyway even if the stream
- // will be cancelled later.
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_number++,
- GetNthClientInitiatedBidirectionalStreamId(1),
- true, true));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_number++,
+ GetNthClientInitiatedBidirectionalStreamId(1),
+ /*should_include_version=*/false,
+ /*fin=*/true);
socket_data1.AddWrite(
SYNCHRONOUS, client_maker_.MakeRetransmissionRstAndDataPacket(
- {1}, packet_number++, true,
+ /*original_packet_numbers=*/{1}, packet_number++,
+ /*include_version=*/false,
GetNthClientInitiatedBidirectionalStreamId(1),
quic::QUIC_STREAM_CANCELLED, GetQpackDecoderStreamId(),
StreamCancellationQpackDecoderInstruction(1)));
+ socket_data1.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_number++,
+ /*include_version=*/false));
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_number++, /*include_version=*/false,
+ /*sequence_number=*/0u));
} else {
+ // The packet triggered writer error will be sent anyway even if the stream
+ // will be cancelled later.
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(packet_number++,
+ GetNthClientInitiatedBidirectionalStreamId(1),
+ /*should_include_version=*/true,
+ /*fin=*/true));
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, true,
@@ -8091,10 +8310,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakeAckAndDataPacket(
- packet_number++, false, GetQpackDecoderStreamId(), 1, 1, false,
- StreamCancellationQpackDecoderInstruction(0, false)));
+ SYNCHRONOUS, client_maker_.MakeDataPacket(
+ packet_number++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false,
+ StreamCancellationQpackDecoderInstruction(0, false)));
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeRstPacket(
packet_number++, false,
@@ -8113,7 +8333,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
QuicStreamRequest request1(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8136,7 +8356,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8155,10 +8375,11 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(2u, session->GetNumActiveStreams());
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream 2 which is non-migratable. This should cause a
// write error, which triggers a connection migration attempt.
@@ -8173,7 +8394,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMixedStreams2(
// closed.
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream 1.
@@ -8214,6 +8435,8 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
MockQuicData failed_socket_data(version_);
MockQuicData socket_data(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
int packet_num = 1;
if (migrate_idle_sessions) {
// The socket data provider for the original socket before migration.
@@ -8227,24 +8450,42 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
// Set up second socket data provider that is used after migration.
socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
- // Although the write error occurs when writing a packet for the
- // non-migratable stream and the stream will be cancelled during migration,
- // the packet will still be retransimitted at the connection level.
- socket_data.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
- // A RESET will be sent to the peer to cancel the non-migratable stream.
if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false,
+ /*fin=*/true);
socket_data.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRetransmissionRstAndDataPacket(
- {1}, packet_num++, true,
+ /*original_packet_numbers=*/{1}, packet_num++,
+ /*include_version=*/false,
GetNthClientInitiatedBidirectionalStreamId(0),
quic::QUIC_STREAM_CANCELLED, GetQpackDecoderStreamId(),
StreamCancellationQpackDecoderInstruction(0)));
+ socket_data.AddWrite(
+ SYNCHRONOUS, client_maker_.MakePingPacket(packet_num++,
+ /*include_version=*/false));
+ socket_data.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
} else {
+ // Although the write error occurs when writing a packet for the
+ // non-migratable stream and the stream will be cancelled during
+ // migration, the packet will still be retransimitted at the connection
+ // level.
+ socket_data.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true,
+ /*fin=*/true));
+ // A RESET will be sent to the peer to cancel the non-migratable stream.
socket_data.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -8264,7 +8505,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8284,9 +8525,10 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream. This should cause a write error, which triggers
// a connection migration attempt.
@@ -8303,7 +8545,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorNonMigratableStream(
// successfully; otherwise the connection is closed.
EXPECT_EQ(migrate_idle_sessions,
QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_EQ(migrate_idle_sessions, HasActiveSession(host_port_pair_));
+ EXPECT_EQ(migrate_idle_sessions, HasActiveSession(scheme_host_port_));
if (migrate_idle_sessions) {
EXPECT_TRUE(failed_socket_data.AllReadDataConsumed());
@@ -8353,7 +8595,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMigrationDisabled(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8372,9 +8614,9 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMigrationDisabled(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Set session config to have connection migration disabled.
quic::test::QuicConfigPeer::SetReceivedDisableConnectionMigration(
@@ -8391,7 +8633,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorMigrationDisabled(
base::RunLoop().RunUntilIdle();
// Migration fails, and session is closed and deleted.
EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
@@ -8406,9 +8648,21 @@ TEST_P(QuicStreamFactoryTest,
TestMigrationOnWriteErrorMigrationDisabled(ASYNC);
}
-// Sets up a test which verifies that connection migration on write error can
-// eventually succeed and rewrite the packet on the new network with singals
-// delivered in the following order (alternate network is always availabe):
+// For IETF QUIC, this test the following scenario:
+// - original network encounters a SYNC/ASYNC write error based on
+// |write_error_mode_on_old_network|, the packet failed to be written is
+// cached, session migrates immediately to the alternate network.
+// - an immediate SYNC/ASYNC write error based on
+// |write_error_mode_on_new_network| is encountered after migration to the
+// alternate network, session migrates immediately to the original network.
+// - After a new socket for the original network is created and starts to read,
+// connection migration fails due to lack of unused connection ID and
+// connection is closed.
+//
+// For gQUIC, sets up a test which verifies that connection migration on write
+// error can eventually succeed and rewrite the packet on the new network with
+// signals delivered in the following order (alternate network is always
+// available):
// - original network encounters a SYNC/ASYNC write error based on
// |write_error_mode_on_old_network|, the packet failed to be written is
// cached, session migrates immediately to the alternate network.
@@ -8446,60 +8700,53 @@ void QuicStreamFactoryTestBase::TestMigrationOnMultipleWriteErrors(
ERR_ADDRESS_UNREACHABLE); // Write Error
socket_data1.AddSocketDataToFactory(socket_factory_.get());
- // Set up the socket data used by the alternate network, which also
- // encounters a write error.
+ // Set up the socket data used by the alternate network, which
+ // - is not used to write as migration fails due to lack of connection ID.
+ // - encounters a write error in gQUIC.
MockQuicData failed_quic_data2(version_);
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
failed_quic_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
failed_quic_data2.AddWrite(write_error_mode_on_new_network, ERR_FAILED);
failed_quic_data2.AddSocketDataToFactory(socket_factory_.get());
- // Set up the third socket data used by original network, which encounters a
- // write error again.
+ // Set up the third socket data used by original network, which
+ // - encounters a write error again.
MockQuicData failed_quic_data1(version_);
failed_quic_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- failed_quic_data1.AddWrite(write_error_mode_on_old_network, ERR_FAILED);
+ if (!VersionUsesHttp3(version_.transport_version)) {
+ failed_quic_data1.AddWrite(write_error_mode_on_old_network, ERR_FAILED);
+ }
failed_quic_data1.AddSocketDataToFactory(socket_factory_.get());
- // Set up the last socket data used by the alternate network, which will
- // finish migration successfully. The request is rewritten to this new socket,
- // and the response to the request is read on this socket.
MockQuicData socket_data2(version_);
- socket_data2.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
- socket_data2.AddRead(
- ASYNC,
- ConstructOkResponsePacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
- socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
- if (VersionUsesHttp3(version_.transport_version)) {
- socket_data2.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, false));
- socket_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ if (!VersionUsesHttp3(version_.transport_version)) {
+ // Set up the last socket data used by the alternate network, which will
+ // finish migration successfully. The request is rewritten to this new
+ // socket, and the response to the request is read on this socket.
socket_data2.AddWrite(
SYNCHRONOUS,
- client_maker_.MakeRstPacket(
- packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
- quic::QUIC_STREAM_CANCELLED));
- } else {
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ true, true));
+ socket_data2.AddRead(
+ ASYNC,
+ ConstructOkResponsePacket(
+ 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
+ socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
socket_data2.AddWrite(
SYNCHRONOUS,
client_maker_.MakeAckAndRstPacket(
packet_num++, false, GetNthClientInitiatedBidirectionalStreamId(0),
quic::QUIC_STREAM_CANCELLED, 1, 1));
+ socket_data2.AddSocketDataToFactory(socket_factory_.get());
}
- socket_data2.AddSocketDataToFactory(socket_factory_.get());
// Create request and QuicHttpStream.
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8518,38 +8765,45 @@ void QuicStreamFactoryTestBase::TestMigrationOnMultipleWriteErrors(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
// This should encounter a write error on network 1,
// then migrate to network 2, which encounters another write error,
// and migrate again to network 1, which encoutners one more write error.
- // Finally the session migrates to network 2 successfully.
HttpResponseInfo response;
HttpRequestHeaders request_headers;
EXPECT_EQ(OK, stream->SendRequest(request_headers, &response,
callback_.callback()));
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_EQ(1u, session->GetNumActiveStreams());
+ if (VersionUsesHttp3(version_.transport_version)) {
+ // Connection is closed as there is no connection ID available yet for the
+ // second migration.
+ EXPECT_FALSE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ stream.reset();
+ } else {
+ EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
+ EXPECT_EQ(1u, session->GetNumActiveStreams());
- // Verify that response headers on the migrated socket were delivered to the
- // stream.
- EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
- EXPECT_EQ(200, response.headers->response_code());
+ // Verify that response headers on the migrated socket were delivered to the
+ // stream.
+ EXPECT_EQ(OK, stream->ReadResponseHeaders(callback_.callback()));
+ EXPECT_EQ(200, response.headers->response_code());
- stream.reset();
+ stream.reset();
+ EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+ EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
+ }
EXPECT_TRUE(socket_data1.AllReadDataConsumed());
EXPECT_TRUE(socket_data1.AllWriteDataConsumed());
EXPECT_TRUE(failed_quic_data2.AllReadDataConsumed());
EXPECT_TRUE(failed_quic_data2.AllWriteDataConsumed());
EXPECT_TRUE(failed_quic_data1.AllReadDataConsumed());
EXPECT_TRUE(failed_quic_data1.AllWriteDataConsumed());
- EXPECT_TRUE(socket_data2.AllReadDataConsumed());
- EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
}
TEST_P(QuicStreamFactoryTest, MigrateSessionOnMultipleWriteErrorsSyncSync) {
@@ -8595,7 +8849,7 @@ TEST_P(QuicStreamFactoryTest, NoMigrationBeforeHandshakeOnNetworkDisconnected) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8606,8 +8860,8 @@ TEST_P(QuicStreamFactoryTest, NoMigrationBeforeHandshakeOnNetworkDisconnected) {
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
EXPECT_EQ(ERR_NETWORK_CHANGED, callback_.WaitForResult());
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_FALSE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_FALSE(HasActiveJob(scheme_host_port_, privacy_mode_));
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
}
@@ -8638,7 +8892,7 @@ void QuicStreamFactoryTestBase::
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8657,23 +8911,42 @@ void QuicStreamFactoryTestBase::
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false, /*fin=*/true);
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, true));
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true));
}
socket_data1.AddRead(
ASYNC,
@@ -8682,9 +8955,11 @@ void QuicStreamFactoryTestBase::
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -8719,7 +8994,7 @@ void QuicStreamFactoryTestBase::
// Verify the session is still alive and not marked as going away post
// migration.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -8795,7 +9070,7 @@ void QuicStreamFactoryTestBase::
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8814,23 +9089,42 @@ void QuicStreamFactoryTestBase::
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
- if (version_.UsesHttp3()) {
+ if (!version_.UsesHttp3()) {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true));
+ } else {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false, /*fin=*/true);
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, true));
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
}
socket_data1.AddRead(
ASYNC,
@@ -8839,9 +9133,11 @@ void QuicStreamFactoryTestBase::
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -8877,7 +9173,7 @@ void QuicStreamFactoryTestBase::
base::RunLoop().RunUntilIdle();
// Verify session is still alive and not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -8958,7 +9254,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -8977,9 +9273,12 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -8989,30 +9288,49 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
// The connection should still be alive, not marked as going away.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
// Set up second socket data provider that is used after migration.
// The response to the earlier request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false, /*fin=*/true);
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- socket_data1.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, false));
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeRetransmissionAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*original_packet_numbers=*/{1, 2},
+ /*sequence_number=*/0u));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -9039,7 +9357,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
// Ensure that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Run the message loop migration for write error can finish.
@@ -9051,7 +9369,7 @@ void QuicStreamFactoryTestBase::TestMigrationOnWriteErrorPauseBeforeConnected(
// Check that the session is still alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// There should be no posted tasks not executed, no way to migrate back to
// default network.
@@ -9113,7 +9431,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreWriteErrorFromOldWriterAfterMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9132,21 +9450,29 @@ TEST_P(QuicStreamFactoryTest, IgnoreWriteErrorFromOldWriterAfterMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The response to the request is read on this new socket.
MockQuicData socket_data1(version_);
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
{1, 2}, packet_num++, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- socket_data1.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -9154,9 +9480,11 @@ TEST_P(QuicStreamFactoryTest, IgnoreWriteErrorFromOldWriterAfterMigration) {
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -9192,7 +9520,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreWriteErrorFromOldWriterAfterMigration) {
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -9240,7 +9568,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9259,26 +9587,40 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is written to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
1, packet_num++, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
socket_data1.AddWrite(
SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
- socket_data1.AddWrite(
- SYNCHRONOUS,
ConstructGetRequestPacket(packet_num++,
GetNthClientInitiatedBidirectionalStreamId(0),
true, true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/true, /*sequence_number=*/0u));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -9286,9 +9628,11 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) {
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -9318,7 +9662,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) {
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -9338,7 +9682,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorFromOldReaderAfterMigration) {
socket_data.Resume();
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -9377,7 +9721,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9396,26 +9740,40 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is written to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
1, packet_num++, true));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
socket_data1.AddWrite(
SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
- socket_data1.AddWrite(
- SYNCHRONOUS,
ConstructGetRequestPacket(packet_num++,
GetNthClientInitiatedBidirectionalStreamId(0),
true, true));
+ if (version_.UsesHttp3()) {
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -9423,9 +9781,11 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) {
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -9455,7 +9815,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) {
socket_data.Resume();
EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Complete migration.
@@ -9463,7 +9823,7 @@ TEST_P(QuicStreamFactoryTest, IgnoreReadErrorOnOldReaderDuringMigration) {
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -9502,11 +9862,19 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
factory_.get(), std::make_unique<QuicChromiumAlarmFactory>(
task_runner.get(), context_.clock()));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
MockQuicData socket_data(version_);
int packet_num = 1;
+ int peer_packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(SYNCHRONOUS,
ConstructInitialSettingsPacket(packet_num++));
+ socket_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false,
+ cid_on_new_path,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
}
socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
@@ -9516,14 +9884,23 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
// migration. The request is written to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
-
if (version_.UsesHttp3()) {
- socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
- 1, packet_num++, true));
+ client_maker_.set_connection_id(cid_on_new_path);
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetransmissionPacket(
+ packet_num++, /*first_received=*/1,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ /*original_packet_numbers=*/{1}));
}
// The PING packet sent post migration.
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, true));
+ if (version_.UsesHttp3()) {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ }
socket_data1.AddWrite(
SYNCHRONOUS,
ConstructGetRequestPacket(packet_num++,
@@ -9532,18 +9909,19 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
// Read two packets so that client will send ACK immediately.
socket_data1.AddRead(
- ASYNC,
- ConstructOkResponsePacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
- socket_data1.AddRead(
- ASYNC, server_maker_.MakeDataPacket(
- 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
- "Hello World"));
+ ASYNC, ConstructOkResponsePacket(
+ peer_packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0), false, false));
+ socket_data1.AddRead(ASYNC, server_maker_.MakeDataPacket(
+ peer_packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ false, false, "Hello World"));
// Read an ACK from server which acks all client data.
- socket_data1.AddRead(SYNCHRONOUS,
- server_maker_.MakeAckPacket(3, packet_num, 1));
- socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1));
+ socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(
+ peer_packet_num++, packet_num, 1));
+ socket_data1.AddWrite(
+ ASYNC, client_maker_.MakeAckPacket(packet_num++, peer_packet_num - 2, 1));
// The PING packet sent for retransmittable on wire.
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, false));
@@ -9571,7 +9949,7 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9590,8 +9968,8 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Now notify network is disconnected, cause the migration to complete
// immediately.
@@ -9601,7 +9979,7 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -9613,20 +9991,10 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(kDefaultRetransmittableOnWireTimeout, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
// Fire the ping alarm with retransmittable-on-wire timeout, send PING.
- delay = kDefaultRetransmittableOnWireTimeout - delay;
- EXPECT_EQ(delay, task_runner->NextPendingTaskDelay());
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(
+ kDefaultRetransmittableOnWireTimeout.InMilliseconds()));
+ task_runner->FastForwardBy(kDefaultRetransmittableOnWireTimeout);
socket_data1.Resume();
@@ -9639,7 +10007,7 @@ TEST_P(QuicStreamFactoryTest, DefaultRetransmittableOnWireTimeoutForMigration) {
// packet reader. Verify that the session is not affected.
socket_data.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -9670,11 +10038,19 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
factory_.get(), std::make_unique<QuicChromiumAlarmFactory>(
task_runner.get(), context_.clock()));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
MockQuicData socket_data(version_);
int packet_num = 1;
+ int peer_packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
socket_data.AddWrite(SYNCHRONOUS,
ConstructInitialSettingsPacket(packet_num++));
+ socket_data.AddRead(ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false,
+ cid_on_new_path,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
}
socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause
socket_data.AddRead(ASYNC, ERR_ADDRESS_UNREACHABLE);
@@ -9685,12 +10061,22 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
if (version_.UsesHttp3()) {
- socket_data1.AddWrite(SYNCHRONOUS, client_maker_.MakeRetransmissionPacket(
- 1, packet_num++, true));
+ client_maker_.set_connection_id(cid_on_new_path);
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetransmissionPacket(
+ packet_num++, /*first_received=*/1,
+ /*largest_received=*/1, /*smallest_received=*/1,
+ /*original_packet_numbers=*/{1}));
}
// The PING packet sent post migration.
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, true));
+ if (version_.UsesHttp3()) {
+ socket_data1.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
+ }
socket_data1.AddWrite(
SYNCHRONOUS,
ConstructGetRequestPacket(packet_num++,
@@ -9699,17 +10085,18 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
socket_data1.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
// Read two packets so that client will send ACK immedaitely.
socket_data1.AddRead(
- ASYNC,
- ConstructOkResponsePacket(
- 1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
- socket_data1.AddRead(
- ASYNC, server_maker_.MakeDataPacket(
- 2, GetNthClientInitiatedBidirectionalStreamId(0), false, false,
- "Hello World"));
+ ASYNC, ConstructOkResponsePacket(
+ peer_packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0), false, false));
+ socket_data1.AddRead(ASYNC, server_maker_.MakeDataPacket(
+ peer_packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false, /*fin=*/false, "Hello World"));
// Read an ACK from server which acks all client data.
- socket_data1.AddRead(SYNCHRONOUS,
- server_maker_.MakeAckPacket(3, packet_num, 1));
- socket_data1.AddWrite(ASYNC, client_maker_.MakeAckPacket(packet_num++, 2, 1));
+ socket_data1.AddRead(SYNCHRONOUS, server_maker_.MakeAckPacket(
+ peer_packet_num++, packet_num, 1));
+ socket_data1.AddWrite(
+ ASYNC, client_maker_.MakeAckPacket(packet_num++, peer_packet_num - 2, 1));
// The PING packet sent for retransmittable on wire.
socket_data1.AddWrite(SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, false));
@@ -9737,7 +10124,7 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9756,8 +10143,8 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Now notify network is disconnected, cause the migration to complete
// immediately.
@@ -9767,7 +10154,7 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -9779,20 +10166,10 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(custom_timeout_value, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
// Fire the ping alarm with retransmittable-on-wire timeout, send PING.
- delay = custom_timeout_value - delay;
- EXPECT_EQ(delay, task_runner->NextPendingTaskDelay());
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(
+ custom_timeout_value.InMilliseconds()));
+ task_runner->FastForwardBy(custom_timeout_value);
socket_data1.Resume();
@@ -9805,7 +10182,7 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeoutForMigration) {
// packet reader. Verify that the session is not affected.
socket_data.Resume();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -9885,7 +10262,7 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -9904,13 +10281,13 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -9922,20 +10299,10 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) {
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(custom_timeout_value, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
// Fire the ping alarm with retransmittable-on-wire timeout, send PING.
- delay = custom_timeout_value - delay;
- EXPECT_EQ(delay, task_runner->NextPendingTaskDelay());
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(
+ custom_timeout_value.InMilliseconds()));
+ task_runner->FastForwardBy(custom_timeout_value);
socket_data1.Resume();
@@ -9947,7 +10314,7 @@ TEST_P(QuicStreamFactoryTest, CustomRetransmittableOnWireTimeout) {
// Resume the old socket data, a read error will be delivered to the old
// packet reader. Verify that the session is not affected.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -10027,7 +10394,7 @@ TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10046,13 +10413,13 @@ TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -10064,21 +10431,15 @@ TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) {
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(kDefaultRetransmittableOnWireTimeout, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
- // Verify that the ping alarm is not set with any default value.
- base::TimeDelta wrong_delay = kDefaultRetransmittableOnWireTimeout - delay;
- delay = task_runner->NextPendingTaskDelay();
- EXPECT_NE(wrong_delay, delay);
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ // Verify the ping alarm is set, but not with the default timeout.
+ const quic::QuicAlarm* const ping_alarm =
+ quic::test::QuicConnectionPeer::GetPingAlarm(session->connection());
+ ASSERT_TRUE(ping_alarm);
+ ASSERT_TRUE(ping_alarm->IsSet());
+ quic::QuicTime::Delta delay =
+ ping_alarm->deadline() - context_.clock()->ApproximateNow();
+ EXPECT_NE(kDefaultRetransmittableOnWireTimeout.InMilliseconds(),
+ delay.ToMilliseconds());
// Verify that response headers on the migrated socket were delivered to the
// stream.
@@ -10088,7 +10449,7 @@ TEST_P(QuicStreamFactoryTest, NoRetransmittableOnWireTimeout) {
// Resume the old socket data, a read error will be delivered to the old
// packet reader. Verify that the session is not affected.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -10168,7 +10529,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10187,13 +10548,13 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -10205,20 +10566,10 @@ TEST_P(QuicStreamFactoryTest,
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(custom_timeout_value, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
// Fire the ping alarm with retransmittable-on-wire timeout, send PING.
- delay = custom_timeout_value - delay;
- EXPECT_EQ(delay, task_runner->NextPendingTaskDelay());
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ context_.AdvanceTime(quic::QuicTime::Delta::FromMilliseconds(
+ custom_timeout_value.InMilliseconds()));
+ task_runner->FastForwardBy(custom_timeout_value);
socket_data1.Resume();
@@ -10230,7 +10581,7 @@ TEST_P(QuicStreamFactoryTest,
// Resume the old socket data, a read error will be delivered to the old
// packet reader. Verify that the session is not affected.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -10312,7 +10663,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10331,13 +10682,13 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Complete migration.
task_runner->RunUntilIdle();
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Send GET request on stream.
@@ -10349,21 +10700,15 @@ TEST_P(QuicStreamFactoryTest,
// Spin up the message loop to read incoming data from server till the ACK.
base::RunLoop().RunUntilIdle();
- // Ack delay time.
- base::TimeDelta delay = task_runner->NextPendingTaskDelay();
- EXPECT_GT(kDefaultRetransmittableOnWireTimeout, delay);
- // Fire the ack alarm, since ack has been sent, no ack will be sent.
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
-
- // Verify the ping alarm is not set with default value.
- base::TimeDelta wrong_delay = kDefaultRetransmittableOnWireTimeout - delay;
- delay = task_runner->NextPendingTaskDelay();
- EXPECT_NE(wrong_delay, delay);
- context_.AdvanceTime(
- quic::QuicTime::Delta::FromMilliseconds(delay.InMilliseconds()));
- task_runner->FastForwardBy(task_runner->NextPendingTaskDelay());
+ // Verify the ping alarm is set, but not with the default timeout.
+ const quic::QuicAlarm* const ping_alarm =
+ quic::test::QuicConnectionPeer::GetPingAlarm(session->connection());
+ ASSERT_TRUE(ping_alarm);
+ ASSERT_TRUE(ping_alarm->IsSet());
+ quic::QuicTime::Delta delay =
+ ping_alarm->deadline() - context_.clock()->ApproximateNow();
+ EXPECT_NE(kDefaultRetransmittableOnWireTimeout.InMilliseconds(),
+ delay.ToMilliseconds());
// Verify that response headers on the migrated socket were delivered to the
// stream.
@@ -10373,7 +10718,7 @@ TEST_P(QuicStreamFactoryTest,
// Resume the old socket data, a read error will be delivered to the old
// packet reader. Verify that the session is not affected.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
stream.reset();
@@ -10411,7 +10756,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10430,22 +10775,32 @@ TEST_P(QuicStreamFactoryTest,
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Set up second socket data provider that is used after
// migration. The request is written to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
if (version_.UsesHttp3()) {
- socket_data1.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, true));
+ client_maker_.set_connection_id(cid_on_new_path);
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true);
+ socket_data1.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true));
}
socket_data1.AddRead(
ASYNC,
@@ -10468,7 +10823,7 @@ TEST_P(QuicStreamFactoryTest,
// Verify session is not closed with read error.
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Complete migration.
@@ -10477,7 +10832,7 @@ TEST_P(QuicStreamFactoryTest,
// default network.
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Verify that response headers on the migrated socket were delivered to the
@@ -10527,7 +10882,7 @@ TEST_P(QuicStreamFactoryTest,
SYNCHRONOUS, /*disconnect_before_connect*/ true);
}
-// Setps up test which verifies that session successfully migrate to alternate
+// Sets up test which verifies that session successfully migrate to alternate
// network with signals delivered in the following order:
// *NOTE* Signal (A) and (B) can reverse order based on
// |disconnect_before_connect|.
@@ -10565,7 +10920,7 @@ void QuicStreamFactoryTestBase::
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10584,9 +10939,12 @@ void QuicStreamFactoryTestBase::
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream. This should cause a write error, which triggers
// a connection migration attempt.
@@ -10601,7 +10959,7 @@ void QuicStreamFactoryTestBase::
// In this particular code path, the network will not yet be marked
// as going away and the session will still be alive.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
EXPECT_EQ(ERR_IO_PENDING, stream->ReadResponseHeaders(callback_.callback()));
@@ -10609,23 +10967,41 @@ void QuicStreamFactoryTestBase::
// migration. The request is rewritten to this new socket, and the
// response to the request is read on this new socket.
MockQuicData socket_data1(version_);
- socket_data1.AddWrite(
- SYNCHRONOUS,
- ConstructGetRequestPacket(packet_num++,
- GetNthClientInitiatedBidirectionalStreamId(0),
- true, true));
+ if (VersionUsesHttp3(version_.transport_version)) {
+ client_maker_.set_connection_id(cid_on_new_path);
+ // Increment packet number to account for packet write error on the old
+ // path. Also save the packet in client_maker_ for constructing the
+ // retransmission packet.
+ ConstructGetRequestPacket(packet_num++,
+ GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/false, /*fin=*/true);
+ } else {
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ ConstructGetRequestPacket(
+ packet_num++, GetNthClientInitiatedBidirectionalStreamId(0),
+ /*should_include_version=*/true, /*fin=*/true));
+ }
socket_data1.AddRead(
ASYNC,
ConstructOkResponsePacket(
1, GetNthClientInitiatedBidirectionalStreamId(0), false, false));
socket_data1.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
- socket_data1.AddWrite(ASYNC, client_maker_.MakeCombinedRetransmissionPacket(
- {1, 2}, packet_num++, false));
+ socket_data1.AddWrite(ASYNC,
+ client_maker_.MakeCombinedRetransmissionPacket(
+ /*original_packet_numbers=*/{1, 2}, packet_num++,
+ /*should_include_version=*/false));
socket_data1.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ socket_data1.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data1.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -10661,7 +11037,7 @@ void QuicStreamFactoryTestBase::
->NotifyNetworkDisconnected(kDefaultNetworkForTests);
}
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// This is the callback for the response headers that returned
@@ -10677,7 +11053,7 @@ void QuicStreamFactoryTestBase::
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10685,8 +11061,8 @@ void QuicStreamFactoryTestBase::
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2.get());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
- EXPECT_EQ(session, GetActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ EXPECT_EQ(session, GetActiveSession(scheme_host_port_));
stream.reset();
stream2.reset();
@@ -10715,7 +11091,23 @@ TEST_P(QuicStreamFactoryTest, DefaultIdleMigrationPeriod) {
QuicStreamFactoryPeer::SetTickClock(factory_.get(),
task_runner->GetMockTickClock());
+ quic::QuicConnectionId cid1 = quic::test::TestConnectionId(1234567);
+ quic::QuicConnectionId cid2 = quic::test::TestConnectionId(2345671);
+ quic::QuicConnectionId cid3 = quic::test::TestConnectionId(3456712);
+ quic::QuicConnectionId cid4 = quic::test::TestConnectionId(4567123);
+ quic::QuicConnectionId cid5 = quic::test::TestConnectionId(5671234);
+ quic::QuicConnectionId cid6 = quic::test::TestConnectionId(6712345);
+ quic::QuicConnectionId cid7 = quic::test::TestConnectionId(7123456);
+
+ int peer_packet_num = 1;
MockQuicData default_socket_data(version_);
+ if (version_.UsesHttp3()) {
+ default_socket_data.AddRead(
+ SYNCHRONOUS, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid1,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
+ }
default_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
int packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
@@ -10726,16 +11118,102 @@ TEST_P(QuicStreamFactoryTest, DefaultIdleMigrationPeriod) {
// Set up second socket data provider that is used after migration.
MockQuicData alternate_socket_data(version_);
- alternate_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid1);
+ alternate_socket_data.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetransmissionPacket(
+ packet_num++,
+ /*first_received=*/1,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*original_packet_numbers=*/{1}));
+ alternate_socket_data.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ alternate_socket_data.AddWrite(
+ ASYNC,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid2,
+ /*sequence_number=*/2u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/2u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid3,
+ /*sequence_number=*/3u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/3u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid4,
+ /*sequence_number=*/4u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/4u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid5,
+ /*sequence_number=*/5u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/5u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid6,
+ /*sequence_number=*/6u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/6u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid7,
+ /*sequence_number=*/7u,
+ /*retire_prior_to=*/1u));
+ alternate_socket_data.AddRead(SYNCHRONOUS,
+ ERR_IO_PENDING); // Hanging read.
+ } else {
+ alternate_socket_data.AddRead(SYNCHRONOUS,
+ ERR_IO_PENDING); // Hanging read.
+ // Ping packet to send after migration.
alternate_socket_data.AddWrite(
SYNCHRONOUS,
- client_maker_.MakeRetransmissionPacket(1, packet_num++, true));
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- // Ping packet to send after migration.
- alternate_socket_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
// Set up probing socket for migrating back to the default network.
@@ -10773,7 +11251,7 @@ TEST_P(QuicStreamFactoryTest, DefaultIdleMigrationPeriod) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10783,7 +11261,7 @@ TEST_P(QuicStreamFactoryTest, DefaultIdleMigrationPeriod) {
EXPECT_TRUE(stream.get());
// Ensure that session is active.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Trigger connection migration. Since there are no active streams,
// the session will be closed.
@@ -10815,7 +11293,13 @@ TEST_P(QuicStreamFactoryTest, DefaultIdleMigrationPeriod) {
// Retry migrate back in 1, 2, 4, 8, 16s.
// Session will be closed due to idle migration timeout.
for (int i = 0; i < 5; i++) {
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ if (version_.UsesHttp3()) {
+ // Fire retire connection ID alarm.
+ base::RunLoop().RunUntilIdle();
+ // Make new connection ID available.
+ alternate_socket_data.Resume();
+ }
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// A task is posted to migrate back to the default network in 2^i seconds.
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_EQ(base::TimeDelta::FromSeconds(UINT64_C(1) << i),
@@ -10846,7 +11330,22 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
QuicStreamFactoryPeer::SetTickClock(factory_.get(),
task_runner->GetMockTickClock());
+ quic::QuicConnectionId cid1 = quic::test::TestConnectionId(1234567);
+ quic::QuicConnectionId cid2 = quic::test::TestConnectionId(2345671);
+ quic::QuicConnectionId cid3 = quic::test::TestConnectionId(3456712);
+ quic::QuicConnectionId cid4 = quic::test::TestConnectionId(4567123);
+ quic::QuicConnectionId cid5 = quic::test::TestConnectionId(5671234);
+ quic::QuicConnectionId cid6 = quic::test::TestConnectionId(6712345);
+
+ int peer_packet_num = 1;
MockQuicData default_socket_data(version_);
+ if (version_.UsesHttp3()) {
+ default_socket_data.AddRead(
+ SYNCHRONOUS,
+ server_maker_.MakeNewConnectionIdPacket(peer_packet_num++, true, cid1,
+ /*sequence_number=*/1u,
+ /*retire_prior_to=*/0u));
+ }
default_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
int packet_num = 1;
if (VersionUsesHttp3(version_.transport_version)) {
@@ -10857,16 +11356,76 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
// Set up second socket data provider that is used after migration.
MockQuicData alternate_socket_data(version_);
- alternate_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read.
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid1);
+ alternate_socket_data.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeAckAndRetransmissionPacket(
+ packet_num++,
+ /*first_received=*/1,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*original_packet_numbers=*/{1}));
+ alternate_socket_data.AddWrite(
+ SYNCHRONOUS,
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/false));
+ alternate_socket_data.AddWrite(
+ ASYNC,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false, /*sequence_number=*/0u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid2,
+ /*sequence_number=*/2u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/2u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid3,
+ /*sequence_number=*/3u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/3u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid4,
+ /*sequence_number=*/4u,
+ /*retire_prior_to=*/1u));
+ ++packet_num; // Probing packet on default network encounters write error.
+ alternate_socket_data.AddWrite(
+ ASYNC, client_maker_.MakeAckAndRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*largest_received=*/peer_packet_num - 1,
+ /*smallest_received=*/1,
+ /*sequence_number=*/4u));
+ alternate_socket_data.AddRead(ASYNC, ERR_IO_PENDING); // Pause.
+ alternate_socket_data.AddRead(
+ ASYNC, server_maker_.MakeNewConnectionIdPacket(
+ peer_packet_num++, /*include_version=*/false, cid5,
+ /*sequence_number=*/5u,
+ /*retire_prior_to=*/1u));
+ alternate_socket_data.AddRead(SYNCHRONOUS,
+ ERR_IO_PENDING); // Hanging read.
+ } else {
+ alternate_socket_data.AddRead(SYNCHRONOUS, ERR_IO_PENDING); // Hanging read
+ // Ping packet to send after migration.
alternate_socket_data.AddWrite(
SYNCHRONOUS,
- client_maker_.MakeRetransmissionPacket(1, packet_num++, true));
+ client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
}
- // Ping packet to send after migration.
- alternate_socket_data.AddWrite(
- SYNCHRONOUS,
- client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
alternate_socket_data.AddSocketDataToFactory(socket_factory_.get());
// Set up probing socket for migrating back to the default network.
@@ -10899,7 +11458,7 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -10909,7 +11468,7 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
EXPECT_TRUE(stream.get());
// Ensure that session is active.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Trigger connection migration. Since there are no active streams,
// the session will be closed.
@@ -10941,7 +11500,13 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
// Retry migrate back in 1, 2, 4, 8s.
// Session will be closed due to idle migration timeout.
for (int i = 0; i < 4; i++) {
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ if (version_.UsesHttp3()) {
+ // Fire retire connection ID alarm.
+ base::RunLoop().RunUntilIdle();
+ // Make new connection ID available.
+ alternate_socket_data.Resume();
+ }
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// A task is posted to migrate back to the default network in 2^i seconds.
EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
EXPECT_EQ(base::TimeDelta::FromSeconds(UINT64_C(1) << i),
@@ -10957,6 +11522,7 @@ TEST_P(QuicStreamFactoryTest, CustomIdleMigrationPeriod) {
TEST_P(QuicStreamFactoryTest, ServerMigration) {
quic_params_->allow_server_migration = true;
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -10982,7 +11548,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11001,9 +11567,12 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
+ quic::QuicConnectionId cid_on_new_path =
+ quic::test::TestConnectionId(12345678);
+ MaybeMakeNewConnectionIdAvailableToSession(cid_on_new_path, session);
// Send GET request on stream.
HttpResponseInfo response;
@@ -11021,6 +11590,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
// response to the request is read on this new socket.
MockQuicData socket_data2(version_);
if (version_.UsesHttp3()) {
+ client_maker_.set_connection_id(cid_on_new_path);
socket_data2.AddWrite(SYNCHRONOUS,
client_maker_.MakeCombinedRetransmissionPacket(
{1, 2}, packet_num++, true));
@@ -11028,6 +11598,12 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
socket_data2.AddWrite(
SYNCHRONOUS,
client_maker_.MakePingPacket(packet_num++, /*include_version=*/true));
+ if (version_.UsesHttp3()) {
+ socket_data2.AddWrite(SYNCHRONOUS,
+ client_maker_.MakeRetireConnectionIdPacket(
+ packet_num++, /*include_version=*/false,
+ /*sequence_number=*/0u));
+ }
socket_data2.AddRead(
ASYNC,
ConstructOkResponsePacket(
@@ -11035,9 +11611,11 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
socket_data2.AddRead(SYNCHRONOUS, ERR_IO_PENDING);
if (VersionUsesHttp3(version_.transport_version)) {
socket_data2.AddWrite(
- SYNCHRONOUS, client_maker_.MakeAckAndDataPacket(
- packet_num++, false, GetQpackDecoderStreamId(), 1, 1,
- false, StreamCancellationQpackDecoderInstruction(0)));
+ SYNCHRONOUS,
+ client_maker_.MakeDataPacket(
+ packet_num++, GetQpackDecoderStreamId(),
+ /*should_include_version=*/false,
+ /*fin=*/false, StreamCancellationQpackDecoderInstruction(0)));
socket_data2.AddWrite(
SYNCHRONOUS,
client_maker_.MakeRstPacket(
@@ -11063,7 +11641,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigration) {
// The session should be alive and active.
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_EQ(1u, session->GetNumActiveStreams());
// Run the message loop so that data queued in the new socket is read by the
@@ -11087,19 +11665,35 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv4) {
// Add alternate IPv4 server address to config.
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123);
quic::QuicConfig config;
- config.SetIPv4AlternateServerAddressToSend(ToQuicSocketAddress(alt_address));
+ if (version_.UsesHttp3()) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ config.SetIPv4AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address), kNewCID,
+ quic::QuicUtils::GenerateStatelessResetToken(kNewCID));
+ } else {
+ config.SetIPv4AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address));
+ }
VerifyServerMigration(config, alt_address);
}
TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv6) {
// Add a resolver rule to make initial connection to an IPv6 address.
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"fe80::aebc:32ff:febb:1e33", "");
// Add alternate IPv6 server address to config.
IPEndPoint alt_address = IPEndPoint(
IPAddress(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16), 123);
quic::QuicConfig config;
- config.SetIPv6AlternateServerAddressToSend(ToQuicSocketAddress(alt_address));
+ if (version_.UsesHttp3()) {
+ SetIetfConnectionMigrationFlagsAndConnectionOptions();
+ config.SetIPv6AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address), kNewCID,
+ quic::QuicUtils::GenerateStatelessResetToken(kNewCID));
+ } else {
+ config.SetIPv6AlternateServerAddressToSend(
+ ToQuicSocketAddress(alt_address));
+ }
VerifyServerMigration(config, alt_address);
}
@@ -11108,7 +11702,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4Fails) {
Initialize();
// Add a resolver rule to make initial connection to an IPv6 address.
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"fe80::aebc:32ff:febb:1e33", "");
// Add alternate IPv4 server address to config.
IPEndPoint alt_address = IPEndPoint(IPAddress(1, 2, 3, 4), 123);
@@ -11144,7 +11738,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4Fails) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11163,9 +11757,9 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv6ToIPv4Fails) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
IPEndPoint actual_address;
session->GetDefaultSocket()->GetPeerAddress(&actual_address);
@@ -11190,7 +11784,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
Initialize();
// Add a resolver rule to make initial connection to an IPv4 address.
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(), "1.2.3.4",
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(), "1.2.3.4",
"");
// Add alternate IPv6 server address to config.
IPEndPoint alt_address = IPEndPoint(
@@ -11227,7 +11821,7 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11246,9 +11840,9 @@ TEST_P(QuicStreamFactoryTest, ServerMigrationIPv4ToIPv6Fails) {
net_log_, CompletionOnceCallback()));
// Ensure that session is alive and active.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
IPEndPoint actual_address;
session->GetDefaultSocket()->GetPeerAddress(&actual_address);
@@ -11288,7 +11882,7 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11297,14 +11891,14 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream);
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
// Change the CA cert and verify that stream saw the event.
factory_->OnCertDBChanged();
EXPECT_TRUE(factory_->is_quic_known_to_work_on_current_network());
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
// Now attempting to request a stream to the same origin should create
// a new session.
@@ -11312,7 +11906,7 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11321,8 +11915,8 @@ TEST_P(QuicStreamFactoryTest, OnCertDBChanged) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
std::unique_ptr<HttpStream> stream2 = CreateStream(&request2);
EXPECT_TRUE(stream2);
- QuicChromiumClientSession* session2 = GetActiveSession(host_port_pair_);
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ QuicChromiumClientSession* session2 = GetActiveSession(scheme_host_port_);
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
EXPECT_NE(session, session2);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session2));
@@ -11349,14 +11943,14 @@ TEST_P(QuicStreamFactoryTest, SharedCryptoConfig) {
r1_host_name.append(cannoncial_suffixes[i]);
r2_host_name.append(cannoncial_suffixes[i]);
- HostPortPair host_port_pair1(r1_host_name, 80);
+ url::SchemeHostPort scheme_host_port1(url::kHttpsScheme, r1_host_name, 80);
// Need to hold onto this through the test, to keep the
// QuicCryptoClientConfig alive.
std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_handle =
QuicStreamFactoryPeer::GetCryptoConfig(factory_.get(),
NetworkIsolationKey());
- quic::QuicServerId server_id1(host_port_pair1.host(),
- host_port_pair1.port(), privacy_mode_);
+ quic::QuicServerId server_id1(scheme_host_port1.host(),
+ scheme_host_port1.port(), privacy_mode_);
quic::QuicCryptoClientConfig::CachedState* cached1 =
crypto_config_handle->GetConfig()->LookupOrCreate(server_id1);
EXPECT_FALSE(cached1->proof_valid());
@@ -11367,9 +11961,9 @@ TEST_P(QuicStreamFactoryTest, SharedCryptoConfig) {
cached1->set_source_address_token(r1_host_name);
cached1->SetProofValid();
- HostPortPair host_port_pair2(r2_host_name, 80);
- quic::QuicServerId server_id2(host_port_pair2.host(),
- host_port_pair2.port(), privacy_mode_);
+ url::SchemeHostPort scheme_host_port2(url::kHttpsScheme, r2_host_name, 80);
+ quic::QuicServerId server_id2(scheme_host_port2.host(),
+ scheme_host_port2.port(), privacy_mode_);
quic::QuicCryptoClientConfig::CachedState* cached2 =
crypto_config_handle->GetConfig()->LookupOrCreate(server_id2);
EXPECT_EQ(cached1->source_address_token(), cached2->source_address_token());
@@ -11389,14 +11983,14 @@ TEST_P(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
r3_host_name.append(cannoncial_suffixes[i]);
r4_host_name.append(cannoncial_suffixes[i]);
- HostPortPair host_port_pair1(r3_host_name, 80);
+ url::SchemeHostPort scheme_host_port1(url::kHttpsScheme, r3_host_name, 80);
// Need to hold onto this through the test, to keep the
// QuicCryptoClientConfig alive.
std::unique_ptr<QuicCryptoClientConfigHandle> crypto_config_handle =
QuicStreamFactoryPeer::GetCryptoConfig(factory_.get(),
NetworkIsolationKey());
- quic::QuicServerId server_id1(host_port_pair1.host(),
- host_port_pair1.port(), privacy_mode_);
+ quic::QuicServerId server_id1(scheme_host_port1.host(),
+ scheme_host_port1.port(), privacy_mode_);
quic::QuicCryptoClientConfig::CachedState* cached1 =
crypto_config_handle->GetConfig()->LookupOrCreate(server_id1);
EXPECT_FALSE(cached1->proof_valid());
@@ -11407,9 +12001,9 @@ TEST_P(QuicStreamFactoryTest, CryptoConfigWhenProofIsInvalid) {
cached1->set_source_address_token(r3_host_name);
cached1->SetProofInvalid();
- HostPortPair host_port_pair2(r4_host_name, 80);
- quic::QuicServerId server_id2(host_port_pair2.host(),
- host_port_pair2.port(), privacy_mode_);
+ url::SchemeHostPort scheme_host_port2(url::kHttpsScheme, r4_host_name, 80);
+ quic::QuicServerId server_id2(scheme_host_port2.host(),
+ scheme_host_port2.port(), privacy_mode_);
quic::QuicCryptoClientConfig::CachedState* cached2 =
crypto_config_handle->GetConfig()->LookupOrCreate(server_id2);
EXPECT_NE(cached1->source_address_token(), cached2->source_address_token());
@@ -11436,13 +12030,13 @@ TEST_P(QuicStreamFactoryTest, EnableNotLoadFromDiskCache) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -11480,12 +12074,13 @@ TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) {
socket_data2.AddWrite(SYNCHRONOUS, ConstructInitialSettingsPacket());
socket_data2.AddSocketDataToFactory(socket_factory_.get());
- HostPortPair server2(kServer2HostName, kDefaultServerPort);
+ url::SchemeHostPort server2(url::kHttpsScheme, kServer2HostName,
+ kDefaultServerPort);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::CONFIRM_HANDSHAKE);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
host_resolver_->rules()->AddIPLiteralRule(server2.host(), "192.168.0.1", "");
@@ -11496,13 +12091,13 @@ TEST_P(QuicStreamFactoryTest, ReducePingTimeoutOnConnectionTimeOutOpenStreams) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(quic::QuicTime::Delta::FromSeconds(quic::kPingTimeoutSecs),
session->connection()->ping_timeout());
@@ -11839,7 +12434,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamFactoryPeer::SetTaskRunner(factory_.get(), runner_.get());
const AlternativeService alternative_service1(
- kProtoQUIC, host_port_pair_.host(), host_port_pair_.port());
+ kProtoQUIC, scheme_host_port_.host(), scheme_host_port_.port());
AlternativeServiceInfoVector alternative_service_info_vector;
base::Time expiration = base::Time::Now() + base::TimeDelta::FromDays(1);
alternative_service_info_vector.push_back(
@@ -11904,9 +12499,11 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
int rv = request.Request(
- HostPortPair(kDefaultServerHostName, kDefaultServerPort), version_,
- privacy_mode_, DEFAULT_PRIORITY, SocketTag(), network_isolation_keys[i],
- SecureDnsPolicy::kAllow, true /* use_dns_aliases */,
+ url::SchemeHostPort(url::kHttpsScheme, kDefaultServerHostName,
+ kDefaultServerPort),
+ version_, privacy_mode_, DEFAULT_PRIORITY, SocketTag(),
+ network_isolation_keys[i], SecureDnsPolicy::kAllow,
+ true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback());
EXPECT_THAT(callback_.GetResult(rv), IsOk());
@@ -11954,7 +12551,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
// Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading
@@ -11966,7 +12563,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterPackets) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12007,7 +12604,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
"192.168.0.1", "");
// Set up the TaskObserver to verify QuicChromiumPacketReader::StartReading
@@ -12019,7 +12616,7 @@ TEST_P(QuicStreamFactoryTest, YieldAfterDuration) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(OK,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12055,7 +12652,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushSessionAffinity) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12069,7 +12666,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushSessionAffinity) {
string url = "https://www.example.org/";
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
quic::QuicClientPromisedInfo promised(
session, GetNthServerInitiatedUnidirectionalStreamId(0), kDefaultUrl);
@@ -12078,7 +12675,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushSessionAffinity) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(OK,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12110,7 +12707,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushPrivacyModeMismatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12123,7 +12720,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushPrivacyModeMismatch) {
EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
string url = "https://www.example.org/";
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
quic::QuicClientPromisedInfo promised(
session, GetNthServerInitiatedUnidirectionalStreamId(0), kDefaultUrl);
@@ -12138,7 +12735,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushPrivacyModeMismatch) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, PRIVACY_MODE_ENABLED,
+ scheme_host_port_, version_, PRIVACY_MODE_ENABLED,
DEFAULT_PRIORITY, SocketTag(), NetworkIsolationKey(),
SecureDnsPolicy::kAllow, true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12191,7 +12788,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushNetworkIsolationKeyMismatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12204,7 +12801,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushNetworkIsolationKeyMismatch) {
EXPECT_EQ(0, QuicStreamFactoryPeer::GetNumPushStreamsCreated(factory_.get()));
string url = "https://www.example.org/";
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
quic::QuicClientPromisedInfo promised(
session, GetNthServerInitiatedUnidirectionalStreamId(0), kDefaultUrl);
@@ -12220,7 +12817,7 @@ TEST_P(QuicStreamFactoryTest, ServerPushNetworkIsolationKeyMismatch) {
EXPECT_EQ(
ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, PRIVACY_MODE_DISABLED, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey::CreateTransient(),
SecureDnsPolicy::kAllow, true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12244,8 +12841,9 @@ TEST_P(QuicStreamFactoryTest, ServerPushNetworkIsolationKeyMismatch) {
TEST_P(QuicStreamFactoryTest, PoolByOrigin) {
Initialize();
- HostPortPair destination1("first.example.com", 443);
- HostPortPair destination2("second.example.com", 443);
+ url::SchemeHostPort destination1(url::kHttpsScheme, "first.example.com", 443);
+ url::SchemeHostPort destination2(url::kHttpsScheme, "second.example.com",
+ 443);
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
@@ -12267,7 +12865,7 @@ TEST_P(QuicStreamFactoryTest, PoolByOrigin) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
std::unique_ptr<HttpStream> stream1 = CreateStream(&request1);
EXPECT_TRUE(stream1.get());
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Second request returns synchronously because it pools to existing session.
TestCompletionCallback callback2;
@@ -12287,9 +12885,10 @@ TEST_P(QuicStreamFactoryTest, PoolByOrigin) {
QuicChromiumClientSession::Handle* session2 =
QuicHttpStreamPeer::GetSessionHandle(stream2.get());
EXPECT_TRUE(session1->SharesSameSession(*session2));
- EXPECT_EQ(quic::QuicServerId(host_port_pair_.host(), host_port_pair_.port(),
- privacy_mode_ == PRIVACY_MODE_ENABLED),
- session1->server_id());
+ EXPECT_EQ(
+ quic::QuicServerId(scheme_host_port_.host(), scheme_host_port_.port(),
+ privacy_mode_ == PRIVACY_MODE_ENABLED),
+ session1->server_id());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -12361,17 +12960,17 @@ class QuicStreamFactoryWithDestinationTest
destination_type_(GetParam().destination_type),
hanging_read_(SYNCHRONOUS, ERR_IO_PENDING, 0) {}
- HostPortPair GetDestination() {
+ url::SchemeHostPort GetDestination() {
switch (destination_type_) {
case SAME_AS_FIRST:
return origin1_;
case SAME_AS_SECOND:
return origin2_;
case DIFFERENT:
- return HostPortPair(kDifferentHostname, 443);
+ return url::SchemeHostPort(url::kHttpsScheme, kDifferentHostname, 443);
default:
NOTREACHED();
- return HostPortPair();
+ return url::SchemeHostPort();
}
}
@@ -12394,8 +12993,8 @@ class QuicStreamFactoryWithDestinationTest
}
DestinationType destination_type_;
- HostPortPair origin1_;
- HostPortPair origin2_;
+ url::SchemeHostPort origin1_;
+ url::SchemeHostPort origin2_;
MockRead hanging_read_;
std::vector<std::unique_ptr<SequencedSocketData>>
sequenced_socket_data_vector_;
@@ -12415,13 +13014,13 @@ TEST_P(QuicStreamFactoryWithDestinationTest, InvalidCertificate) {
Initialize();
GURL url("https://mail.example.com/");
- origin1_ = HostPortPair::FromURL(url);
+ origin1_ = url::SchemeHostPort(url);
// Not used for requests, but this provides a test case where the certificate
// is valid for the hostname of the alternative service.
- origin2_ = HostPortPair("mail.example.org", 433);
+ origin2_ = url::SchemeHostPort(url::kHttpsScheme, "mail.example.org", 433);
- HostPortPair destination = GetDestination();
+ url::SchemeHostPort destination = GetDestination();
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -12455,10 +13054,10 @@ TEST_P(QuicStreamFactoryWithDestinationTest, SharedCertificate) {
GURL url1("https://www.example.org/");
GURL url2("https://mail.example.org/");
- origin1_ = HostPortPair::FromURL(url1);
- origin2_ = HostPortPair::FromURL(url2);
+ origin1_ = url::SchemeHostPort(url1);
+ origin2_ = url::SchemeHostPort(url2);
- HostPortPair destination = GetDestination();
+ url::SchemeHostPort destination = GetDestination();
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -12524,10 +13123,10 @@ TEST_P(QuicStreamFactoryWithDestinationTest, DifferentPrivacyMode) {
GURL url1("https://www.example.org/");
GURL url2("https://mail.example.org/");
- origin1_ = HostPortPair::FromURL(url1);
- origin2_ = HostPortPair::FromURL(url2);
+ origin1_ = url::SchemeHostPort(url1);
+ origin2_ = url::SchemeHostPort(url2);
- HostPortPair destination = GetDestination();
+ url::SchemeHostPort destination = GetDestination();
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -12609,10 +13208,10 @@ TEST_P(QuicStreamFactoryWithDestinationTest, DifferentSecureDnsPolicy) {
GURL url1("https://www.example.org/");
GURL url2("https://mail.example.org/");
- origin1_ = HostPortPair::FromURL(url1);
- origin2_ = HostPortPair::FromURL(url2);
+ origin1_ = url::SchemeHostPort(url1);
+ origin2_ = url::SchemeHostPort(url2);
- HostPortPair destination = GetDestination();
+ url::SchemeHostPort destination = GetDestination();
scoped_refptr<X509Certificate> cert(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -12688,10 +13287,10 @@ TEST_P(QuicStreamFactoryWithDestinationTest, DisjointCertificate) {
GURL url1("https://news.example.org/");
GURL url2("https://mail.example.com/");
- origin1_ = HostPortPair::FromURL(url1);
- origin2_ = HostPortPair::FromURL(url2);
+ origin1_ = url::SchemeHostPort(url1);
+ origin2_ = url::SchemeHostPort(url2);
- HostPortPair destination = GetDestination();
+ url::SchemeHostPort destination = GetDestination();
scoped_refptr<X509Certificate> cert1(
ImportCertFromFile(GetTestCertsDirectory(), "wildcard.pem"));
@@ -12863,7 +13462,7 @@ TEST_P(QuicStreamFactoryTest, HostResolverUsesRequestPriority) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, MAXIMUM_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, MAXIMUM_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12893,7 +13492,7 @@ TEST_P(QuicStreamFactoryTest, HostResolverRequestReprioritizedOnSetPriority) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, MAXIMUM_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, MAXIMUM_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -12905,7 +13504,7 @@ TEST_P(QuicStreamFactoryTest, HostResolverRequestReprioritizedOnSetPriority) {
QuicStreamRequest request2(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url2_, net_log_, &net_error_details_,
@@ -12945,7 +13544,7 @@ TEST_P(QuicStreamFactoryTest, HostResolverUsesParams) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), kNetworkIsolationKey, SecureDnsPolicy::kDisable,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13000,7 +13599,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackAsyncSync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13055,7 +13654,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackAsyncAsync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13107,7 +13706,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackSyncSync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_QUIC_PROTOCOL_ERROR,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13146,7 +13745,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackSyncAsync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13175,13 +13774,13 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackFailSync) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
// Host resolution will fail synchronously.
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
host_resolver_->set_synchronous_mode(true);
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_NAME_NOT_RESOLVED,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13203,12 +13802,12 @@ TEST_P(QuicStreamFactoryTest, ResultAfterHostResolutionCallbackFailAsync) {
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13241,11 +13840,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionSync) {
// Set an address in resolver for synchronous return.
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13264,7 +13863,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionSync) {
QuicStreamRequest request(factory_.get());
EXPECT_THAT(request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13272,7 +13871,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionSync) {
IsOk());
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
EXPECT_TRUE(quic_data.AllReadDataConsumed());
@@ -13290,7 +13889,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionAsync) {
// Set an address in resolver for asynchronous return.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
MockQuicData quic_data(version_);
@@ -13302,7 +13901,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionAsync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13320,7 +13919,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceAndHostResolutionAsync) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
@@ -13339,11 +13938,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncStaleMatch) {
// Set an address in resolver for asynchronous return.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kCachedIPAddress.ToString(), "");
// Set up the same address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13363,15 +13962,15 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncStaleMatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check that the racing job is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Resolve dns and return.
host_resolver_->ResolveAllPending();
@@ -13379,7 +13978,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncStaleMatch) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(),
kCachedIPAddress.ToString());
@@ -13403,11 +14002,11 @@ TEST_P(QuicStreamFactoryTest,
factory_->set_is_quic_known_to_work_on_current_network(false);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kCachedIPAddress.ToString(), "");
// Set up the same address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13428,7 +14027,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13440,8 +14039,8 @@ TEST_P(QuicStreamFactoryTest,
base::RunLoop().RunUntilIdle();
// Check that the racing job is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Resolve dns and call back, make sure job finishes.
host_resolver_->ResolveAllPending();
@@ -13450,7 +14049,7 @@ TEST_P(QuicStreamFactoryTest,
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(),
kCachedIPAddress.ToString());
@@ -13474,11 +14073,11 @@ TEST_P(QuicStreamFactoryTest,
factory_->set_is_quic_known_to_work_on_current_network(false);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kCachedIPAddress.ToString(), "");
// Set up the same address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13499,7 +14098,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13518,7 +14117,7 @@ TEST_P(QuicStreamFactoryTest,
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(),
kCachedIPAddress.ToString());
@@ -13538,11 +14137,11 @@ TEST_P(QuicStreamFactoryTest,
// Set an address in resolver for asynchronous return.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13578,15 +14177,15 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check the stale connection is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Finish dns resolution and check the job has finished.
host_resolver_->ResolveAllPending();
@@ -13595,7 +14194,7 @@ TEST_P(QuicStreamFactoryTest,
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
@@ -13619,11 +14218,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
factory_->set_is_quic_known_to_work_on_current_network(false);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13661,7 +14260,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13671,8 +14270,8 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
crypto_client_stream_factory_.last_stream()
->NotifySessionOneRttKeyAvailable();
base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Finish host resolution and check the job is done.
host_resolver_->ResolveAllPending();
@@ -13681,7 +14280,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleAsyncResolveAsyncNoMatch) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
EXPECT_TRUE(quic_data.AllReadDataConsumed());
@@ -13704,11 +14303,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncStaleAsyncNoMatch) {
factory_->set_is_quic_known_to_work_on_current_network(false);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13742,7 +14341,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncStaleAsyncNoMatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13757,7 +14356,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncStaleAsyncNoMatch) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
EXPECT_TRUE(quic_data.AllReadDataConsumed());
@@ -13777,7 +14376,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveError) {
// Set synchronous failure in resolver.
host_resolver_->set_synchronous_mode(true);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
MockQuicData quic_data(version_);
quic_data.AddSocketDataToFactory(socket_factory_.get());
@@ -13785,7 +14384,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveError) {
EXPECT_EQ(ERR_NAME_NOT_RESOLVED,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13803,7 +14402,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncError) {
// Set asynchronous failure in resolver.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
MockQuicData quic_data(version_);
quic_data.AddSocketDataToFactory(socket_factory_.get());
@@ -13811,7 +14410,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsyncError) {
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -13833,10 +14432,10 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleSyncHostResolveError) {
// Set asynchronous failure in resolver.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
// Set up an address in the stale cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13864,15 +14463,15 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleSyncHostResolveError) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check that the stale connection is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Finish host resolution.
host_resolver_->ResolveAllPending();
@@ -13894,11 +14493,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSMatches) {
// Set an address in host resolver for asynchronous return.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kCachedIPAddress.ToString(), "");
// Set up the same address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13921,13 +14520,13 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSMatches) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
- EXPECT_FALSE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
host_resolver_->ResolveAllPending();
EXPECT_THAT(callback_.WaitForResult(), IsError(ERR_ADDRESS_IN_USE));
@@ -13944,11 +14543,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatch) {
// Set an address in host resolver.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -13974,15 +14573,15 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatch) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check that the stale connection fails.
- EXPECT_FALSE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Finish host resolution and check the job finishes ok.
host_resolver_->ResolveAllPending();
@@ -13991,7 +14590,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatch) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
@@ -14010,11 +14609,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatchError) {
// Set an address in host resolver asynchronously.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in the stale cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -14038,15 +14637,15 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceStaleErrorDNSNoMatchError) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check the stale connection fails.
- EXPECT_FALSE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// Check the resolved dns connection fails.
host_resolver_->ResolveAllPending();
@@ -14064,11 +14663,11 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
// Add asynchronous failure in host resolver.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
factory_->set_is_quic_known_to_work_on_current_network(false);
// Set up an address in stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -14096,7 +14695,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceResolveAsyncErrorStaleAsync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14123,10 +14722,10 @@ TEST_P(QuicStreamFactoryTest,
// Add asynchronous failure to host resolver.
host_resolver_->set_ondemand_mode(true);
factory_->set_is_quic_known_to_work_on_current_network(false);
- host_resolver_->rules()->AddSimulatedFailure(host_port_pair_.host());
+ host_resolver_->rules()->AddSimulatedFailure(scheme_host_port_.host());
// Set up an address in stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -14153,7 +14752,7 @@ TEST_P(QuicStreamFactoryTest,
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14178,7 +14777,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsync) {
crypto_client_stream_factory_.AddProofVerifyDetails(&verify_details);
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
MockQuicData quic_data(version_);
@@ -14190,7 +14789,7 @@ TEST_P(QuicStreamFactoryTest, ResultAfterDNSRaceHostResolveAsync) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14227,11 +14826,11 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
// Set an address in resolver for asynchronous return.
host_resolver_->set_ondemand_mode(true);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up the same address in the stale resolver cache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -14259,15 +14858,15 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check that the racing job is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// By disconnecting the network, the stale session will be killed.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -14279,7 +14878,7 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedAfterHandshake) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
@@ -14304,11 +14903,11 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
factory_->set_is_quic_known_to_work_on_current_network(false);
crypto_client_stream_factory_.set_handshake_mode(
MockCryptoClientStream::ZERO_RTT);
- host_resolver_->rules()->AddIPLiteralRule(host_port_pair_.host(),
+ host_resolver_->rules()->AddIPLiteralRule(scheme_host_port_.host(),
kNonCachedIPAddress, "");
// Set up a different address in the stale resolvercache.
- HostCache::Key key(host_port_pair_.host(), DnsQueryType::UNSPECIFIED, 0,
+ HostCache::Key key(scheme_host_port_.host(), DnsQueryType::UNSPECIFIED, 0,
HostResolverSource::ANY, NetworkIsolationKey());
HostCache::Entry entry(OK,
AddressList::CreateFromIPAddress(kCachedIPAddress, 0),
@@ -14336,15 +14935,15 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
// Check that the racing job is running.
- EXPECT_TRUE(HasLiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_TRUE(HasLiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// By disconnecting the network, the stale session will be killed.
scoped_mock_network_change_notifier_->mock_network_change_notifier()
@@ -14360,7 +14959,7 @@ TEST_P(QuicStreamFactoryTest, StaleNetworkFailedBeforeHandshake) {
std::unique_ptr<HttpStream> stream = CreateStream(&request);
EXPECT_TRUE(stream.get());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(session->peer_address().host().ToString(), kNonCachedIPAddress);
EXPECT_TRUE(quic_data.AllReadDataConsumed());
@@ -14406,15 +15005,15 @@ TEST_P(QuicStreamFactoryTest, ConfigInitialRttForHandshake) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
failed_on_default_network_callback_, callback_.callback()));
base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
- EXPECT_TRUE(HasActiveJob(host_port_pair_, privacy_mode_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
+ EXPECT_TRUE(HasActiveJob(scheme_host_port_, privacy_mode_));
// The pending task is scheduled for handshake timeout retransmission,
// which is 2 * 400ms with crypto frames and 1.5 * 400ms otherwise.
@@ -14435,7 +15034,7 @@ TEST_P(QuicStreamFactoryTest, ConfigInitialRttForHandshake) {
EXPECT_THAT(callback_.WaitForResult(), IsOk());
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_EQ(400000u, session->config()->GetInitialRoundTripTimeUsToSend());
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
@@ -14475,7 +15074,7 @@ TEST_P(QuicStreamFactoryTest, Tag) {
// Request a stream with |tag1|.
QuicStreamRequest request1(factory_.get());
int rv = request1.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, tag1,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, tag1,
NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14492,7 +15091,7 @@ TEST_P(QuicStreamFactoryTest, Tag) {
// Request a stream with |tag1| and verify underlying session is reused.
QuicStreamRequest request2(factory_.get());
rv = request2.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, tag1,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, tag1,
NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14507,7 +15106,7 @@ TEST_P(QuicStreamFactoryTest, Tag) {
// Request a stream with |tag2| and verify a new session is created.
QuicStreamRequest request3(factory_.get());
rv = request3.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY, tag2,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY, tag2,
NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14545,7 +15144,7 @@ TEST_P(QuicStreamFactoryTest, ReadErrorClosesConnection) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14555,14 +15154,14 @@ TEST_P(QuicStreamFactoryTest, ReadErrorClosesConnection) {
EXPECT_TRUE(stream.get());
// Ensure that the session is alive and active before we read the error.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Resume the socket data to get the read error delivered.
socket_data.Resume();
// Ensure that the session is no longer active.
- EXPECT_FALSE(HasActiveSession(host_port_pair_));
+ EXPECT_FALSE(HasActiveSession(scheme_host_port_));
}
TEST_P(QuicStreamFactoryTest, MessageTooBigReadErrorDoesNotCloseConnection) {
@@ -14582,7 +15181,7 @@ TEST_P(QuicStreamFactoryTest, MessageTooBigReadErrorDoesNotCloseConnection) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14592,14 +15191,14 @@ TEST_P(QuicStreamFactoryTest, MessageTooBigReadErrorDoesNotCloseConnection) {
EXPECT_TRUE(stream.get());
// Ensure that the session is alive and active before we read the error.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Resume the socket data to get the read error delivered.
socket_data.Resume();
// Ensure that the session is still active.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
}
TEST_P(QuicStreamFactoryTest, ZeroLengthReadDoesNotCloseConnection) {
@@ -14619,7 +15218,7 @@ TEST_P(QuicStreamFactoryTest, ZeroLengthReadDoesNotCloseConnection) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14629,21 +15228,21 @@ TEST_P(QuicStreamFactoryTest, ZeroLengthReadDoesNotCloseConnection) {
EXPECT_TRUE(stream.get());
// Ensure that the session is alive and active before we read the error.
- QuicChromiumClientSession* session = GetActiveSession(host_port_pair_);
+ QuicChromiumClientSession* session = GetActiveSession(scheme_host_port_);
EXPECT_TRUE(QuicStreamFactoryPeer::IsLiveSession(factory_.get(), session));
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
// Resume the socket data to get the zero-length read delivered.
socket_data.Resume();
// Ensure that the session is still active.
- EXPECT_TRUE(HasActiveSession(host_port_pair_));
+ EXPECT_TRUE(HasActiveSession(scheme_host_port_));
}
TEST_P(QuicStreamFactoryTest, DnsAliasesCanBeAccessedFromStream) {
std::vector<std::string> dns_aliases(
- {"alias1", "alias2", host_port_pair_.host()});
+ {"alias1", "alias2", scheme_host_port_.host()});
host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases(
- host_port_pair_.host(), "192.168.0.1", std::move(dns_aliases));
+ scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases));
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -14658,7 +15257,7 @@ TEST_P(QuicStreamFactoryTest, DnsAliasesCanBeAccessedFromStream) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14673,14 +15272,15 @@ TEST_P(QuicStreamFactoryTest, DnsAliasesCanBeAccessedFromStream) {
EXPECT_TRUE(socket_data.AllReadDataConsumed());
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
- EXPECT_THAT(stream->GetDnsAliases(),
- testing::ElementsAre("alias1", "alias2", host_port_pair_.host()));
+ EXPECT_THAT(
+ stream->GetDnsAliases(),
+ testing::ElementsAre("alias1", "alias2", scheme_host_port_.host()));
}
TEST_P(QuicStreamFactoryTest, NoAdditionalDnsAliases) {
std::vector<std::string> dns_aliases;
host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases(
- host_port_pair_.host(), "192.168.0.1", std::move(dns_aliases));
+ scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases));
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -14695,7 +15295,7 @@ TEST_P(QuicStreamFactoryTest, NoAdditionalDnsAliases) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14711,13 +15311,13 @@ TEST_P(QuicStreamFactoryTest, NoAdditionalDnsAliases) {
EXPECT_TRUE(socket_data.AllWriteDataConsumed());
EXPECT_THAT(stream->GetDnsAliases(),
- testing::ElementsAre(host_port_pair_.host()));
+ testing::ElementsAre(scheme_host_port_.host()));
}
TEST_P(QuicStreamFactoryTest, DoNotUseDnsAliases) {
std::vector<std::string> dns_aliases({"alias1", "alias2"});
host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases(
- host_port_pair_.host(), "192.168.0.1", std::move(dns_aliases));
+ scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases));
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -14732,7 +15332,7 @@ TEST_P(QuicStreamFactoryTest, DoNotUseDnsAliases) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
false /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14753,7 +15353,7 @@ TEST_P(QuicStreamFactoryTest, DoNotUseDnsAliases) {
TEST_P(QuicStreamFactoryTest, ConnectErrorInCreateWithDnsAliases) {
std::vector<std::string> dns_aliases({"alias1", "alias2"});
host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases(
- host_port_pair_.host(), "192.168.0.1", std::move(dns_aliases));
+ scheme_host_port_.host(), "192.168.0.1", std::move(dns_aliases));
Initialize();
ProofVerifyDetailsChromium verify_details = DefaultProofVerifyDetails();
@@ -14766,7 +15366,7 @@ TEST_P(QuicStreamFactoryTest, ConnectErrorInCreateWithDnsAliases) {
QuicStreamRequest request(factory_.get());
EXPECT_EQ(ERR_IO_PENDING,
request.Request(
- host_port_pair_, version_, privacy_mode_, DEFAULT_PRIORITY,
+ scheme_host_port_, version_, privacy_mode_, DEFAULT_PRIORITY,
SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
true /* use_dns_aliases */,
/*cert_verify_flags=*/0, url_, net_log_, &net_error_details_,
@@ -14912,8 +15512,8 @@ TEST_P(QuicStreamFactoryDnsAliasPoolingTest, IPPooling) {
const GURL kUrl1(kDefaultUrl);
const GURL kUrl2(kServer2Url);
- const HostPortPair kOrigin1 = HostPortPair::FromURL(kUrl1);
- const HostPortPair kOrigin2 = HostPortPair::FromURL(kUrl2);
+ const url::SchemeHostPort kOrigin1 = url::SchemeHostPort(kUrl1);
+ const url::SchemeHostPort kOrigin2 = url::SchemeHostPort(kUrl2);
host_resolver_->rules()->AddIPLiteralRuleWithDnsAliases(
kOrigin1.host(), "192.168.0.1", std::move(dns_aliases1_));
diff --git a/chromium/net/quic/quic_test_packet_maker.cc b/chromium/net/quic/quic_test_packet_maker.cc
index f2e7b4a179d..f7f1a70f346 100644
--- a/chromium/net/quic/quic_test_packet_maker.cc
+++ b/chromium/net/quic/quic_test_packet_maker.cc
@@ -171,6 +171,46 @@ std::unique_ptr<quic::QuicReceivedPacket> QuicTestPacketMaker::MakePingPacket(
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeRetireConnectionIdPacket(uint64_t num,
+ bool include_version,
+ uint64_t sequence_number) {
+ InitializeHeader(num, include_version);
+ AddQuicRetireConnectionIdFrame(sequence_number);
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeNewConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to) {
+ InitializeHeader(num, include_version);
+ AddQuicNewConnectionIdFrame(
+ cid, sequence_number, retire_prior_to,
+ quic::QuicUtils::GenerateStatelessResetToken(cid));
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeAckAndNewConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to) {
+ InitializeHeader(num, include_version);
+ AddQuicAckFrame(largest_received, smallest_received);
+ AddQuicNewConnectionIdFrame(
+ cid, sequence_number, retire_prior_to,
+ quic::QuicUtils::GenerateStatelessResetToken(cid));
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeDummyCHLOPacket(uint64_t packet_num) {
SetEncryptionLevel(quic::ENCRYPTION_INITIAL);
InitializeHeader(packet_num, /*include_version=*/true);
@@ -207,6 +247,35 @@ QuicTestPacketMaker::MakeAckAndPingPacket(uint64_t num,
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeAckAndRetireConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ uint64_t sequence_number) {
+ InitializeHeader(num, include_version);
+ AddQuicAckFrame(largest_received, smallest_received);
+ AddQuicRetireConnectionIdFrame(sequence_number);
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeRetransmissionAndRetireConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ const std::vector<uint64_t>& original_packet_numbers,
+ uint64_t sequence_number) {
+ InitializeHeader(num, include_version);
+ for (auto it : original_packet_numbers) {
+ for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) {
+ frames_.push_back(frame);
+ }
+ }
+ AddQuicRetireConnectionIdFrame(sequence_number);
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeStreamsBlockedPacket(
uint64_t num,
bool include_version,
@@ -561,7 +630,7 @@ QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket(
const std::string& quic_error_details) {
InitializeHeader(num, include_version);
- AddQuicAckFrame(largest_received, smallest_received);
+ AddQuicAckFrame(largest_received, smallest_received);
AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
if (version_.HasIetfQuicFrames()) {
@@ -569,7 +638,6 @@ QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket(
}
AddQuicRstStreamFrame(rst_stream_id, error_code);
- AddQuicAckFrame(largest_received, smallest_received);
AddQuicConnectionCloseFrame(quic_error, quic_error_details);
return BuildPacket();
@@ -590,8 +658,6 @@ QuicTestPacketMaker::MakeDataRstAckAndConnectionClosePacket(
uint64_t frame_type) {
InitializeHeader(num, include_version);
- AddQuicAckFrame(largest_received, smallest_received);
-
AddQuicStreamFrame(data_stream_id, /* fin = */ false, data);
if (version_.HasIetfQuicFrames()) {
AddQuicStopSendingFrame(rst_stream_id, error_code);
@@ -698,6 +764,29 @@ QuicTestPacketMaker::MakeAckAndDataPacket(uint64_t packet_number,
}
std::unique_ptr<quic::QuicReceivedPacket>
+QuicTestPacketMaker::MakeAckRetransmissionAndDataPacket(
+ uint64_t packet_number,
+ bool include_version,
+ const std::vector<uint64_t>& original_packet_numbers,
+ quic::QuicStreamId stream_id,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ bool fin,
+ absl::string_view data) {
+ InitializeHeader(packet_number, include_version);
+
+ AddQuicAckFrame(largest_received, smallest_received);
+ for (auto it : original_packet_numbers) {
+ for (auto frame : saved_frames_[quic::QuicPacketNumber(it)]) {
+ frames_.push_back(frame);
+ }
+ }
+ AddQuicStreamFrame(stream_id, fin, data);
+
+ return BuildPacket();
+}
+
+std::unique_ptr<quic::QuicReceivedPacket>
QuicTestPacketMaker::MakeRequestHeadersAndMultipleDataFramesPacket(
uint64_t packet_number,
quic::QuicStreamId stream_id,
@@ -1119,7 +1208,7 @@ QuicTestPacketMaker::MakeStatelessResetPacket() {
void QuicTestPacketMaker::RemoveSavedStreamFrames(
quic::QuicStreamId stream_id) {
for (auto& kv : saved_frames_) {
- auto it = kv.second.begin();
+ auto* it = kv.second.begin();
while (it != kv.second.end()) {
if (it->type == quic::STREAM_FRAME &&
it->stream_frame.stream_id == stream_id) {
@@ -1263,6 +1352,28 @@ void QuicTestPacketMaker::AddQuicPingFrame() {
DVLOG(1) << "Adding frame: " << frames_.back();
}
+void QuicTestPacketMaker::AddQuicRetireConnectionIdFrame(
+ uint64_t sequence_number) {
+ auto* retire_cid_frame = new quic::QuicRetireConnectionIdFrame();
+ retire_cid_frame->sequence_number = sequence_number;
+ frames_.push_back(quic::QuicFrame(retire_cid_frame));
+ DVLOG(1) << "Adding frame: " << frames_.back();
+}
+
+void QuicTestPacketMaker::AddQuicNewConnectionIdFrame(
+ const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to,
+ quic::StatelessResetToken reset_token) {
+ auto* new_cid_frame = new quic::QuicNewConnectionIdFrame();
+ new_cid_frame->connection_id = cid;
+ new_cid_frame->sequence_number = sequence_number;
+ new_cid_frame->retire_prior_to = retire_prior_to;
+ new_cid_frame->stateless_reset_token = reset_token;
+ frames_.push_back(quic::QuicFrame(new_cid_frame));
+ DVLOG(1) << "Adding frame: " << frames_.back();
+}
+
void QuicTestPacketMaker::AddQuicMaxStreamsFrame(
quic::QuicControlFrameId control_frame_id,
quic::QuicStreamCount stream_count,
diff --git a/chromium/net/quic/quic_test_packet_maker.h b/chromium/net/quic/quic_test_packet_maker.h
index 89b28837110..b020d02c783 100644
--- a/chromium/net/quic/quic_test_packet_maker.h
+++ b/chromium/net/quic/quic_test_packet_maker.h
@@ -8,6 +8,7 @@
#define NET_QUIC_QUIC_TEST_PACKET_MAKER_H_
#include <stddef.h>
+#include <sys/types.h>
#include <memory>
#include <string>
@@ -55,6 +56,10 @@ class QuicTestPacketMaker {
void set_hostname(const std::string& host);
+ void set_connection_id(const quic::QuicConnectionId& connection_id) {
+ connection_id_ = connection_id;
+ }
+
std::unique_ptr<quic::QuicReceivedPacket> MakeConnectivityProbingPacket(
uint64_t num,
bool include_version);
@@ -63,6 +68,27 @@ class QuicTestPacketMaker {
uint64_t num,
bool include_version);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeRetireConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ uint64_t sequence_number);
+
+ std::unique_ptr<quic::QuicReceivedPacket> MakeNewConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to);
+
+ std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndNewConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to);
+
std::unique_ptr<quic::QuicReceivedPacket> MakeDummyCHLOPacket(
uint64_t packet_num);
@@ -72,6 +98,20 @@ class QuicTestPacketMaker {
uint64_t largest_received,
uint64_t smallest_received);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndRetireConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ uint64_t sequence_number);
+
+ std::unique_ptr<quic::QuicReceivedPacket>
+ MakeRetransmissionAndRetireConnectionIdPacket(
+ uint64_t num,
+ bool include_version,
+ const std::vector<uint64_t>& original_packet_numbers,
+ uint64_t sequence_number);
+
std::unique_ptr<quic::QuicReceivedPacket> MakeStreamsBlockedPacket(
uint64_t num,
bool include_version,
@@ -290,6 +330,16 @@ class QuicTestPacketMaker {
bool fin,
absl::string_view data);
+ std::unique_ptr<quic::QuicReceivedPacket> MakeAckRetransmissionAndDataPacket(
+ uint64_t packet_number,
+ bool include_version,
+ const std::vector<uint64_t>& original_packet_numbers,
+ quic::QuicStreamId stream_id,
+ uint64_t largest_received,
+ uint64_t smallest_received,
+ bool fin,
+ absl::string_view data);
+
std::unique_ptr<quic::QuicReceivedPacket> MakeAckAndRetransmissionPacket(
uint64_t packet_number,
uint64_t first_received,
@@ -460,6 +510,11 @@ class QuicTestPacketMaker {
// Add frames to current packet.
void AddQuicPaddingFrame();
void AddQuicPingFrame();
+ void AddQuicRetireConnectionIdFrame(uint64_t sequence_number);
+ void AddQuicNewConnectionIdFrame(const quic::QuicConnectionId& cid,
+ uint64_t sequence_number,
+ uint64_t retire_prior_to,
+ quic::StatelessResetToken reset_token);
void AddQuicMaxStreamsFrame(quic::QuicControlFrameId control_frame_id,
quic::QuicStreamCount stream_count,
bool unidirectional);
diff --git a/chromium/net/quic/quic_transport_client.cc b/chromium/net/quic/quic_transport_client.cc
index 292b7a59b33..11dc85a6f58 100644
--- a/chromium/net/quic/quic_transport_client.cc
+++ b/chromium/net/quic/quic_transport_client.cc
@@ -5,8 +5,8 @@
#include "net/quic/quic_transport_client.h"
#include "base/containers/contains.h"
+#include "base/containers/cxx20_erase.h"
#include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
#include "base/strings/abseil_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
@@ -17,6 +17,7 @@
#include "net/third_party/quiche/src/quic/core/quic_connection.h"
#include "net/third_party/quiche/src/quic/core/quic_utils.h"
#include "net/url_request/url_request_context.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -213,7 +214,7 @@ int QuicTransportClient::DoResolveHost() {
next_connect_state_ = CONNECT_STATE_RESOLVE_HOST_COMPLETE;
HostResolver::ResolveHostParameters parameters;
resolve_host_request_ = context_->host_resolver()->CreateRequest(
- HostPortPair::FromURL(url_), isolation_key_, net_log_, absl::nullopt);
+ url::SchemeHostPort(url_), isolation_key_, net_log_, absl::nullopt);
return resolve_host_request_->Start(
base::BindOnce(&QuicTransportClient::DoLoop, base::Unretained(this)));
}
diff --git a/chromium/net/quiche/common/platform/impl/DEPS b/chromium/net/quiche/common/platform/impl/DEPS
index b61ff60dc66..2c12fec5f33 100644
--- a/chromium/net/quiche/common/platform/impl/DEPS
+++ b/chromium/net/quiche/common/platform/impl/DEPS
@@ -1,10 +1,4 @@
include_rules = [
- # This is a temporary rule to simplify migrating QUICHE to using Abseil
- # directly.
- # TODO(b/166325009): remove this rule.
- "+third_party/abseil-cpp/absl/base/macros.h",
- "+third_party/abseil-cpp/absl/container/node_hash_map.h",
- "+third_party/abseil-cpp/absl/hash/hash.h",
+ # Allow string_view.h since absl::string_view is widely used in QUICHE API.
"+third_party/abseil-cpp/absl/strings",
- "+third_party/abseil-cpp/absl/types/optional.h",
]
diff --git a/chromium/net/quiche/common/platform/impl/quiche_test_impl.cc b/chromium/net/quiche/common/platform/impl/quiche_test_impl.cc
new file mode 100644
index 00000000000..8b70d6a632a
--- /dev/null
+++ b/chromium/net/quiche/common/platform/impl/quiche_test_impl.cc
@@ -0,0 +1,21 @@
+// Copyright (c) 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/quiche/common/platform/impl/quiche_test_impl.h"
+
+#include <string>
+
+#include "base/files/file_path.h"
+#include "net/test/test_data_directory.h"
+
+namespace quiche {
+namespace test {
+
+std::string QuicheGetCommonSourcePathImpl() {
+ base::FilePath net_path = net::GetTestNetDirectory();
+ return net_path.AppendASCII("third_party/quiche/common").MaybeAsASCII();
+}
+
+} // namespace test
+} // namespace quiche
diff --git a/chromium/net/quiche/common/platform/impl/quiche_test_impl.h b/chromium/net/quiche/common/platform/impl/quiche_test_impl.h
index a2db91e274d..43475be089b 100644
--- a/chromium/net/quiche/common/platform/impl/quiche_test_impl.h
+++ b/chromium/net/quiche/common/platform/impl/quiche_test_impl.h
@@ -10,10 +10,14 @@
namespace quiche {
namespace test {
+
class QuicheTest : public ::testing::Test {};
template <class T>
class QuicheTestWithParamImpl : public ::testing::TestWithParam<T> {};
+
+std::string QuicheGetCommonSourcePathImpl();
+
} // namespace test
} // namespace quiche
diff --git a/chromium/net/reporting/DIR_METADATA b/chromium/net/reporting/DIR_METADATA
new file mode 100644
index 00000000000..0e8a7811c99
--- /dev/null
+++ b/chromium/net/reporting/DIR_METADATA
@@ -0,0 +1,3 @@
+monorail {
+ component: "Internals>Network>ReportingAndNEL"
+}
diff --git a/chromium/net/reporting/OWNERS b/chromium/net/reporting/OWNERS
index cb7da64f211..acbf93af41e 100644
--- a/chromium/net/reporting/OWNERS
+++ b/chromium/net/reporting/OWNERS
@@ -1,3 +1 @@
-chlily@chromium.org
-
-# Component: Internals>Network>ReportingAndNEL
+yhirano@chromium.org
diff --git a/chromium/net/reporting/mock_persistent_reporting_store.h b/chromium/net/reporting/mock_persistent_reporting_store.h
index 04f1d897965..b53e39752ae 100644
--- a/chromium/net/reporting/mock_persistent_reporting_store.h
+++ b/chromium/net/reporting/mock_persistent_reporting_store.h
@@ -5,7 +5,6 @@
#ifndef NET_REPORTING_MOCK_PERSISTENT_REPORTING_STORE_H_
#define NET_REPORTING_MOCK_PERSISTENT_REPORTING_STORE_H_
-#include <string>
#include <vector>
#include "base/callback.h"
diff --git a/chromium/net/reporting/reporting_browsing_data_remover.cc b/chromium/net/reporting/reporting_browsing_data_remover.cc
index 084b8d6c96f..a68d8c84747 100644
--- a/chromium/net/reporting/reporting_browsing_data_remover.cc
+++ b/chromium/net/reporting/reporting_browsing_data_remover.cc
@@ -27,9 +27,7 @@ void ReportingBrowsingDataRemover::RemoveBrowsingData(
reports_to_remove.push_back(report);
}
- cache->RemoveReports(
- reports_to_remove,
- ReportingReport::Outcome::ERASED_BROWSING_DATA_REMOVED);
+ cache->RemoveReports(reports_to_remove);
}
if ((data_type_mask & DATA_TYPE_CLIENTS) != 0) {
@@ -46,8 +44,7 @@ void ReportingBrowsingDataRemover::RemoveAllBrowsingData(
ReportingCache* cache,
uint64_t data_type_mask) {
if ((data_type_mask & DATA_TYPE_REPORTS) != 0) {
- cache->RemoveAllReports(
- ReportingReport::Outcome::ERASED_BROWSING_DATA_REMOVED);
+ cache->RemoveAllReports();
}
if ((data_type_mask & DATA_TYPE_CLIENTS) != 0) {
cache->RemoveAllClients();
diff --git a/chromium/net/reporting/reporting_cache.h b/chromium/net/reporting/reporting_cache.h
index d891801304e..6c5411e808c 100644
--- a/chromium/net/reporting/reporting_cache.h
+++ b/chromium/net/reporting/reporting_cache.h
@@ -12,7 +12,6 @@
#include "base/callback.h"
#include "base/macros.h"
-#include "base/stl_util.h"
#include "base/time/time.h"
#include "base/values.h"
#include "net/base/net_export.h"
@@ -107,12 +106,12 @@ class NET_EXPORT ReportingCache {
// Removes a set of reports. Any reports that are pending will not be removed
// immediately, but rather marked doomed and removed once they are no longer
// pending.
- virtual void RemoveReports(const std::vector<const ReportingReport*>& reports,
- ReportingReport::Outcome outcome) = 0;
+ virtual void RemoveReports(
+ const std::vector<const ReportingReport*>& reports) = 0;
// Removes all reports. Like |RemoveReports()|, pending reports are doomed
// until no longer pending.
- virtual void RemoveAllReports(ReportingReport::Outcome outcome) = 0;
+ virtual void RemoveAllReports() = 0;
// Gets the count of reports in the cache, *including* doomed reports.
//
diff --git a/chromium/net/reporting/reporting_cache_impl.cc b/chromium/net/reporting/reporting_cache_impl.cc
index 8b742949435..4b073b09cf3 100644
--- a/chromium/net/reporting/reporting_cache_impl.cc
+++ b/chromium/net/reporting/reporting_cache_impl.cc
@@ -15,6 +15,7 @@
#include "base/time/tick_clock.h"
#include "net/base/url_util.h"
#include "net/log/net_log.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
namespace net {
@@ -23,12 +24,7 @@ ReportingCacheImpl::ReportingCacheImpl(ReportingContext* context)
DCHECK(context_);
}
-ReportingCacheImpl::~ReportingCacheImpl() {
- for (const auto& report : reports_) {
- if (report->status != ReportingReport::Status::DOOMED)
- report->outcome = ReportingReport::Outcome::ERASED_REPORTING_SHUT_DOWN;
- }
-}
+ReportingCacheImpl::~ReportingCacheImpl() = default;
void ReportingCacheImpl::AddReport(
const NetworkIsolationKey& network_isolation_key,
@@ -41,8 +37,8 @@ void ReportingCacheImpl::AddReport(
base::TimeTicks queued,
int attempts) {
auto report = std::make_unique<ReportingReport>(
- network_isolation_key, url, user_agent, group_name, type, std::move(body),
- depth, queued, attempts);
+ absl::nullopt, network_isolation_key, url, user_agent, group_name, type,
+ std::move(body), depth, queued, attempts);
auto inserted = reports_.insert(std::move(report));
DCHECK(inserted.second);
@@ -55,7 +51,6 @@ void ReportingCacheImpl::AddReport(
// The newly-added report isn't pending, so even if all other reports are
// pending, the cache should have a report to evict.
DCHECK(!to_evict->get()->IsUploadPending());
- to_evict->get()->outcome = ReportingReport::Outcome::ERASED_EVICTED;
reports_.erase(to_evict);
}
@@ -175,14 +170,11 @@ void ReportingCacheImpl::IncrementEndpointDeliveries(
}
void ReportingCacheImpl::RemoveReports(
- const std::vector<const ReportingReport*>& reports,
- ReportingReport::Outcome outcome) {
+ const std::vector<const ReportingReport*>& reports) {
for (const ReportingReport* report : reports) {
auto it = reports_.find(report);
DCHECK(it != reports_.end());
- it->get()->outcome = outcome;
-
if (it->get()->IsUploadPending()) {
it->get()->status = ReportingReport::Status::DOOMED;
} else {
@@ -192,10 +184,10 @@ void ReportingCacheImpl::RemoveReports(
context_->NotifyCachedReportsUpdated();
}
-void ReportingCacheImpl::RemoveAllReports(ReportingReport::Outcome outcome) {
+void ReportingCacheImpl::RemoveAllReports() {
std::vector<const ReportingReport*> reports_to_remove;
GetReports(&reports_to_remove);
- RemoveReports(reports_to_remove, outcome);
+ RemoveReports(reports_to_remove);
}
size_t ReportingCacheImpl::GetFullReportCountForTesting() const {
diff --git a/chromium/net/reporting/reporting_cache_impl.h b/chromium/net/reporting/reporting_cache_impl.h
index 59b1ed8c383..83283da29f9 100644
--- a/chromium/net/reporting/reporting_cache_impl.h
+++ b/chromium/net/reporting/reporting_cache_impl.h
@@ -58,9 +58,9 @@ class ReportingCacheImpl : public ReportingCache {
const GURL& url,
int reports_delivered,
bool successful) override;
- void RemoveReports(const std::vector<const ReportingReport*>& reports,
- ReportingReport::Outcome outcome) override;
- void RemoveAllReports(ReportingReport::Outcome outcome) override;
+ void RemoveReports(
+ const std::vector<const ReportingReport*>& reports) override;
+ void RemoveAllReports() override;
size_t GetFullReportCountForTesting() const override;
bool IsReportPendingForTesting(const ReportingReport* report) const override;
bool IsReportDoomedForTesting(const ReportingReport* report) const override;
diff --git a/chromium/net/reporting/reporting_cache_unittest.cc b/chromium/net/reporting/reporting_cache_unittest.cc
index a13448da238..3f8515d147c 100644
--- a/chromium/net/reporting/reporting_cache_unittest.cc
+++ b/chromium/net/reporting/reporting_cache_unittest.cc
@@ -263,7 +263,7 @@ TEST_P(ReportingCacheTest, Reports) {
ASSERT_TRUE(report);
EXPECT_EQ(1, report->attempts);
- cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveReports(reports);
EXPECT_EQ(3, observer()->cached_reports_update_count());
cache()->GetReports(&reports);
@@ -285,7 +285,7 @@ TEST_P(ReportingCacheTest, RemoveAllReports) {
cache()->GetReports(&reports);
EXPECT_EQ(2u, reports.size());
- cache()->RemoveAllReports(ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveAllReports();
EXPECT_EQ(3, observer()->cached_reports_update_count());
cache()->GetReports(&reports);
@@ -314,7 +314,7 @@ TEST_P(ReportingCacheTest, RemovePendingReports) {
// pending, so another call to GetReportsToDeliver should return nothing.
EXPECT_EQ(0u, cache()->GetReportsToDeliver().size());
- cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveReports(reports);
EXPECT_TRUE(cache()->IsReportPendingForTesting(reports[0]));
EXPECT_TRUE(cache()->IsReportDoomedForTesting(reports[0]));
EXPECT_EQ(2, observer()->cached_reports_update_count());
@@ -352,7 +352,7 @@ TEST_P(ReportingCacheTest, RemoveAllPendingReports) {
// pending, so another call to GetReportsToDeliver should return nothing.
EXPECT_EQ(0u, cache()->GetReportsToDeliver().size());
- cache()->RemoveAllReports(ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveAllReports();
EXPECT_TRUE(cache()->IsReportPendingForTesting(reports[0]));
EXPECT_TRUE(cache()->IsReportDoomedForTesting(reports[0]));
EXPECT_EQ(2, observer()->cached_reports_update_count());
@@ -385,7 +385,7 @@ TEST_P(ReportingCacheTest, GetReportsAsValue) {
EXPECT_THAT(cache()->GetReportsToDeliver(),
::testing::UnorderedElementsAre(report1, report2));
// Mark report2 as doomed.
- cache()->RemoveReports({report2}, ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveReports({report2});
base::Value actual = cache()->GetReportsAsValue();
base::Value expected = base::test::ParseJson(base::StringPrintf(
@@ -937,8 +937,8 @@ TEST_P(ReportingCacheTest, GetClientsAsValue) {
kNik_.ToDebugString().c_str(), kOtherNik_.ToDebugString().c_str()));
// Compare disregarding order.
- auto expected_list = expected.TakeList();
- auto actual_list = actual.TakeList();
+ auto expected_list = std::move(expected).TakeList();
+ auto actual_list = std::move(actual).TakeList();
std::sort(expected_list.begin(), expected_list.end());
std::sort(actual_list.begin(), actual_list.end());
EXPECT_EQ(expected_list, actual_list);
diff --git a/chromium/net/reporting/reporting_delivery_agent.cc b/chromium/net/reporting/reporting_delivery_agent.cc
index 1e815abd625..7e195aa07ff 100644
--- a/chromium/net/reporting/reporting_delivery_agent.cc
+++ b/chromium/net/reporting/reporting_delivery_agent.cc
@@ -136,7 +136,7 @@ class Delivery {
group_name_and_count.second, success);
}
if (success) {
- cache->RemoveReports(reports_, ReportingReport::Outcome::DELIVERED);
+ cache->RemoveReports(reports_);
} else {
cache->IncrementReportsAttempts(reports_);
}
diff --git a/chromium/net/reporting/reporting_delivery_agent_unittest.cc b/chromium/net/reporting/reporting_delivery_agent_unittest.cc
index 17c62318488..dc63387c234 100644
--- a/chromium/net/reporting/reporting_delivery_agent_unittest.cc
+++ b/chromium/net/reporting/reporting_delivery_agent_unittest.cc
@@ -399,7 +399,7 @@ TEST_F(ReportingDeliveryAgentTest, ConcurrentRemove) {
EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
// Report should appear removed, even though the cache has doomed it.
- cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveReports(reports);
cache()->GetReports(&reports);
EXPECT_TRUE(reports.empty());
EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
@@ -431,7 +431,7 @@ TEST_F(ReportingDeliveryAgentTest, ConcurrentRemoveDuringPermissionsCheck) {
EXPECT_FALSE(cache()->IsReportDoomedForTesting(report));
// Report should appear removed, even though the cache has doomed it.
- cache()->RemoveReports(reports, ReportingReport::Outcome::UNKNOWN);
+ cache()->RemoveReports(reports);
cache()->GetReports(&reports);
EXPECT_TRUE(reports.empty());
EXPECT_TRUE(cache()->IsReportDoomedForTesting(report));
diff --git a/chromium/net/reporting/reporting_endpoint.cc b/chromium/net/reporting/reporting_endpoint.cc
index 843065d6db0..6f40aa1bd1f 100644
--- a/chromium/net/reporting/reporting_endpoint.cc
+++ b/chromium/net/reporting/reporting_endpoint.cc
@@ -19,9 +19,31 @@ ReportingEndpointGroupKey::ReportingEndpointGroupKey(
const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
const std::string& group_name)
+ : ReportingEndpointGroupKey(network_isolation_key,
+ absl::nullopt,
+ origin,
+ group_name) {}
+
+ReportingEndpointGroupKey::ReportingEndpointGroupKey(
+ const NetworkIsolationKey& network_isolation_key,
+ absl::optional<base::UnguessableToken> reporting_source,
+ const url::Origin& origin,
+ const std::string& group_name)
: network_isolation_key(network_isolation_key),
+ reporting_source(std::move(reporting_source)),
origin(origin),
- group_name(group_name) {}
+ group_name(group_name) {
+ // If |reporting_source| is present, it must not be empty.
+ DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
+}
+
+ReportingEndpointGroupKey::ReportingEndpointGroupKey(
+ const ReportingEndpointGroupKey& other,
+ const absl::optional<base::UnguessableToken>& reporting_source)
+ : ReportingEndpointGroupKey(other.network_isolation_key,
+ reporting_source,
+ other.origin,
+ other.group_name) {}
ReportingEndpointGroupKey::ReportingEndpointGroupKey(
const ReportingEndpointGroupKey& other) = default;
@@ -37,8 +59,10 @@ ReportingEndpointGroupKey::~ReportingEndpointGroupKey() = default;
bool operator==(const ReportingEndpointGroupKey& lhs,
const ReportingEndpointGroupKey& rhs) {
- return std::tie(lhs.network_isolation_key, lhs.origin, lhs.group_name) ==
- std::tie(rhs.network_isolation_key, rhs.origin, rhs.group_name);
+ return std::tie(lhs.reporting_source, lhs.network_isolation_key, lhs.origin,
+ lhs.group_name) == std::tie(rhs.reporting_source,
+ rhs.network_isolation_key,
+ rhs.origin, rhs.group_name);
}
bool operator!=(const ReportingEndpointGroupKey& lhs,
@@ -48,18 +72,24 @@ bool operator!=(const ReportingEndpointGroupKey& lhs,
bool operator<(const ReportingEndpointGroupKey& lhs,
const ReportingEndpointGroupKey& rhs) {
- return std::tie(lhs.network_isolation_key, lhs.origin, lhs.group_name) <
- std::tie(rhs.network_isolation_key, rhs.origin, rhs.group_name);
+ return std::tie(lhs.reporting_source, lhs.network_isolation_key, lhs.origin,
+ lhs.group_name) < std::tie(rhs.reporting_source,
+ rhs.network_isolation_key,
+ rhs.origin, rhs.group_name);
}
bool operator>(const ReportingEndpointGroupKey& lhs,
const ReportingEndpointGroupKey& rhs) {
- return std::tie(lhs.network_isolation_key, lhs.origin, lhs.group_name) >
- std::tie(rhs.network_isolation_key, rhs.origin, rhs.group_name);
+ return std::tie(lhs.reporting_source, lhs.network_isolation_key, lhs.origin,
+ lhs.group_name) > std::tie(rhs.reporting_source,
+ rhs.network_isolation_key,
+ rhs.origin, rhs.group_name);
}
std::string ReportingEndpointGroupKey::ToString() const {
- return "NIK: " + network_isolation_key.ToDebugString() +
+ return "Source: " +
+ (reporting_source ? "null" : reporting_source->ToString()) +
+ "; NIK: " + network_isolation_key.ToDebugString() +
"; Origin: " + origin.Serialize() + "; Group name: " + group_name;
}
diff --git a/chromium/net/reporting/reporting_endpoint.h b/chromium/net/reporting/reporting_endpoint.h
index 53f4ebef8e9..406d989d23c 100644
--- a/chromium/net/reporting/reporting_endpoint.h
+++ b/chromium/net/reporting/reporting_endpoint.h
@@ -10,8 +10,10 @@
#include "base/macros.h"
#include "base/time/time.h"
+#include "base/unguessable_token.h"
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -25,6 +27,16 @@ struct NET_EXPORT ReportingEndpointGroupKey {
const url::Origin& origin,
const std::string& group_name);
+ ReportingEndpointGroupKey(
+ const NetworkIsolationKey& network_isolation_key,
+ absl::optional<base::UnguessableToken> reporting_source,
+ const url::Origin& origin,
+ const std::string& group_name);
+
+ ReportingEndpointGroupKey(
+ const ReportingEndpointGroupKey& other,
+ const absl::optional<base::UnguessableToken>& reporting_source);
+
ReportingEndpointGroupKey(const ReportingEndpointGroupKey& other);
ReportingEndpointGroupKey(ReportingEndpointGroupKey&& other);
@@ -39,6 +51,11 @@ struct NET_EXPORT ReportingEndpointGroupKey {
// third party contexts across sites.
NetworkIsolationKey network_isolation_key;
+ // Source token for the document or worker which configured this endpoint, if
+ // this was configured with the Reporting-Endpoints header. For endpoint
+ // groups configured with the Report-To header, this will be nullopt.
+ absl::optional<base::UnguessableToken> reporting_source;
+
// Origin that configured this endpoint group.
url::Origin origin;
diff --git a/chromium/net/reporting/reporting_endpoint_manager.cc b/chromium/net/reporting/reporting_endpoint_manager.cc
index c903335b5e7..645ab993080 100644
--- a/chromium/net/reporting/reporting_endpoint_manager.cc
+++ b/chromium/net/reporting/reporting_endpoint_manager.cc
@@ -15,7 +15,6 @@
#include "base/macros.h"
#include "base/notreached.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/time/tick_clock.h"
#include "net/base/backoff_entry.h"
#include "net/base/network_isolation_key.h"
diff --git a/chromium/net/reporting/reporting_endpoint_manager.h b/chromium/net/reporting/reporting_endpoint_manager.h
index a760849bdaa..5b14a597b04 100644
--- a/chromium/net/reporting/reporting_endpoint_manager.h
+++ b/chromium/net/reporting/reporting_endpoint_manager.h
@@ -6,7 +6,6 @@
#define NET_REPORTING_REPORTING_ENDPOINT_MANAGER_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "net/base/net_export.h"
diff --git a/chromium/net/reporting/reporting_endpoint_manager_unittest.cc b/chromium/net/reporting/reporting_endpoint_manager_unittest.cc
index 3c67771104c..b72935f5c78 100644
--- a/chromium/net/reporting/reporting_endpoint_manager_unittest.cc
+++ b/chromium/net/reporting/reporting_endpoint_manager_unittest.cc
@@ -85,13 +85,11 @@ class TestReportingCache : public ReportingCache {
bool successful) override {
NOTREACHED();
}
- void RemoveReports(const std::vector<const ReportingReport*>& reports,
- ReportingReport::Outcome outcome) override {
- NOTREACHED();
- }
- void RemoveAllReports(ReportingReport::Outcome outcome) override {
+ void RemoveReports(
+ const std::vector<const ReportingReport*>& reports) override {
NOTREACHED();
}
+ void RemoveAllReports() override { NOTREACHED(); }
size_t GetFullReportCountForTesting() const override {
NOTREACHED();
return 0;
diff --git a/chromium/net/reporting/reporting_garbage_collector.cc b/chromium/net/reporting/reporting_garbage_collector.cc
index be1cc8688bc..e144c5fe4d9 100644
--- a/chromium/net/reporting/reporting_garbage_collector.cc
+++ b/chromium/net/reporting/reporting_garbage_collector.cc
@@ -70,10 +70,8 @@ class ReportingGarbageCollectorImpl : public ReportingGarbageCollector,
// Don't restart the timer on the garbage collector's own updates.
context_->RemoveCacheObserver(this);
- context_->cache()->RemoveReports(failed_reports,
- ReportingReport::Outcome::ERASED_FAILED);
- context_->cache()->RemoveReports(expired_reports,
- ReportingReport::Outcome::ERASED_EXPIRED);
+ context_->cache()->RemoveReports(failed_reports);
+ context_->cache()->RemoveReports(expired_reports);
context_->AddCacheObserver(this);
}
diff --git a/chromium/net/reporting/reporting_header_parser.cc b/chromium/net/reporting/reporting_header_parser.cc
index 10f6cef3041..d26f1790a74 100644
--- a/chromium/net/reporting/reporting_header_parser.cc
+++ b/chromium/net/reporting/reporting_header_parser.cc
@@ -194,18 +194,15 @@ bool ProcessEndpointGroup(ReportingDelegate* delegate,
// Processes a single endpoint tuple received in a Reporting-Endpoints header.
//
// |group_key| is the key for the endpoint group this endpoint belongs.
-// |value| is the parsed parameterized member representing the endpoint url.
+// |endpoint_url_string| is the endpoint url as received in the header.
//
// |endpoint_info_out| is the endpoint info parsed out of the value.
-bool ProcessEndpointStructuredHeader(
- ReportingDelegate* delegate,
- const ReportingEndpointGroupKey& group_key,
- const structured_headers::ParameterizedMember& value,
- ReportingEndpoint::EndpointInfo& endpoint_info_out) {
- if (value.member_is_inner_list || !value.member.front().item.is_string())
+bool ProcessEndpoint(ReportingDelegate* delegate,
+ const ReportingEndpointGroupKey& group_key,
+ const std::string& endpoint_url_string,
+ ReportingEndpoint::EndpointInfo& endpoint_info_out) {
+ if (endpoint_url_string.empty())
return false;
- const std::string& endpoint_url_string =
- value.member.front().item.GetString();
GURL endpoint_url;
if (!ProcessEndpointURLString(endpoint_url_string, group_key.origin,
@@ -227,15 +224,16 @@ bool ProcessEndpointStructuredHeader(
// the endpoint group we create here is just a wrapper for that endpoint. The
// endpoint name will be stored in the group name here as individual endpoint
// doesn't have names.
-bool ProcessEndpointGroupStructuredHeader(
+bool ProcessDocumentEndpoint(
ReportingDelegate* delegate,
ReportingCache* cache,
const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
- const structured_headers::DictionaryMember& value,
+ const std::string& endpoint_name,
+ const std::string& endpoint_url_string,
ReportingEndpointGroup& parsed_endpoint_group_out) {
ReportingEndpointGroupKey group_key(network_isolation_key, origin,
- value.first);
+ endpoint_name);
parsed_endpoint_group_out.group_key = group_key;
// Default to a fixed number of days as Reporting-Endpoints doesn't have the
@@ -246,8 +244,8 @@ bool ProcessEndpointGroupStructuredHeader(
ReportingEndpoint::EndpointInfo parsed_endpoint;
- if (!ProcessEndpointStructuredHeader(delegate, group_key, value.second,
- parsed_endpoint)) {
+ if (!ProcessEndpoint(delegate, group_key, endpoint_url_string,
+ parsed_endpoint)) {
// Remove the group if it does not have a proper endpoint.
cache->RemoveEndpointGroup(group_key);
return false;
@@ -258,6 +256,26 @@ bool ProcessEndpointGroupStructuredHeader(
} // namespace
+absl::optional<base::flat_map<std::string, std::string>>
+ParseReportingEndpoints(const std::string& header) {
+ absl::optional<structured_headers::Dictionary> header_dict =
+ structured_headers::ParseDictionary(header);
+ if (!header_dict) {
+ return absl::nullopt;
+ }
+ base::flat_map<std::string, std::string> parsed_header;
+ for (const structured_headers::DictionaryMember& entry : *header_dict) {
+ if (entry.second.member_is_inner_list ||
+ !entry.second.member.front().item.is_string()) {
+ return absl::nullopt;
+ }
+ const std::string& endpoint_url_string =
+ entry.second.member.front().item.GetString();
+ parsed_header[entry.first] = endpoint_url_string;
+ }
+ return parsed_header;
+}
+
// static
void ReportingHeaderParser::RecordReportingHeaderType(
ReportingHeaderType header_type) {
@@ -311,11 +329,11 @@ void ReportingHeaderParser::ParseReportToHeader(
}
// static
-void ReportingHeaderParser::ParseReportingEndpointsHeader(
+void ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
ReportingContext* context,
const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
- std::unique_ptr<structured_headers::Dictionary> value) {
+ base::flat_map<std::string, std::string> header) {
DCHECK(base::FeatureList::IsEnabled(net::features::kDocumentReporting));
DCHECK(GURL::SchemeIsCryptographic(origin.scheme()));
@@ -324,12 +342,11 @@ void ReportingHeaderParser::ParseReportingEndpointsHeader(
std::vector<ReportingEndpointGroup> parsed_header;
- for (const structured_headers::DictionaryMember& member : *value) {
- ReportingEndpointGroup parsed_endpoint_group;
- if (ProcessEndpointGroupStructuredHeader(delegate, cache,
- network_isolation_key, origin,
- member, parsed_endpoint_group)) {
- parsed_header.push_back(std::move(parsed_endpoint_group));
+ for (const auto& member : header) {
+ ReportingEndpointGroup parsed_endpoint;
+ if (ProcessDocumentEndpoint(delegate, cache, network_isolation_key, origin,
+ member.first, member.second, parsed_endpoint)) {
+ parsed_header.push_back(std::move(parsed_endpoint));
}
}
diff --git a/chromium/net/reporting/reporting_header_parser.h b/chromium/net/reporting/reporting_header_parser.h
index a332f4529b8..6a1b955ee9a 100644
--- a/chromium/net/reporting/reporting_header_parser.h
+++ b/chromium/net/reporting/reporting_header_parser.h
@@ -7,9 +7,11 @@
#include <memory>
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "net/base/net_export.h"
#include "net/http/structured_headers.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
@@ -22,6 +24,13 @@ namespace net {
class NetworkIsolationKey;
class ReportingContext;
+// Tries to parse a Reporting-Endpoints header. Returns base::nullopt if parsing
+// failed and the header should be ignored; otherwise returns a (possibly
+// empty) mapping of endpoint names to URLs.
+NET_EXPORT
+absl::optional<base::flat_map<std::string, std::string>>
+ParseReportingEndpoints(const std::string& header);
+
class NET_EXPORT ReportingHeaderParser {
public:
// These values are persisted to logs. Entries should not be renumbered and
@@ -38,11 +47,11 @@ class NET_EXPORT ReportingHeaderParser {
const GURL& url,
std::unique_ptr<base::Value> value);
- static void ParseReportingEndpointsHeader(
+ static void ProcessParsedReportingEndpointsHeader(
ReportingContext* context,
const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
- std::unique_ptr<structured_headers::Dictionary> value);
+ base::flat_map<std::string, std::string> parsed_header);
static void RecordReportingHeaderType(ReportingHeaderType header_type);
diff --git a/chromium/net/reporting/reporting_header_parser_unittest.cc b/chromium/net/reporting/reporting_header_parser_unittest.cc
index fe0dc05367f..af7eaf74d75 100644
--- a/chromium/net/reporting/reporting_header_parser_unittest.cc
+++ b/chromium/net/reporting/reporting_header_parser_unittest.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/json/json_reader.h"
-#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -1774,14 +1773,12 @@ class ReportingHeaderParserStructuredHeaderTest
void ParseHeader(const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
const std::string& header_string) {
- absl::optional<Dictionary> header_dict =
- structured_headers::ParseDictionary(header_string);
-
- if (header_dict) {
- std::unique_ptr<Dictionary> header_value =
- std::make_unique<Dictionary>(std::move(*header_dict));
- ReportingHeaderParser::ParseReportingEndpointsHeader(
- context(), network_isolation_key, origin, std::move(header_value));
+ absl::optional<base::flat_map<std::string, std::string>> header_map =
+ ParseReportingEndpoints(header_string);
+
+ if (header_map) {
+ ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
+ context(), network_isolation_key, origin, *header_map);
}
}
};
diff --git a/chromium/net/reporting/reporting_network_change_observer.cc b/chromium/net/reporting/reporting_network_change_observer.cc
index c7acb8843fe..4e1d20ea04d 100644
--- a/chromium/net/reporting/reporting_network_change_observer.cc
+++ b/chromium/net/reporting/reporting_network_change_observer.cc
@@ -39,8 +39,7 @@ class ReportingNetworkChangeObserverImpl
return;
if (!context_->policy().persist_reports_across_network_changes)
- context_->cache()->RemoveAllReports(
- ReportingReport::Outcome::ERASED_NETWORK_CHANGED);
+ context_->cache()->RemoveAllReports();
if (!context_->policy().persist_clients_across_network_changes)
context_->cache()->RemoveAllClients();
diff --git a/chromium/net/reporting/reporting_report.cc b/chromium/net/reporting/reporting_report.cc
index 3bc047dfcb6..ce0befe51fe 100644
--- a/chromium/net/reporting/reporting_report.cc
+++ b/chromium/net/reporting/reporting_report.cc
@@ -8,23 +8,14 @@
#include <string>
#include <utility>
-#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "base/values.h"
#include "url/gurl.h"
namespace net {
-namespace {
-
-void RecordReportOutcome(ReportingReport::Outcome outcome) {
- UMA_HISTOGRAM_ENUMERATION("Net.Reporting.ReportOutcome", outcome,
- ReportingReport::Outcome::MAX);
-}
-
-} // namespace
-
ReportingReport::ReportingReport(
+ const absl::optional<base::UnguessableToken>& reporting_source,
const NetworkIsolationKey& network_isolation_key,
const GURL& url,
const std::string& user_agent,
@@ -34,7 +25,8 @@ ReportingReport::ReportingReport(
int depth,
base::TimeTicks queued,
int attempts)
- : network_isolation_key(network_isolation_key),
+ : reporting_source(reporting_source),
+ network_isolation_key(network_isolation_key),
url(url),
user_agent(user_agent),
group(group),
@@ -42,27 +34,18 @@ ReportingReport::ReportingReport(
body(std::move(body)),
depth(depth),
queued(queued),
- attempts(attempts) {}
-
-ReportingReport::~ReportingReport() {
- RecordReportOutcome(outcome);
+ attempts(attempts) {
+ // If |reporting_source| is present, it must not be empty.
+ DCHECK(!(reporting_source.has_value() && reporting_source->is_empty()));
}
+ReportingReport::~ReportingReport() = default;
+
ReportingEndpointGroupKey ReportingReport::GetGroupKey() const {
- return ReportingEndpointGroupKey(network_isolation_key,
+ return ReportingEndpointGroupKey(network_isolation_key, reporting_source,
url::Origin::Create(url), group);
}
-// static
-void ReportingReport::RecordReportDiscardedForNoURLRequestContext() {
- RecordReportOutcome(Outcome::DISCARDED_NO_URL_REQUEST_CONTEXT);
-}
-
-// static
-void ReportingReport::RecordReportDiscardedForNoReportingService() {
- RecordReportOutcome(Outcome::DISCARDED_NO_REPORTING_SERVICE);
-}
-
bool ReportingReport::IsUploadPending() const {
return status == Status::PENDING || status == Status::DOOMED;
}
diff --git a/chromium/net/reporting/reporting_report.h b/chromium/net/reporting/reporting_report.h
index 5da1dc27693..049095bec70 100644
--- a/chromium/net/reporting/reporting_report.h
+++ b/chromium/net/reporting/reporting_report.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/time/time.h"
+#include "base/unguessable_token.h"
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
#include "net/reporting/reporting_endpoint.h"
@@ -24,22 +25,6 @@ namespace net {
// An undelivered report.
struct NET_EXPORT ReportingReport {
public:
- // Used in histograms; please add new items at end and do not reorder.
- enum class Outcome {
- UNKNOWN = 0,
- DISCARDED_NO_URL_REQUEST_CONTEXT = 1,
- DISCARDED_NO_REPORTING_SERVICE = 2,
- ERASED_FAILED = 3,
- ERASED_EXPIRED = 4,
- ERASED_EVICTED = 5,
- ERASED_NETWORK_CHANGED = 6,
- ERASED_BROWSING_DATA_REMOVED = 7,
- ERASED_REPORTING_SHUT_DOWN = 8,
- DELIVERED = 9,
-
- MAX
- };
-
enum class Status {
// Report has been queued but no attempt has been made to deliver it yet.
QUEUED,
@@ -53,17 +38,18 @@ struct NET_EXPORT ReportingReport {
};
// TODO(chlily): Remove |attempts| argument as it is (almost?) always 0.
- ReportingReport(const NetworkIsolationKey& network_isolation_key,
- const GURL& url,
- const std::string& user_agent,
- const std::string& group,
- const std::string& type,
- std::unique_ptr<const base::Value> body,
- int depth,
- base::TimeTicks queued,
- int attempts);
-
- // Records metrics about report outcome.
+ ReportingReport(
+ const absl::optional<base::UnguessableToken>& reporting_source,
+ const NetworkIsolationKey& network_isolation_key,
+ const GURL& url,
+ const std::string& user_agent,
+ const std::string& group,
+ const std::string& type,
+ std::unique_ptr<const base::Value> body,
+ int depth,
+ base::TimeTicks queued,
+ int attempts);
+
~ReportingReport();
// Bundles together the NIK, origin of the report URL, and group name.
@@ -79,6 +65,17 @@ struct NET_EXPORT ReportingReport {
// Whether the report is part of an ongoing delivery attempt.
bool IsUploadPending() const;
+ // The reporting source token for the document or worker which triggered this
+ // report, if it can be associated with one, or nullopt otherwise (Network
+ // reports, such as NEL, for instance, do not support such attribution.)
+ // This is used to identify appropriate endpoints to deliver this report to;
+ // reports with an attached source token may be delivered to a named endpoint
+ // with a matching source, but are also eligible to be delivered to an
+ // endpoint group without a source. Reports without a source token can only be
+ // delivered to endpoint groups without one.
+ // (Not included in the delivered report.)
+ absl::optional<base::UnguessableToken> reporting_source;
+
// The NIK of the request that triggered this report. (Not included in the
// delivered report.)
NetworkIsolationKey network_isolation_key;
@@ -113,8 +110,6 @@ struct NET_EXPORT ReportingReport {
// attempt. (Not included in the delivered report.)
int attempts = 0;
- Outcome outcome = Outcome::UNKNOWN;
-
Status status = Status::QUEUED;
DISALLOW_COPY_AND_ASSIGN(ReportingReport);
diff --git a/chromium/net/reporting/reporting_service.cc b/chromium/net/reporting/reporting_service.cc
index 3e237a8f245..d59d46953f8 100644
--- a/chromium/net/reporting/reporting_service.cc
+++ b/chromium/net/reporting/reporting_service.cc
@@ -32,7 +32,6 @@ namespace {
constexpr int kMaxJsonSize = 16 * 1024;
constexpr int kMaxJsonDepth = 5;
-constexpr int kMaxSHSize = 16 * 1024;
// If constructed with a PersistentReportingStore, the first call to any of
// QueueReport(), ProcessHeader(), RemoveBrowsingData(), or
@@ -56,6 +55,16 @@ class ReportingServiceImpl : public ReportingService {
context_->cache()->Flush();
}
+ void SetDocumentReportingEndpoints(
+ const url::Origin& origin,
+ const net::NetworkIsolationKey& network_isolation_key,
+ const base::flat_map<std::string, std::string>& endpoints) override {
+ DoOrBacklogTask(base::BindOnce(
+ &ReportingServiceImpl::DoSetDocumentReportingEndpoints,
+ base::Unretained(this), FixupNetworkIsolationKey(network_isolation_key),
+ origin, endpoints));
+ }
+
void QueueReport(const GURL& url,
const NetworkIsolationKey& network_isolation_key,
const std::string& user_agent,
@@ -104,31 +113,6 @@ class ReportingServiceImpl : public ReportingService {
std::move(header_value)));
}
- void ProcessReportingEndpointsHeader(
- const url::Origin& origin,
- const NetworkIsolationKey& network_isolation_key,
- const std::string& header_string) override {
- if (header_string.size() == 0 || header_string.size() > kMaxSHSize)
- return;
-
- absl::optional<structured_headers::Dictionary> header_dict =
- structured_headers::ParseDictionary(header_string);
- if (!header_dict) {
- DVLOG(1) << "Error processing Reporting-Endpoints header string: "
- << header_string;
- return;
- }
- std::unique_ptr<structured_headers::Dictionary> header_value =
- std::make_unique<structured_headers::Dictionary>(
- std::move(*header_dict));
-
- DVLOG(1) << "Received Reporting-Endpoints header policy for " << origin;
- DoOrBacklogTask(base::BindOnce(
- &ReportingServiceImpl::DoProcessReportingEndpointsHeader,
- base::Unretained(this), FixupNetworkIsolationKey(network_isolation_key),
- origin, std::move(header_value)));
- }
-
void RemoveBrowsingData(uint64_t data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>&
origin_filter) override {
@@ -201,12 +185,12 @@ class ReportingServiceImpl : public ReportingService {
context_.get(), network_isolation_key, url, std::move(header_value));
}
- void DoProcessReportingEndpointsHeader(
+ void DoSetDocumentReportingEndpoints(
const NetworkIsolationKey& network_isolation_key,
const url::Origin& origin,
- std::unique_ptr<structured_headers::Dictionary> header_value) {
+ base::flat_map<std::string, std::string> header_value) {
DCHECK(initialized_);
- ReportingHeaderParser::ParseReportingEndpointsHeader(
+ ReportingHeaderParser::ProcessParsedReportingEndpointsHeader(
context_.get(), network_isolation_key, origin, std::move(header_value));
}
diff --git a/chromium/net/reporting/reporting_service.h b/chromium/net/reporting/reporting_service.h
index ab2859a84ae..07d0c681cb2 100644
--- a/chromium/net/reporting/reporting_service.h
+++ b/chromium/net/reporting/reporting_service.h
@@ -9,6 +9,7 @@
#include <string>
#include "base/callback.h"
+#include "base/containers/flat_map.h"
#include "base/macros.h"
#include "net/base/net_export.h"
#include "net/reporting/reporting_cache.h"
@@ -71,13 +72,13 @@ class NET_EXPORT ReportingService {
const NetworkIsolationKey& network_isolation_key,
const std::string& header_value) = 0;
- // Processes a Reporting-Endpoints header. |url| is the URL that originated
- // the header; |header_value| is the normalized value of the
- // Reporting-Endpoints header.
- virtual void ProcessReportingEndpointsHeader(
+ // Configures reporting endpoints set by the Reporting-Endpoints header, once
+ // the associated document has been committed.
+ // |endpoints| is a mapping of endpoint names to URLs.
+ virtual void SetDocumentReportingEndpoints(
const url::Origin& origin,
const NetworkIsolationKey& network_isolation_key,
- const std::string& header_value) = 0;
+ const base::flat_map<std::string, std::string>& endpoints) = 0;
// Removes browsing data from the Reporting system. See
// ReportingBrowsingDataRemover for more details.
diff --git a/chromium/net/reporting/reporting_service_unittest.cc b/chromium/net/reporting/reporting_service_unittest.cc
index 83874936dce..3ce13d2de27 100644
--- a/chromium/net/reporting/reporting_service_unittest.cc
+++ b/chromium/net/reporting/reporting_service_unittest.cc
@@ -188,8 +188,10 @@ TEST_P(ReportingServiceTest, ProcessReportToHeader) {
TEST_P(ReportingServiceTest, ProcessReportingEndpointsHeader) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
- service()->ProcessReportingEndpointsHeader(
- kOrigin_, kNik_, kGroup_ + "=\"" + kEndpoint_.spec() + "\"");
+ auto parsed_header =
+ ParseReportingEndpoints(kGroup_ + "=\"" + kEndpoint_.spec() + "\"");
+ ASSERT_TRUE(parsed_header.has_value());
+ service()->SetDocumentReportingEndpoints(kOrigin_, kNik_, *parsed_header);
FinishLoading(true /* load_success */);
EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
@@ -200,8 +202,9 @@ TEST_P(ReportingServiceTest, ProcessReportingEndpointsHeader) {
TEST_P(ReportingServiceTest, ProcessReportingEndpointsHeaderPathAbsolute) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(net::features::kDocumentReporting);
- service()->ProcessReportingEndpointsHeader(kOrigin_, kNik_,
- kGroup_ + "=\"/path-absolute\"");
+ auto parsed_header = ParseReportingEndpoints(kGroup_ + "=\"/path-absolute\"");
+ ASSERT_TRUE(parsed_header.has_value());
+ service()->SetDocumentReportingEndpoints(kOrigin_, kNik_, *parsed_header);
FinishLoading(true /* load_success */);
EXPECT_EQ(1u, context()->cache()->GetEndpointCount());
diff --git a/chromium/net/reporting/reporting_test_util.cc b/chromium/net/reporting/reporting_test_util.cc
index 47c3d83e94a..5a36a2f0f1f 100644
--- a/chromium/net/reporting/reporting_test_util.cc
+++ b/chromium/net/reporting/reporting_test_util.cc
@@ -334,13 +334,6 @@ void TestReportingService::ProcessReportToHeader(
NOTREACHED();
}
-void TestReportingService::ProcessReportingEndpointsHeader(
- const url::Origin& origin,
- const NetworkIsolationKey& network_isolation_key,
- const std::string& header_value) {
- NOTREACHED();
-}
-
void TestReportingService::RemoveBrowsingData(
uint64_t data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>& origin_filter) {
diff --git a/chromium/net/reporting/reporting_test_util.h b/chromium/net/reporting/reporting_test_util.h
index 629e7651057..e4648d3759d 100644
--- a/chromium/net/reporting/reporting_test_util.h
+++ b/chromium/net/reporting/reporting_test_util.h
@@ -313,6 +313,11 @@ class TestReportingService : public ReportingService {
~TestReportingService() override;
+ void SetDocumentReportingEndpoints(
+ const url::Origin& origin,
+ const net::NetworkIsolationKey& network_isolation_key,
+ const base::flat_map<std::string, std::string>& endpoints) override {}
+
void QueueReport(const GURL& url,
const NetworkIsolationKey& network_isolation_key,
const std::string& user_agent,
@@ -325,11 +330,6 @@ class TestReportingService : public ReportingService {
const NetworkIsolationKey& network_isolation_key,
const std::string& header_value) override;
- void ProcessReportingEndpointsHeader(
- const url::Origin& origin,
- const NetworkIsolationKey& network_isolation_key,
- const std::string& header_value) override;
-
void RemoveBrowsingData(
uint64_t data_type_mask,
const base::RepeatingCallback<bool(const GURL&)>& origin_filter) override;
diff --git a/chromium/net/reporting/reporting_uploader_unittest.cc b/chromium/net/reporting/reporting_uploader_unittest.cc
index 484184b2576..d2de42ac882 100644
--- a/chromium/net/reporting/reporting_uploader_unittest.cc
+++ b/chromium/net/reporting/reporting_uploader_unittest.cc
@@ -452,8 +452,9 @@ TEST_F(ReportingUploaderTest, DontSendCookies) {
ResultSavingCookieCallback<CookieAccessResult> cookie_callback;
GURL url = server_.GetURL("/");
- auto cookie = CanonicalCookie::Create(url, "foo=bar", base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie = CanonicalCookie::Create(
+ url, "foo=bar", base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
context_.cookie_store()->SetCanonicalCookieAsync(
std::move(cookie), url, CookieOptions::MakeAllInclusive(),
cookie_callback.MakeCallback());
diff --git a/chromium/net/server/OWNERS b/chromium/net/server/OWNERS
new file mode 100644
index 00000000000..4392ef47220
--- /dev/null
+++ b/chromium/net/server/OWNERS
@@ -0,0 +1 @@
+ricea@chromium.org
diff --git a/chromium/net/server/http_server_unittest.cc b/chromium/net/server/http_server_unittest.cc
index 4d2b23f7451..b32ba77c2e2 100644
--- a/chromium/net/server/http_server_unittest.cc
+++ b/chromium/net/server/http_server_unittest.cc
@@ -8,6 +8,7 @@
#include <algorithm>
#include <memory>
+#include <unordered_map>
#include <utility>
#include <vector>
@@ -16,6 +17,7 @@
#include "base/callback_helpers.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
#include "base/location.h"
#include "base/memory/ptr_util.h"
@@ -24,7 +26,6 @@
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/net/socket/client_socket_handle.cc b/chromium/net/socket/client_socket_handle.cc
index 8a265355524..d9b84c75759 100644
--- a/chromium/net/socket/client_socket_handle.cc
+++ b/chromium/net/socket/client_socket_handle.cc
@@ -46,7 +46,7 @@ int ClientSocketHandle::Init(
const NetLogWithSource& net_log) {
requesting_source_ = net_log.source();
- CHECK(!group_id.destination().IsEmpty());
+ CHECK(group_id.destination().IsValid());
ResetInternal(true /* cancel */, false /* cancel_connect_job */);
ResetErrorState();
pool_ = pool;
@@ -90,7 +90,7 @@ void ClientSocketHandle::ResetAndCloseSocket() {
LoadState ClientSocketHandle::GetLoadState() const {
CHECK(!is_initialized());
- CHECK(!group_id_.destination().IsEmpty());
+ CHECK(group_id_.destination().IsValid());
// Because of http://crbug.com/37810 we may not have a pool, but have
// just a raw socket.
if (!pool_)
@@ -211,7 +211,7 @@ void ClientSocketHandle::ResetInternal(bool cancel, bool cancel_connect_job) {
DCHECK(cancel || !cancel_connect_job);
// Was Init called?
- if (!group_id_.destination().IsEmpty()) {
+ if (group_id_.destination().IsValid()) {
// If so, we must have a pool.
CHECK(pool_);
if (is_initialized()) {
diff --git a/chromium/net/socket/client_socket_handle.h b/chromium/net/socket/client_socket_handle.h
index 1a8f4c5499a..2e41eba29f6 100644
--- a/chromium/net/socket/client_socket_handle.h
+++ b/chromium/net/socket/client_socket_handle.h
@@ -6,7 +6,6 @@
#define NET_SOCKET_CLIENT_SOCKET_HANDLE_H_
#include <memory>
-#include <string>
#include <utility>
#include "base/bind.h"
diff --git a/chromium/net/socket/client_socket_pool.cc b/chromium/net/socket/client_socket_pool.cc
index 60d011d3fb5..f3ec46ff9b0 100644
--- a/chromium/net/socket/client_socket_pool.cc
+++ b/chromium/net/socket/client_socket_pool.cc
@@ -4,22 +4,29 @@
#include "net/socket/client_socket_pool.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/check_op.h"
#include "base/feature_list.h"
#include "net/base/features.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/proxy_server.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_proxy_connect_job.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/connect_job.h"
+#include "net/socket/connect_job_factory.h"
#include "net/socket/socks_connect_job.h"
#include "net/socket/ssl_connect_job.h"
#include "net/socket/stream_socket.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_session_pool.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
@@ -66,23 +73,27 @@ ClientSocketPool::SocketParams::CreateForHttpForTesting() {
}
ClientSocketPool::GroupId::GroupId()
- : socket_type_(SocketType::kHttp),
- privacy_mode_(PrivacyMode::PRIVACY_MODE_DISABLED) {}
+ : privacy_mode_(PrivacyMode::PRIVACY_MODE_DISABLED) {}
-ClientSocketPool::GroupId::GroupId(const HostPortPair& destination,
- SocketType socket_type,
+ClientSocketPool::GroupId::GroupId(url::SchemeHostPort destination,
PrivacyMode privacy_mode,
NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy)
- : destination_(destination),
- socket_type_(socket_type),
+ : destination_(std::move(destination)),
privacy_mode_(privacy_mode),
network_isolation_key_(
base::FeatureList::IsEnabled(
features::kPartitionConnectionsByNetworkIsolationKey)
- ? network_isolation_key
+ ? std::move(network_isolation_key)
: NetworkIsolationKey()),
- secure_dns_policy_(secure_dns_policy) {}
+ secure_dns_policy_(secure_dns_policy) {
+ DCHECK(destination_.IsValid());
+
+ // ClientSocketPool only expected to be used for HTTP/HTTPS/WS/WSS cases, and
+ // "ws"/"wss" schemes should be converted to "http"/"https" equivalent first.
+ DCHECK(destination_.scheme() == url::kHttpScheme ||
+ destination_.scheme() == url::kHttpsScheme);
+}
ClientSocketPool::GroupId::GroupId(const GroupId& group_id) = default;
@@ -95,15 +106,8 @@ ClientSocketPool::GroupId& ClientSocketPool::GroupId::operator=(
GroupId&& group_id) = default;
std::string ClientSocketPool::GroupId::ToString() const {
- std::string result = destination_.ToString();
- switch (socket_type_) {
- case ClientSocketPool::SocketType::kHttp:
- break;
+ std::string result = destination_.Serialize();
- case ClientSocketPool::SocketType::kSsl:
- result = "ssl/" + result;
- break;
- }
if (privacy_mode_)
result = "pm/" + result;
@@ -138,7 +142,13 @@ void ClientSocketPool::set_used_idle_socket_timeout(base::TimeDelta timeout) {
g_used_idle_socket_timeout_s = timeout.InSeconds();
}
-ClientSocketPool::ClientSocketPool() = default;
+ClientSocketPool::ClientSocketPool(
+ bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
+ std::unique_ptr<ConnectJobFactory> connect_job_factory)
+ : is_for_websockets_(is_for_websockets),
+ common_connect_job_params_(common_connect_job_params),
+ connect_job_factory_(std::move(connect_job_factory)) {}
void ClientSocketPool::NetLogTcpClientSocketPoolRequestedSocket(
const NetLogWithSource& net_log,
@@ -161,42 +171,44 @@ std::unique_ptr<ConnectJob> ClientSocketPool::CreateConnectJob(
scoped_refptr<SocketParams> socket_params,
const ProxyServer& proxy_server,
const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- bool is_for_websockets,
- const CommonConnectJobParams* common_connect_job_params,
RequestPriority request_priority,
SocketTag socket_tag,
ConnectJob::Delegate* delegate) {
- bool using_ssl = group_id.socket_type() == ClientSocketPool::SocketType::kSsl;
+ bool using_ssl = GURL::SchemeIsCryptographic(group_id.destination().scheme());
// If applicable, set up a callback to handle checking for H2 IP pooling
// opportunities.
OnHostResolutionCallback resolution_callback;
if (using_ssl && proxy_server.is_direct()) {
resolution_callback = base::BindRepeating(
- &OnHostResolution, common_connect_job_params->spdy_session_pool,
- SpdySessionKey(
- group_id.destination(), proxy_server, group_id.privacy_mode(),
- SpdySessionKey::IsProxySession::kFalse, socket_tag,
- group_id.network_isolation_key(), group_id.secure_dns_policy()),
- is_for_websockets);
+ &OnHostResolution, common_connect_job_params_->spdy_session_pool,
+ // TODO(crbug.com/1206799): Pass along as SchemeHostPort.
+ SpdySessionKey(HostPortPair::FromSchemeHostPort(group_id.destination()),
+ proxy_server, group_id.privacy_mode(),
+ SpdySessionKey::IsProxySession::kFalse, socket_tag,
+ group_id.network_isolation_key(),
+ group_id.secure_dns_policy()),
+ is_for_websockets_);
} else if (proxy_server.is_https()) {
resolution_callback = base::BindRepeating(
- &OnHostResolution, common_connect_job_params->spdy_session_pool,
+ &OnHostResolution, common_connect_job_params_->spdy_session_pool,
SpdySessionKey(proxy_server.host_port_pair(), ProxyServer::Direct(),
group_id.privacy_mode(),
SpdySessionKey::IsProxySession::kTrue, socket_tag,
group_id.network_isolation_key(),
group_id.secure_dns_policy()),
- is_for_websockets);
+ is_for_websockets_);
}
- return ConnectJob::CreateConnectJob(
- using_ssl, group_id.destination(), proxy_server, proxy_annotation_tag,
+ // TODO(crbug.com/1206799): Pass along as SchemeHostPort.
+ return connect_job_factory_->CreateConnectJob(
+ using_ssl, HostPortPair::FromSchemeHostPort(group_id.destination()),
+ proxy_server, proxy_annotation_tag,
socket_params->ssl_config_for_origin(),
- socket_params->ssl_config_for_proxy(), is_for_websockets,
+ socket_params->ssl_config_for_proxy(), is_for_websockets_,
group_id.privacy_mode(), resolution_callback, request_priority,
socket_tag, group_id.network_isolation_key(),
- group_id.secure_dns_policy(), common_connect_job_params, delegate);
+ group_id.secure_dns_policy(), common_connect_job_params_, delegate);
}
} // namespace net
diff --git a/chromium/net/socket/client_socket_pool.h b/chromium/net/socket/client_socket_pool.h
index 5bd1661451c..900051df32b 100644
--- a/chromium/net/socket/client_socket_pool.h
+++ b/chromium/net/socket/client_socket_pool.h
@@ -24,6 +24,7 @@
#include "net/socket/connect_job.h"
#include "net/socket/socket_tag.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
namespace base {
class Value;
@@ -35,7 +36,7 @@ class ProcessMemoryDump;
namespace net {
class ClientSocketHandle;
-struct CommonConnectJobParams;
+class ConnectJobFactory;
class HttpAuthController;
class HttpResponseInfo;
class NetLogWithSource;
@@ -97,21 +98,12 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
base::OnceClosure restart_with_auth_callback)>
ProxyAuthCallback;
- enum class SocketType {
- kHttp,
-
- // This is a connection that uses an SSL connection to the final
- // destination, though not necessarily to the proxy, if there is one.
- kSsl,
- };
-
// Group ID for a socket request. Requests with the same group ID are
// considered indistinguishable.
class NET_EXPORT GroupId {
public:
GroupId();
- GroupId(const HostPortPair& destination,
- SocketType socket_type,
+ GroupId(url::SchemeHostPort destination,
PrivacyMode privacy_mode,
NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy);
@@ -122,9 +114,7 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
GroupId& operator=(const GroupId& group_id);
GroupId& operator=(GroupId&& group_id);
- const HostPortPair& destination() const { return destination_; }
-
- SocketType socket_type() const { return socket_type_; }
+ const url::SchemeHostPort& destination() const { return destination_; }
PrivacyMode privacy_mode() const { return privacy_mode_; }
@@ -138,26 +128,22 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
std::string ToString() const;
bool operator==(const GroupId& other) const {
- return std::tie(destination_, socket_type_, privacy_mode_,
- network_isolation_key_, secure_dns_policy_) ==
- std::tie(other.destination_, other.socket_type_,
- other.privacy_mode_, other.network_isolation_key_,
- other.secure_dns_policy_);
+ return std::tie(destination_, privacy_mode_, network_isolation_key_,
+ secure_dns_policy_) ==
+ std::tie(other.destination_, other.privacy_mode_,
+ other.network_isolation_key_, other.secure_dns_policy_);
}
bool operator<(const GroupId& other) const {
- return std::tie(destination_, socket_type_, privacy_mode_,
- network_isolation_key_, secure_dns_policy_) <
- std::tie(other.destination_, other.socket_type_,
- other.privacy_mode_, other.network_isolation_key_,
- other.secure_dns_policy_);
+ return std::tie(destination_, privacy_mode_, network_isolation_key_,
+ secure_dns_policy_) <
+ std::tie(other.destination_, other.privacy_mode_,
+ other.network_isolation_key_, other.secure_dns_policy_);
}
private:
- // The host and port of the final destination (not the proxy).
- HostPortPair destination_;
-
- SocketType socket_type_;
+ // The endpoint of the final destination (not the proxy).
+ url::SchemeHostPort destination_;
// If this request is for a privacy mode / uncredentialed connection.
PrivacyMode privacy_mode_;
@@ -355,7 +341,9 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
static void set_used_idle_socket_timeout(base::TimeDelta timeout);
protected:
- ClientSocketPool();
+ ClientSocketPool(bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
+ std::unique_ptr<ConnectJobFactory> connect_job_factory);
void NetLogTcpClientSocketPoolRequestedSocket(const NetLogWithSource& net_log,
const GroupId& group_id);
@@ -363,18 +351,20 @@ class NET_EXPORT ClientSocketPool : public LowerLayeredPool {
// Utility method to log a GroupId with a NetLog event.
static base::Value NetLogGroupIdParams(const GroupId& group_id);
- static std::unique_ptr<ConnectJob> CreateConnectJob(
+ std::unique_ptr<ConnectJob> CreateConnectJob(
GroupId group_id,
scoped_refptr<SocketParams> socket_params,
const ProxyServer& proxy_server,
const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- bool is_for_websockets,
- const CommonConnectJobParams* common_connect_job_params,
RequestPriority request_priority,
SocketTag socket_tag,
ConnectJob::Delegate* delegate);
private:
+ const bool is_for_websockets_;
+ const CommonConnectJobParams* const common_connect_job_params_;
+ const std::unique_ptr<ConnectJobFactory> connect_job_factory_;
+
DISALLOW_COPY_AND_ASSIGN(ClientSocketPool);
};
diff --git a/chromium/net/socket/client_socket_pool_base_unittest.cc b/chromium/net/socket/client_socket_pool_base_unittest.cc
index 80d4868698b..b9e924c6d0f 100644
--- a/chromium/net/socket/client_socket_pool_base_unittest.cc
+++ b/chromium/net/socket/client_socket_pool_base_unittest.cc
@@ -12,13 +12,13 @@
#include "base/callback.h"
#include "base/callback_helpers.h"
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
@@ -26,6 +26,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "net/base/features.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_timing_info.h"
#include "net/base/load_timing_info_test_util.h"
#include "net/base/net_errors.h"
@@ -47,6 +48,7 @@
#include "net/log/test_net_log_util.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
+#include "net/socket/connect_job_factory.h"
#include "net/socket/datagram_client_socket.h"
#include "net/socket/socket_performance_watcher.h"
#include "net/socket/socket_tag.h"
@@ -62,6 +64,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -79,13 +83,12 @@ constexpr base::TimeDelta kUnusedIdleSocketTimeout =
base::TimeDelta::FromSeconds(10);
ClientSocketPool::GroupId TestGroupId(
- const std::string& host,
+ base::StringPiece host,
int port = 80,
- ClientSocketPool::SocketType socket_type =
- ClientSocketPool::SocketType::kHttp,
+ base::StringPiece scheme = url::kHttpScheme,
PrivacyMode privacy_mode = PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey network_isolation_key = NetworkIsolationKey()) {
- return ClientSocketPool::GroupId(HostPortPair(host, port), socket_type,
+ return ClientSocketPool::GroupId(url::SchemeHostPort(scheme, host, port),
privacy_mode, network_isolation_key,
SecureDnsPolicy::kAllow);
}
@@ -538,29 +541,10 @@ class TestConnectJob : public ConnectJob {
DISALLOW_COPY_AND_ASSIGN(TestConnectJob);
};
-class TestConnectJobFactory
- : public TransportClientSocketPool::ConnectJobFactory {
+class TestConnectJobFactory : public ConnectJobFactory {
public:
- TestConnectJobFactory(MockClientSocketFactory* client_socket_factory,
- NetLog* net_log)
- : common_connect_job_params_(
- nullptr /* client_socket_factory */,
- nullptr /* host_resolver */,
- nullptr /* http_auth_cache */,
- nullptr /* http_auth_handler_factory */,
- nullptr /* spdy_session_pool */,
- nullptr /* quic_supported_versions */,
- nullptr /* quic_stream_factory */,
- nullptr /* proxy_delegate */,
- nullptr /* http_user_agent_settings */,
- nullptr /* ssl_client_context */,
- nullptr /* socket_performance_watcher_factory */,
- nullptr /* network_quality_estimator */,
- net_log,
- nullptr /* websocket_endpoint_lock_manager */),
- job_type_(TestConnectJob::kMockJob),
- job_types_(nullptr),
- client_socket_factory_(client_socket_factory) {}
+ explicit TestConnectJobFactory(MockClientSocketFactory* client_socket_factory)
+ : client_socket_factory_(client_socket_factory) {}
~TestConnectJobFactory() override = default;
@@ -577,12 +561,20 @@ class TestConnectJobFactory
// ConnectJobFactory implementation.
- std::unique_ptr<ConnectJob> NewConnectJob(
- ClientSocketPool::GroupId group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
+ std::unique_ptr<ConnectJob> CreateConnectJob(
+ Endpoint endpoint,
+ const ProxyServer& proxy_server,
const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
RequestPriority request_priority,
SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
ConnectJob::Delegate* delegate) const override {
EXPECT_TRUE(!job_types_ || !job_types_->empty());
TestConnectJob::JobType job_type = job_type_;
@@ -592,13 +584,12 @@ class TestConnectJobFactory
}
return std::make_unique<TestConnectJob>(
job_type, request_priority, socket_tag, timeout_duration_,
- &common_connect_job_params_, delegate, client_socket_factory_);
+ common_connect_job_params, delegate, client_socket_factory_);
}
private:
- const CommonConnectJobParams common_connect_job_params_;
- TestConnectJob::JobType job_type_;
- std::list<TestConnectJob::JobType>* job_types_;
+ TestConnectJob::JobType job_type_ = TestConnectJob::kMockJob;
+ std::list<TestConnectJob::JobType>* job_types_ = nullptr;
base::TimeDelta timeout_duration_;
MockClientSocketFactory* const client_socket_factory_;
@@ -667,12 +658,12 @@ class ClientSocketPoolBaseTest : public TestWithTaskEnvironment {
ProxyServer proxy_server = ProxyServer::Direct()) {
DCHECK(!pool_.get());
std::unique_ptr<TestConnectJobFactory> connect_job_factory =
- std::make_unique<TestConnectJobFactory>(&client_socket_factory_,
- &net_log_);
+ std::make_unique<TestConnectJobFactory>(&client_socket_factory_);
connect_job_factory_ = connect_job_factory.get();
pool_ = TransportClientSocketPool::CreateForTesting(
max_sockets, max_sockets_per_group, unused_idle_socket_timeout,
- used_idle_socket_timeout, proxy_server, std::move(connect_job_factory),
+ used_idle_socket_timeout, proxy_server, /*is_for_websockets=*/false,
+ &common_connect_job_params_, std::move(connect_job_factory),
nullptr /* ssl_config_service */, enable_backup_connect_jobs);
}
@@ -727,6 +718,21 @@ class ClientSocketPoolBaseTest : public TestWithTaskEnvironment {
size_t completion_count() const { return test_base_.completion_count(); }
RecordingTestNetLog net_log_;
+ const CommonConnectJobParams common_connect_job_params_{
+ nullptr /* client_socket_factory */,
+ nullptr /* host_resolver */,
+ nullptr /* http_auth_cache */,
+ nullptr /* http_auth_handler_factory */,
+ nullptr /* spdy_session_pool */,
+ nullptr /* quic_supported_versions */,
+ nullptr /* quic_stream_factory */,
+ nullptr /* proxy_delegate */,
+ nullptr /* http_user_agent_settings */,
+ nullptr /* ssl_client_context */,
+ nullptr /* socket_performance_watcher_factory */,
+ nullptr /* network_quality_estimator */,
+ &net_log_,
+ nullptr /* websocket_endpoint_lock_manager */};
bool connect_backup_jobs_enabled_;
MockClientSocketFactory client_socket_factory_;
TestConnectJobFactory* connect_job_factory_;
@@ -856,9 +862,9 @@ TEST_F(ClientSocketPoolBaseTest, GroupSeparation) {
{"b", 80},
};
- const ClientSocketPool::SocketType kSocketTypes[] = {
- ClientSocketPool::SocketType::kHttp,
- ClientSocketPool::SocketType::kSsl,
+ const char* const kSchemes[] = {
+ url::kHttpScheme,
+ url::kHttpsScheme,
};
const PrivacyMode kPrivacyModes[] = {PrivacyMode::PRIVACY_MODE_DISABLED,
@@ -880,8 +886,8 @@ TEST_F(ClientSocketPoolBaseTest, GroupSeparation) {
// group does not return a previously connected socket for another group.
for (const auto& host_port_pair : kHostPortPairs) {
SCOPED_TRACE(host_port_pair.ToString());
- for (const auto& socket_type : kSocketTypes) {
- SCOPED_TRACE(static_cast<int>(socket_type));
+ for (const char* scheme : kSchemes) {
+ SCOPED_TRACE(scheme);
for (const auto& privacy_mode : kPrivacyModes) {
SCOPED_TRACE(privacy_mode);
for (const auto& network_isolation_key : kNetworkIsolationKeys) {
@@ -892,8 +898,9 @@ TEST_F(ClientSocketPoolBaseTest, GroupSeparation) {
connect_job_factory_->set_job_type(TestConnectJob::kMockPendingJob);
ClientSocketPool::GroupId group_id(
- host_port_pair, socket_type, privacy_mode,
- network_isolation_key, secure_dns_policy);
+ url::SchemeHostPort(scheme, host_port_pair.host(),
+ host_port_pair.port()),
+ privacy_mode, network_isolation_key, secure_dns_policy);
EXPECT_FALSE(pool_->HasGroupForTesting(group_id));
@@ -1301,13 +1308,13 @@ TEST_F(ClientSocketPoolBaseTest, CancelStalledSocketAtSocketLimit) {
ClientSocketHandle handles[kDefaultMaxSockets];
TestCompletionCallback callbacks[kDefaultMaxSockets];
for (int i = 0; i < kDefaultMaxSockets; ++i) {
- EXPECT_EQ(OK,
- handles[i].Init(TestGroupId(base::NumberToString(i)), params_,
- absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callbacks[i].callback(),
- ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
+ EXPECT_EQ(OK, handles[i].Init(TestGroupId("a" + base::NumberToString(i)),
+ params_, absl::nullopt, DEFAULT_PRIORITY,
+ SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callbacks[i].callback(),
+ ClientSocketPool::ProxyAuthCallback(),
+ pool_.get(), NetLogWithSource()));
}
// Force a stalled group.
@@ -1342,12 +1349,12 @@ TEST_F(ClientSocketPoolBaseTest, CancelPendingSocketAtSocketLimit) {
for (int i = 0; i < kDefaultMaxSockets; ++i) {
TestCompletionCallback callback;
EXPECT_EQ(ERR_IO_PENDING,
- handles[i].Init(TestGroupId(base::NumberToString(i)), params_,
- absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(),
- ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
+ handles[i].Init(
+ TestGroupId("a" + base::NumberToString(i)), params_,
+ absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+ pool_.get(), NetLogWithSource()));
}
// Force a stalled group.
@@ -1409,7 +1416,7 @@ TEST_F(ClientSocketPoolBaseTest, WaitForStalledSocketAtSocketLimit) {
TestCompletionCallback callback;
EXPECT_EQ(
OK, handles[i].Init(
- TestGroupId(base::StringPrintf("Take 2: %d", i)), params_,
+ TestGroupId(base::StringPrintf("take-2-%d", i)), params_,
absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
ClientSocketPool::ProxyAuthCallback(), pool_.get(),
@@ -1449,12 +1456,13 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
for (int i = 0; i < kDefaultMaxSockets; ++i) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- EXPECT_EQ(OK, handle.Init(TestGroupId(base::NumberToString(i)), params_,
- absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(),
- ClientSocketPool::ProxyAuthCallback(),
- pool_.get(), NetLogWithSource()));
+ EXPECT_EQ(
+ OK,
+ handle.Init(TestGroupId("a" + base::NumberToString(i)), params_,
+ absl::nullopt, DEFAULT_PRIORITY, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+ pool_.get(), NetLogWithSource()));
}
// Flush all the DoReleaseSocket tasks.
@@ -1466,11 +1474,11 @@ TEST_F(ClientSocketPoolBaseTest, CloseIdleSocketAtSocketLimitDeleteGroup) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- // "0" is special here, since it should be the first entry in the sorted map,
+ // "a0" is special here, since it should be the first entry in the sorted map,
// which is the one which we would close an idle socket for. We shouldn't
// close an idle socket though, since we should reuse the idle socket.
EXPECT_EQ(OK, handle.Init(
- TestGroupId("0"), params_, absl::nullopt, DEFAULT_PRIORITY,
+ TestGroupId("a0"), params_, absl::nullopt, DEFAULT_PRIORITY,
SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
callback.callback(), ClientSocketPool::ProxyAuthCallback(),
pool_.get(), NetLogWithSource()));
@@ -5651,7 +5659,7 @@ class ClientSocketPoolBaseRefreshTest
}
static ClientSocketPool::GroupId GetGroupId() {
- return TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl);
+ return TestGroupId("a", 443, url::kHttpsScheme);
}
static ClientSocketPool::GroupId GetGroupIdInPartition() {
@@ -5659,7 +5667,7 @@ class ClientSocketPoolBaseRefreshTest
// kPartitionConnectionsByNetworkIsolationKey is enabled.
const SchemefulSite kSite(GURL("https://b/"));
const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
- return TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl,
+ return TestGroupId("a", 443, url::kHttpsScheme,
PrivacyMode::PRIVACY_MODE_DISABLED,
kNetworkIsolationKey);
}
@@ -5740,9 +5748,9 @@ TEST_F(ClientSocketPoolBaseTest,
RefreshGroupDoesNotCloseIdleConnectJobsInOtherGroup) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
const ClientSocketPool::GroupId kGroupId =
- TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("a", 443, url::kHttpsScheme);
const ClientSocketPool::GroupId kOtherGroupId =
- TestGroupId("b", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("b", 443, url::kHttpsScheme);
pool_->RequestSockets(kOtherGroupId, params_, absl::nullopt, 2,
NetLogWithSource());
@@ -5782,9 +5790,9 @@ TEST_F(ClientSocketPoolBaseTest,
RefreshGroupDoesNotPreventSocketReuseInOtherGroup) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
const ClientSocketPool::GroupId kGroupId =
- TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("a", 443, url::kHttpsScheme);
const ClientSocketPool::GroupId kOtherGroupId =
- TestGroupId("b", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("b", 443, url::kHttpsScheme);
ClientSocketHandle handle;
TestCompletionCallback callback;
@@ -5852,11 +5860,11 @@ TEST_F(ClientSocketPoolBaseTest, RefreshProxyRefreshesAllGroups) {
ProxyServer::FromPacString("HTTPS myproxy:70"));
const ClientSocketPool::GroupId kGroupId1 =
- TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("a", 443, url::kHttpsScheme);
const ClientSocketPool::GroupId kGroupId2 =
- TestGroupId("b", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("b", 443, url::kHttpsScheme);
const ClientSocketPool::GroupId kGroupId3 =
- TestGroupId("c", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("c", 443, url::kHttpsScheme);
// Make three sockets in three different groups. The third socket is released
// to the pool as idle.
@@ -5924,14 +5932,12 @@ TEST_F(ClientSocketPoolBaseTest, RefreshProxyRefreshesAllGroups) {
TEST_F(ClientSocketPoolBaseTest, RefreshBothPrivacyAndNormalSockets) {
CreatePool(kDefaultMaxSockets, kDefaultMaxSocketsPerGroup);
- const ClientSocketPool::GroupId kGroupId =
- TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED);
- const ClientSocketPool::GroupId kGroupIdPrivacy =
- TestGroupId("a", 443, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_ENABLED);
+ const ClientSocketPool::GroupId kGroupId = TestGroupId(
+ "a", 443, url::kHttpsScheme, PrivacyMode::PRIVACY_MODE_DISABLED);
+ const ClientSocketPool::GroupId kGroupIdPrivacy = TestGroupId(
+ "a", 443, url::kHttpsScheme, PrivacyMode::PRIVACY_MODE_ENABLED);
const ClientSocketPool::GroupId kOtherGroupId =
- TestGroupId("b", 443, ClientSocketPool::SocketType::kSsl);
+ TestGroupId("b", 443, url::kHttpsScheme);
// Make a socket in each groups.
ClientSocketHandle handle1, handle2, handle3;
diff --git a/chromium/net/socket/client_socket_pool_manager.cc b/chromium/net/socket/client_socket_pool_manager.cc
index 0a8e29845fd..c8cf594a9a8 100644
--- a/chromium/net/socket/client_socket_pool_manager.cc
+++ b/chromium/net/socket/client_socket_pool_manager.cc
@@ -5,10 +5,12 @@
#include "net/socket/client_socket_pool_manager.h"
#include <memory>
+#include <utility>
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/metrics/field_trial_params.h"
-#include "base/stl_util.h"
+#include "base/strings/string_piece.h"
#include "build/build_config.h"
#include "net/base/features.h"
#include "net/base/load_flags.h"
@@ -20,6 +22,9 @@
#include "net/socket/connect_job.h"
#include "net/ssl/ssl_config.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
@@ -64,26 +69,6 @@ static_assert(base::size(g_max_sockets_per_proxy_server) ==
HttpNetworkSession::NUM_SOCKET_POOL_TYPES,
"max sockets per proxy server length mismatch");
-ClientSocketPool::GroupId CreateGroupId(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
- const ProxyInfo& proxy_info,
- PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy) {
- // Build the string used to uniquely identify connections of this type.
- // Determine the host and port to connect to.
- DCHECK(!endpoint.IsEmpty());
-
- ClientSocketPool::SocketType socket_type =
- ClientSocketPool::SocketType::kHttp;
- if (group_type == ClientSocketPoolManager::SSL_GROUP)
- socket_type = ClientSocketPool::SocketType::kSsl;
-
- return ClientSocketPool::GroupId(endpoint, socket_type, privacy_mode,
- network_isolation_key, secure_dns_policy);
-}
-
// TODO(https://crbug.com/921369) In order to resolve longstanding issues
// related to pooling distinguishable sockets together, get rid of SocketParams
// entirely.
@@ -92,8 +77,8 @@ scoped_refptr<ClientSocketPool::SocketParams> CreateSocketParams(
const ProxyServer& proxy_server,
const SSLConfig& ssl_config_for_origin,
const SSLConfig& ssl_config_for_proxy) {
- bool using_ssl = group_id.socket_type() == ClientSocketPool::SocketType::kSsl;
- bool using_proxy_ssl = proxy_server.is_http_like() && !proxy_server.is_http();
+ bool using_ssl = GURL::SchemeIsCryptographic(group_id.destination().scheme());
+ bool using_proxy_ssl = proxy_server.is_secure_http_like();
return base::MakeRefCounted<ClientSocketPool::SocketParams>(
using_ssl ? std::make_unique<SSLConfig>(ssl_config_for_origin) : nullptr,
using_proxy_ssl ? std::make_unique<SSLConfig>(ssl_config_for_proxy)
@@ -101,8 +86,7 @@ scoped_refptr<ClientSocketPool::SocketParams> CreateSocketParams(
}
int InitSocketPoolHelper(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
+ url::SchemeHostPort endpoint,
int request_load_flags,
RequestPriority request_priority,
HttpNetworkSession* session,
@@ -111,7 +95,7 @@ int InitSocketPoolHelper(
const SSLConfig& ssl_config_for_proxy,
bool is_for_websockets,
PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
+ NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy,
const SocketTag& socket_tag,
const NetLogWithSource& net_log,
@@ -120,18 +104,20 @@ int InitSocketPoolHelper(
HttpNetworkSession::SocketPoolType socket_pool_type,
CompletionOnceCallback callback,
const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
- bool using_ssl = group_type == ClientSocketPoolManager::SSL_GROUP;
- HostPortPair origin_host_port = endpoint;
+ DCHECK(endpoint.IsValid());
+ bool using_ssl = GURL::SchemeIsCryptographic(endpoint.scheme());
if (!using_ssl && session->params().testing_fixed_http_port != 0) {
- origin_host_port.set_port(session->params().testing_fixed_http_port);
+ endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
+ session->params().testing_fixed_http_port);
} else if (using_ssl && session->params().testing_fixed_https_port != 0) {
- origin_host_port.set_port(session->params().testing_fixed_https_port);
+ endpoint = url::SchemeHostPort(endpoint.scheme(), endpoint.host(),
+ session->params().testing_fixed_https_port);
}
- ClientSocketPool::GroupId connection_group =
- CreateGroupId(group_type, origin_host_port, proxy_info, privacy_mode,
- network_isolation_key, secure_dns_policy);
+ ClientSocketPool::GroupId connection_group(std::move(endpoint), privacy_mode,
+ std::move(network_isolation_key),
+ secure_dns_policy);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
CreateSocketParams(connection_group, proxy_info.proxy_server(),
ssl_config_for_origin, ssl_config_for_proxy);
@@ -237,8 +223,7 @@ base::TimeDelta ClientSocketPoolManager::unused_idle_socket_timeout(
}
int InitSocketHandleForHttpRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
+ url::SchemeHostPort endpoint,
int request_load_flags,
RequestPriority request_priority,
HttpNetworkSession* session,
@@ -246,7 +231,7 @@ int InitSocketHandleForHttpRequest(
const SSLConfig& ssl_config_for_origin,
const SSLConfig& ssl_config_for_proxy,
PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
+ NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy,
const SocketTag& socket_tag,
const NetLogWithSource& net_log,
@@ -255,17 +240,16 @@ int InitSocketHandleForHttpRequest(
const ClientSocketPool::ProxyAuthCallback& proxy_auth_callback) {
DCHECK(socket_handle);
return InitSocketPoolHelper(
- group_type, endpoint, request_load_flags, request_priority, session,
+ std::move(endpoint), request_load_flags, request_priority, session,
proxy_info, ssl_config_for_origin, ssl_config_for_proxy,
- false /* is_for_websockets */, privacy_mode, network_isolation_key,
- secure_dns_policy, socket_tag, net_log, 0, socket_handle,
- HttpNetworkSession::NORMAL_SOCKET_POOL, std::move(callback),
- proxy_auth_callback);
+ false /* is_for_websockets */, privacy_mode,
+ std::move(network_isolation_key), secure_dns_policy, socket_tag, net_log,
+ 0, socket_handle, HttpNetworkSession::NORMAL_SOCKET_POOL,
+ std::move(callback), proxy_auth_callback);
}
int InitSocketHandleForWebSocketRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
+ url::SchemeHostPort endpoint,
int request_load_flags,
RequestPriority request_priority,
HttpNetworkSession* session,
@@ -273,7 +257,7 @@ int InitSocketHandleForWebSocketRequest(
const SSLConfig& ssl_config_for_origin,
const SSLConfig& ssl_config_for_proxy,
PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
+ NetworkIsolationKey network_isolation_key,
const NetLogWithSource& net_log,
ClientSocketHandle* socket_handle,
CompletionOnceCallback callback,
@@ -283,36 +267,44 @@ int InitSocketHandleForWebSocketRequest(
// QUIC proxies are currently not supported through this method.
DCHECK(!proxy_info.is_quic());
+ // Expect websocket schemes (ws and wss) to be converted to the http(s)
+ // equivalent.
+ DCHECK(endpoint.scheme() == url::kHttpScheme ||
+ endpoint.scheme() == url::kHttpsScheme);
+
return InitSocketPoolHelper(
- group_type, endpoint, request_load_flags, request_priority, session,
+ std::move(endpoint), request_load_flags, request_priority, session,
proxy_info, ssl_config_for_origin, ssl_config_for_proxy,
- true /* is_for_websockets */, privacy_mode, network_isolation_key,
- SecureDnsPolicy::kAllow, SocketTag(), net_log, 0, socket_handle,
- HttpNetworkSession::WEBSOCKET_SOCKET_POOL, std::move(callback),
- proxy_auth_callback);
+ true /* is_for_websockets */, privacy_mode,
+ std::move(network_isolation_key), SecureDnsPolicy::kAllow, SocketTag(),
+ net_log, 0, socket_handle, HttpNetworkSession::WEBSOCKET_SOCKET_POOL,
+ std::move(callback), proxy_auth_callback);
}
-int PreconnectSocketsForHttpRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
- int request_load_flags,
- RequestPriority request_priority,
- HttpNetworkSession* session,
- const ProxyInfo& proxy_info,
- const SSLConfig& ssl_config_for_origin,
- const SSLConfig& ssl_config_for_proxy,
- PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- const NetLogWithSource& net_log,
- int num_preconnect_streams) {
+int PreconnectSocketsForHttpRequest(url::SchemeHostPort endpoint,
+ int request_load_flags,
+ RequestPriority request_priority,
+ HttpNetworkSession* session,
+ const ProxyInfo& proxy_info,
+ const SSLConfig& ssl_config_for_origin,
+ const SSLConfig& ssl_config_for_proxy,
+ PrivacyMode privacy_mode,
+ NetworkIsolationKey network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const NetLogWithSource& net_log,
+ int num_preconnect_streams) {
// QUIC proxies are currently not supported through this method.
DCHECK(!proxy_info.is_quic());
+ // Expect websocket schemes (ws and wss) to be converted to the http(s)
+ // equivalent.
+ DCHECK(endpoint.scheme() == url::kHttpScheme ||
+ endpoint.scheme() == url::kHttpsScheme);
+
return InitSocketPoolHelper(
- group_type, endpoint, request_load_flags, request_priority, session,
+ std::move(endpoint), request_load_flags, request_priority, session,
proxy_info, ssl_config_for_origin, ssl_config_for_proxy,
- false /* force_tunnel */, privacy_mode, network_isolation_key,
+ false /* force_tunnel */, privacy_mode, std::move(network_isolation_key),
secure_dns_policy, SocketTag(), net_log, num_preconnect_streams, nullptr,
HttpNetworkSession::NORMAL_SOCKET_POOL, CompletionOnceCallback(),
ClientSocketPool::ProxyAuthCallback());
diff --git a/chromium/net/socket/client_socket_pool_manager.h b/chromium/net/socket/client_socket_pool_manager.h
index 6e5bee9c50a..69ea1ccbae3 100644
--- a/chromium/net/socket/client_socket_pool_manager.h
+++ b/chromium/net/socket/client_socket_pool_manager.h
@@ -17,6 +17,7 @@
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_network_session.h"
#include "net/socket/client_socket_pool.h"
+#include "url/scheme_host_port.h"
namespace base {
class Value;
@@ -28,7 +29,6 @@ class ProcessMemoryDump;
namespace net {
class ClientSocketHandle;
-class HostPortPair;
class NetLogWithSource;
class NetworkIsolationKey;
class ProxyInfo;
@@ -42,11 +42,6 @@ enum DefaultMaxValues { kDefaultMaxSocketsPerProxyServer = 32 };
class NET_EXPORT_PRIVATE ClientSocketPoolManager {
public:
- enum SocketGroupType {
- SSL_GROUP, // For all TLS sockets.
- NORMAL_GROUP, // For normal HTTP sockets.
- };
-
ClientSocketPoolManager();
virtual ~ClientSocketPoolManager();
@@ -101,8 +96,7 @@ class NET_EXPORT_PRIVATE ClientSocketPoolManager {
// resolved. If |resolution_callback| does not return OK, then the
// connection will be aborted with that value.
int InitSocketHandleForHttpRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
+ url::SchemeHostPort endpoint,
int request_load_flags,
RequestPriority request_priority,
HttpNetworkSession* session,
@@ -110,7 +104,7 @@ int InitSocketHandleForHttpRequest(
const SSLConfig& ssl_config_for_origin,
const SSLConfig& ssl_config_for_proxy,
PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
+ NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy,
const SocketTag& socket_tag,
const NetLogWithSource& net_log,
@@ -128,8 +122,7 @@ int InitSocketHandleForHttpRequest(
// connection will be aborted with that value.
// This function uses WEBSOCKET_SOCKET_POOL socket pools.
int InitSocketHandleForWebSocketRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
+ url::SchemeHostPort endpoint,
int request_load_flags,
RequestPriority request_priority,
HttpNetworkSession* session,
@@ -137,7 +130,7 @@ int InitSocketHandleForWebSocketRequest(
const SSLConfig& ssl_config_for_origin,
const SSLConfig& ssl_config_for_proxy,
PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
+ NetworkIsolationKey network_isolation_key,
const NetLogWithSource& net_log,
ClientSocketHandle* socket_handle,
CompletionOnceCallback callback,
@@ -145,20 +138,18 @@ int InitSocketHandleForWebSocketRequest(
// Similar to InitSocketHandleForHttpRequest except that it initiates the
// desired number of preconnect streams from the relevant socket pool.
-int PreconnectSocketsForHttpRequest(
- ClientSocketPoolManager::SocketGroupType group_type,
- const HostPortPair& endpoint,
- int request_load_flags,
- RequestPriority request_priority,
- HttpNetworkSession* session,
- const ProxyInfo& proxy_info,
- const SSLConfig& ssl_config_for_origin,
- const SSLConfig& ssl_config_for_proxy,
- PrivacyMode privacy_mode,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- const NetLogWithSource& net_log,
- int num_preconnect_streams);
+int PreconnectSocketsForHttpRequest(url::SchemeHostPort endpoint,
+ int request_load_flags,
+ RequestPriority request_priority,
+ HttpNetworkSession* session,
+ const ProxyInfo& proxy_info,
+ const SSLConfig& ssl_config_for_origin,
+ const SSLConfig& ssl_config_for_proxy,
+ PrivacyMode privacy_mode,
+ NetworkIsolationKey network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const NetLogWithSource& net_log,
+ int num_preconnect_streams);
} // namespace net
diff --git a/chromium/net/socket/client_socket_pool_unittest.cc b/chromium/net/socket/client_socket_pool_unittest.cc
index ce7987f296e..8f8c24c0f3a 100644
--- a/chromium/net/socket/client_socket_pool_unittest.cc
+++ b/chromium/net/socket/client_socket_pool_unittest.cc
@@ -16,6 +16,8 @@
#include "net/dns/public/secure_dns_policy.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
@@ -29,14 +31,21 @@ TEST(ClientSocketPool, GroupIdOperators) {
// Each of these lists is in "<" order, as defined by Group::operator< on the
// corresponding field.
- // HostPortPair::operator< compares port before host.
- const HostPortPair kHostPortPairs[] = {
- {"b", 79}, {"a", 80}, {"b", 80}, {"c", 81}, {"a", 443}, {"c", 443},
+ const uint16_t kPorts[] = {
+ 80,
+ 81,
+ 443,
};
- const ClientSocketPool::SocketType kSocketTypes[] = {
- ClientSocketPool::SocketType::kHttp,
- ClientSocketPool::SocketType::kSsl,
+ const char* kSchemes[] = {
+ url::kHttpScheme,
+ url::kHttpsScheme,
+ };
+
+ const char* kHosts[] = {
+ "a",
+ "b",
+ "c",
};
const PrivacyMode kPrivacyModes[] = {
@@ -59,32 +68,35 @@ TEST(ClientSocketPool, GroupIdOperators) {
std::vector<ClientSocketPool::GroupId> group_ids;
// Iterate through all sets of group ids, from least to greatest.
- for (const auto& host_port_pair : kHostPortPairs) {
- SCOPED_TRACE(host_port_pair.ToString());
- for (const auto& socket_type : kSocketTypes) {
- SCOPED_TRACE(static_cast<int>(socket_type));
- for (const auto& privacy_mode : kPrivacyModes) {
- SCOPED_TRACE(privacy_mode);
- for (const auto& network_isolation_key : kNetworkIsolationKeys) {
- SCOPED_TRACE(network_isolation_key.ToString());
- for (const auto& secure_dns_policy : kDisableSecureDnsValues) {
- ClientSocketPool::GroupId group_id(
- host_port_pair, socket_type, privacy_mode,
- network_isolation_key, secure_dns_policy);
- for (const auto& lower_group_id : group_ids) {
- EXPECT_FALSE(lower_group_id == group_id);
- EXPECT_TRUE(lower_group_id < group_id);
- EXPECT_FALSE(group_id < lower_group_id);
+ for (const auto& port : kPorts) {
+ SCOPED_TRACE(port);
+ for (const char* scheme : kSchemes) {
+ SCOPED_TRACE(scheme);
+ for (const char* host : kHosts) {
+ SCOPED_TRACE(host);
+ for (const auto& privacy_mode : kPrivacyModes) {
+ SCOPED_TRACE(privacy_mode);
+ for (const auto& network_isolation_key : kNetworkIsolationKeys) {
+ SCOPED_TRACE(network_isolation_key.ToString());
+ for (const auto& secure_dns_policy : kDisableSecureDnsValues) {
+ ClientSocketPool::GroupId group_id(
+ url::SchemeHostPort(scheme, host, port), privacy_mode,
+ network_isolation_key, secure_dns_policy);
+ for (const auto& lower_group_id : group_ids) {
+ EXPECT_FALSE(lower_group_id == group_id);
+ EXPECT_TRUE(lower_group_id < group_id);
+ EXPECT_FALSE(group_id < lower_group_id);
+ }
+
+ group_ids.push_back(group_id);
+
+ // Compare |group_id| to itself. Use two different copies of
+ // |group_id|'s value, since to protect against bugs where an
+ // object only equals itself.
+ EXPECT_TRUE(group_ids.back() == group_id);
+ EXPECT_FALSE(group_ids.back() < group_id);
+ EXPECT_FALSE(group_id < group_ids.back());
}
-
- group_ids.push_back(group_id);
-
- // Compare |group_id| to itself. Use two different copies of
- // |group_id|'s value, since to protect against bugs where an object
- // only equals itself.
- EXPECT_TRUE(group_ids.back() == group_id);
- EXPECT_FALSE(group_ids.back() < group_id);
- EXPECT_FALSE(group_id < group_ids.back());
}
}
}
@@ -97,56 +109,56 @@ TEST(ClientSocketPool, GroupIdToString) {
feature_list.InitAndEnableFeature(
features::kPartitionConnectionsByNetworkIsolationKey);
- EXPECT_EQ("foo:80 <null null>",
+ EXPECT_EQ("http://foo <null null>",
ClientSocketPool::GroupId(
- HostPortPair("foo", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "foo", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("bar:443 <null null>",
+ EXPECT_EQ("http://bar:443 <null null>",
ClientSocketPool::GroupId(
- HostPortPair("bar", 443), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "bar", 443),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("pm/bar:80 <null null>",
+ EXPECT_EQ("pm/http://bar <null null>",
ClientSocketPool::GroupId(
- HostPortPair("bar", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "bar", 80),
PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("ssl/foo:80 <null null>",
+ EXPECT_EQ("https://foo:80 <null null>",
ClientSocketPool::GroupId(
- HostPortPair("foo", 80), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "foo", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("ssl/bar:443 <null null>",
+ EXPECT_EQ("https://bar <null null>",
ClientSocketPool::GroupId(
- HostPortPair("bar", 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "bar", 443),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("pm/ssl/bar:80 <null null>",
+ EXPECT_EQ("pm/https://bar:80 <null null>",
ClientSocketPool::GroupId(
- HostPortPair("bar", 80), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "bar", 80),
PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("ssl/foo:443 <https://foo.test https://bar.test>",
+ EXPECT_EQ("https://foo <https://foo.test https://bar.test>",
ClientSocketPool::GroupId(
- HostPortPair("foo", 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "foo", 443),
PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(SchemefulSite(GURL("https://foo.test")),
SchemefulSite(GURL("https://bar.test"))),
SecureDnsPolicy::kAllow)
.ToString());
- EXPECT_EQ("dsd/pm/ssl/bar:80 <null null>",
+ EXPECT_EQ("dsd/pm/https://bar:80 <null null>",
ClientSocketPool::GroupId(
- HostPortPair("bar", 80), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "bar", 80),
PrivacyMode::PRIVACY_MODE_ENABLED, NetworkIsolationKey(),
SecureDnsPolicy::kDisable)
.ToString());
@@ -160,12 +172,12 @@ TEST(ClientSocketPool, PartitionConnectionsByNetworkIsolationKeyDisabled) {
features::kPartitionConnectionsByNetworkIsolationKey);
ClientSocketPool::GroupId group_id1(
- HostPortPair("foo", 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "foo", 443),
PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(kSiteFoo, kSiteFoo), SecureDnsPolicy::kAllow);
ClientSocketPool::GroupId group_id2(
- HostPortPair("foo", 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "foo", 443),
PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(kSiteBar, kSiteBar), SecureDnsPolicy::kAllow);
@@ -175,8 +187,8 @@ TEST(ClientSocketPool, PartitionConnectionsByNetworkIsolationKeyDisabled) {
group_id2.network_isolation_key());
EXPECT_EQ(group_id1, group_id2);
- EXPECT_EQ("ssl/foo:443", group_id1.ToString());
- EXPECT_EQ("ssl/foo:443", group_id2.ToString());
+ EXPECT_EQ("https://foo", group_id1.ToString());
+ EXPECT_EQ("https://foo", group_id2.ToString());
}
} // namespace
diff --git a/chromium/net/socket/connect_job.cc b/chromium/net/socket/connect_job.cc
index 156dd00a80c..873bb95824b 100644
--- a/chromium/net/socket/connect_job.cc
+++ b/chromium/net/socket/connect_job.cc
@@ -20,7 +20,6 @@
#include "net/socket/ssl_connect_job.h"
#include "net/socket/stream_socket.h"
#include "net/socket/transport_connect_job.h"
-#include "net/ssl/ssl_config.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
namespace net {
@@ -96,97 +95,6 @@ ConnectJob::~ConnectJob() {
net_log().EndEvent(NetLogEventType::CONNECT_JOB);
}
-std::unique_ptr<ConnectJob> ConnectJob::CreateConnectJob(
- bool using_ssl,
- const HostPortPair& endpoint,
- const ProxyServer& proxy_server,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- const SSLConfig* ssl_config_for_origin,
- const SSLConfig* ssl_config_for_proxy,
- bool force_tunnel,
- PrivacyMode privacy_mode,
- const OnHostResolutionCallback& resolution_callback,
- RequestPriority request_priority,
- SocketTag socket_tag,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- const CommonConnectJobParams* common_connect_job_params,
- ConnectJob::Delegate* delegate) {
- scoped_refptr<HttpProxySocketParams> http_proxy_params;
- scoped_refptr<SOCKSSocketParams> socks_params;
-
- if (!proxy_server.is_direct()) {
- // No need to use a NetworkIsolationKey for looking up the proxy's IP
- // address. Cached proxy IP addresses doesn't really expose useful
- // information to destination sites, and not caching them has a performance
- // cost.
- auto proxy_tcp_params = base::MakeRefCounted<TransportSocketParams>(
- proxy_server.host_port_pair(), NetworkIsolationKey(), secure_dns_policy,
- resolution_callback);
-
- if (proxy_server.is_http_like()) {
- scoped_refptr<SSLSocketParams> ssl_params;
- if (proxy_server.is_secure_http_like()) {
- DCHECK(ssl_config_for_proxy);
- // Set ssl_params, and unset proxy_tcp_params
- ssl_params = base::MakeRefCounted<SSLSocketParams>(
- std::move(proxy_tcp_params), nullptr, nullptr,
- proxy_server.host_port_pair(), *ssl_config_for_proxy,
- PRIVACY_MODE_DISABLED, network_isolation_key);
- proxy_tcp_params = nullptr;
- }
-
- http_proxy_params = base::MakeRefCounted<HttpProxySocketParams>(
- std::move(proxy_tcp_params), std::move(ssl_params),
- proxy_server.is_quic(), endpoint, force_tunnel || using_ssl,
- *proxy_annotation_tag, network_isolation_key);
- } else {
- DCHECK(proxy_server.is_socks());
- socks_params = base::MakeRefCounted<SOCKSSocketParams>(
- std::move(proxy_tcp_params),
- proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5, endpoint,
- network_isolation_key, *proxy_annotation_tag);
- }
- }
-
- // Deal with SSL - which layers on top of any given proxy.
- if (using_ssl) {
- DCHECK(ssl_config_for_origin);
- scoped_refptr<TransportSocketParams> ssl_tcp_params;
- if (proxy_server.is_direct()) {
- ssl_tcp_params = base::MakeRefCounted<TransportSocketParams>(
- endpoint, network_isolation_key, secure_dns_policy,
- resolution_callback);
- }
- auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
- std::move(ssl_tcp_params), std::move(socks_params),
- std::move(http_proxy_params), endpoint, *ssl_config_for_origin,
- privacy_mode, network_isolation_key);
- return std::make_unique<SSLConnectJob>(
- request_priority, socket_tag, common_connect_job_params,
- std::move(ssl_params), delegate, nullptr /* net_log */);
- }
-
- if (proxy_server.is_http_like()) {
- return std::make_unique<HttpProxyConnectJob>(
- request_priority, socket_tag, common_connect_job_params,
- std::move(http_proxy_params), delegate, nullptr /* net_log */);
- }
-
- if (proxy_server.is_socks()) {
- return std::make_unique<SOCKSConnectJob>(
- request_priority, socket_tag, common_connect_job_params,
- std::move(socks_params), delegate, nullptr /* net_log */);
- }
-
- DCHECK(proxy_server.is_direct());
- auto tcp_params = base::MakeRefCounted<TransportSocketParams>(
- endpoint, network_isolation_key, secure_dns_policy, resolution_callback);
- return TransportConnectJob::CreateTransportConnectJob(
- std::move(tcp_params), request_priority, socket_tag,
- common_connect_job_params, delegate, nullptr /* net_log */);
-}
-
std::unique_ptr<StreamSocket> ConnectJob::PassSocket() {
return std::move(socket_);
}
diff --git a/chromium/net/socket/connect_job.h b/chromium/net/socket/connect_job.h
index ace3b8b7939..a662e0e156a 100644
--- a/chromium/net/socket/connect_job.h
+++ b/chromium/net/socket/connect_job.h
@@ -18,10 +18,8 @@
#include "net/base/load_states.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_export.h"
-#include "net/base/privacy_mode.h"
#include "net/base/request_priority.h"
#include "net/dns/public/resolve_error_info.h"
-#include "net/dns/public/secure_dns_policy.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/socket_tag.h"
@@ -41,13 +39,9 @@ class HttpResponseInfo;
class HttpUserAgentSettings;
class NetLog;
class NetLogWithSource;
-class NetworkIsolationKey;
class NetworkQualityEstimator;
-struct NetworkTrafficAnnotationTag;
class ProxyDelegate;
-class ProxyServer;
class SocketPerformanceWatcherFactory;
-struct SSLConfig;
class StreamSocket;
class WebSocketEndpointLockManager;
class QuicStreamFactory;
@@ -175,26 +169,6 @@ class NET_EXPORT_PRIVATE ConnectJob {
NetLogEventType net_log_connect_event_type);
virtual ~ConnectJob();
- // Creates a ConnectJob with the specified parameters.
- // |common_connect_job_params| and |delegate| must outlive the returned
- // ConnectJob.
- static std::unique_ptr<ConnectJob> CreateConnectJob(
- bool using_ssl,
- const HostPortPair& endpoint,
- const ProxyServer& proxy_server,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- const SSLConfig* ssl_config_for_origin,
- const SSLConfig* ssl_config_for_proxy,
- bool force_tunnel,
- PrivacyMode privacy_mode,
- const OnHostResolutionCallback& resolution_callback,
- RequestPriority request_priority,
- SocketTag socket_tag,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- const CommonConnectJobParams* common_connect_job_params,
- ConnectJob::Delegate* delegate);
-
// Accessors
const NetLogWithSource& net_log() { return net_log_; }
RequestPriority priority() const { return priority_; }
diff --git a/chromium/net/socket/connect_job_factory.cc b/chromium/net/socket/connect_job_factory.cc
new file mode 100644
index 00000000000..d7e231fd1c1
--- /dev/null
+++ b/chromium/net/socket/connect_job_factory.cc
@@ -0,0 +1,247 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/socket/connect_job_factory.h"
+
+#include <memory>
+#include <utility>
+
+#include "base/check.h"
+#include "base/memory/scoped_refptr.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/network_isolation_key.h"
+#include "net/base/privacy_mode.h"
+#include "net/base/proxy_server.h"
+#include "net/base/request_priority.h"
+#include "net/dns/public/secure_dns_policy.h"
+#include "net/http/http_proxy_connect_job.h"
+#include "net/socket/connect_job.h"
+#include "net/socket/socket_tag.h"
+#include "net/socket/socks_connect_job.h"
+#include "net/socket/ssl_connect_job.h"
+#include "net/socket/transport_connect_job.h"
+#include "net/socket/websocket_transport_connect_job.h"
+#include "net/ssl/ssl_config.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+
+namespace net {
+
+namespace {
+
+template <typename T>
+std::unique_ptr<T> CreateFactoryIfNull(std::unique_ptr<T> in) {
+ if (in)
+ return in;
+ return std::make_unique<T>();
+}
+
+bool UsingSsl(const ConnectJobFactory::Endpoint& endpoint) {
+ if (absl::holds_alternative<url::SchemeHostPort>(endpoint)) {
+ return GURL::SchemeIsCryptographic(
+ base::ToLowerASCII(absl::get<url::SchemeHostPort>(endpoint).scheme()));
+ }
+
+ DCHECK(
+ absl::holds_alternative<ConnectJobFactory::SchemelessEndpoint>(endpoint));
+ return absl::get<ConnectJobFactory::SchemelessEndpoint>(endpoint).using_ssl;
+}
+
+HostPortPair ToHostPortPair(const ConnectJobFactory::Endpoint& endpoint) {
+ if (absl::holds_alternative<url::SchemeHostPort>(endpoint)) {
+ return HostPortPair::FromSchemeHostPort(
+ absl::get<url::SchemeHostPort>(endpoint));
+ }
+
+ DCHECK(
+ absl::holds_alternative<ConnectJobFactory::SchemelessEndpoint>(endpoint));
+ return absl::get<ConnectJobFactory::SchemelessEndpoint>(endpoint)
+ .host_port_pair;
+}
+
+TransportSocketParams::Endpoint ToTransportEndpoint(
+ const ConnectJobFactory::Endpoint& endpoint) {
+ if (absl::holds_alternative<url::SchemeHostPort>(endpoint))
+ return absl::get<url::SchemeHostPort>(endpoint);
+
+ DCHECK(
+ absl::holds_alternative<ConnectJobFactory::SchemelessEndpoint>(endpoint));
+ return absl::get<ConnectJobFactory::SchemelessEndpoint>(endpoint)
+ .host_port_pair;
+}
+
+} // namespace
+
+ConnectJobFactory::ConnectJobFactory(
+ std::unique_ptr<HttpProxyConnectJob::Factory>
+ http_proxy_connect_job_factory,
+ std::unique_ptr<SOCKSConnectJob::Factory> socks_connect_job_factory,
+ std::unique_ptr<SSLConnectJob::Factory> ssl_connect_job_factory,
+ std::unique_ptr<TransportConnectJob::Factory> transport_connect_job_factory,
+ std::unique_ptr<WebSocketTransportConnectJob::Factory>
+ websocket_transport_connect_job_factory)
+ : http_proxy_connect_job_factory_(
+ CreateFactoryIfNull(std::move(http_proxy_connect_job_factory))),
+ socks_connect_job_factory_(
+ CreateFactoryIfNull(std::move(socks_connect_job_factory))),
+ ssl_connect_job_factory_(
+ CreateFactoryIfNull(std::move(ssl_connect_job_factory))),
+ transport_connect_job_factory_(
+ CreateFactoryIfNull(std::move(transport_connect_job_factory))),
+ websocket_transport_connect_job_factory_(CreateFactoryIfNull(
+ std::move(websocket_transport_connect_job_factory))) {}
+
+ConnectJobFactory::~ConnectJobFactory() = default;
+
+std::unique_ptr<ConnectJob> ConnectJobFactory::CreateConnectJob(
+ url::SchemeHostPort endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const {
+ return CreateConnectJob(
+ Endpoint(std::move(endpoint)), proxy_server, proxy_annotation_tag,
+ ssl_config_for_origin, ssl_config_for_proxy, force_tunnel, privacy_mode,
+ resolution_callback, request_priority, socket_tag, network_isolation_key,
+ secure_dns_policy, common_connect_job_params, delegate);
+}
+
+std::unique_ptr<ConnectJob> ConnectJobFactory::CreateConnectJob(
+ bool using_ssl,
+ HostPortPair endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const {
+ SchemelessEndpoint schemeless_endpoint{using_ssl, std::move(endpoint)};
+ return CreateConnectJob(
+ std::move(schemeless_endpoint), proxy_server, proxy_annotation_tag,
+ ssl_config_for_origin, ssl_config_for_proxy, force_tunnel, privacy_mode,
+ resolution_callback, request_priority, socket_tag, network_isolation_key,
+ secure_dns_policy, common_connect_job_params, delegate);
+}
+
+std::unique_ptr<ConnectJob> ConnectJobFactory::CreateConnectJob(
+ Endpoint endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const {
+ scoped_refptr<HttpProxySocketParams> http_proxy_params;
+ scoped_refptr<SOCKSSocketParams> socks_params;
+
+ if (!proxy_server.is_direct()) {
+ auto proxy_tcp_params = base::MakeRefCounted<TransportSocketParams>(
+ proxy_server.host_port_pair(), proxy_dns_network_isolation_key_,
+ secure_dns_policy, resolution_callback);
+
+ if (proxy_server.is_http_like()) {
+ scoped_refptr<SSLSocketParams> ssl_params;
+ if (proxy_server.is_secure_http_like()) {
+ DCHECK(ssl_config_for_proxy);
+ // Set ssl_params, and unset proxy_tcp_params
+ ssl_params = base::MakeRefCounted<SSLSocketParams>(
+ std::move(proxy_tcp_params), nullptr, nullptr,
+ proxy_server.host_port_pair(), *ssl_config_for_proxy,
+ PRIVACY_MODE_DISABLED, network_isolation_key);
+ proxy_tcp_params = nullptr;
+ }
+
+ // TODO(crbug.com/1206799): Pass `endpoint` directly (preserving scheme
+ // when available)?
+ http_proxy_params = base::MakeRefCounted<HttpProxySocketParams>(
+ std::move(proxy_tcp_params), std::move(ssl_params),
+ proxy_server.is_quic(), ToHostPortPair(endpoint),
+ force_tunnel || UsingSsl(endpoint), *proxy_annotation_tag,
+ network_isolation_key);
+ } else {
+ DCHECK(proxy_server.is_socks());
+ // TODO(crbug.com/1206799): Pass `endpoint` directly (preserving scheme
+ // when available)?
+ socks_params = base::MakeRefCounted<SOCKSSocketParams>(
+ std::move(proxy_tcp_params),
+ proxy_server.scheme() == ProxyServer::SCHEME_SOCKS5,
+ ToHostPortPair(endpoint), network_isolation_key,
+ *proxy_annotation_tag);
+ }
+ }
+
+ // Deal with SSL - which layers on top of any given proxy.
+ if (UsingSsl(endpoint)) {
+ DCHECK(ssl_config_for_origin);
+ scoped_refptr<TransportSocketParams> ssl_tcp_params;
+ if (proxy_server.is_direct()) {
+ ssl_tcp_params = base::MakeRefCounted<TransportSocketParams>(
+ ToTransportEndpoint(endpoint), network_isolation_key,
+ secure_dns_policy, resolution_callback);
+ }
+ // TODO(crbug.com/1206799): Pass `endpoint` directly (preserving scheme
+ // when available)?
+ auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
+ std::move(ssl_tcp_params), std::move(socks_params),
+ std::move(http_proxy_params), ToHostPortPair(endpoint),
+ *ssl_config_for_origin, privacy_mode, network_isolation_key);
+ return ssl_connect_job_factory_->Create(
+ request_priority, socket_tag, common_connect_job_params,
+ std::move(ssl_params), delegate, /*net_log=*/nullptr);
+ }
+
+ if (proxy_server.is_http_like()) {
+ return http_proxy_connect_job_factory_->Create(
+ request_priority, socket_tag, common_connect_job_params,
+ std::move(http_proxy_params), delegate, /*net_log=*/nullptr);
+ }
+
+ if (proxy_server.is_socks()) {
+ return socks_connect_job_factory_->Create(
+ request_priority, socket_tag, common_connect_job_params,
+ std::move(socks_params), delegate, /*net_log=*/nullptr);
+ }
+
+ DCHECK(proxy_server.is_direct());
+ auto tcp_params = base::MakeRefCounted<TransportSocketParams>(
+ ToTransportEndpoint(endpoint), network_isolation_key, secure_dns_policy,
+ resolution_callback);
+ if (!common_connect_job_params->websocket_endpoint_lock_manager) {
+ return transport_connect_job_factory_->Create(
+ request_priority, socket_tag, common_connect_job_params, tcp_params,
+ delegate, /*net_log=*/nullptr);
+ }
+
+ return websocket_transport_connect_job_factory_->Create(
+ request_priority, socket_tag, common_connect_job_params, tcp_params,
+ delegate, /*net_log=*/nullptr);
+}
+
+} // namespace net
diff --git a/chromium/net/socket/connect_job_factory.h b/chromium/net/socket/connect_job_factory.h
new file mode 100644
index 00000000000..98979a1ae67
--- /dev/null
+++ b/chromium/net/socket/connect_job_factory.h
@@ -0,0 +1,137 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_SOCKET_CONNECT_JOB_FACTORY_H_
+#define NET_SOCKET_CONNECT_JOB_FACTORY_H_
+
+#include <memory>
+
+#include "net/base/host_port_pair.h"
+#include "net/base/network_isolation_key.h"
+#include "net/base/privacy_mode.h"
+#include "net/base/request_priority.h"
+#include "net/dns/public/secure_dns_policy.h"
+#include "net/http/http_proxy_connect_job.h"
+#include "net/socket/connect_job.h"
+#include "net/socket/socket_tag.h"
+#include "net/socket/socks_connect_job.h"
+#include "net/socket/ssl_connect_job.h"
+#include "net/socket/transport_connect_job.h"
+#include "net/socket/websocket_transport_connect_job.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
+
+namespace net {
+
+class NetworkIsolationKey;
+struct NetworkTrafficAnnotationTag;
+class ProxyServer;
+struct SSLConfig;
+
+// Common factory for all ConnectJob types. Determines and creates the correct
+// ConnectJob depending on the passed in parameters.
+class NET_EXPORT_PRIVATE ConnectJobFactory {
+ public:
+ // The endpoint of a connection when the endpoint does not have a known
+ // standard scheme.
+ struct SchemelessEndpoint {
+ bool using_ssl;
+ HostPortPair host_port_pair;
+ };
+
+ // Representation of the endpoint of a connection. Could be schemeful or
+ // schemeless.
+ using Endpoint = absl::variant<url::SchemeHostPort, SchemelessEndpoint>;
+
+ // Default factory will be used if passed the default `nullptr`.
+ explicit ConnectJobFactory(
+ std::unique_ptr<HttpProxyConnectJob::Factory>
+ http_proxy_connect_job_factory = nullptr,
+ std::unique_ptr<SOCKSConnectJob::Factory> socks_connect_job_factory =
+ nullptr,
+ std::unique_ptr<SSLConnectJob::Factory> ssl_connect_job_factory = nullptr,
+ std::unique_ptr<TransportConnectJob::Factory>
+ transport_connect_job_factory = nullptr,
+ std::unique_ptr<WebSocketTransportConnectJob::Factory>
+ websocket_transport_connect_job_factory = nullptr);
+
+ // Not copyable/movable. Intended for polymorphic use via pointer.
+ ConnectJobFactory(const ConnectJobFactory&) = delete;
+ ConnectJobFactory& operator=(const ConnectJobFactory&) = delete;
+
+ virtual ~ConnectJobFactory();
+
+ // `common_connect_job_params` and `delegate` must outlive the returned
+ // ConnectJob.
+ std::unique_ptr<ConnectJob> CreateConnectJob(
+ url::SchemeHostPort endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const;
+
+ // TODO(crbug.com/1206799): Rename to discourage use except in cases where the
+ // scheme is non-standard or unknown.
+ std::unique_ptr<ConnectJob> CreateConnectJob(
+ bool using_ssl,
+ HostPortPair endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const;
+
+ private:
+ virtual std::unique_ptr<ConnectJob> CreateConnectJob(
+ Endpoint endpoint,
+ const ProxyServer& proxy_server,
+ const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
+ const SSLConfig* ssl_config_for_origin,
+ const SSLConfig* ssl_config_for_proxy,
+ bool force_tunnel,
+ PrivacyMode privacy_mode,
+ const OnHostResolutionCallback& resolution_callback,
+ RequestPriority request_priority,
+ SocketTag socket_tag,
+ const NetworkIsolationKey& network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ const CommonConnectJobParams* common_connect_job_params,
+ ConnectJob::Delegate* delegate) const;
+
+ std::unique_ptr<HttpProxyConnectJob::Factory> http_proxy_connect_job_factory_;
+ std::unique_ptr<SOCKSConnectJob::Factory> socks_connect_job_factory_;
+ std::unique_ptr<SSLConnectJob::Factory> ssl_connect_job_factory_;
+ std::unique_ptr<TransportConnectJob::Factory> transport_connect_job_factory_;
+ std::unique_ptr<WebSocketTransportConnectJob::Factory>
+ websocket_transport_connect_job_factory_;
+
+ // Use a single NetworkIsolationKey for looking up proxy hostnames. Proxies
+ // are typically used across sites, but cached proxy IP addresses don't
+ // really expose useful information to destination sites, and not caching
+ // them has a performance cost.
+ net::NetworkIsolationKey proxy_dns_network_isolation_key_ =
+ net::NetworkIsolationKey::CreateTransient();
+};
+
+} // namespace net
+
+#endif // NET_SOCKET_CONNECT_JOB_FACTORY_H_
diff --git a/chromium/net/socket/connect_job_factory_unittest.cc b/chromium/net/socket/connect_job_factory_unittest.cc
new file mode 100644
index 00000000000..d29a873d925
--- /dev/null
+++ b/chromium/net/socket/connect_job_factory_unittest.cc
@@ -0,0 +1,614 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "net/socket/connect_job_factory.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/memory/scoped_refptr.h"
+#include "net/base/host_port_pair.h"
+#include "net/base/network_isolation_key.h"
+#include "net/base/privacy_mode.h"
+#include "net/base/proxy_server.h"
+#include "net/base/request_priority.h"
+#include "net/dns/public/secure_dns_policy.h"
+#include "net/http/http_proxy_connect_job.h"
+#include "net/log/net_log_with_source.h"
+#include "net/socket/connect_job.h"
+#include "net/socket/connect_job_test_util.h"
+#include "net/socket/socket_tag.h"
+#include "net/socket/socks_connect_job.h"
+#include "net/socket/ssl_connect_job.h"
+#include "net/socket/transport_connect_job.h"
+#include "net/socket/websocket_endpoint_lock_manager.h"
+#include "net/socket/websocket_transport_connect_job.h"
+#include "net/ssl/ssl_config.h"
+#include "net/test/test_with_task_environment.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
+
+namespace net {
+namespace {
+
+// Mock HttpProxyConnectJob::Factory that records the `params` used and then
+// passes on to a real factory.
+class TestHttpProxyConnectJobFactory : public HttpProxyConnectJob::Factory {
+ public:
+ std::unique_ptr<HttpProxyConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<HttpProxySocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) override {
+ params_.push_back(params);
+ return HttpProxyConnectJob::Factory::Create(priority, socket_tag,
+ common_connect_job_params,
+ params, delegate, net_log);
+ }
+
+ const std::vector<scoped_refptr<HttpProxySocketParams>>& params() const {
+ return params_;
+ }
+
+ private:
+ std::vector<scoped_refptr<HttpProxySocketParams>> params_;
+};
+
+// Mock SOCKSConnectJob::Factory that records the `params` used and then passes
+// on to a real factory.
+class TestSocksConnectJobFactory : public SOCKSConnectJob::Factory {
+ public:
+ std::unique_ptr<SOCKSConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SOCKSSocketParams> socks_params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) override {
+ params_.push_back(socks_params);
+ return SOCKSConnectJob::Factory::Create(priority, socket_tag,
+ common_connect_job_params,
+ socks_params, delegate, net_log);
+ }
+
+ const std::vector<scoped_refptr<SOCKSSocketParams>>& params() const {
+ return params_;
+ }
+
+ private:
+ std::vector<scoped_refptr<SOCKSSocketParams>> params_;
+};
+
+// Mock SSLConnectJob::Factory that records the `params` used and then passes on
+// to a real factory.
+class TestSslConnectJobFactory : public SSLConnectJob::Factory {
+ public:
+ std::unique_ptr<SSLConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SSLSocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) override {
+ params_.push_back(params);
+ return SSLConnectJob::Factory::Create(priority, socket_tag,
+ common_connect_job_params, params,
+ delegate, net_log);
+ }
+
+ const std::vector<scoped_refptr<SSLSocketParams>>& params() const {
+ return params_;
+ }
+
+ private:
+ std::vector<scoped_refptr<SSLSocketParams>> params_;
+};
+
+// Mock TransportConnectJob::Factory that records the `params` used and then
+// passes on to a real factory.
+class TestTransportConnectJobFactory : public TransportConnectJob::Factory {
+ public:
+ std::unique_ptr<TransportConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) override {
+ params_.push_back(params);
+ return TransportConnectJob::Factory::Create(priority, socket_tag,
+ common_connect_job_params,
+ params, delegate, net_log);
+ }
+
+ const std::vector<scoped_refptr<TransportSocketParams>>& params() const {
+ return params_;
+ }
+
+ private:
+ std::vector<scoped_refptr<TransportSocketParams>> params_;
+};
+
+// Mock WebSocketTransportConnectJob::Factory that records the `params` used and
+// then passes on to a real factory.
+class TestWebsocketConnectJobFactory
+ : public WebSocketTransportConnectJob::Factory {
+ public:
+ std::unique_ptr<WebSocketTransportConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) override {
+ params_.push_back(params);
+ return WebSocketTransportConnectJob::Factory::Create(
+ priority, socket_tag, common_connect_job_params, params, delegate,
+ net_log);
+ }
+
+ const std::vector<scoped_refptr<TransportSocketParams>>& params() const {
+ return params_;
+ }
+
+ private:
+ std::vector<scoped_refptr<TransportSocketParams>> params_;
+};
+
+class ConnectJobFactoryTest : public TestWithTaskEnvironment {
+ public:
+ ConnectJobFactoryTest() {
+ auto http_proxy_job_factory =
+ std::make_unique<TestHttpProxyConnectJobFactory>();
+ http_proxy_job_factory_ = http_proxy_job_factory.get();
+
+ auto socks_job_factory = std::make_unique<TestSocksConnectJobFactory>();
+ socks_job_factory_ = socks_job_factory.get();
+
+ auto ssl_job_factory = std::make_unique<TestSslConnectJobFactory>();
+ ssl_job_factory_ = ssl_job_factory.get();
+
+ auto transport_job_factory =
+ std::make_unique<TestTransportConnectJobFactory>();
+ transport_job_factory_ = transport_job_factory.get();
+
+ auto websocket_job_factory =
+ std::make_unique<TestWebsocketConnectJobFactory>();
+ websocket_job_factory_ = websocket_job_factory.get();
+
+ factory_ = std::make_unique<ConnectJobFactory>(
+ std::move(http_proxy_job_factory), std::move(socks_job_factory),
+ std::move(ssl_job_factory), std::move(transport_job_factory),
+ std::move(websocket_job_factory));
+ }
+
+ protected:
+ // Gets the total number of ConnectJob creations across all types.
+ size_t GetCreationCount() const {
+ return http_proxy_job_factory_->params().size() +
+ socks_job_factory_->params().size() +
+ ssl_job_factory_->params().size() +
+ transport_job_factory_->params().size() +
+ websocket_job_factory_->params().size();
+ }
+
+ const CommonConnectJobParams common_connect_job_params_{
+ /*client_socket_factory=*/nullptr,
+ /*host_resolver=*/nullptr,
+ /*http_auth_cache=*/nullptr,
+ /*http_auth_handler_factory=*/nullptr,
+ /*spdy_session_pool=*/nullptr,
+ /*quic_supported_versions=*/nullptr,
+ /*quic_stream_factory=*/nullptr,
+ /*proxy_delegate=*/nullptr,
+ /*http_user_agent_settings=*/nullptr,
+ /*ssl_client_context=*/nullptr,
+ /*socket_performance_watcher_factory=*/nullptr,
+ /*network_quality_estimator=*/nullptr,
+ /*net_log=*/nullptr,
+ /*websocket_endpoint_lock_manager=*/nullptr};
+ TestConnectJobDelegate delegate_;
+
+ TestHttpProxyConnectJobFactory* http_proxy_job_factory_;
+ TestSocksConnectJobFactory* socks_job_factory_;
+ TestSslConnectJobFactory* ssl_job_factory_;
+ TestTransportConnectJobFactory* transport_job_factory_;
+ TestWebsocketConnectJobFactory* websocket_job_factory_;
+
+ std::unique_ptr<ConnectJobFactory> factory_;
+};
+
+TEST_F(ConnectJobFactoryTest, CreateConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpScheme, "test", 82);
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(transport_job_factory_->params(), testing::SizeIs(1));
+ const TransportSocketParams& params =
+ *transport_job_factory_->params().front();
+ EXPECT_THAT(params.destination(),
+ testing::VariantWith<url::SchemeHostPort>(kEndpoint));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 82);
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/false, kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(transport_job_factory_->params(), testing::SizeIs(1));
+ const TransportSocketParams& params =
+ *transport_job_factory_->params().front();
+ EXPECT_THAT(params.destination(),
+ testing::VariantWith<HostPortPair>(kEndpoint));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpsConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "test", 84);
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/&ssl_config,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(ssl_job_factory_->params(), testing::SizeIs(1));
+ const SSLSocketParams& params = *ssl_job_factory_->params().front();
+ EXPECT_EQ(params.host_and_port(),
+ HostPortPair::FromSchemeHostPort(kEndpoint));
+
+ ASSERT_EQ(params.GetConnectionType(), SSLSocketParams::DIRECT);
+ const TransportSocketParams& transport_params =
+ *params.GetDirectConnectionParams();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<url::SchemeHostPort>(kEndpoint));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpsConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 84);
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/true, kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/&ssl_config,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(ssl_job_factory_->params(), testing::SizeIs(1));
+ const SSLSocketParams& params = *ssl_job_factory_->params().front();
+ EXPECT_EQ(params.host_and_port(), kEndpoint);
+
+ ASSERT_EQ(params.GetConnectionType(), SSLSocketParams::DIRECT);
+ const TransportSocketParams& transport_params =
+ *params.GetDirectConnectionParams();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kEndpoint));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpProxyConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpScheme, "test", 85);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTP,
+ HostPortPair("proxy.test", 86));
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(http_proxy_job_factory_->params(), testing::SizeIs(1));
+ const HttpProxySocketParams& params =
+ *http_proxy_job_factory_->params().front();
+ EXPECT_FALSE(params.is_quic());
+ EXPECT_EQ(params.endpoint(), HostPortPair::FromSchemeHostPort(kEndpoint));
+
+ ASSERT_TRUE(params.transport_params());
+ const TransportSocketParams& transport_params = *params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpProxyConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 85);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTP,
+ HostPortPair("proxy.test", 86));
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/false, kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(http_proxy_job_factory_->params(), testing::SizeIs(1));
+ const HttpProxySocketParams& params =
+ *http_proxy_job_factory_->params().front();
+ EXPECT_FALSE(params.is_quic());
+ EXPECT_EQ(params.endpoint(), kEndpoint);
+
+ ASSERT_TRUE(params.transport_params());
+ const TransportSocketParams& transport_params = *params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpProxyConnectJobForHttps) {
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "test", 87);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTP,
+ HostPortPair("proxy.test", 88));
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/&ssl_config,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(ssl_job_factory_->params(), testing::SizeIs(1));
+ const SSLSocketParams& params = *ssl_job_factory_->params().front();
+ EXPECT_EQ(params.host_and_port(),
+ HostPortPair::FromSchemeHostPort(kEndpoint));
+
+ ASSERT_EQ(params.GetConnectionType(), SSLSocketParams::HTTP_PROXY);
+ const HttpProxySocketParams& proxy_params =
+ *params.GetHttpProxyConnectionParams();
+ EXPECT_FALSE(proxy_params.is_quic());
+ EXPECT_EQ(proxy_params.endpoint(),
+ HostPortPair::FromSchemeHostPort(kEndpoint));
+
+ ASSERT_TRUE(proxy_params.transport_params());
+ const TransportSocketParams& transport_params =
+ *proxy_params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpProxyConnectJobForHttpsWithoutScheme) {
+ const HostPortPair kEndpoint("test", 87);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTP,
+ HostPortPair("proxy.test", 88));
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/true, kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/&ssl_config,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(ssl_job_factory_->params(), testing::SizeIs(1));
+ const SSLSocketParams& params = *ssl_job_factory_->params().front();
+ EXPECT_EQ(params.host_and_port(), kEndpoint);
+
+ ASSERT_EQ(params.GetConnectionType(), SSLSocketParams::HTTP_PROXY);
+ const HttpProxySocketParams& proxy_params =
+ *params.GetHttpProxyConnectionParams();
+ EXPECT_FALSE(proxy_params.is_quic());
+ EXPECT_EQ(proxy_params.endpoint(), kEndpoint);
+
+ ASSERT_TRUE(proxy_params.transport_params());
+ const TransportSocketParams& transport_params =
+ *proxy_params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpsProxyConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpScheme, "test", 89);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTPS,
+ HostPortPair("proxy.test", 90));
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/&ssl_config,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(http_proxy_job_factory_->params(), testing::SizeIs(1));
+ const HttpProxySocketParams& params =
+ *http_proxy_job_factory_->params().front();
+ EXPECT_FALSE(params.is_quic());
+ EXPECT_EQ(params.endpoint(), HostPortPair::FromSchemeHostPort(kEndpoint));
+
+ ASSERT_TRUE(params.ssl_params());
+ const SSLSocketParams& ssl_params = *params.ssl_params();
+ EXPECT_EQ(ssl_params.host_and_port(), kProxy.host_port_pair());
+
+ ASSERT_EQ(ssl_params.GetConnectionType(), SSLSocketParams::DIRECT);
+ const TransportSocketParams& transport_params =
+ *ssl_params.GetDirectConnectionParams();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateHttpsProxyConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 89);
+ const ProxyServer kProxy(ProxyServer::SCHEME_HTTPS,
+ HostPortPair("proxy.test", 90));
+ SSLConfig ssl_config;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/false, kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/&ssl_config,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(http_proxy_job_factory_->params(), testing::SizeIs(1));
+ const HttpProxySocketParams& params =
+ *http_proxy_job_factory_->params().front();
+ EXPECT_FALSE(params.is_quic());
+ EXPECT_EQ(params.endpoint(), kEndpoint);
+
+ ASSERT_TRUE(params.ssl_params());
+ const SSLSocketParams& ssl_params = *params.ssl_params();
+ EXPECT_EQ(ssl_params.host_and_port(), kProxy.host_port_pair());
+
+ ASSERT_EQ(ssl_params.GetConnectionType(), SSLSocketParams::DIRECT);
+ const TransportSocketParams& transport_params =
+ *ssl_params.GetDirectConnectionParams();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateSocksProxyConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpScheme, "test", 91);
+ const ProxyServer kProxy(ProxyServer::SCHEME_SOCKS5,
+ HostPortPair("proxy.test", 92));
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(socks_job_factory_->params(), testing::SizeIs(1));
+ const SOCKSSocketParams& params = *socks_job_factory_->params().front();
+ EXPECT_EQ(params.destination(), HostPortPair::FromSchemeHostPort(kEndpoint));
+ EXPECT_TRUE(params.is_socks_v5());
+
+ const TransportSocketParams& transport_params = *params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateSocksProxyConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 91);
+ const ProxyServer kProxy(ProxyServer::SCHEME_SOCKS5,
+ HostPortPair("proxy.test", 92));
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/false, kEndpoint, kProxy, TRAFFIC_ANNOTATION_FOR_TESTS,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params_, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(socks_job_factory_->params(), testing::SizeIs(1));
+ const SOCKSSocketParams& params = *socks_job_factory_->params().front();
+ EXPECT_EQ(params.destination(), kEndpoint);
+ EXPECT_TRUE(params.is_socks_v5());
+
+ const TransportSocketParams& transport_params = *params.transport_params();
+ EXPECT_THAT(transport_params.destination(),
+ testing::VariantWith<HostPortPair>(kProxy.host_port_pair()));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateWebsocketConnectJob) {
+ const url::SchemeHostPort kEndpoint(url::kHttpScheme, "test", 93);
+
+ WebSocketEndpointLockManager websocket_endpoint_lock_manager;
+ CommonConnectJobParams common_connect_job_params = common_connect_job_params_;
+ common_connect_job_params.websocket_endpoint_lock_manager =
+ &websocket_endpoint_lock_manager;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(websocket_job_factory_->params(), testing::SizeIs(1));
+ const TransportSocketParams& params =
+ *websocket_job_factory_->params().front();
+ EXPECT_THAT(params.destination(),
+ testing::VariantWith<url::SchemeHostPort>(kEndpoint));
+}
+
+TEST_F(ConnectJobFactoryTest, CreateWebsocketConnectJobWithoutScheme) {
+ const HostPortPair kEndpoint("test", 93);
+
+ WebSocketEndpointLockManager websocket_endpoint_lock_manager;
+ CommonConnectJobParams common_connect_job_params = common_connect_job_params_;
+ common_connect_job_params.websocket_endpoint_lock_manager =
+ &websocket_endpoint_lock_manager;
+
+ std::unique_ptr<ConnectJob> job = factory_->CreateConnectJob(
+ /*using_ssl=*/false, kEndpoint, ProxyServer::Direct(),
+ /*proxy_annotation_tag=*/absl::nullopt,
+ /*ssl_config_for_origin=*/nullptr,
+ /*ssl_config_for_proxy=*/nullptr,
+ /*force_tunnel=*/false, PrivacyMode::PRIVACY_MODE_DISABLED,
+ OnHostResolutionCallback(), DEFAULT_PRIORITY, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ &common_connect_job_params, &delegate_);
+ EXPECT_EQ(GetCreationCount(), 1u);
+
+ ASSERT_THAT(websocket_job_factory_->params(), testing::SizeIs(1));
+ const TransportSocketParams& params =
+ *websocket_job_factory_->params().front();
+ EXPECT_THAT(params.destination(),
+ testing::VariantWith<HostPortPair>(kEndpoint));
+}
+
+} // namespace
+} // namespace net
diff --git a/chromium/net/socket/fuzzed_server_socket.h b/chromium/net/socket/fuzzed_server_socket.h
index 03c6467246b..7d8dc80b566 100644
--- a/chromium/net/socket/fuzzed_server_socket.h
+++ b/chromium/net/socket/fuzzed_server_socket.h
@@ -8,7 +8,6 @@
#include <stdint.h>
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/net/socket/sequenced_socket_data_unittest.cc b/chromium/net/socket/sequenced_socket_data_unittest.cc
index 0586b15c38e..b65552165b3 100644
--- a/chromium/net/socket/sequenced_socket_data_unittest.cc
+++ b/chromium/net/socket/sequenced_socket_data_unittest.cc
@@ -6,10 +6,10 @@
#include <string>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "net/base/completion_once_callback.h"
#include "net/base/io_buffer.h"
#include "net/base/test_completion_callback.h"
diff --git a/chromium/net/socket/socket_descriptor.h b/chromium/net/socket/socket_descriptor.h
index 9a42a960acb..b5f85a365a9 100644
--- a/chromium/net/socket/socket_descriptor.h
+++ b/chromium/net/socket/socket_descriptor.h
@@ -9,14 +9,14 @@
#include "net/base/net_export.h"
#if defined(OS_WIN)
-#include <winsock2.h>
+#include "base/win/windows_types.h"
#endif // OS_WIN
namespace net {
#if defined(OS_WIN)
-typedef SOCKET SocketDescriptor;
-const SocketDescriptor kInvalidSocket = INVALID_SOCKET;
+typedef UINT_PTR SocketDescriptor;
+const SocketDescriptor kInvalidSocket = (SocketDescriptor)(~0);
#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
typedef int SocketDescriptor;
const SocketDescriptor kInvalidSocket = -1;
diff --git a/chromium/net/socket/socket_net_log_params.h b/chromium/net/socket/socket_net_log_params.h
index e727d60d23d..0497ec6f758 100644
--- a/chromium/net/socket/socket_net_log_params.h
+++ b/chromium/net/socket/socket_net_log_params.h
@@ -5,7 +5,6 @@
#ifndef NET_SOCKET_SOCKET_NET_LOG_PARAMS_H_
#define NET_SOCKET_SOCKET_NET_LOG_PARAMS_H_
-#include "net/base/sys_addrinfo.h"
#include "net/log/net_log_event_type.h"
namespace base {
diff --git a/chromium/net/socket/socket_test_util.cc b/chromium/net/socket/socket_test_util.cc
index 8d6dac1c252..9f3195dbc65 100644
--- a/chromium/net/socket/socket_test_util.cc
+++ b/chromium/net/socket/socket_test_util.cc
@@ -17,13 +17,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "net/base/address_family.h"
@@ -304,7 +304,8 @@ MockWriteResult StaticSocketDataProvider::OnWrite(const std::string& data) {
return MockWriteResult(SYNCHRONOUS, data.length());
}
EXPECT_FALSE(helper_.AllWriteDataConsumed())
- << "No more mock data to match write:\n"
+ << "No more mock data to match write:\nFormatted write data:\n"
+ << printer_->PrintWrite(data) << "Raw write data:\n"
<< HexDump(data);
if (helper_.AllWriteDataConsumed()) {
return MockWriteResult(SYNCHRONOUS, ERR_UNEXPECTED);
@@ -496,7 +497,8 @@ MockRead SequencedSocketData::OnRead() {
MockWriteResult SequencedSocketData::OnWrite(const std::string& data) {
CHECK_EQ(IDLE, write_state_);
CHECK(!helper_.AllWriteDataConsumed())
- << "\nNo more mock data to match write:\n"
+ << "\nNo more mock data to match write:\nFormatted write data:\n"
+ << printer_->PrintWrite(data) << "Raw write data:\n"
<< HexDump(data);
NET_TRACE(1, " *** ") << "sequence_number: " << sequence_number_;
@@ -1557,16 +1559,20 @@ void MockSSLClientSocket::Disconnect() {
void MockSSLClientSocket::RunConfirmHandshakeCallback(
CompletionOnceCallback callback,
int result) {
+ DCHECK(in_confirm_handshake_);
+ in_confirm_handshake_ = false;
data_->is_confirm_data_consumed = true;
std::move(callback).Run(result);
}
int MockSSLClientSocket::ConfirmHandshake(CompletionOnceCallback callback) {
DCHECK(stream_socket_->IsConnected());
+ DCHECK(!in_confirm_handshake_);
if (data_->is_confirm_data_consumed)
return data_->confirm.result;
RunClosureIfNonNull(std::move(data_->confirm_callback));
if (data_->confirm.mode == ASYNC) {
+ in_confirm_handshake_ = true;
RunCallbackAsync(
base::BindOnce(&MockSSLClientSocket::RunConfirmHandshakeCallback,
base::Unretained(this), std::move(callback)),
@@ -1574,6 +1580,11 @@ int MockSSLClientSocket::ConfirmHandshake(CompletionOnceCallback callback) {
return ERR_IO_PENDING;
}
data_->is_confirm_data_consumed = true;
+ if (data_->confirm.result == ERR_IO_PENDING) {
+ // `MockConfirm(SYNCHRONOUS, ERR_IO_PENDING)` means `ConfirmHandshake()`
+ // never completes.
+ in_confirm_handshake_ = true;
+ }
return data_->confirm.result;
}
diff --git a/chromium/net/socket/socket_test_util.h b/chromium/net/socket/socket_test_util.h
index 4764ab20296..4df01324ac4 100644
--- a/chromium/net/socket/socket_test_util.h
+++ b/chromium/net/socket/socket_test_util.h
@@ -1020,6 +1020,7 @@ class MockSSLClientSocket : public AsyncSocket, public SSLClientSocket {
void RunConfirmHandshakeCallback(CompletionOnceCallback callback, int result);
bool connected_ = false;
+ bool in_confirm_handshake_ = false;
NetLogWithSource net_log_;
std::unique_ptr<StreamSocket> stream_socket_;
SSLSocketDataProvider* data_;
diff --git a/chromium/net/socket/socks5_client_socket.cc b/chromium/net/socket/socks5_client_socket.cc
index e22ddb2630b..0390ad8c2cf 100644
--- a/chromium/net/socket/socks5_client_socket.cc
+++ b/chromium/net/socket/socks5_client_socket.cc
@@ -9,12 +9,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/format_macros.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/sys_byteorder.h"
#include "base/trace_event/trace_event.h"
#include "net/base/io_buffer.h"
+#include "net/base/sys_addrinfo.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
diff --git a/chromium/net/socket/socks5_client_socket_unittest.cc b/chromium/net/socket/socks5_client_socket_unittest.cc
index 5edac149b24..77cd05f82cf 100644
--- a/chromium/net/socket/socks5_client_socket_unittest.cc
+++ b/chromium/net/socket/socks5_client_socket_unittest.cc
@@ -11,9 +11,9 @@
#include <utility>
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/stl_util.h"
#include "base/sys_byteorder.h"
#include "build/build_config.h"
#include "net/base/address_list.h"
diff --git a/chromium/net/socket/socks_client_socket.cc b/chromium/net/socket/socks_client_socket.cc
index d1a1d4cb619..680961704db 100644
--- a/chromium/net/socket/socks_client_socket.cc
+++ b/chromium/net/socket/socks_client_socket.cc
@@ -9,7 +9,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/sys_byteorder.h"
#include "net/base/io_buffer.h"
#include "net/dns/public/dns_query_type.h"
diff --git a/chromium/net/socket/socks_client_socket_unittest.cc b/chromium/net/socket/socks_client_socket_unittest.cc
index 13005edce3a..de5015584fa 100644
--- a/chromium/net/socket/socks_client_socket_unittest.cc
+++ b/chromium/net/socket/socks_client_socket_unittest.cc
@@ -8,8 +8,8 @@
#include <utility>
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/macros.h"
-#include "base/stl_util.h"
#include "build/build_config.h"
#include "net/base/address_list.h"
#include "net/base/test_completion_callback.h"
diff --git a/chromium/net/socket/socks_connect_job.cc b/chromium/net/socket/socks_connect_job.cc
index 97ee6f2f5cf..c5824014384 100644
--- a/chromium/net/socket/socks_connect_job.cc
+++ b/chromium/net/socket/socks_connect_job.cc
@@ -37,6 +37,18 @@ SOCKSSocketParams::SOCKSSocketParams(
SOCKSSocketParams::~SOCKSSocketParams() = default;
+std::unique_ptr<SOCKSConnectJob> SOCKSConnectJob::Factory::Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SOCKSSocketParams> socks_params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) {
+ return std::make_unique<SOCKSConnectJob>(
+ priority, socket_tag, common_connect_job_params, std::move(socks_params),
+ delegate, net_log);
+}
+
SOCKSConnectJob::SOCKSConnectJob(
RequestPriority priority,
const SocketTag& socket_tag,
diff --git a/chromium/net/socket/socks_connect_job.h b/chromium/net/socket/socks_connect_job.h
index 7ce44f52636..96033281646 100644
--- a/chromium/net/socket/socks_connect_job.h
+++ b/chromium/net/socket/socks_connect_job.h
@@ -6,7 +6,6 @@
#define NET_SOCKET_SOCKS_CONNECT_JOB_H_
#include <memory>
-#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -70,6 +69,20 @@ class NET_EXPORT_PRIVATE SOCKSSocketParams
class NET_EXPORT_PRIVATE SOCKSConnectJob : public ConnectJob,
public ConnectJob::Delegate {
public:
+ class NET_EXPORT_PRIVATE Factory {
+ public:
+ Factory() = default;
+ virtual ~Factory() = default;
+
+ virtual std::unique_ptr<SOCKSConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SOCKSSocketParams> socks_params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log);
+ };
+
SOCKSConnectJob(RequestPriority priority,
const SocketTag& socket_tag,
const CommonConnectJobParams* common_connect_job_params,
diff --git a/chromium/net/socket/ssl_client_socket_impl.cc b/chromium/net/socket/ssl_client_socket_impl.cc
index d049893b0b5..62672bfa326 100644
--- a/chromium/net/socket/ssl_client_socket_impl.cc
+++ b/chromium/net/socket/ssl_client_socket_impl.cc
@@ -16,6 +16,7 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/feature_list.h"
#include "base/lazy_instance.h"
#include "base/location.h"
@@ -26,7 +27,6 @@
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/synchronization/lock.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -851,7 +851,7 @@ int SSLClientSocketImpl::Init() {
// Use BoringSSL defaults, but disable HMAC-SHA1 ciphers in ECDSA. These are
// the remaining CBC-mode ECDSA ciphers.
- std::string command("ALL::!aPSK:!ECDSA+SHA1");
+ std::string command("ALL:!aPSK:!ECDSA+SHA1");
if (ssl_config_.require_ecdhe)
command.append(":!kRSA");
@@ -1555,6 +1555,14 @@ void SSLClientSocketImpl::DoPeek() {
UMA_HISTOGRAM_ENUMERATION("Net.SSLHandshakeEarlyDataReason",
SSL_get_early_data_reason(ssl_.get()),
ssl_early_data_reason_max_value + 1);
+ if (IsGoogleHost(host_and_port_.host())) {
+ // Most Google hosts are known to implement 0-RTT, so this gives more
+ // targeted metrics as we initially roll out client support. See
+ // https://crbug.com/641225.
+ UMA_HISTOGRAM_ENUMERATION("Net.SSLHandshakeEarlyDataReason.Google",
+ SSL_get_early_data_reason(ssl_.get()),
+ ssl_early_data_reason_max_value + 1);
+ }
// On early data reject, clear early data on any other sessions in the
// cache, so retries do not get stuck attempting 0-RTT. See
diff --git a/chromium/net/socket/ssl_client_socket_unittest.cc b/chromium/net/socket/ssl_client_socket_unittest.cc
index 099b67af7fd..b31b2ed9abf 100644
--- a/chromium/net/socket/ssl_client_socket_unittest.cc
+++ b/chromium/net/socket/ssl_client_socket_unittest.cc
@@ -14,13 +14,13 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/test/bind.h"
@@ -5151,11 +5151,7 @@ TEST_F(SSLClientSocketZeroRTTTest, ZeroRTTWrongVersion) {
int rv = ReadAndWait(buf.get(), 4096);
EXPECT_EQ(ERR_WRONG_VERSION_ON_EARLY_DATA, rv);
rv = WriteAndWait(kRequest);
- // TODO(https://crbug.com/1078515): This should be
- // ERR_WRONG_VERSION_ON_EARLY_DATA. We assert on the current value so that,
- // when the bug is fixed (likely in BoringSSL), we remember to fix the test to
- // set a proper test expectation.
- EXPECT_EQ(ERR_SSL_PROTOCOL_ERROR, rv);
+ EXPECT_EQ(ERR_WRONG_VERSION_ON_EARLY_DATA, rv);
// Retrying the connection should succeed.
socket = MakeClient(true);
diff --git a/chromium/net/socket/ssl_connect_job.cc b/chromium/net/socket/ssl_connect_job.cc
index 8d67c8cd2f6..18791fc03a0 100644
--- a/chromium/net/socket/ssl_connect_job.cc
+++ b/chromium/net/socket/ssl_connect_job.cc
@@ -5,6 +5,7 @@
#include "net/socket/ssl_connect_job.h"
#include <cstdlib>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -102,6 +103,18 @@ SSLSocketParams::GetHttpProxyConnectionParams() const {
return http_proxy_params_;
}
+std::unique_ptr<SSLConnectJob> SSLConnectJob::Factory::Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SSLSocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log) {
+ return std::make_unique<SSLConnectJob>(priority, socket_tag,
+ common_connect_job_params,
+ std::move(params), delegate, net_log);
+}
+
SSLConnectJob::SSLConnectJob(
RequestPriority priority,
const SocketTag& socket_tag,
diff --git a/chromium/net/socket/ssl_connect_job.h b/chromium/net/socket/ssl_connect_job.h
index f5ea9b9a4b8..40cd4d8560c 100644
--- a/chromium/net/socket/ssl_connect_job.h
+++ b/chromium/net/socket/ssl_connect_job.h
@@ -87,6 +87,20 @@ class NET_EXPORT_PRIVATE SSLSocketParams
class NET_EXPORT_PRIVATE SSLConnectJob : public ConnectJob,
public ConnectJob::Delegate {
public:
+ class NET_EXPORT_PRIVATE Factory {
+ public:
+ Factory() = default;
+ virtual ~Factory() = default;
+
+ virtual std::unique_ptr<SSLConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ scoped_refptr<SSLSocketParams> params,
+ ConnectJob::Delegate* delegate,
+ const NetLogWithSource* net_log);
+ };
+
// Note: the SSLConnectJob does not own |messenger| so it must outlive the
// job.
SSLConnectJob(RequestPriority priority,
diff --git a/chromium/net/socket/ssl_connect_job_unittest.cc b/chromium/net/socket/ssl_connect_job_unittest.cc
index 2643b9bb1a2..118df885dd7 100644
--- a/chromium/net/socket/ssl_connect_job_unittest.cc
+++ b/chromium/net/socket/ssl_connect_job_unittest.cc
@@ -9,7 +9,7 @@
#include "base/callback.h"
#include "base/compiler_specific.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/test/metrics/histogram_tester.h"
@@ -54,6 +54,8 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
namespace {
@@ -91,11 +93,11 @@ class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
ssl_config_service_(new SSLConfigServiceDefaults),
http_auth_handler_factory_(HttpAuthHandlerFactory::CreateDefault()),
session_(CreateNetworkSession()),
- direct_transport_socket_params_(
- new TransportSocketParams(HostPortPair("host", 443),
- NetworkIsolationKey(),
- SecureDnsPolicy::kAllow,
- OnHostResolutionCallback())),
+ direct_transport_socket_params_(new TransportSocketParams(
+ url::SchemeHostPort(url::kHttpsScheme, "host", 443),
+ NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow,
+ OnHostResolutionCallback())),
proxy_transport_socket_params_(
new TransportSocketParams(HostPortPair("proxy", 443),
NetworkIsolationKey(),
@@ -148,7 +150,7 @@ class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
}
HttpNetworkSession* CreateNetworkSession() {
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.host_resolver = &host_resolver_;
session_context.cert_verifier = &cert_verifier_;
session_context.transport_security_state = &transport_security_state_;
@@ -160,8 +162,7 @@ class SSLConnectJobTest : public WithTaskEnvironment, public testing::Test {
http_auth_handler_factory_.get();
session_context.http_server_properties = &http_server_properties_;
session_context.quic_context = &quic_context_;
- return new HttpNetworkSession(HttpNetworkSession::Params(),
- session_context);
+ return new HttpNetworkSession(HttpNetworkSessionParams(), session_context);
}
protected:
@@ -430,7 +431,8 @@ TEST_F(SSLConnectJobTest, SecureDnsPolicy) {
TestConnectJobDelegate test_delegate;
direct_transport_socket_params_ =
base::MakeRefCounted<TransportSocketParams>(
- HostPortPair("host", 443), NetworkIsolationKey(), secure_dns_policy,
+ url::SchemeHostPort(url::kHttpsScheme, "host", 443),
+ NetworkIsolationKey(), secure_dns_policy,
OnHostResolutionCallback());
auto common_connect_job_params = session_->CreateCommonConnectJobParams();
std::unique_ptr<ConnectJob> ssl_connect_job =
@@ -760,13 +762,14 @@ TEST_F(SSLConnectJobTest, SOCKSHostResolutionFailure) {
TEST_F(SSLConnectJobTest, SOCKSBasic) {
for (IoMode io_mode : {SYNCHRONOUS, ASYNC}) {
SCOPED_TRACE(io_mode);
- const char kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
- 'o', 'c', 'k', 's', 'h', 'o',
- 's', 't', 0x01, 0xBB};
+ const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
+ 'o', 'c', 'k', 's', 'h', 'o',
+ 's', 't', 0x01, 0xBB};
MockWrite writes[] = {
MockWrite(io_mode, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength),
- MockWrite(io_mode, kSOCKS5Request, base::size(kSOCKS5Request)),
+ MockWrite(io_mode, reinterpret_cast<const char*>(kSOCKS5Request),
+ base::size(kSOCKS5Request)),
};
MockRead reads[] = {
@@ -794,12 +797,14 @@ TEST_F(SSLConnectJobTest, SOCKSBasic) {
}
TEST_F(SSLConnectJobTest, SOCKSHasEstablishedConnection) {
- const char kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's', 'o', 'c',
- 'k', 's', 'h', 'o', 's', 't', 0x01, 0xBB};
+ const uint8_t kSOCKS5Request[] = {0x05, 0x01, 0x00, 0x03, 0x09, 's',
+ 'o', 'c', 'k', 's', 'h', 'o',
+ 's', 't', 0x01, 0xBB};
MockWrite writes[] = {
MockWrite(SYNCHRONOUS, kSOCKS5GreetRequest, kSOCKS5GreetRequestLength, 0),
- MockWrite(SYNCHRONOUS, kSOCKS5Request, base::size(kSOCKS5Request), 3),
+ MockWrite(SYNCHRONOUS, reinterpret_cast<const char*>(kSOCKS5Request),
+ base::size(kSOCKS5Request), 3),
};
MockRead reads[] = {
diff --git a/chromium/net/socket/ssl_server_socket_unittest.cc b/chromium/net/socket/ssl_server_socket_unittest.cc
index 4a6d7d1367c..f527d363e2d 100644
--- a/chromium/net/socket/ssl_server_socket_unittest.cc
+++ b/chromium/net/socket/ssl_server_socket_unittest.cc
@@ -26,6 +26,7 @@
#include "base/check.h"
#include "base/compiler_specific.h"
#include "base/containers/queue.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/location.h"
@@ -33,7 +34,6 @@
#include "base/notreached.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
diff --git a/chromium/net/socket/transport_client_socket_pool.cc b/chromium/net/socket/transport_client_socket_pool.cc
index b7aff278c31..6b53f8fbfbd 100644
--- a/chromium/net/socket/transport_client_socket_pool.cc
+++ b/chromium/net/socket/transport_client_socket_pool.cc
@@ -24,12 +24,15 @@
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/values.h"
+#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/proxy_server.h"
#include "net/log/net_log.h"
#include "net/log/net_log_event_type.h"
#include "net/log/net_log_source.h"
+#include "net/socket/connect_job_factory.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "url/gurl.h"
using base::TimeDelta;
@@ -70,47 +73,6 @@ const char TransportClientSocketPool::kSocketPoolDestroyed[] =
const char TransportClientSocketPool::kSslConfigChanged[] =
"SSL configuration changed";
-// ConnectJobFactory implementation that creates the standard ConnectJob
-// classes, using SocketParams.
-class TransportClientSocketPool::ConnectJobFactoryImpl
- : public TransportClientSocketPool::ConnectJobFactory {
- public:
- ConnectJobFactoryImpl(const ProxyServer& proxy_server,
- bool is_for_websockets,
- const CommonConnectJobParams* common_connect_job_params)
- : proxy_server_(proxy_server),
- is_for_websockets_(is_for_websockets),
- common_connect_job_params_(common_connect_job_params) {
- // This class should not be used with WebSockets. Note that
- // |common_connect_job_params| may be nullptr in tests.
- DCHECK(!common_connect_job_params ||
- !common_connect_job_params->websocket_endpoint_lock_manager);
- }
-
- ~ConnectJobFactoryImpl() override = default;
-
- // TransportClientSocketPool::ConnectJobFactory methods.
- std::unique_ptr<ConnectJob> NewConnectJob(
- ClientSocketPool::GroupId group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- RequestPriority request_priority,
- SocketTag socket_tag,
- ConnectJob::Delegate* delegate) const override {
- return CreateConnectJob(group_id, socket_params, proxy_server_,
- proxy_annotation_tag, is_for_websockets_,
- common_connect_job_params_, request_priority,
- socket_tag, delegate);
- }
-
- private:
- const ProxyServer proxy_server_;
- const bool is_for_websockets_;
- const CommonConnectJobParams* common_connect_job_params_;
-
- DISALLOW_COPY_AND_ASSIGN(ConnectJobFactoryImpl);
-};
-
TransportClientSocketPool::Request::Request(
ClientSocketHandle* handle,
CompletionOnceCallback callback,
@@ -161,17 +123,16 @@ TransportClientSocketPool::TransportClientSocketPool(
const ProxyServer& proxy_server,
bool is_for_websockets,
const CommonConnectJobParams* common_connect_job_params)
- : TransportClientSocketPool(
- max_sockets,
- max_sockets_per_group,
- unused_idle_socket_timeout,
- ClientSocketPool::used_idle_socket_timeout(),
- proxy_server,
- std::make_unique<ConnectJobFactoryImpl>(proxy_server,
- is_for_websockets,
- common_connect_job_params),
- common_connect_job_params->ssl_client_context,
- true /* connect_backup_jobs_enabled */) {}
+ : TransportClientSocketPool(max_sockets,
+ max_sockets_per_group,
+ unused_idle_socket_timeout,
+ ClientSocketPool::used_idle_socket_timeout(),
+ proxy_server,
+ is_for_websockets,
+ common_connect_job_params,
+ std::make_unique<ConnectJobFactory>(),
+ common_connect_job_params->ssl_client_context,
+ true /* connect_backup_jobs_enabled */) {}
TransportClientSocketPool::~TransportClientSocketPool() {
// Clean up any idle sockets and pending connect jobs. Assert that we have no
@@ -197,15 +158,17 @@ TransportClientSocketPool::CreateForTesting(
base::TimeDelta unused_idle_socket_timeout,
base::TimeDelta used_idle_socket_timeout,
const ProxyServer& proxy_server,
+ bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
std::unique_ptr<ConnectJobFactory> connect_job_factory,
SSLClientContext* ssl_client_context,
bool connect_backup_jobs_enabled) {
return base::WrapUnique<TransportClientSocketPool>(
new TransportClientSocketPool(
max_sockets, max_sockets_per_group, unused_idle_socket_timeout,
- used_idle_socket_timeout, proxy_server,
- std::move(connect_job_factory), ssl_client_context,
- connect_backup_jobs_enabled));
+ used_idle_socket_timeout, proxy_server, is_for_websockets,
+ common_connect_job_params, std::move(connect_job_factory),
+ ssl_client_context, connect_backup_jobs_enabled));
}
TransportClientSocketPool::CallbackResultPair::CallbackResultPair()
@@ -434,9 +397,9 @@ int TransportClientSocketPool::RequestSocketInternal(const GroupId& group_id,
group = GetOrCreateGroup(group_id);
connecting_socket_count_++;
std::unique_ptr<ConnectJob> owned_connect_job(
- connect_job_factory_->NewConnectJob(
- group_id, request.socket_params(), request.proxy_annotation_tag(),
- request.priority(), request.socket_tag(), group));
+ CreateConnectJob(group_id, request.socket_params(), proxy_server_,
+ request.proxy_annotation_tag(), request.priority(),
+ request.socket_tag(), group));
owned_connect_job->net_log().AddEvent(
NetLogEventType::SOCKET_POOL_CONNECT_JOB_CREATED, [&] {
return NetLogCreateConnectJobParams(false /* backup_job */, &group_id);
@@ -830,10 +793,15 @@ TransportClientSocketPool::TransportClientSocketPool(
base::TimeDelta unused_idle_socket_timeout,
base::TimeDelta used_idle_socket_timeout,
const ProxyServer& proxy_server,
+ bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
std::unique_ptr<ConnectJobFactory> connect_job_factory,
SSLClientContext* ssl_client_context,
bool connect_backup_jobs_enabled)
- : idle_socket_count_(0),
+ : ClientSocketPool(is_for_websockets,
+ common_connect_job_params,
+ std::move(connect_job_factory)),
+ idle_socket_count_(0),
connecting_socket_count_(0),
handed_out_socket_count_(0),
max_sockets_(max_sockets),
@@ -841,7 +809,6 @@ TransportClientSocketPool::TransportClientSocketPool(
unused_idle_socket_timeout_(unused_idle_socket_timeout),
used_idle_socket_timeout_(used_idle_socket_timeout),
proxy_server_(proxy_server),
- connect_job_factory_(std::move(connect_job_factory)),
connect_backup_jobs_enabled_(connect_backup_jobs_enabled &&
g_connect_backup_jobs_enabled),
ssl_client_context_(ssl_client_context) {
@@ -865,6 +832,7 @@ void TransportClientSocketPool::OnSSLConfigChanged(
}
}
+// TODO(crbug.com/1206799): Get `server` as SchemeHostPort?
void TransportClientSocketPool::OnSSLConfigForServerChanged(
const HostPortPair& server) {
// Current time value. Retrieving it once at the function start rather than
@@ -883,8 +851,10 @@ void TransportClientSocketPool::OnSSLConfigForServerChanged(
bool refreshed_any = false;
for (auto it = group_map_.begin(); it != group_map_.end();) {
auto to_refresh = it++;
- if (proxy_matches || (to_refresh->first.socket_type() == SocketType::kSsl &&
- to_refresh->first.destination() == server)) {
+ if (proxy_matches || (GURL::SchemeIsCryptographic(
+ to_refresh->first.destination().scheme()) &&
+ HostPortPair::FromSchemeHostPort(
+ to_refresh->first.destination()) == server)) {
refreshed_any = true;
// Note this call may destroy the group and invalidate |to_refresh|.
RefreshGroup(to_refresh, now, kSslConfigChanged);
@@ -1634,8 +1604,9 @@ void TransportClientSocketPool::Group::OnBackupJobTimerFired(
Request* request = unbound_requests_.FirstMax().value().get();
std::unique_ptr<ConnectJob> owned_backup_job =
- client_socket_pool_->connect_job_factory_->NewConnectJob(
- group_id, request->socket_params(), request->proxy_annotation_tag(),
+ client_socket_pool_->CreateConnectJob(
+ group_id, request->socket_params(),
+ client_socket_pool_->proxy_server_, request->proxy_annotation_tag(),
request->priority(), request->socket_tag(), this);
owned_backup_job->net_log().AddEvent(
NetLogEventType::SOCKET_POOL_CONNECT_JOB_CREATED, [&] {
@@ -1731,6 +1702,12 @@ void TransportClientSocketPool::Group::RemoveAllUnboundJobs() {
}
unassigned_jobs_.clear();
never_assigned_job_count_ = 0;
+
+ // Diagnostics check for crbug.com/1231248. `Group`s are deleted only on
+ // removal from `TransportClientSocketPool::group_map_`, so if this check
+ // fails, `this` has been deleted, likely through some reentrancy issue.
+ CHECK(client_socket_pool_->HasGroup(group_id_));
+
// Delete active jobs.
jobs_.clear();
// Stop backup job timer.
diff --git a/chromium/net/socket/transport_client_socket_pool.h b/chromium/net/socket/transport_client_socket_pool.h
index b711242e380..80f432de5ff 100644
--- a/chromium/net/socket/transport_client_socket_pool.h
+++ b/chromium/net/socket/transport_client_socket_pool.h
@@ -50,6 +50,7 @@ class ProcessMemoryDump;
namespace net {
struct CommonConnectJobParams;
+class ConnectJobFactory;
struct NetLogSource;
struct NetworkTrafficAnnotationTag;
@@ -150,23 +151,6 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool
DISALLOW_COPY_AND_ASSIGN(Request);
};
- class ConnectJobFactory {
- public:
- ConnectJobFactory() {}
- virtual ~ConnectJobFactory() {}
-
- virtual std::unique_ptr<ConnectJob> NewConnectJob(
- ClientSocketPool::GroupId group_id,
- scoped_refptr<ClientSocketPool::SocketParams> socket_params,
- const absl::optional<NetworkTrafficAnnotationTag>& proxy_annotation_tag,
- RequestPriority request_priority,
- SocketTag socket_tag,
- ConnectJob::Delegate* delegate) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConnectJobFactory);
- };
-
TransportClientSocketPool(
int max_sockets,
int max_sockets_per_group,
@@ -186,6 +170,8 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool
base::TimeDelta unused_idle_socket_timeout,
base::TimeDelta used_idle_socket_timeout,
const ProxyServer& proxy_server,
+ bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
std::unique_ptr<ConnectJobFactory> connect_job_factory,
SSLClientContext* ssl_client_context,
bool connect_backup_jobs_enabled);
@@ -281,8 +267,6 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool
void OnSSLConfigForServerChanged(const HostPortPair& server) override;
private:
- class ConnectJobFactoryImpl;
-
// Entry for a persistent socket which became idle at time |start_time|.
struct IdleSocket {
IdleSocket() : socket(nullptr) {}
@@ -614,6 +598,8 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool
base::TimeDelta unused_idle_socket_timeout,
base::TimeDelta used_idle_socket_timeout,
const ProxyServer& proxy_server,
+ bool is_for_websockets,
+ const CommonConnectJobParams* common_connect_job_params,
std::unique_ptr<ConnectJobFactory> connect_job_factory,
SSLClientContext* ssl_client_context,
bool connect_backup_jobs_enabled);
@@ -805,8 +791,6 @@ class NET_EXPORT_PRIVATE TransportClientSocketPool
const ProxyServer proxy_server_;
- const std::unique_ptr<ConnectJobFactory> connect_job_factory_;
-
// TODO(vandebo) Remove when backup jobs move to TransportClientSocketPool
bool connect_backup_jobs_enabled_;
diff --git a/chromium/net/socket/transport_client_socket_pool_unittest.cc b/chromium/net/socket/transport_client_socket_pool_unittest.cc
index b016786f8bc..62ab35e5a5d 100644
--- a/chromium/net/socket/transport_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/transport_client_socket_pool_unittest.cc
@@ -10,9 +10,9 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/test/bind.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/platform_thread.h"
@@ -57,6 +57,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -106,8 +108,7 @@ class TransportClientSocketPoolTest : public ::testing::Test,
: WithTaskEnvironment(time_source),
connect_backup_jobs_enabled_(
TransportClientSocketPool::set_connect_backup_jobs_enabled(true)),
- group_id_(HostPortPair("www.google.com", 80),
- ClientSocketPool::SocketType::kHttp,
+ group_id_(url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
@@ -157,7 +158,7 @@ class TransportClientSocketPoolTest : public ::testing::Test,
int StartRequest(const std::string& host_name, RequestPriority priority) {
ClientSocketPool::GroupId group_id(
- HostPortPair(host_name, 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, host_name, 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
return test_base_.StartRequestUsingPool(
@@ -264,7 +265,7 @@ TEST_F(TransportClientSocketPoolTest, SetSecureDnsPolicy) {
TestCompletionCallback callback;
ClientSocketHandle handle;
ClientSocketPool::GroupId group_id(
- HostPortPair("www.google.com", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
secure_dns_policy);
EXPECT_EQ(
@@ -1037,7 +1038,8 @@ TEST_F(TransportClientSocketPoolTest, SSLCertError) {
SSLSocketDataProvider ssl(ASYNC, ERR_CERT_COMMON_NAME_INVALID);
tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl);
- const HostPortPair kHostPortPair("ssl.server.test", 443);
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "ssl.server.test",
+ 443);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
base::MakeRefCounted<ClientSocketPool::SocketParams>(
@@ -1046,15 +1048,13 @@ TEST_F(TransportClientSocketPoolTest, SSLCertError) {
ClientSocketHandle handle;
TestCompletionCallback callback;
- int rv =
- handle.Init(ClientSocketPool::GroupId(
- kHostPortPair, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
- socket_params, absl::nullopt /* proxy_annotation_tag */,
- MEDIUM, SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
- callback.callback(), ClientSocketPool::ProxyAuthCallback(),
- tagging_pool_.get(), NetLogWithSource());
+ int rv = handle.Init(
+ ClientSocketPool::GroupId(kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
+ socket_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
+ SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
+ callback.callback(), ClientSocketPool::ProxyAuthCallback(),
+ tagging_pool_.get(), NetLogWithSource());
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
EXPECT_FALSE(handle.is_initialized());
EXPECT_FALSE(handle.socket());
@@ -1305,7 +1305,7 @@ TEST_F(TransportClientSocketPoolTest, BackupSocketFailAfterDelay) {
// Test the case that SOCKSSocketParams are provided.
TEST_F(TransportClientSocketPoolTest, SOCKS) {
- const HostPortPair kDestination("host", 80);
+ const url::SchemeHostPort kDestination(url::kHttpScheme, "host", 80);
TransportClientSocketPool proxy_pool(
kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout,
@@ -1326,9 +1326,8 @@ TEST_F(TransportClientSocketPoolTest, SOCKS) {
TestCompletionCallback callback;
int rv = handle.Init(
ClientSocketPool::GroupId(
- kDestination, ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ kDestination, PrivacyMode::PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
ClientSocketPool::ProxyAuthCallback(), &proxy_pool, NetLogWithSource());
@@ -1346,7 +1345,8 @@ TEST_F(TransportClientSocketPoolTest, SOCKS) {
//
// See https://crbug.com/940848
TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) {
- const HostPortPair kEndpoint("unresolvable.host.name", 443);
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme,
+ "unresolvable.host.name", 443);
session_deps_.host_resolver->set_synchronous_mode(true);
@@ -1361,7 +1361,8 @@ TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) {
SpdyTestUtil spdy_util;
spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect(
- nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, kEndpoint));
+ nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
+ HostPortPair::FromSchemeHostPort(kEndpoint)));
MockWrite writes[] = {
CreateMockWrite(connect, 0, ASYNC),
@@ -1393,8 +1394,7 @@ TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) {
std::make_unique<SSLConfig>() /* ssl_config_for_proxy */);
ClientSocketPool::GroupId group_id(
- kEndpoint, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
// Start the first connection attempt.
@@ -1436,7 +1436,8 @@ TEST_F(TransportClientSocketPoolTest, SpdyOneConnectJobTwoRequestsError) {
//
// See https://crbug.com/940848
TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) {
- const HostPortPair kEndpoint("unresolvable.host.name", 443);
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme,
+ "unresolvable.host.name", 443);
const HostPortPair kProxy("unresolvable.proxy.name", 443);
session_deps_.host_resolver->set_synchronous_mode(true);
@@ -1450,7 +1451,8 @@ TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) {
SpdyTestUtil spdy_util;
spdy::SpdySerializedFrame connect(spdy_util.ConstructSpdyConnect(
- nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority, kEndpoint));
+ nullptr, 0, 1, HttpProxyConnectJob::kH2QuicTunnelPriority,
+ HostPortPair::FromSchemeHostPort(kEndpoint)));
MockWrite writes[] = {
CreateMockWrite(connect, 0, ASYNC),
@@ -1497,8 +1499,7 @@ TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) {
std::make_unique<SSLConfig>() /* ssl_config_for_proxy */);
ClientSocketPool::GroupId group_id(
- kEndpoint, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
// Start the first connection attempt.
@@ -1543,7 +1544,7 @@ TEST_F(TransportClientSocketPoolTest, SpdyAuthOneConnectJobTwoRequests) {
}
TEST_F(TransportClientSocketPoolTest, HttpTunnelSetupRedirect) {
- const HostPortPair kEndpoint("host.test", 443);
+ const url::SchemeHostPort kEndpoint(url::kHttpsScheme, "host.test", 443);
const std::string kRedirectTarget = "https://some.other.host.test/";
@@ -1595,9 +1596,8 @@ TEST_F(TransportClientSocketPoolTest, HttpTunnelSetupRedirect) {
int rv = handle.Init(
ClientSocketPool::GroupId(
- kEndpoint, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ kEndpoint, PrivacyMode::PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
socket_params, TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
@@ -1627,7 +1627,7 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKey) {
session_deps_.host_resolver->set_ondemand_mode(true);
TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
SecureDnsPolicy::kAllow);
ClientSocketHandle handle;
@@ -1665,7 +1665,7 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySsl) {
session_deps_.host_resolver->set_ondemand_mode(true);
TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 443), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, kHost, 443),
PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
SecureDnsPolicy::kAllow);
ClientSocketHandle handle;
@@ -1687,10 +1687,14 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySsl) {
session_deps_.host_resolver->request_network_isolation_key(1));
}
-// Test that, in the case of an HTTP proxy, the NetworkIsolationKey is not used.
+// Test that, in the case of an HTTP proxy, the same transient
+// NetworkIsolationKey is reused for resolving the proxy's host, regardless of
+// input NIK.
TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpProxy) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
+ const SchemefulSite kSite1(GURL("https://foo.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
+ const SchemefulSite kSite2(GURL("https://bar.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
const char kHost[] = "bar.test";
const ProxyServer kProxyServer = ProxyServer::FromURI(
"http://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
@@ -1709,35 +1713,59 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpProxy) {
kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 80), ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
+ TransportClientSocketPool::GroupId group_id1(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
SecureDnsPolicy::kAllow);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
+ ClientSocketHandle handle1;
+ TestCompletionCallback callback1;
EXPECT_THAT(
- handle.Init(group_id,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
- NetLogWithSource()),
+ handle1.Init(group_id1,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
IsError(ERR_IO_PENDING));
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
+ TransportClientSocketPool::GroupId group_id2(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
+ SecureDnsPolicy::kAllow);
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ EXPECT_THAT(
+ handle2.Init(group_id2,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
+ IsError(ERR_IO_PENDING));
+
+ ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
EXPECT_EQ(kProxyServer.host_port_pair().host(),
session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(NetworkIsolationKey(),
- session_deps_.host_resolver->request_network_isolation_key(1));
+ EXPECT_EQ(kProxyServer.host_port_pair().host(),
+ session_deps_.host_resolver->request_host(2));
+ EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
+ .IsTransient());
+ EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
+ session_deps_.host_resolver->request_network_isolation_key(2));
}
-// Test that, in the case of an HTTPS proxy, the NetworkIsolationKey is not
-// used.
+// Test that, in the case of an HTTPS proxy, the same transient
+// NetworkIsolationKey is reused for resolving the proxy's host, regardless of
+// input NIK.
TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpsProxy) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
+ const SchemefulSite kSite1(GURL("https://foo.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
+ const SchemefulSite kSite2(GURL("https://bar.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
const char kHost[] = "bar.test";
const ProxyServer kProxyServer = ProxyServer::FromURI(
"https://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
@@ -1756,35 +1784,60 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeyHttpsProxy) {
kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 80), ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
+ TransportClientSocketPool::GroupId group_id1(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
SecureDnsPolicy::kAllow);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
- EXPECT_THAT(
- handle.Init(group_id,
+ ClientSocketHandle handle1;
+ TestCompletionCallback callback1;
+ EXPECT_THAT(handle1.Init(
+ group_id1,
base::MakeRefCounted<ClientSocketPool::SocketParams>(
nullptr /* ssl_config_for_origin */,
std::make_unique<SSLConfig>() /* ssl_config_for_proxy */),
TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
- NetLogWithSource()),
- IsError(ERR_IO_PENDING));
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
+ IsError(ERR_IO_PENDING));
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
+ TransportClientSocketPool::GroupId group_id2(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
+ SecureDnsPolicy::kAllow);
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ EXPECT_THAT(handle2.Init(
+ group_id2,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ std::make_unique<SSLConfig>() /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
+ IsError(ERR_IO_PENDING));
+
+ ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
EXPECT_EQ(kProxyServer.host_port_pair().host(),
session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(NetworkIsolationKey(),
- session_deps_.host_resolver->request_network_isolation_key(1));
+ EXPECT_EQ(kProxyServer.host_port_pair().host(),
+ session_deps_.host_resolver->request_host(2));
+ EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
+ .IsTransient());
+ EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
+ session_deps_.host_resolver->request_network_isolation_key(2));
}
-// Test that, in the case of a SOCKS5 proxy, the NetworkIsolationKey is only
-// used for the destination DNS lookup, not the proxy DNS lookup.
+// Test that, in the case of a SOCKS5 proxy, the passed in NetworkIsolationKey
+// is used for the destination DNS lookup, and the same transient
+// NetworkIsolationKey is reused for resolving the proxy's host, regardless of
+// input NIK.
TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks4Proxy) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
+ const SchemefulSite kSite1(GURL("https://foo.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
+ const SchemefulSite kSite2(GURL("https://bar.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
const char kHost[] = "bar.test";
const ProxyServer kProxyServer = ProxyServer::FromURI(
"socks4://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
@@ -1799,54 +1852,86 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks4Proxy) {
session_deps_.host_resolver->set_ondemand_mode(true);
- // Test will establish a connection, but never use it to transfer data, since
- // it stalls at the second DNS lookup.
- StaticSocketDataProvider data;
- data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
- tagging_client_socket_factory_.AddSocketDataProvider(&data);
+ // Test will establish two connections, but never use them to transfer data,
+ // since thet stall on the followup DNS lookups.
+ StaticSocketDataProvider data1;
+ data1.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ tagging_client_socket_factory_.AddSocketDataProvider(&data1);
+ StaticSocketDataProvider data2;
+ data2.set_connect_data(MockConnect(SYNCHRONOUS, OK));
+ tagging_client_socket_factory_.AddSocketDataProvider(&data2);
TransportClientSocketPool proxy_pool(
kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 80), ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
+ TransportClientSocketPool::GroupId group_id1(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
SecureDnsPolicy::kAllow);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
+ ClientSocketHandle handle1;
+ TestCompletionCallback callback1;
EXPECT_THAT(
- handle.Init(group_id,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
- NetLogWithSource()),
+ handle1.Init(group_id1,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
IsError(ERR_IO_PENDING));
- // First lookup is for the proxy's hostname, and should not use the NIK.
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kProxyServer.host_port_pair().host(),
- session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(NetworkIsolationKey(),
- session_deps_.host_resolver->request_network_isolation_key(1));
+ TransportClientSocketPool::GroupId group_id2(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
+ SecureDnsPolicy::kAllow);
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ EXPECT_THAT(
+ handle2.Init(group_id2,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
+ IsError(ERR_IO_PENDING));
- // First lookup completes, starting the second one. The second lookup is for
- // the destination's hostname, and should use the NIK.
- session_deps_.host_resolver->ResolveOnlyRequestNow();
+ // First two lookups are for the proxy's hostname, and should use the same
+ // transient NIK.
ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
- EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(2));
- EXPECT_EQ(kNetworkIsolationKey,
+ EXPECT_EQ(kProxyServer.host_port_pair().host(),
+ session_deps_.host_resolver->request_host(1));
+ EXPECT_EQ(kProxyServer.host_port_pair().host(),
+ session_deps_.host_resolver->request_host(2));
+ EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
+ .IsTransient());
+ EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
session_deps_.host_resolver->request_network_isolation_key(2));
+
+ // First two lookups completes, starting the next two, which should be for the
+ // destination's hostname, and should use the passed in NIKs.
+ session_deps_.host_resolver->ResolveNow(1);
+ session_deps_.host_resolver->ResolveNow(2);
+ ASSERT_EQ(4u, session_deps_.host_resolver->last_id());
+ EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(3));
+ EXPECT_EQ(kNetworkIsolationKey1,
+ session_deps_.host_resolver->request_network_isolation_key(3));
+ EXPECT_EQ(kHost, session_deps_.host_resolver->request_host(4));
+ EXPECT_EQ(kNetworkIsolationKey2,
+ session_deps_.host_resolver->request_network_isolation_key(4));
}
-// Test that, in the case of a SOCKS5 proxy, the NetworkIsolationKey is not
-// used.
+// Test that, in the case of a SOCKS5 proxy, the same transient
+// NetworkIsolationKey is reused for resolving the proxy's host, regardless of
+// input NIK.
TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks5Proxy) {
- const SchemefulSite kSite(GURL("https://foo.test/"));
- const NetworkIsolationKey kNetworkIsolationKey(kSite, kSite);
+ const SchemefulSite kSite1(GURL("https://foo.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey1(kSite1, kSite1);
+ const SchemefulSite kSite2(GURL("https://bar.test/"));
+ const NetworkIsolationKey kNetworkIsolationKey2(kSite2, kSite2);
const char kHost[] = "bar.test";
const ProxyServer kProxyServer = ProxyServer::FromURI(
"socks5://proxy.test", ProxyServer::SCHEME_HTTP /* default_scheme */);
@@ -1865,28 +1950,49 @@ TEST_F(TransportClientSocketPoolTest, NetworkIsolationKeySocks5Proxy) {
kMaxSockets, kMaxSocketsPerGroup, kUnusedIdleSocketTimeout, kProxyServer,
false /* is_for_websockets */, tagging_common_connect_job_params_.get());
- TransportClientSocketPool::GroupId group_id(
- HostPortPair(kHost, 80), ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
+ TransportClientSocketPool::GroupId group_id1(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey1,
SecureDnsPolicy::kAllow);
- ClientSocketHandle handle;
- TestCompletionCallback callback;
+ ClientSocketHandle handle1;
+ TestCompletionCallback callback1;
EXPECT_THAT(
- handle.Init(group_id,
- base::MakeRefCounted<ClientSocketPool::SocketParams>(
- nullptr /* ssl_config_for_origin */,
- nullptr /* ssl_config_for_proxy */),
- TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
- ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
- ClientSocketPool::ProxyAuthCallback(), &proxy_pool,
- NetLogWithSource()),
+ handle1.Init(group_id1,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback1.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
IsError(ERR_IO_PENDING));
- ASSERT_EQ(1u, session_deps_.host_resolver->last_id());
+ TransportClientSocketPool::GroupId group_id2(
+ url::SchemeHostPort(url::kHttpScheme, kHost, 80),
+ PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey2,
+ SecureDnsPolicy::kAllow);
+ ClientSocketHandle handle2;
+ TestCompletionCallback callback2;
+ EXPECT_THAT(
+ handle2.Init(group_id2,
+ base::MakeRefCounted<ClientSocketPool::SocketParams>(
+ nullptr /* ssl_config_for_origin */,
+ nullptr /* ssl_config_for_proxy */),
+ TRAFFIC_ANNOTATION_FOR_TESTS, LOW, SocketTag(),
+ ClientSocketPool::RespectLimits::ENABLED,
+ callback2.callback(), ClientSocketPool::ProxyAuthCallback(),
+ &proxy_pool, NetLogWithSource()),
+ IsError(ERR_IO_PENDING));
+
+ ASSERT_EQ(2u, session_deps_.host_resolver->last_id());
EXPECT_EQ(kProxyServer.host_port_pair().host(),
session_deps_.host_resolver->request_host(1));
- EXPECT_EQ(NetworkIsolationKey(),
- session_deps_.host_resolver->request_network_isolation_key(1));
+ EXPECT_EQ(kProxyServer.host_port_pair().host(),
+ session_deps_.host_resolver->request_host(2));
+ EXPECT_TRUE(session_deps_.host_resolver->request_network_isolation_key(1)
+ .IsTransient());
+ EXPECT_EQ(session_deps_.host_resolver->request_network_isolation_key(1),
+ session_deps_.host_resolver->request_network_isolation_key(2));
}
// Test that SocketTag passed into TransportClientSocketPool is applied to
@@ -1912,7 +2018,7 @@ TEST_F(TransportClientSocketPoolTest, Tag) {
// Test socket is tagged before connected.
uint64_t old_traffic = GetTaggedBytes(tag_val1);
const ClientSocketPool::GroupId kGroupId(
- test_server.host_port_pair(), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(test_server.base_url()),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> params =
@@ -2037,10 +2143,9 @@ TEST_F(TransportClientSocketPoolTest, TagSOCKSProxy) {
SocketTag tag1(SocketTag::UNSET_UID, 0x12345678);
SocketTag tag2(getuid(), 0x87654321);
- const HostPortPair kDestination("host", 80);
+ const url::SchemeHostPort kDestination(url::kHttpScheme, "host", 80);
const ClientSocketPool::GroupId kGroupId(
- kDestination, ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> socks_params =
base::MakeRefCounted<ClientSocketPool::SocketParams>(
@@ -2133,7 +2238,7 @@ TEST_F(TransportClientSocketPoolTest, TagSSLDirect) {
int32_t tag_val2 = 0x87654321;
SocketTag tag2(getuid(), tag_val2);
const ClientSocketPool::GroupId kGroupId(
- test_server.host_port_pair(), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(test_server.base_url()),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
@@ -2204,7 +2309,7 @@ TEST_F(TransportClientSocketPoolTest, TagSSLDirectTwoSockets) {
int32_t tag_val2 = 0x87654321;
SocketTag tag2(getuid(), tag_val2);
const ClientSocketPool::GroupId kGroupId(
- test_server.host_port_pair(), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(test_server.base_url()),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
@@ -2268,7 +2373,7 @@ TEST_F(TransportClientSocketPoolTest, TagSSLDirectTwoSocketsFullPool) {
int32_t tag_val2 = 0x87654321;
SocketTag tag2(getuid(), tag_val2);
const ClientSocketPool::GroupId kGroupId(
- test_server.host_port_pair(), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(test_server.base_url()),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
@@ -2346,10 +2451,10 @@ TEST_F(TransportClientSocketPoolTest, TagHttpProxyNoTunnel) {
socket_data.set_connect_data(MockConnect(SYNCHRONOUS, OK));
tagging_client_socket_factory_.AddSocketDataProvider(&socket_data);
- const HostPortPair kDestination("www.google.com", 80);
+ const url::SchemeHostPort kDestination(url::kHttpScheme, "www.google.com",
+ 80);
const ClientSocketPool::GroupId kGroupId(
- kDestination, ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
base::MakeRefCounted<ClientSocketPool::SocketParams>(
@@ -2419,10 +2524,10 @@ TEST_F(TransportClientSocketPoolTest, TagHttpProxyTunnel) {
SSLSocketDataProvider ssl_data(SYNCHRONOUS, OK);
tagging_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
- const HostPortPair kDestination("www.google.com", 443);
+ const url::SchemeHostPort kDestination(url::kHttpsScheme, "www.google.com",
+ 443);
const ClientSocketPool::GroupId kGroupId(
- kDestination, ClientSocketPool::SocketType::kSsl,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
+ kDestination, PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
scoped_refptr<ClientSocketPool::SocketParams> socket_params =
@@ -2483,8 +2588,10 @@ class TransportClientSocketPoolMockNowSourceTest
// required since requesting a new socket triggers cleanup of idle timedout
// sockets. Next, the test verifies the count of idle timed-out sockets.
TEST_F(TransportClientSocketPoolMockNowSourceTest, IdleUnusedSocketTimeout) {
- const HostPortPair kHostPortPair1("www.foo.com", 80);
- const HostPortPair kHostPortPair2("www.bar.com", 80);
+ const url::SchemeHostPort kSchemeHostPort1(url::kHttpScheme, "www.foo.com",
+ 80);
+ const url::SchemeHostPort kSchemeHostPort2(url::kHttpScheme, "www.bar.com",
+ 80);
const struct {
bool use_first_socket;
@@ -2541,9 +2648,8 @@ TEST_F(TransportClientSocketPoolMockNowSourceTest, IdleUnusedSocketTimeout) {
TestCompletionCallback callback;
int rv = connection.Init(
ClientSocketPool::GroupId(
- kHostPortPair1, ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ kSchemeHostPort1, PrivacyMode::PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
ClientSocketPool::SocketParams::CreateForHttpForTesting(),
absl::nullopt /* proxy_annotation_tag */, MEDIUM, SocketTag(),
ClientSocketPool::RespectLimits::ENABLED, callback.callback(),
@@ -2590,9 +2696,8 @@ TEST_F(TransportClientSocketPoolMockNowSourceTest, IdleUnusedSocketTimeout) {
TestCompletionCallback callback;
int rv = connection.Init(
ClientSocketPool::GroupId(
- kHostPortPair2, ClientSocketPool::SocketType::kHttp,
- PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ kSchemeHostPort2, PrivacyMode::PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
socket_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
callback.callback(), ClientSocketPool::ProxyAuthCallback(),
diff --git a/chromium/net/socket/transport_connect_job.cc b/chromium/net/socket/transport_connect_job.cc
index 555b0e7e71f..7c5c9ddbdf2 100644
--- a/chromium/net/socket/transport_connect_job.cc
+++ b/chromium/net/socket/transport_connect_job.cc
@@ -17,6 +17,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
+#include "net/base/host_port_pair.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
#include "net/base/trace_constants.h"
@@ -31,6 +32,8 @@
#include "net/socket/socket_performance_watcher_factory.h"
#include "net/socket/tcp_client_socket.h"
#include "net/socket/websocket_transport_connect_job.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -46,20 +49,45 @@ bool AddressListOnlyContainsIPv6(const AddressList& list) {
return true;
}
+// TODO(crbug.com/1206799): Delete once endpoint usage is converted to using
+// url::SchemeHostPort when available.
+HostPortPair ToLegacyDestinationEndpoint(
+ const TransportSocketParams::Endpoint& endpoint) {
+ if (absl::holds_alternative<url::SchemeHostPort>(endpoint)) {
+ return HostPortPair::FromSchemeHostPort(
+ absl::get<url::SchemeHostPort>(endpoint));
+ }
+
+ DCHECK(absl::holds_alternative<HostPortPair>(endpoint));
+ return absl::get<HostPortPair>(endpoint);
+}
+
} // namespace
TransportSocketParams::TransportSocketParams(
- const HostPortPair& host_port_pair,
- const NetworkIsolationKey& network_isolation_key,
+ Endpoint destination,
+ NetworkIsolationKey network_isolation_key,
SecureDnsPolicy secure_dns_policy,
- const OnHostResolutionCallback& host_resolution_callback)
- : destination_(host_port_pair),
- network_isolation_key_(network_isolation_key),
+ OnHostResolutionCallback host_resolution_callback)
+ : destination_(std::move(destination)),
+ network_isolation_key_(std::move(network_isolation_key)),
secure_dns_policy_(secure_dns_policy),
- host_resolution_callback_(host_resolution_callback) {}
+ host_resolution_callback_(std::move(host_resolution_callback)) {}
TransportSocketParams::~TransportSocketParams() = default;
+std::unique_ptr<TransportConnectJob> TransportConnectJob::Factory::Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ Delegate* delegate,
+ const NetLogWithSource* net_log) {
+ return std::make_unique<TransportConnectJob>(priority, socket_tag,
+ common_connect_job_params,
+ params, delegate, net_log);
+}
+
// TODO(eroman): The use of this constant needs to be re-evaluated. The time
// needed for TCPClientSocketXXX::Connect() can be arbitrarily long, since
// the address list may contain many alternatives, and most of those may
@@ -271,9 +299,9 @@ int TransportConnectJob::DoResolveHost() {
HostResolver::ResolveHostParameters parameters;
parameters.initial_priority = priority();
parameters.secure_dns_policy = params_->secure_dns_policy();
- request_ = host_resolver()->CreateRequest(params_->destination(),
- params_->network_isolation_key(),
- net_log(), parameters);
+ request_ = host_resolver()->CreateRequest(
+ ToLegacyDestinationEndpoint(params_->destination()),
+ params_->network_isolation_key(), net_log(), parameters);
return request_->Start(base::BindOnce(&TransportConnectJob::OnIOComplete,
base::Unretained(this)));
@@ -300,7 +328,8 @@ int TransportConnectJob::DoResolveHostComplete(int result) {
if (!params_->host_resolution_callback().is_null()) {
OnHostResolutionCallbackResult callback_result =
params_->host_resolution_callback().Run(
- params_->destination(), request_->GetAddressResults().value());
+ ToLegacyDestinationEndpoint(params_->destination()),
+ request_->GetAddressResults().value());
if (callback_result == OnHostResolutionCallbackResult::kMayBeDeletedAsync) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&TransportConnectJob::OnIOComplete,
diff --git a/chromium/net/socket/transport_connect_job.h b/chromium/net/socket/transport_connect_job.h
index 5b3942348a9..acf2c6be073 100644
--- a/chromium/net/socket/transport_connect_job.h
+++ b/chromium/net/socket/transport_connect_job.h
@@ -6,7 +6,6 @@
#define NET_SOCKET_TRANSPORT_CONNECT_JOB_H_
#include <memory>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
@@ -23,6 +22,8 @@
#include "net/socket/connect_job.h"
#include "net/socket/connection_attempts.h"
#include "net/socket/socket_tag.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
namespace net {
@@ -32,17 +33,22 @@ class SocketTag;
class NET_EXPORT_PRIVATE TransportSocketParams
: public base::RefCounted<TransportSocketParams> {
public:
+ // Representation of the destination endpoint of the transport
+ // socket/connection. Unlike ConnectJobFactory::Endpoint, this does not have a
+ // `using_ssl` field for schemeless endpoints because that has no meaning for
+ // transport parameters.
+ using Endpoint = absl::variant<url::SchemeHostPort, HostPortPair>;
+
// |host_resolution_callback| will be invoked after the the hostname is
// resolved. |network_isolation_key| is passed to the HostResolver to prevent
// cross-NIK leaks. If |host_resolution_callback| does not return OK, then the
// connection will be aborted with that value.
- TransportSocketParams(
- const HostPortPair& host_port_pair,
- const NetworkIsolationKey& network_isolation_key,
- SecureDnsPolicy secure_dns_policy,
- const OnHostResolutionCallback& host_resolution_callback);
+ TransportSocketParams(Endpoint destination,
+ NetworkIsolationKey network_isolation_key,
+ SecureDnsPolicy secure_dns_policy,
+ OnHostResolutionCallback host_resolution_callback);
- const HostPortPair& destination() const { return destination_; }
+ const Endpoint& destination() const { return destination_; }
const NetworkIsolationKey& network_isolation_key() const {
return network_isolation_key_;
}
@@ -55,7 +61,7 @@ class NET_EXPORT_PRIVATE TransportSocketParams
friend class base::RefCounted<TransportSocketParams>;
~TransportSocketParams();
- const HostPortPair destination_;
+ const Endpoint destination_;
const NetworkIsolationKey network_isolation_key_;
const SecureDnsPolicy secure_dns_policy_;
const OnHostResolutionCallback host_resolution_callback_;
@@ -82,6 +88,20 @@ class NET_EXPORT_PRIVATE TransportConnectJob : public ConnectJob {
RACE_IPV6_SOLO,
};
+ class NET_EXPORT_PRIVATE Factory {
+ public:
+ Factory() = default;
+ virtual ~Factory() = default;
+
+ virtual std::unique_ptr<TransportConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ Delegate* delegate,
+ const NetLogWithSource* net_log);
+ };
+
// TransportConnectJobs will time out after this many seconds. Note this is
// the total time, including both host resolution and TCP connect() times.
static const int kTimeoutInSeconds;
diff --git a/chromium/net/socket/transport_connect_job_unittest.cc b/chromium/net/socket/transport_connect_job_unittest.cc
index 313b44c9282..66df9f37488 100644
--- a/chromium/net/socket/transport_connect_job_unittest.cc
+++ b/chromium/net/socket/transport_connect_job_unittest.cc
@@ -13,6 +13,7 @@
#include "base/test/task_environment.h"
#include "net/base/address_family.h"
#include "net/base/address_list.h"
+#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
@@ -27,6 +28,8 @@
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
namespace net {
namespace {
@@ -59,8 +62,9 @@ class TransportConnectJobTest : public WithTaskEnvironment,
static scoped_refptr<TransportSocketParams> DefaultParams() {
return base::MakeRefCounted<TransportSocketParams>(
- HostPortPair(kHostName, 80), NetworkIsolationKey(),
- SecureDnsPolicy::kAllow, OnHostResolutionCallback());
+ url::SchemeHostPort(url::kHttpScheme, kHostName, 80),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ OnHostResolutionCallback());
}
protected:
@@ -262,6 +266,35 @@ TEST_F(TransportConnectJobTest, ConnectionSuccess) {
}
}
+// TODO(crbug.com/1206799): Set up `host_resolver_` to require the expected
+// scheme.
+TEST_F(TransportConnectJobTest, HandlesHttpsEndpoint) {
+ TestConnectJobDelegate test_delegate;
+ TransportConnectJob transport_connect_job(
+ DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
+ base::MakeRefCounted<TransportSocketParams>(
+ url::SchemeHostPort(url::kHttpsScheme, kHostName, 80),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ OnHostResolutionCallback()),
+ &test_delegate, nullptr /* net_log */);
+ test_delegate.StartJobExpectingResult(&transport_connect_job, OK,
+ false /* expect_sync_result */);
+}
+
+// TODO(crbug.com/1206799): Set up `host_resolver_` to require the expected
+// lack of scheme.
+TEST_F(TransportConnectJobTest, HandlesNonStandardEndpoint) {
+ TestConnectJobDelegate test_delegate;
+ TransportConnectJob transport_connect_job(
+ DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
+ base::MakeRefCounted<TransportSocketParams>(
+ HostPortPair(kHostName, 80), NetworkIsolationKey(),
+ SecureDnsPolicy::kAllow, OnHostResolutionCallback()),
+ &test_delegate, nullptr /* net_log */);
+ test_delegate.StartJobExpectingResult(&transport_connect_job, OK,
+ false /* expect_sync_result */);
+}
+
TEST_F(TransportConnectJobTest, SecureDnsPolicy) {
for (auto secure_dns_policy :
{SecureDnsPolicy::kAllow, SecureDnsPolicy::kDisable}) {
@@ -269,8 +302,9 @@ TEST_F(TransportConnectJobTest, SecureDnsPolicy) {
TransportConnectJob transport_connect_job(
DEFAULT_PRIORITY, SocketTag(), &common_connect_job_params_,
base::MakeRefCounted<TransportSocketParams>(
- HostPortPair(kHostName, 80), NetworkIsolationKey(),
- secure_dns_policy, OnHostResolutionCallback()),
+ url::SchemeHostPort(url::kHttpScheme, kHostName, 80),
+ NetworkIsolationKey(), secure_dns_policy,
+ OnHostResolutionCallback()),
&test_delegate, nullptr /* net_log */);
test_delegate.StartJobExpectingResult(&transport_connect_job, OK,
false /* expect_sync_result */);
diff --git a/chromium/net/socket/udp_socket_posix.cc b/chromium/net/socket/udp_socket_posix.cc
index 47f31493a41..c34a1e72958 100644
--- a/chromium/net/socket/udp_socket_posix.cc
+++ b/chromium/net/socket/udp_socket_posix.cc
@@ -832,7 +832,7 @@ int UDPSocketPosix::InternalRecvFromNonConnectedSocket(IOBuffer* buf,
SockaddrStorage storage;
struct iovec iov = {
.iov_base = buf->data(),
- .iov_len = buf_len,
+ .iov_len = static_cast<size_t>(buf_len),
};
struct msghdr msg = {
.msg_name = storage.addr,
diff --git a/chromium/net/socket/udp_socket_posix_unittest.cc b/chromium/net/socket/udp_socket_posix_unittest.cc
index 730d966ad40..be20d83e064 100644
--- a/chromium/net/socket/udp_socket_posix_unittest.cc
+++ b/chromium/net/socket/udp_socket_posix_unittest.cc
@@ -224,8 +224,9 @@ class UDPSocketPosixTest : public TestWithTaskEnvironment {
bool callback_fired_;
int rv_;
std::string msgs_[kNumMsgs] = {kHelloMsg, kSecondMsg, kThirdMsg};
- int lengths_[kNumMsgs] = {kHelloMsg.length(), kSecondMsg.length(),
- kThirdMsg.length()};
+ int lengths_[kNumMsgs] = {static_cast<int>(kHelloMsg.length()),
+ static_cast<int>(kSecondMsg.length()),
+ static_cast<int>(kThirdMsg.length())};
int total_lengths_ =
kHelloMsg.length() + kSecondMsg.length() + kThirdMsg.length();
DatagramBuffer* buffer_ptrs_[kNumMsgs];
diff --git a/chromium/net/socket/udp_socket_unittest.cc b/chromium/net/socket/udp_socket_unittest.cc
index 155831aa87f..91e72469caa 100644
--- a/chromium/net/socket/udp_socket_unittest.cc
+++ b/chromium/net/socket/udp_socket_unittest.cc
@@ -8,12 +8,12 @@
#include "base/bind.h"
#include "base/containers/circular_deque.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/scoped_clear_last_error.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread.h"
@@ -657,8 +657,9 @@ TEST_F(UDPSocketTest, JoinMulticastGroup) {
socket.Close();
}
-#if defined(OS_IOS)
-// TODO(https://crbug.com/947115): failing on device on iOS 12.2.
+// TODO(https://crbug.com/947115): failing on device on iOS 12.2.
+// TODO(https://crbug.com/1227554): flaky on Mac 11.
+#if defined(OS_IOS) || defined (OS_MAC)
#define MAYBE_SharedMulticastAddress DISABLED_SharedMulticastAddress
#else
#define MAYBE_SharedMulticastAddress SharedMulticastAddress
diff --git a/chromium/net/socket/udp_socket_win.h b/chromium/net/socket/udp_socket_win.h
index eca4d3ff006..a75bd08f497 100644
--- a/chromium/net/socket/udp_socket_win.h
+++ b/chromium/net/socket/udp_socket_win.h
@@ -9,7 +9,9 @@
#include <stdint.h>
#include <winsock2.h>
+#include <atomic>
#include <memory>
+#include <set>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
diff --git a/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc b/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
index e3fccd42110..d2a2a0d596c 100644
--- a/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
+++ b/chromium/net/socket/unix_domain_server_socket_posix_unittest.cc
@@ -11,7 +11,6 @@
#include "base/files/file_path.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool.cc b/chromium/net/socket/websocket_transport_client_socket_pool.cc
index 37488be81de..7d32868a251 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool.cc
+++ b/chromium/net/socket/websocket_transport_client_socket_pool.cc
@@ -22,6 +22,7 @@
#include "net/log/net_log_source_type.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/connect_job.h"
+#include "net/socket/connect_job_factory.h"
#include "net/socket/websocket_endpoint_lock_manager.h"
#include "net/socket/websocket_transport_connect_job.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
@@ -33,12 +34,14 @@ WebSocketTransportClientSocketPool::WebSocketTransportClientSocketPool(
int max_sockets_per_group,
const ProxyServer& proxy_server,
const CommonConnectJobParams* common_connect_job_params)
- : proxy_server_(proxy_server),
- common_connect_job_params_(common_connect_job_params),
+ : ClientSocketPool(/*is_for_websockets=*/true,
+ common_connect_job_params,
+ std::make_unique<ConnectJobFactory>()),
+ proxy_server_(proxy_server),
max_sockets_(max_sockets),
handed_out_socket_count_(0),
flushing_(false) {
- DCHECK(common_connect_job_params_->websocket_endpoint_lock_manager);
+ DCHECK(common_connect_job_params->websocket_endpoint_lock_manager);
}
WebSocketTransportClientSocketPool::~WebSocketTransportClientSocketPool() {
@@ -105,7 +108,6 @@ int WebSocketTransportClientSocketPool::RequestSocket(
std::unique_ptr<ConnectJob> connect_job =
CreateConnectJob(group_id, params, proxy_server_, proxy_annotation_tag,
- true /* is_for_websockets */, common_connect_job_params_,
priority, SocketTag(), connect_job_delegate.get());
int result = connect_job_delegate->Connect(std::move(connect_job));
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool.h b/chromium/net/socket/websocket_transport_client_socket_pool.h
index e6438a3c071..d82281f2d5d 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool.h
+++ b/chromium/net/socket/websocket_transport_client_socket_pool.h
@@ -200,7 +200,6 @@ class NET_EXPORT_PRIVATE WebSocketTransportClientSocketPool
bool DeleteStalledRequest(ClientSocketHandle* handle);
const ProxyServer proxy_server_;
- const CommonConnectJobParams* const common_connect_job_params_;
std::set<const ClientSocketHandle*> pending_callbacks_;
PendingConnectsMap pending_connects_;
StalledRequestQueue stalled_request_queue_;
diff --git a/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc b/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
index 171e180590d..0ed4fe4c433 100644
--- a/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
+++ b/chromium/net/socket/websocket_transport_client_socket_pool_unittest.cc
@@ -4,15 +4,16 @@
#include "net/socket/websocket_transport_client_socket_pool.h"
+#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -46,6 +47,8 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -70,8 +73,7 @@ void RunLoopForTimePeriod(base::TimeDelta period) {
class WebSocketTransportClientSocketPoolTest : public TestWithTaskEnvironment {
protected:
WebSocketTransportClientSocketPoolTest()
- : group_id_(HostPortPair("www.google.com", 80),
- ClientSocketPool::SocketType::kHttp,
+ : group_id_(url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
@@ -188,16 +190,15 @@ TEST_F(WebSocketTransportClientSocketPoolTest, SetResolvePriorityOnInit) {
}
TEST_F(WebSocketTransportClientSocketPoolTest, InitHostResolutionFailure) {
- HostPortPair host_port_pair("unresolvable.host.name", 80);
- host_resolver_->rules()->AddSimulatedTimeoutFailure(host_port_pair.host());
+ url::SchemeHostPort endpoint(url::kHttpScheme, "unresolvable.host.name", 80);
+ host_resolver_->rules()->AddSimulatedTimeoutFailure(endpoint.host());
TestCompletionCallback callback;
ClientSocketHandle handle;
EXPECT_EQ(
ERR_IO_PENDING,
handle.Init(ClientSocketPool::GroupId(
- host_port_pair, ClientSocketPool::SocketType::kHttp,
- PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
- SecureDnsPolicy::kAllow),
+ std::move(endpoint), PRIVACY_MODE_DISABLED,
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow),
ClientSocketPool::SocketParams::CreateForHttpForTesting(),
absl::nullopt /* proxy_annotation_tag */, kDefaultPriority,
SocketTag(), ClientSocketPool::RespectLimits::ENABLED,
@@ -1151,7 +1152,7 @@ TEST_F(WebSocketTransportClientSocketPoolTest, NetworkIsolationKey) {
TestCompletionCallback callback;
ClientSocketHandle handle;
ClientSocketPool::GroupId group_id(
- HostPortPair("www.google.com", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "www.google.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, kNetworkIsolationKey,
SecureDnsPolicy::kAllow);
EXPECT_THAT(
diff --git a/chromium/net/socket/websocket_transport_connect_job.cc b/chromium/net/socket/websocket_transport_connect_job.cc
index 4993f3e62c7..a979d064b60 100644
--- a/chromium/net/socket/websocket_transport_connect_job.cc
+++ b/chromium/net/socket/websocket_transport_connect_job.cc
@@ -14,6 +14,7 @@
#include "base/trace_event/trace_event.h"
#include "base/values.h"
#include "net/base/address_list.h"
+#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/trace_constants.h"
#include "net/dns/public/secure_dns_policy.h"
@@ -23,9 +24,41 @@
#include "net/socket/transport_connect_job.h"
#include "net/socket/websocket_endpoint_lock_manager.h"
#include "net/socket/websocket_transport_connect_sub_job.h"
+#include "third_party/abseil-cpp/absl/types/variant.h"
+#include "url/scheme_host_port.h"
namespace net {
+namespace {
+
+// TODO(crbug.com/1206799): Delete once endpoint usage is converted to using
+// url::SchemeHostPort when available.
+HostPortPair ToLegacyDestinationEndpoint(
+ const TransportSocketParams::Endpoint& endpoint) {
+ if (absl::holds_alternative<url::SchemeHostPort>(endpoint)) {
+ return HostPortPair::FromSchemeHostPort(
+ absl::get<url::SchemeHostPort>(endpoint));
+ }
+
+ DCHECK(absl::holds_alternative<HostPortPair>(endpoint));
+ return absl::get<HostPortPair>(endpoint);
+}
+
+} // namespace
+
+std::unique_ptr<WebSocketTransportConnectJob>
+WebSocketTransportConnectJob::Factory::Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ Delegate* delegate,
+ const NetLogWithSource* net_log) {
+ return std::make_unique<WebSocketTransportConnectJob>(
+ priority, socket_tag, common_connect_job_params, params, delegate,
+ net_log);
+}
+
WebSocketTransportConnectJob::WebSocketTransportConnectJob(
RequestPriority priority,
const SocketTag& socket_tag,
@@ -118,9 +151,9 @@ int WebSocketTransportConnectJob::DoResolveHost() {
HostResolver::ResolveHostParameters parameters;
parameters.initial_priority = priority();
DCHECK_EQ(SecureDnsPolicy::kAllow, params_->secure_dns_policy());
- request_ = host_resolver()->CreateRequest(params_->destination(),
- params_->network_isolation_key(),
- net_log(), parameters);
+ request_ = host_resolver()->CreateRequest(
+ ToLegacyDestinationEndpoint(params_->destination()),
+ params_->network_isolation_key(), net_log(), parameters);
return request_->Start(base::BindOnce(
&WebSocketTransportConnectJob::OnIOComplete, base::Unretained(this)));
@@ -146,7 +179,8 @@ int WebSocketTransportConnectJob::DoResolveHostComplete(int result) {
if (!params_->host_resolution_callback().is_null()) {
OnHostResolutionCallbackResult callback_result =
params_->host_resolution_callback().Run(
- params_->destination(), request_->GetAddressResults().value());
+ ToLegacyDestinationEndpoint(params_->destination()),
+ request_->GetAddressResults().value());
if (callback_result == OnHostResolutionCallbackResult::kMayBeDeletedAsync) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&WebSocketTransportConnectJob::OnIOComplete,
diff --git a/chromium/net/socket/websocket_transport_connect_job.h b/chromium/net/socket/websocket_transport_connect_job.h
index aa7939e6436..ab739039418 100644
--- a/chromium/net/socket/websocket_transport_connect_job.h
+++ b/chromium/net/socket/websocket_transport_connect_job.h
@@ -7,7 +7,6 @@
#include <memory>
#include <set>
-#include <string>
#include "base/macros.h"
#include "base/memory/ref_counted.h"
@@ -39,6 +38,20 @@ class WebSocketTransportConnectSubJob;
// logging), and provide performance information to SocketPerformanceWatcher.
class NET_EXPORT_PRIVATE WebSocketTransportConnectJob : public ConnectJob {
public:
+ class NET_EXPORT_PRIVATE Factory {
+ public:
+ Factory() = default;
+ virtual ~Factory() = default;
+
+ virtual std::unique_ptr<WebSocketTransportConnectJob> Create(
+ RequestPriority priority,
+ const SocketTag& socket_tag,
+ const CommonConnectJobParams* common_connect_job_params,
+ const scoped_refptr<TransportSocketParams>& params,
+ Delegate* delegate,
+ const NetLogWithSource* net_log);
+ };
+
WebSocketTransportConnectJob(
RequestPriority priority,
const SocketTag& socket_tag,
diff --git a/chromium/net/spdy/OWNERS b/chromium/net/spdy/OWNERS
index cc876f7f8b5..3499310aff1 100644
--- a/chromium/net/spdy/OWNERS
+++ b/chromium/net/spdy/OWNERS
@@ -1,6 +1,4 @@
birenroy@chromium.org
bnc@chromium.org
-dahollings@chromium.org
diannahu@chromium.org
rch@chromium.org
-yasong@chromium.org
diff --git a/chromium/net/spdy/bidirectional_stream_spdy_impl_unittest.cc b/chromium/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
index b16793f207f..23d632e45dd 100644
--- a/chromium/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
+++ b/chromium/net/spdy/bidirectional_stream_spdy_impl_unittest.cc
@@ -7,8 +7,8 @@
#include <string>
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/time/time.h"
diff --git a/chromium/net/spdy/platform/impl/DEPS b/chromium/net/spdy/platform/impl/DEPS
deleted file mode 100644
index 52b2de4b778..00000000000
--- a/chromium/net/spdy/platform/impl/DEPS
+++ /dev/null
@@ -1,7 +0,0 @@
-include_rules = [
- # This is a temporary rule to simplify migrating QUICHE to using Abseil
- # directly.
- # TODO(b/166325009): remove this rule.
- "+third_party/abseil-cpp/absl/strings",
-]
-
diff --git a/chromium/net/spdy/platform/impl/spdy_containers_impl.h b/chromium/net/spdy/platform/impl/spdy_containers_impl.h
deleted file mode 100644
index 8d3675afbd1..00000000000
--- a/chromium/net/spdy/platform/impl/spdy_containers_impl.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-#ifndef NET_SPDY_PLATFORM_IMPL_SPDY_CONTAINERS_IMPL_H_
-#define NET_SPDY_PLATFORM_IMPL_SPDY_CONTAINERS_IMPL_H_
-
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "base/containers/small_map.h"
-#include "base/strings/string_piece.h"
-#include "net/third_party/quiche/src/common/quiche_linked_hash_map.h"
-
-namespace spdy {
-
-template <typename Key, typename Value, typename Hash, typename Eq>
-using SpdyLinkedHashMapImpl = quiche::QuicheLinkedHashMap<Key, Value, Hash, Eq>;
-
-template <typename T, size_t N, typename A = std::allocator<T>>
-using SpdyInlinedVectorImpl = std::vector<T, A>;
-
-} // namespace spdy
-
-#endif // NET_SPDY_PLATFORM_IMPL_SPDY_CONTAINERS_IMPL_H_
diff --git a/chromium/net/spdy/platform/impl/spdy_string_utils_impl.cc b/chromium/net/spdy/platform/impl/spdy_string_utils_impl.cc
deleted file mode 100644
index b6a85c5d05b..00000000000
--- a/chromium/net/spdy/platform/impl/spdy_string_utils_impl.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/spdy/platform/impl/spdy_string_utils_impl.h"
-
-#include <string>
-
-namespace spdy {
-
-bool SpdyHexDecodeToUInt32Impl(absl::string_view data, uint32_t* out) {
- if (data.empty() || data.size() > 8u)
- return false;
- // Pad with leading zeros.
- std::string data_padded(8u, '0');
- memcpy(&data_padded[8u - data.size()], data.data(), data.size());
- return base::HexStringToUInt(data_padded, out);
-}
-
-} // namespace spdy
diff --git a/chromium/net/spdy/platform/impl/spdy_string_utils_impl.h b/chromium/net/spdy/platform/impl/spdy_string_utils_impl.h
deleted file mode 100644
index 18d2bfcb085..00000000000
--- a/chromium/net/spdy/platform/impl/spdy_string_utils_impl.h
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef NET_SPDY_PLATFORM_IMPL_SPDY_STRING_UTILS_IMPL_H_
-#define NET_SPDY_PLATFORM_IMPL_SPDY_STRING_UTILS_IMPL_H_
-
-#include <sstream>
-#include <utility>
-
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "net/base/hex_utils.h"
-#include "net/third_party/quiche/src/common/quiche_text_utils.h"
-#include "third_party/abseil-cpp/absl/strings/string_view.h"
-
-namespace spdy {
-
-inline char SpdyHexDigitToIntImpl(char c) {
- return base::HexDigitToInt(c);
-}
-
-NET_EXPORT_PRIVATE bool SpdyHexDecodeToUInt32Impl(absl::string_view data,
- uint32_t* out);
-
-inline std::string SpdyHexDumpImpl(absl::string_view data) {
- return quiche::QuicheTextUtils::HexDump(data);
-}
-
-} // namespace spdy
-
-#endif // NET_SPDY_PLATFORM_IMPL_SPDY_STRING_UTILS_IMPL_H_
diff --git a/chromium/net/spdy/spdy_buffer_unittest.cc b/chromium/net/spdy/spdy_buffer_unittest.cc
index 2e0e9817f92..df6bf3a83d0 100644
--- a/chromium/net/spdy/spdy_buffer_unittest.cc
+++ b/chromium/net/spdy/spdy_buffer_unittest.cc
@@ -11,8 +11,8 @@
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
#include "net/base/io_buffer.h"
#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/spdy/spdy_http_stream.cc b/chromium/net/spdy/spdy_http_stream.cc
index e3af6e9fef0..590f8308801 100644
--- a/chromium/net/spdy/spdy_http_stream.cc
+++ b/chromium/net/spdy/spdy_http_stream.cc
@@ -122,8 +122,6 @@ SpdyHttpStream::SpdyHttpStream(const base::WeakPtr<SpdySession>& spdy_session,
upload_stream_in_progress_(false),
user_buffer_len_(0),
request_body_buf_size_(0),
- buffered_read_callback_pending_(false),
- more_read_data_pending_(false),
was_alpn_negotiated_(false),
dns_aliases_(std::move(dns_aliases)) {
DCHECK(spdy_session_.get());
@@ -464,12 +462,7 @@ void SpdyHttpStream::OnDataReceived(std::unique_ptr<SpdyBuffer> buffer) {
DCHECK(!stream_->IsClosed() || stream_->type() == SPDY_PUSH_STREAM);
if (buffer) {
response_body_queue_.Enqueue(std::move(buffer));
-
- if (user_buffer_.get()) {
- // Handing small chunks of data to the caller creates measurable overhead.
- // We buffer data in short time-spans and send a single read notification.
- ScheduleBufferedReadCallback();
- }
+ MaybeScheduleBufferedReadCallback();
}
}
@@ -615,38 +608,36 @@ void SpdyHttpStream::OnRequestBodyReadCompleted(int status) {
eof ? NO_MORE_DATA_TO_SEND : MORE_DATA_TO_SEND);
}
-void SpdyHttpStream::ScheduleBufferedReadCallback() {
- // If there is already a scheduled DoBufferedReadCallback, don't issue
- // another one. Mark that we have received more data and return.
- if (buffered_read_callback_pending_) {
- more_read_data_pending_ = true;
- return;
- }
+void SpdyHttpStream::MaybeScheduleBufferedReadCallback() {
+ DCHECK(!stream_closed_);
- more_read_data_pending_ = false;
- buffered_read_callback_pending_ = true;
- const base::TimeDelta kBufferTime = base::TimeDelta::FromMilliseconds(1);
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::BindOnce(&SpdyHttpStream::DoBufferedReadCallback,
- weak_factory_.GetWeakPtr()),
- kBufferTime);
-}
+ if (!user_buffer_.get())
+ return;
-// Checks to see if we should wait for more buffered data before notifying
-// the caller. Returns true if we should wait, false otherwise.
-bool SpdyHttpStream::ShouldWaitForMoreBufferedData() const {
- // If the response is complete, there is no point in waiting.
- if (stream_closed_)
- return false;
+ // If enough data was received to fill the user buffer, invoke
+ // DoBufferedReadCallback() with no delay.
+ //
+ // Note: DoBufferedReadCallback() is invoked asynchronously to preserve
+ // historical behavior. It would be interesting to evaluate whether it can be
+ // invoked synchronously to avoid the overhead of posting a task. A long time
+ // ago, the callback was invoked synchronously
+ // https://codereview.chromium.org/652209/diff/2018/net/spdy/spdy_stream.cc.
+ if (response_body_queue_.GetTotalSize() >=
+ static_cast<size_t>(user_buffer_len_)) {
+ buffered_read_timer_.Start(FROM_HERE, base::TimeDelta() /* no delay */,
+ this, &SpdyHttpStream::DoBufferedReadCallback);
+ return;
+ }
- DCHECK_GT(user_buffer_len_, 0);
- return response_body_queue_.GetTotalSize() <
- static_cast<size_t>(user_buffer_len_);
+ // Handing small chunks of data to the caller creates measurable overhead.
+ // Wait 1ms to allow handing off multiple chunks of data received within a
+ // short time span at once.
+ buffered_read_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(1),
+ this, &SpdyHttpStream::DoBufferedReadCallback);
}
void SpdyHttpStream::DoBufferedReadCallback() {
- buffered_read_callback_pending_ = false;
+ buffered_read_timer_.Stop();
// If the transaction is cancelled or errored out, we don't need to complete
// the read.
@@ -656,14 +647,6 @@ void SpdyHttpStream::DoBufferedReadCallback() {
return;
}
- // When more_read_data_pending_ is true, it means that more data has
- // arrived since we started waiting. Wait a little longer and continue
- // to buffer.
- if (more_read_data_pending_ && ShouldWaitForMoreBufferedData()) {
- ScheduleBufferedReadCallback();
- return;
- }
-
if (!user_buffer_.get())
return;
diff --git a/chromium/net/spdy/spdy_http_stream.h b/chromium/net/spdy/spdy_http_stream.h
index 11ec965cf3e..ccfab26332c 100644
--- a/chromium/net/spdy/spdy_http_stream.h
+++ b/chromium/net/spdy/spdy_http_stream.h
@@ -14,6 +14,7 @@
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string_piece.h"
+#include "base/timer/timer.h"
#include "net/base/completion_once_callback.h"
#include "net/base/load_timing_info.h"
#include "net/base/net_export.h"
@@ -144,9 +145,8 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
// Call the user callback associated with reading the response.
void DoResponseCallback(int rv);
- void ScheduleBufferedReadCallback();
+ void MaybeScheduleBufferedReadCallback();
void DoBufferedReadCallback();
- bool ShouldWaitForMoreBufferedData() const;
const base::WeakPtr<SpdySession> spdy_session_;
@@ -213,11 +213,8 @@ class NET_EXPORT_PRIVATE SpdyHttpStream : public SpdyStream::Delegate,
scoped_refptr<IOBufferWithSize> request_body_buf_;
int request_body_buf_size_;
- // Is there a scheduled read callback pending.
- bool buffered_read_callback_pending_;
- // Has more data been received from the network during the wait for the
- // scheduled read callback.
- bool more_read_data_pending_;
+ // Timer to execute DoBufferedReadCallback() with a delay.
+ base::OneShotTimer buffered_read_timer_;
bool was_alpn_negotiated_;
diff --git a/chromium/net/spdy/spdy_http_stream_unittest.cc b/chromium/net/spdy/spdy_http_stream_unittest.cc
index 925a8e8a949..84d76252c65 100644
--- a/chromium/net/spdy/spdy_http_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_http_stream_unittest.cc
@@ -9,8 +9,8 @@
#include <string>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "crypto/ec_private_key.h"
#include "crypto/ec_signature_creator.h"
@@ -144,7 +144,6 @@ class SpdyHttpStreamTest : public TestWithTaskEnvironment {
protected:
void TearDown() override {
- crypto::ECSignatureCreator::SetFactoryForTesting(nullptr);
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(sequenced_data_->AllReadDataConsumed());
EXPECT_TRUE(sequenced_data_->AllWriteDataConsumed());
@@ -176,7 +175,6 @@ class SpdyHttpStreamTest : public TestWithTaskEnvironment {
base::WeakPtr<SpdySession> session_;
private:
- MockECSignatureCreatorFactory ec_signature_creator_factory_;
SSLSocketDataProvider ssl_;
};
diff --git a/chromium/net/spdy/spdy_network_transaction_unittest.cc b/chromium/net/spdy/spdy_network_transaction_unittest.cc
index 2106dce5ada..7e937bf3f23 100644
--- a/chromium/net/spdy/spdy_network_transaction_unittest.cc
+++ b/chromium/net/spdy/spdy_network_transaction_unittest.cc
@@ -9,10 +9,10 @@
#include "base/bind.h"
#include "base/callback_helpers.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -5159,14 +5159,12 @@ TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
EXPECT_THAT(rv, IsError(ERR_IO_PENDING));
TransactionHelperResult out = helper.output();
- out.rv = callback.WaitForResult();
- EXPECT_EQ(out.rv, OK);
+ rv = callback.WaitForResult();
+ EXPECT_EQ(rv, OK);
const HttpResponseInfo* response = trans->GetResponseInfo();
EXPECT_TRUE(response->headers);
EXPECT_TRUE(response->was_fetched_via_spdy);
- out.status_line = response->headers->GetStatusLine();
- out.response_info = *response; // Make a copy so we can verify.
// Read Data
TestCompletionCallback read_callback;
@@ -5174,18 +5172,18 @@ TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
std::string content;
int reads_completed = 0;
do {
- // Read small chunks at a time.
- const int kSmallReadSize = 14;
+ // Allocate a large buffer to allow buffering. If a single read fills the
+ // buffer, no buffering happens.
+ const int kLargeReadSize = 1000;
scoped_refptr<IOBuffer> buf =
- base::MakeRefCounted<IOBuffer>(kSmallReadSize);
- rv = trans->Read(buf.get(), kSmallReadSize, read_callback.callback());
+ base::MakeRefCounted<IOBuffer>(kLargeReadSize);
+ rv = trans->Read(buf.get(), kLargeReadSize, read_callback.callback());
if (rv == ERR_IO_PENDING) {
data.Resume();
rv = read_callback.WaitForResult();
}
- if (rv > 0) {
- content.append(buf->data(), rv);
- } else if (rv < 0) {
+
+ if (rv < 0) {
// This test intentionally closes the connection, and will get an error.
EXPECT_THAT(rv, IsError(ERR_CONNECTION_CLOSED));
break;
@@ -5195,8 +5193,6 @@ TEST_F(SpdyNetworkTransactionTest, BufferedClosed) {
EXPECT_EQ(0, reads_completed);
- out.response_data.swap(content);
-
// Flush the MessageLoop while the SpdySessionDependencies (in particular, the
// MockClientSocketFactory) are still alive.
base::RunLoop().RunUntilIdle();
@@ -10510,14 +10506,14 @@ TEST_F(SpdyNetworkTransactionTest, GreaseFrameTypeWithGetRequest) {
spdy_util_.ConstructSpdyHeaders(1, std::move(headers), DEFAULT_PRIORITY,
/* fin = */ false));
- const char kRawFrameData[] = {
+ uint8_t kRawFrameData[] = {
0x00, 0x00, 0x03, // length
0x0b, // type
0xcc, // flags
0x00, 0x00, 0x00, 0x01, // stream ID
'f', 'o', 'o' // payload
};
- spdy::SpdySerializedFrame grease(const_cast<char*>(kRawFrameData),
+ spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
base::size(kRawFrameData),
/* owns_buffer = */ false);
spdy::SpdySerializedFrame empty_body(
@@ -10569,14 +10565,14 @@ TEST_F(SpdyNetworkTransactionTest,
spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
- const char kRawFrameData[] = {
+ uint8_t kRawFrameData[] = {
0x00, 0x00, 0x03, // length
0x0b, // type
0xcc, // flags
0x00, 0x00, 0x00, 0x01, // stream ID
'f', 'o', 'o' // payload
};
- spdy::SpdySerializedFrame grease(const_cast<char*>(kRawFrameData),
+ spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
base::size(kRawFrameData),
/* owns_buffer = */ false);
spdy::SpdySerializedFrame request_body(
@@ -10629,14 +10625,14 @@ TEST_F(SpdyNetworkTransactionTest,
spdy::SpdySerializedFrame req(spdy_util_.ConstructSpdyPost(
kDefaultUrl, 1, kUploadDataSize, LOWEST, nullptr, 0));
- const char kRawFrameData[] = {
+ uint8_t kRawFrameData[] = {
0x00, 0x00, 0x03, // length
0x0b, // type
0xcc, // flags
0x00, 0x00, 0x00, 0x01, // stream ID
'f', 'o', 'o' // payload
};
- spdy::SpdySerializedFrame grease(const_cast<char*>(kRawFrameData),
+ spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
base::size(kRawFrameData),
/* owns_buffer = */ false);
spdy::SpdySerializedFrame request_body(
@@ -10775,14 +10771,14 @@ TEST_F(SpdyNetworkTransactionTest, OnDataSentDoesNotCrashWithGreasedFrameType) {
spdy_util_.ConstructSpdyHeaders(1, std::move(headers), DEFAULT_PRIORITY,
/* fin = */ false));
- const char kRawFrameData[] = {
+ uint8_t kRawFrameData[] = {
0x00, 0x00, 0x03, // length
0x0b, // type
0xcc, // flags
0x00, 0x00, 0x00, 0x01, // stream ID
'f', 'o', 'o' // payload
};
- spdy::SpdySerializedFrame grease(const_cast<char*>(kRawFrameData),
+ spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
base::size(kRawFrameData),
/* owns_buffer = */ false);
spdy::SpdySerializedFrame empty_body(
diff --git a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
index 799f0834010..96690a0ac2f 100644
--- a/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
+++ b/chromium/net/spdy/spdy_proxy_client_socket_unittest.cc
@@ -13,6 +13,7 @@
#include "base/strings/string_piece.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/address_list.h"
+#include "net/base/host_port_pair.h"
#include "net/base/load_timing_info.h"
#include "net/base/proxy_server.h"
#include "net/base/test_completion_callback.h"
@@ -49,6 +50,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#include "url/scheme_host_port.h"
using net::test::IsError;
using net::test::IsOk;
@@ -85,6 +87,7 @@ static const char kRedirectUrl[] = "https://example.com/";
// Creates a SpdySession with a StreamSocket, instead of a ClientSocketHandle.
base::WeakPtr<SpdySession> CreateSpdyProxySession(
+ const url::SchemeHostPort& destination,
HttpNetworkSession* http_session,
SpdySessionDependencies* session_deps,
const SpdySessionKey& key,
@@ -94,12 +97,13 @@ base::WeakPtr<SpdySession> CreateSpdyProxySession(
NetLogWithSource()));
auto transport_params = base::MakeRefCounted<TransportSocketParams>(
- key.host_port_pair(), NetworkIsolationKey(), SecureDnsPolicy::kAllow,
+ destination, NetworkIsolationKey(), SecureDnsPolicy::kAllow,
OnHostResolutionCallback());
SSLConfig ssl_config;
auto ssl_params = base::MakeRefCounted<SSLSocketParams>(
- transport_params, nullptr, nullptr, key.host_port_pair(), ssl_config,
+ transport_params, nullptr, nullptr,
+ HostPortPair::FromSchemeHostPort(destination), ssl_config,
key.privacy_mode(), key.network_isolation_key());
TestConnectJobDelegate connect_job_delegate;
SSLConnectJob connect_job(MEDIUM, SocketTag(), common_connect_job_params,
@@ -255,9 +259,9 @@ void SpdyProxyClientSocketTest::Initialize(base::span<const MockRead> reads,
session_->CreateCommonConnectJobParams());
// Creates the SPDY session and stream.
- spdy_session_ = CreateSpdyProxySession(session_.get(), &session_deps_,
- endpoint_spdy_session_key_,
- common_connect_job_params_.get());
+ spdy_session_ = CreateSpdyProxySession(
+ url::SchemeHostPort(url_), session_.get(), &session_deps_,
+ endpoint_spdy_session_key_, common_connect_job_params_.get());
base::WeakPtr<SpdyStream> spdy_stream(
CreateStreamSynchronously(
diff --git a/chromium/net/spdy/spdy_read_queue_unittest.cc b/chromium/net/spdy/spdy_read_queue_unittest.cc
index 237e8dc0acc..edd5d31f8e7 100644
--- a/chromium/net/spdy/spdy_read_queue_unittest.cc
+++ b/chromium/net/spdy/spdy_read_queue_unittest.cc
@@ -12,7 +12,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/spdy/spdy_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/spdy/spdy_session.cc b/chromium/net/spdy/spdy_session.cc
index 057e96477b0..22d5d30c2f0 100644
--- a/chromium/net/spdy/spdy_session.cc
+++ b/chromium/net/spdy/spdy_session.cc
@@ -589,6 +589,8 @@ SpdyProtocolErrorDetails MapFramerErrorToProtocolError(
case http2::Http2DecoderAdapter::
SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
return SPDY_ERROR_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT;
+ case http2::Http2DecoderAdapter::SPDY_STOP_PROCESSING:
+ return SPDY_ERROR_STOP_PROCESSING;
case http2::Http2DecoderAdapter::LAST_ERROR:
NOTREACHED();
@@ -633,6 +635,8 @@ Error MapFramerErrorToNetError(
case http2::Http2DecoderAdapter::
SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
return ERR_HTTP2_COMPRESSION_ERROR;
+ case http2::Http2DecoderAdapter::SPDY_STOP_PROCESSING:
+ return ERR_HTTP2_COMPRESSION_ERROR;
case http2::Http2DecoderAdapter::SPDY_COMPRESS_FAILURE:
return ERR_HTTP2_COMPRESSION_ERROR;
case http2::Http2DecoderAdapter::SPDY_GOAWAY_FRAME_CORRUPT:
@@ -845,6 +849,9 @@ void SpdyStreamRequest::Reset() {
void SpdyStreamRequest::OnConfirmHandshakeComplete(int rv) {
DCHECK_NE(ERR_IO_PENDING, rv);
+ if (!session_)
+ return;
+
if (rv != OK) {
OnRequestCompleteFailure(rv);
return;
@@ -1251,6 +1258,12 @@ bool SpdySession::ShouldSendPriorityUpdate() const {
}
int SpdySession::ConfirmHandshake(CompletionOnceCallback callback) {
+ if (availability_state_ == STATE_GOING_AWAY)
+ return ERR_FAILED;
+
+ if (availability_state_ == STATE_DRAINING)
+ return ERR_CONNECTION_CLOSED;
+
int rv = ERR_IO_PENDING;
if (!in_confirm_handshake_) {
rv = socket_->ConfirmHandshake(
@@ -1551,6 +1564,8 @@ void SpdySession::StartGoingAway(spdy::SpdyStreamId last_good_stream_id,
// The loops below are carefully written to avoid reentrancy problems.
+ NotifyRequestsOfConfirmation(status);
+
while (true) {
size_t old_size = GetTotalSize(pending_create_stream_queues_);
base::WeakPtr<SpdyStreamRequest> pending_request =
@@ -3061,10 +3076,6 @@ void SpdySession::DoDrainSession(Error err, const std::string& description) {
}
MakeUnavailable();
- // Notify any requests waiting for handshake confirmation that there is an
- // error.
- NotifyRequestsOfConfirmation(err);
-
// Mark host_port_pair requiring HTTP/1.1 for subsequent connections.
if (err == ERR_HTTP_1_1_REQUIRED) {
http_server_properties_->SetHTTP11Required(
@@ -3272,7 +3283,9 @@ void SpdySession::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
base::StringPiece debug_data) {
CHECK(in_io_loop_);
- // TODO(jgraettinger): UMA histogram on |error_code|.
+ // Use sparse histogram to record the unlikely case that a server sends
+ // an unknown error code.
+ base::UmaHistogramSparse("Net.SpdySession.GoAwayReceived", error_code);
net_log_.AddEvent(
NetLogEventType::HTTP2_SESSION_RECV_GOAWAY,
diff --git a/chromium/net/spdy/spdy_session.h b/chromium/net/spdy/spdy_session.h
index 22135881003..582282a18de 100644
--- a/chromium/net/spdy/spdy_session.h
+++ b/chromium/net/spdy/spdy_session.h
@@ -144,6 +144,7 @@ enum SpdyProtocolErrorDetails {
SPDY_ERROR_HPACK_TRUNCATED_BLOCK = 56,
SPDY_ERROR_HPACK_FRAGMENT_TOO_LONG = 57,
SPDY_ERROR_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT = 58,
+ SPDY_ERROR_STOP_PROCESSING = 59,
// spdy::SpdyErrorCode mappings.
STATUS_CODE_NO_ERROR = 41,
STATUS_CODE_PROTOCOL_ERROR = 11,
@@ -174,7 +175,7 @@ enum SpdyProtocolErrorDetails {
PROTOCOL_ERROR_RECEIVE_WINDOW_VIOLATION = 28,
// Next free value.
- NUM_SPDY_PROTOCOL_ERROR_DETAILS = 59,
+ NUM_SPDY_PROTOCOL_ERROR_DETAILS = 60,
};
SpdyProtocolErrorDetails NET_EXPORT_PRIVATE MapFramerErrorToProtocolError(
http2::Http2DecoderAdapter::SpdyFramerError error);
@@ -214,7 +215,7 @@ enum class SpdyPushedStreamFate {
// If these compile asserts fail then SpdyProtocolErrorDetails needs
// to be updated with new values, as do the mapping functions above.
-static_assert(33 == http2::Http2DecoderAdapter::LAST_ERROR,
+static_assert(34 == http2::Http2DecoderAdapter::LAST_ERROR,
"SpdyProtocolErrorDetails / Spdy Errors mismatch");
static_assert(13 == spdy::SpdyErrorCode::ERROR_CODE_MAX,
"SpdyProtocolErrorDetails / spdy::SpdyErrorCode mismatch");
@@ -1303,10 +1304,9 @@ class NET_EXPORT SpdySession : public BufferedSpdyFramerVisitorInterface,
// nullptr.
NetworkQualityEstimator* network_quality_estimator_;
- // Used for posting asynchronous IO tasks. We use this even though
- // SpdySession is refcounted because we don't need to keep the SpdySession
- // alive if the last reference is within a RunnableMethod. Just revoke the
- // method.
+ // Used for accessing the SpdySession from asynchronous tasks. An asynchronous
+ // must check if its WeakPtr<SpdySession> is valid before accessing it, to
+ // correctly handle the case where it became unavailable and was deleted.
base::WeakPtrFactory<SpdySession> weak_factory_{this};
};
diff --git a/chromium/net/spdy/spdy_session_fuzzer.cc b/chromium/net/spdy/spdy_session_fuzzer.cc
index 964454a32ad..08d2dae0874 100644
--- a/chromium/net/spdy/spdy_session_fuzzer.cc
+++ b/chromium/net/spdy/spdy_session_fuzzer.cc
@@ -4,9 +4,9 @@
#include <fuzzer/FuzzedDataProvider.h>
+#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
#include "net/base/request_priority.h"
@@ -24,7 +24,7 @@
namespace {
-const char kCertData[] = {
+const uint8_t kCertData[] = {
#include "net/data/ssl/certificates/spdy_pooling.inc"
};
@@ -110,8 +110,7 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
socket_factory.set_fuzz_connect_result(false);
net::SSLSocketDataProvider ssl_provider(net::ASYNC, net::OK);
- ssl_provider.ssl_info.cert =
- net::X509Certificate::CreateFromBytes(kCertData, base::size(kCertData));
+ ssl_provider.ssl_info.cert = net::X509Certificate::CreateFromBytes(kCertData);
CHECK(ssl_provider.ssl_info.cert);
socket_factory.AddSSLSocketDataProvider(&ssl_provider);
diff --git a/chromium/net/spdy/spdy_session_pool.cc b/chromium/net/spdy/spdy_session_pool.cc
index 22bf08e4cb4..dfc81d0b1e0 100644
--- a/chromium/net/spdy/spdy_session_pool.cc
+++ b/chromium/net/spdy/spdy_session_pool.cc
@@ -23,7 +23,7 @@
#include "net/base/trace_constants.h"
#include "net/dns/dns_alias_utility.h"
#include "net/dns/host_resolver.h"
-#include "net/dns/host_resolver_source.h"
+#include "net/dns/public/host_resolver_source.h"
#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_stream_request.h"
@@ -276,17 +276,14 @@ OnHostResolutionCallbackResult SpdySessionPool::OnHostResolutionComplete(
// nothing, but inform the caller to wait for such a task to run.
auto existing_session_it = LookupAvailableSessionByKey(key);
if (existing_session_it != available_sessions_.end()) {
- // If this is an alias, the host resolution is for a websocket
- // connection, and the aliased session doesn't support websockets,
- // continue looking for an aliased session that does. Unlikely there
- // is one, but can't hurt to check.
- bool continue_searching_for_websockets =
- is_websocket && !existing_session_it->second->support_websocket();
-
- if (!continue_searching_for_websockets)
- return OnHostResolutionCallbackResult::kMayBeDeletedAsync;
- }
+ if (is_websocket && !existing_session_it->second->support_websocket()) {
+ // We don't look for aliased sessions because it would not be possible to
+ // add them to the available_sessions_ map. See https://crbug.com/1220771.
+ return OnHostResolutionCallbackResult::kContinue;
+ }
+ return OnHostResolutionCallbackResult::kMayBeDeletedAsync;
+ }
for (const auto& address : addresses) {
auto range = aliases_.equal_range(address);
for (auto alias_it = range.first; alias_it != range.second; ++alias_it) {
@@ -521,6 +518,11 @@ void SpdySessionPool::OnSSLConfigForServerChanged(const HostPortPair& server) {
(proxy_server.is_http_like() && !proxy_server.is_http() &&
proxy_server.host_port_pair() == server)) {
session->MakeUnavailable();
+ // Note this call preserves active streams but fails any streams that are
+ // waiting on a stream ID.
+ // TODO(https://crbug.com/1213609): This is not ideal, but SpdySession
+ // does not have a state that supports this.
+ session->StartGoingAway(kLastStreamId, ERR_NETWORK_CHANGED);
session->MaybeFinishGoingAway();
DCHECK(!IsSessionAvailable(session));
}
diff --git a/chromium/net/spdy/spdy_session_pool_unittest.cc b/chromium/net/spdy/spdy_session_pool_unittest.cc
index 50cb955e2a8..6d4259608b4 100644
--- a/chromium/net/spdy/spdy_session_pool_unittest.cc
+++ b/chromium/net/spdy/spdy_session_pool_unittest.cc
@@ -8,15 +8,16 @@
#include <utility>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/traced_value.h"
#include "build/build_config.h"
+#include "net/base/test_completion_callback.h"
#include "net/dns/host_cache.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_network_session.h"
@@ -24,6 +25,7 @@
#include "net/log/test_net_log.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/socket_tag.h"
+#include "net/socket/socket_test_util.h"
#include "net/socket/transport_client_socket_pool.h"
#include "net/spdy/spdy_session.h"
#include "net/spdy/spdy_stream_test_util.h"
@@ -33,6 +35,8 @@
#include "net/test/test_certificate_data.h"
#include "net/test/test_data_directory.h"
#include "net/test/test_with_task_environment.h"
+#include "net/third_party/quiche/src/spdy/core/spdy_protocol.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -78,6 +82,10 @@ class SpdySessionPoolTest : public TestWithTaskEnvironment {
return session->active_streams_.size();
}
+ size_t max_concurrent_streams(base::WeakPtr<SpdySession> session) {
+ return session->max_concurrent_streams_;
+ }
+
SpdySessionDependencies session_deps_;
std::unique_ptr<HttpNetworkSession> http_session_;
SpdySessionPool* spdy_session_pool_;
@@ -811,8 +819,7 @@ TEST_F(SpdySessionPoolTest, IPPoolingDisabled) {
// pooling.
TEST_F(SpdySessionPoolTest, IPPoolingClientCert) {
SSLSocketDataProvider ssl(ASYNC, OK);
- ssl.ssl_info.cert = X509Certificate::CreateFromBytes(
- reinterpret_cast<const char*>(webkit_der), sizeof(webkit_der));
+ ssl.ssl_info.cert = X509Certificate::CreateFromBytes(webkit_der);
ASSERT_TRUE(ssl.ssl_info.cert);
ssl.ssl_info.client_cert_sent = true;
ssl.next_proto = kProtoHTTP2;
@@ -1462,8 +1469,8 @@ static const struct {
false},
};
-// Tests the OnSSLConfigForServerChanged() method when there are no streams
-// active.
+// Tests the OnSSLConfigForServerChanged() method matches SpdySessions as
+// expected.
TEST_F(SpdySessionPoolTest, SSLConfigForServerChanged) {
const MockConnect connect_data(SYNCHRONOUS, OK);
const MockRead reads[] = {
@@ -1516,76 +1523,158 @@ TEST_F(SpdySessionPoolTest, SSLConfigForServerChanged) {
}
}
-// Tests the OnSSLConfigForServerChanged() method when there are streams active.
+// Tests the OnSSLConfigForServerChanged() method when there are streams open.
TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithStreams) {
+ // Set up a SpdySession with an active, created, and pending stream.
+ SpdyTestUtil spdy_util;
+ spdy::SettingsMap settings;
+ settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 2;
+ spdy::SpdySerializedFrame settings_frame =
+ spdy_util.ConstructSpdySettings(settings);
+ spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
+ spdy::SpdySerializedFrame req(
+ spdy_util.ConstructSpdyGet(nullptr, 0, 1, MEDIUM));
+
const MockConnect connect_data(SYNCHRONOUS, OK);
const MockRead reads[] = {
+ CreateMockRead(settings_frame),
MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
};
+ const MockWrite writes[] = {
+ CreateMockWrite(settings_ack),
+ CreateMockWrite(req),
+ };
- std::vector<std::unique_ptr<StaticSocketDataProvider>> socket_data;
- size_t num_tests = base::size(kSSLServerTests);
- for (size_t i = 0; i < num_tests; i++) {
- socket_data.push_back(std::make_unique<StaticSocketDataProvider>(
- reads, base::span<MockWrite>()));
- socket_data.back()->set_connect_data(connect_data);
- session_deps_.socket_factory->AddSocketDataProvider(
- socket_data.back().get());
- AddSSLSocketData();
- }
+ StaticSocketDataProvider socket_data(reads, writes);
+ socket_data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
+ AddSSLSocketData();
CreateNetworkSession();
- std::vector<base::WeakPtr<SpdySession>> sessions;
- std::vector<base::WeakPtr<SpdyStream>> streams;
- for (size_t i = 0; i < num_tests; i++) {
- SCOPED_TRACE(i);
- SpdySessionKey key(
- HostPortPair::FromURL(GURL(kSSLServerTests[i].url)),
- ProxyServer::FromPacString(kSSLServerTests[i].proxy_pac_string),
- PRIVACY_MODE_DISABLED, SpdySessionKey::IsProxySession::kFalse,
- SocketTag(), NetworkIsolationKey(), SecureDnsPolicy::kAllow);
- sessions.push_back(
- CreateSpdySession(http_session_.get(), key, NetLogWithSource()));
- streams.push_back(CreateStreamSynchronously(
- SPDY_BIDIRECTIONAL_STREAM, sessions.back(),
- GURL(kSSLServerTests[i].url), MEDIUM, NetLogWithSource()));
- ASSERT_TRUE(streams.back());
- }
+ const GURL url(kDefaultUrl);
+ SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED,
+ SpdySessionKey::IsProxySession::kFalse, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow);
+ base::WeakPtr<SpdySession> session =
+ CreateSpdySession(http_session_.get(), key, NetLogWithSource());
- // All sessions are active and available.
- for (size_t i = 0; i < num_tests; i++) {
- SCOPED_TRACE(i);
- EXPECT_TRUE(sessions[i]->is_active());
- EXPECT_TRUE(sessions[i]->IsAvailable());
- }
+ // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(2u, max_concurrent_streams(session));
+
+ // The first two stream requests should succeed.
+ base::WeakPtr<SpdyStream> active_stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
+ test::StreamDelegateDoNothing active_stream_delegate(active_stream);
+ active_stream->SetDelegate(&active_stream_delegate);
+ base::WeakPtr<SpdyStream> created_stream = CreateStreamSynchronously(
+ SPDY_REQUEST_RESPONSE_STREAM, session, url, MEDIUM, NetLogWithSource());
+ test::StreamDelegateDoNothing created_stream_delegate(created_stream);
+ created_stream->SetDelegate(&created_stream_delegate);
+
+ // The third will block.
+ TestCompletionCallback callback;
+ SpdyStreamRequest stream_request;
+ EXPECT_THAT(
+ stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
+ /*can_send_early=*/false, MEDIUM, SocketTag(),
+ NetLogWithSource(), callback.callback(),
+ TRAFFIC_ANNOTATION_FOR_TESTS),
+ IsError(ERR_IO_PENDING));
- spdy_session_pool_->OnSSLConfigForServerChanged(
- HostPortPair(kSSLServerTestHost, 443));
+ // Activate the first stream by sending data.
+ spdy::Http2HeaderBlock headers(spdy_util.ConstructGetHeaderBlock(url.spec()));
+ active_stream->SendRequestHeaders(std::move(headers), NO_MORE_DATA_TO_SEND);
+ base::RunLoop().RunUntilIdle();
- // The sessions should continue to be active, but now some are unavailable.
- for (size_t i = 0; i < num_tests; i++) {
- SCOPED_TRACE(i);
- ASSERT_TRUE(sessions[i]);
- EXPECT_TRUE(sessions[i]->is_active());
- if (kSSLServerTests[i].expect_invalidated) {
- EXPECT_FALSE(sessions[i]->IsAvailable());
- EXPECT_TRUE(sessions[i]->IsGoingAway());
- } else {
- EXPECT_TRUE(sessions[i]->IsAvailable());
- EXPECT_FALSE(sessions[i]->IsGoingAway());
- }
- }
+ // The active stream should now have a stream ID.
+ EXPECT_EQ(1u, active_stream->stream_id());
+ EXPECT_EQ(spdy::kInvalidStreamId, created_stream->stream_id());
+ EXPECT_TRUE(session->is_active());
+ EXPECT_TRUE(session->IsAvailable());
- // Each stream is still around. Close them.
- for (size_t i = 0; i < num_tests; i++) {
- SCOPED_TRACE(i);
- ASSERT_TRUE(streams[i]);
- streams[i]->Close();
- }
+ spdy_session_pool_->OnSSLConfigForServerChanged(HostPortPair::FromURL(url));
+ base::RunLoop().RunUntilIdle();
+
+ // The active stream is still alive, so the session is still active.
+ ASSERT_TRUE(session);
+ EXPECT_TRUE(session->is_active());
+ ASSERT_TRUE(active_stream);
+
+ // The session is no longer available.
+ EXPECT_FALSE(session->IsAvailable());
+ EXPECT_TRUE(session->IsGoingAway());
+
+ // The pending and created stream are cancelled.
+ // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
+ EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
+ EXPECT_THAT(created_stream_delegate.WaitForClose(),
+ IsError(ERR_NETWORK_CHANGED));
+
+ // Close the active stream.
+ active_stream->Close();
+ // TODO(https://crbug.com/982499): The invalidated session should be closed
+ // after a RunUntilIdle(), but it is not.
+}
+
+// Tests the OnSSLConfigForServerChanged() method when there only pending
+// streams active.
+TEST_F(SpdySessionPoolTest, SSLConfigForServerChangedWithOnlyPendingStreams) {
+ // Set up a SpdySession that accepts no streams.
+ SpdyTestUtil spdy_util;
+ spdy::SettingsMap settings;
+ settings[spdy::SETTINGS_MAX_CONCURRENT_STREAMS] = 0;
+ spdy::SpdySerializedFrame settings_frame =
+ spdy_util.ConstructSpdySettings(settings);
+ spdy::SpdySerializedFrame settings_ack = spdy_util.ConstructSpdySettingsAck();
+
+ const MockConnect connect_data(SYNCHRONOUS, OK);
+ const MockRead reads[] = {
+ CreateMockRead(settings_frame),
+ MockRead(SYNCHRONOUS, ERR_IO_PENDING) // Stall forever.
+ };
+ const MockWrite writes[] = {
+ CreateMockWrite(settings_ack),
+ };
+
+ StaticSocketDataProvider socket_data(reads, writes);
+ socket_data.set_connect_data(connect_data);
+ session_deps_.socket_factory->AddSocketDataProvider(&socket_data);
+ AddSSLSocketData();
+
+ CreateNetworkSession();
+
+ const GURL url(kDefaultUrl);
+ SpdySessionKey key(HostPortPair::FromURL(url), ProxyServer::Direct(),
+ PRIVACY_MODE_DISABLED,
+ SpdySessionKey::IsProxySession::kFalse, SocketTag(),
+ NetworkIsolationKey(), SecureDnsPolicy::kAllow);
+ base::WeakPtr<SpdySession> session =
+ CreateSpdySession(http_session_.get(), key, NetLogWithSource());
+
+ // Pick up the SETTINGS frame to update SETTINGS_MAX_CONCURRENT_STREAMS.
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0u, max_concurrent_streams(session));
+
+ // Create a stream. It should block on the stream limit.
+ TestCompletionCallback callback;
+ SpdyStreamRequest stream_request;
+ ASSERT_THAT(
+ stream_request.StartRequest(SPDY_REQUEST_RESPONSE_STREAM, session, url,
+ /*can_send_early=*/false, MEDIUM, SocketTag(),
+ NetLogWithSource(), callback.callback(),
+ TRAFFIC_ANNOTATION_FOR_TESTS),
+ IsError(ERR_IO_PENDING));
+
+ spdy_session_pool_->OnSSLConfigForServerChanged(HostPortPair::FromURL(url));
+ base::RunLoop().RunUntilIdle();
- // TODO(https://crbug.com/982499): The invalidated sessions should be closed
- // after a RunUntilIdle(), but they are not.
+ // The pending stream is cancelled.
+ // TODO(https://crbug.com/1213609): Ideally, this would be recoverable.
+ EXPECT_THAT(callback.WaitForResult(), IsError(ERR_NETWORK_CHANGED));
+ EXPECT_FALSE(session);
}
} // namespace net
diff --git a/chromium/net/spdy/spdy_session_unittest.cc b/chromium/net/spdy/spdy_session_unittest.cc
index 5c720d11512..7c4c2390405 100644
--- a/chromium/net/spdy/spdy_session_unittest.cc
+++ b/chromium/net/spdy/spdy_session_unittest.cc
@@ -11,8 +11,8 @@
#include "base/base64.h"
#include "base/bind.h"
#include "base/callback.h"
+#include "base/cxx17_backports.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
@@ -28,6 +28,7 @@
#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
#include "net/base/schemeful_site.h"
+#include "net/base/test_completion_callback.h"
#include "net/base/test_data_stream.h"
#include "net/cert/ct_policy_status.h"
#include "net/dns/public/secure_dns_policy.h"
@@ -60,6 +61,8 @@
#include "testing/platform_test.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -3629,12 +3632,11 @@ TEST_F(SpdySessionTest, CloseOneIdleConnection) {
// Trying to create a new connection should cause the pool to be stalled, and
// post a task asynchronously to try and close the session.
TestCompletionCallback callback2;
- HostPortPair host_port2("2.com", 80);
auto connection2 = std::make_unique<ClientSocketHandle>();
EXPECT_EQ(ERR_IO_PENDING,
connection2->Init(
ClientSocketPool::GroupId(
- host_port2, ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "2.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
ClientSocketPool::SocketParams::CreateForHttpForTesting(),
@@ -3719,12 +3721,11 @@ TEST_F(SpdySessionTest, CloseOneIdleConnectionWithAlias) {
// Trying to create a new connection should cause the pool to be stalled, and
// post a task asynchronously to try and close the session.
TestCompletionCallback callback3;
- HostPortPair host_port3("3.com", 80);
auto connection3 = std::make_unique<ClientSocketHandle>();
EXPECT_EQ(ERR_IO_PENDING,
connection3->Init(
ClientSocketPool::GroupId(
- host_port3, ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "3.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
ClientSocketPool::SocketParams::CreateForHttpForTesting(),
@@ -3800,12 +3801,11 @@ TEST_F(SpdySessionTest, CloseSessionOnIdleWhenPoolStalled) {
// Trying to create a new connection should cause the pool to be stalled, and
// post a task asynchronously to try and close the session.
TestCompletionCallback callback2;
- HostPortPair host_port2("2.com", 80);
auto connection2 = std::make_unique<ClientSocketHandle>();
EXPECT_EQ(ERR_IO_PENDING,
connection2->Init(
ClientSocketPool::GroupId(
- host_port2, ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "2.com", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
ClientSocketPool::SocketParams::CreateForHttpForTesting(),
@@ -6032,14 +6032,14 @@ TEST_F(SpdySessionTest, GreaseFrameTypeAfterSettings) {
CombineFrames({&preface, &settings_frame});
// Greased frame sent on stream 0 after initial SETTINGS frame.
- const char kRawFrameData[] = {
+ uint8_t kRawFrameData[] = {
0x00, 0x00, 0x03, // length
0x0b, // type
0xcc, // flags
0x00, 0x00, 0x00, 0x00, // stream ID
'f', 'o', 'o' // payload
};
- spdy::SpdySerializedFrame grease(const_cast<char*>(kRawFrameData),
+ spdy::SpdySerializedFrame grease(reinterpret_cast<char*>(kRawFrameData),
base::size(kRawFrameData),
/* owns_buffer = */ false);
@@ -7424,4 +7424,37 @@ TEST_F(SpdySessionTest, AlpsAcceptChInvalidOrigin) {
kOnlyInvalidEntries, 1);
}
+// Test that ConfirmHandshake() correctly handles the client aborting the
+// connection. See https://crbug.com/1211639.
+TEST_F(SpdySessionTest, ConfirmHandshakeAfterClose) {
+ base::HistogramTester histogram_tester;
+
+ session_deps_.enable_early_data = true;
+ // Arrange for StreamSocket::ConfirmHandshake() to hang.
+ ssl_.confirm = MockConfirm(SYNCHRONOUS, ERR_IO_PENDING);
+ SequencedSocketData data;
+ session_deps_.socket_factory->AddSocketDataProvider(&data);
+ AddSSLSocketData();
+
+ CreateNetworkSession();
+ CreateSpdySession();
+
+ TestCompletionCallback callback1;
+ int rv1 = session_->ConfirmHandshake(callback1.callback());
+ EXPECT_THAT(rv1, IsError(ERR_IO_PENDING));
+
+ // Abort the session. Although the underlying StreamSocket::ConfirmHandshake()
+ // operation never completes, SpdySession::ConfirmHandshake() is signaled when
+ // the session is discarded.
+ session_->CloseSessionOnError(ERR_ABORTED, "Aborting session");
+ EXPECT_THAT(callback1.GetResult(rv1), IsError(ERR_ABORTED));
+
+ // Subsequent calls to SpdySession::ConfirmHandshake() fail gracefully. This
+ // tests that SpdySession honors StreamSocket::ConfirmHandshake() invariants.
+ // (MockSSLClientSocket::ConfirmHandshake() checks it internally.)
+ TestCompletionCallback callback2;
+ int rv2 = session_->ConfirmHandshake(callback2.callback());
+ EXPECT_THAT(rv2, IsError(ERR_CONNECTION_CLOSED));
+}
+
} // namespace net
diff --git a/chromium/net/spdy/spdy_stream_test_util.cc b/chromium/net/spdy/spdy_stream_test_util.cc
index a8d17c7f96b..ad00817a45e 100644
--- a/chromium/net/spdy/spdy_stream_test_util.cc
+++ b/chromium/net/spdy/spdy_stream_test_util.cc
@@ -7,7 +7,6 @@
#include <cstddef>
#include <utility>
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "net/spdy/spdy_stream.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/spdy/spdy_stream_unittest.cc b/chromium/net/spdy/spdy_stream_unittest.cc
index 7c17dfc5675..402e220f1c3 100644
--- a/chromium/net/spdy/spdy_stream_unittest.cc
+++ b/chromium/net/spdy/spdy_stream_unittest.cc
@@ -15,9 +15,9 @@
#include <vector>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "net/base/request_priority.h"
#include "net/dns/public/secure_dns_policy.h"
diff --git a/chromium/net/spdy/spdy_test_util_common.cc b/chromium/net/spdy/spdy_test_util_common.cc
index 8a1892adbe2..b4b2b35dbfc 100644
--- a/chromium/net/spdy/spdy_test_util_common.cc
+++ b/chromium/net/spdy/spdy_test_util_common.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
+#include "base/containers/span.h"
#include "base/notreached.h"
#include "base/strings/abseil_string_conversions.h"
#include "base/strings/string_number_conversions.h"
@@ -47,6 +48,8 @@
#include "net/url_request/url_request_job_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -280,48 +283,6 @@ void StreamReleaserCallback::OnComplete(
SetResult(result);
}
-MockECSignatureCreator::MockECSignatureCreator(crypto::ECPrivateKey* key)
- : key_(key) {
-}
-
-bool MockECSignatureCreator::Sign(const uint8_t* data,
- int data_len,
- std::vector<uint8_t>* signature) {
- std::vector<uint8_t> private_key;
- if (!key_->ExportPrivateKey(&private_key))
- return false;
- std::string head = "fakesignature";
- std::string tail = "/fakesignature";
-
- signature->clear();
- signature->insert(signature->end(), head.begin(), head.end());
- signature->insert(signature->end(), private_key.begin(), private_key.end());
- signature->insert(signature->end(), '-');
- signature->insert(signature->end(), data, data + data_len);
- signature->insert(signature->end(), tail.begin(), tail.end());
- return true;
-}
-
-bool MockECSignatureCreator::DecodeSignature(
- const std::vector<uint8_t>& signature,
- std::vector<uint8_t>* out_raw_sig) {
- *out_raw_sig = signature;
- return true;
-}
-
-MockECSignatureCreatorFactory::MockECSignatureCreatorFactory() {
- crypto::ECSignatureCreator::SetFactoryForTesting(this);
-}
-
-MockECSignatureCreatorFactory::~MockECSignatureCreatorFactory() {
- crypto::ECSignatureCreator::SetFactoryForTesting(nullptr);
-}
-
-std::unique_ptr<crypto::ECSignatureCreator>
-MockECSignatureCreatorFactory::Create(crypto::ECPrivateKey* key) {
- return std::make_unique<MockECSignatureCreator>(key);
-}
-
SpdySessionDependencies::SpdySessionDependencies()
: SpdySessionDependencies(
ConfiguredProxyResolutionService::CreateDirect()) {}
@@ -372,8 +333,8 @@ std::unique_ptr<HttpNetworkSession>
SpdySessionDependencies::SpdyCreateSessionWithSocketFactory(
SpdySessionDependencies* session_deps,
ClientSocketFactory* factory) {
- HttpNetworkSession::Params session_params = CreateSessionParams(session_deps);
- HttpNetworkSession::Context session_context =
+ HttpNetworkSessionParams session_params = CreateSessionParams(session_deps);
+ HttpNetworkSessionContext session_context =
CreateSessionContext(session_deps);
session_context.client_socket_factory = factory;
auto http_session =
@@ -384,9 +345,9 @@ SpdySessionDependencies::SpdyCreateSessionWithSocketFactory(
}
// static
-HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
+HttpNetworkSessionParams SpdySessionDependencies::CreateSessionParams(
SpdySessionDependencies* session_deps) {
- HttpNetworkSession::Params params;
+ HttpNetworkSessionParams params;
params.enable_spdy_ping_based_connection_checking = session_deps->enable_ping;
params.enable_user_alternate_protocol_ports =
session_deps->enable_user_alternate_protocol_ports;
@@ -415,9 +376,9 @@ HttpNetworkSession::Params SpdySessionDependencies::CreateSessionParams(
return params;
}
-HttpNetworkSession::Context SpdySessionDependencies::CreateSessionContext(
+HttpNetworkSessionContext SpdySessionDependencies::CreateSessionContext(
SpdySessionDependencies* session_deps) {
- HttpNetworkSession::Context context;
+ HttpNetworkSessionContext context;
context.client_socket_factory = session_deps->socket_factory.get();
context.host_resolver = session_deps->GetHostResolver();
context.cert_verifier = session_deps->cert_verifier.get();
@@ -456,10 +417,10 @@ SpdyURLRequestContext::SpdyURLRequestContext() : storage_(this) {
storage_.set_http_server_properties(std::make_unique<HttpServerProperties>());
storage_.set_quic_context(std::make_unique<QuicContext>());
storage_.set_job_factory(std::make_unique<URLRequestJobFactory>());
- HttpNetworkSession::Params session_params;
+ HttpNetworkSessionParams session_params;
session_params.enable_spdy_ping_based_connection_checking = false;
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.client_socket_factory = &socket_factory_;
session_context.host_resolver = host_resolver();
session_context.cert_verifier = cert_verifier();
@@ -510,7 +471,9 @@ base::WeakPtr<SpdySession> CreateSpdySessionHelper(
nullptr /* ssl_config_for_proxy */);
int rv = connection->Init(
ClientSocketPool::GroupId(
- key.host_port_pair(), ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme,
+ key.host_port_pair().HostForURL(),
+ key.host_port_pair().port()),
key.privacy_mode(), NetworkIsolationKey(), SecureDnsPolicy::kAllow),
socket_params, absl::nullopt /* proxy_annotation_tag */, MEDIUM,
key.socket_tag(), ClientSocketPool::RespectLimits::ENABLED,
diff --git a/chromium/net/spdy/spdy_test_util_common.h b/chromium/net/spdy/spdy_test_util_common.h
index d5defb178c5..327bd6b636f 100644
--- a/chromium/net/spdy/spdy_test_util_common.h
+++ b/chromium/net/spdy/spdy_test_util_common.h
@@ -13,11 +13,11 @@
#include <string>
#include <vector>
+#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "crypto/ec_private_key.h"
-#include "crypto/ec_signature_creator.h"
#include "net/base/completion_once_callback.h"
#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
@@ -141,38 +141,6 @@ class StreamReleaserCallback : public TestCompletionCallbackBase {
void OnComplete(SpdyStreamRequest* request, int result);
};
-// An ECSignatureCreator that returns deterministic signatures.
-class MockECSignatureCreator : public crypto::ECSignatureCreator {
- public:
- explicit MockECSignatureCreator(crypto::ECPrivateKey* key);
-
- // crypto::ECSignatureCreator
- bool Sign(const uint8_t* data,
- int data_len,
- std::vector<uint8_t>* signature) override;
- bool DecodeSignature(const std::vector<uint8_t>& signature,
- std::vector<uint8_t>* out_raw_sig) override;
-
- private:
- crypto::ECPrivateKey* key_;
-
- DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreator);
-};
-
-// An ECSignatureCreatorFactory creates MockECSignatureCreator.
-class MockECSignatureCreatorFactory : public crypto::ECSignatureCreatorFactory {
- public:
- MockECSignatureCreatorFactory();
- ~MockECSignatureCreatorFactory() override;
-
- // crypto::ECSignatureCreatorFactory
- std::unique_ptr<crypto::ECSignatureCreator> Create(
- crypto::ECPrivateKey* key) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockECSignatureCreatorFactory);
-};
-
// Helper to manage the lifetimes of the dependencies for a
// HttpNetworkTransaction.
struct SpdySessionDependencies {
@@ -198,9 +166,9 @@ struct SpdySessionDependencies {
static std::unique_ptr<HttpNetworkSession> SpdyCreateSessionWithSocketFactory(
SpdySessionDependencies* session_deps,
ClientSocketFactory* factory);
- static HttpNetworkSession::Params CreateSessionParams(
+ static HttpNetworkSessionParams CreateSessionParams(
SpdySessionDependencies* session_deps);
- static HttpNetworkSession::Context CreateSessionContext(
+ static HttpNetworkSessionContext CreateSessionContext(
SpdySessionDependencies* session_deps);
// NOTE: host_resolver must be ordered before http_auth_handler_factory.
diff --git a/chromium/net/spdy/spdy_write_queue_unittest.cc b/chromium/net/spdy/spdy_write_queue_unittest.cc
index 3cc5623b3ac..36a422fdafb 100644
--- a/chromium/net/spdy/spdy_write_queue_unittest.cc
+++ b/chromium/net/spdy/spdy_write_queue_unittest.cc
@@ -10,9 +10,9 @@
#include <utility>
#include "base/bind.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ref_counted.h"
#include "base/notreached.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "net/base/request_priority.h"
#include "net/log/net_log_with_source.h"
diff --git a/chromium/net/ssl/OWNERS b/chromium/net/ssl/OWNERS
index f8d21715738..dd7bb8bad81 100644
--- a/chromium/net/ssl/OWNERS
+++ b/chromium/net/ssl/OWNERS
@@ -1,3 +1,2 @@
davidben@chromium.org
-mattm@chromium.org
svaldez@chromium.org
diff --git a/chromium/net/ssl/client_cert_identity_unittest.cc b/chromium/net/ssl/client_cert_identity_unittest.cc
index f13236a1aad..443d296120a 100644
--- a/chromium/net/ssl/client_cert_identity_unittest.cc
+++ b/chromium/net/ssl/client_cert_identity_unittest.cc
@@ -27,7 +27,8 @@ TEST(ClientCertIdentitySorter, SortClientCertificates) {
ASSERT_TRUE(x509_util::CreateSelfSignedCert(
key->key(), x509_util::DIGEST_SHA256, "CN=expired", 1,
base::Time::UnixEpoch(), base::Time::UnixEpoch(), {}, &der_cert));
- cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_cert)));
ASSERT_TRUE(cert);
certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr));
@@ -37,7 +38,8 @@ TEST(ClientCertIdentitySorter, SortClientCertificates) {
key->key(), x509_util::DIGEST_SHA256, "CN=not yet valid", 2,
now + base::TimeDelta::FromDays(10), now + base::TimeDelta::FromDays(15),
{}, &der_cert));
- cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_cert)));
ASSERT_TRUE(cert);
certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr));
@@ -45,7 +47,8 @@ TEST(ClientCertIdentitySorter, SortClientCertificates) {
key->key(), x509_util::DIGEST_SHA256, "CN=older cert", 3,
now - base::TimeDelta::FromDays(5), now + base::TimeDelta::FromDays(5),
{}, &der_cert));
- cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_cert)));
ASSERT_TRUE(cert);
certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr));
@@ -53,7 +56,8 @@ TEST(ClientCertIdentitySorter, SortClientCertificates) {
key->key(), x509_util::DIGEST_SHA256, "CN=newer cert", 2,
now - base::TimeDelta::FromDays(3), now + base::TimeDelta::FromDays(5),
{}, &der_cert));
- cert = X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size());
+ cert = X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(der_cert)));
ASSERT_TRUE(cert);
certs.push_back(std::make_unique<FakeClientCertIdentity>(cert, nullptr));
diff --git a/chromium/net/ssl/client_cert_store_mac.cc b/chromium/net/ssl/client_cert_store_mac.cc
index 7d97f1d0904..b382b07d5c9 100644
--- a/chromium/net/ssl/client_cert_store_mac.cc
+++ b/chromium/net/ssl/client_cert_store_mac.cc
@@ -20,10 +20,10 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/logging.h"
#include "base/mac/mac_logging.h"
#include "base/mac/scoped_cftyperef.h"
-#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task_runner_util.h"
diff --git a/chromium/net/ssl/client_cert_store_nss.cc b/chromium/net/ssl/client_cert_store_nss.cc
index 9ef425caaa5..0999bd82213 100644
--- a/chromium/net/ssl/client_cert_store_nss.cc
+++ b/chromium/net/ssl/client_cert_store_nss.cc
@@ -120,9 +120,8 @@ void ClientCertStoreNSS::FilterCertsOnWorkerThread(
intermediates.reserve(nss_intermediates.size());
for (const ScopedCERTCertificate& nss_intermediate : nss_intermediates) {
bssl::UniquePtr<CRYPTO_BUFFER> intermediate_cert_handle(
- X509Certificate::CreateCertBufferFromBytes(
- reinterpret_cast<const char*>(nss_intermediate->derCert.data),
- nss_intermediate->derCert.len));
+ X509Certificate::CreateCertBufferFromBytes(base::make_span(
+ nss_intermediate->derCert.data, nss_intermediate->derCert.len)));
if (!intermediate_cert_handle)
break;
intermediates.push_back(std::move(intermediate_cert_handle));
diff --git a/chromium/net/ssl/client_cert_store_win.cc b/chromium/net/ssl/client_cert_store_win.cc
index 226d7efbbcc..bd5a95a6130 100644
--- a/chromium/net/ssl/client_cert_store_win.cc
+++ b/chromium/net/ssl/client_cert_store_win.cc
@@ -18,11 +18,11 @@
#include "base/callback_helpers.h"
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
+#include "base/scoped_generic.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/wincrypt_shim.h"
-#include "crypto/scoped_capi_types.h"
#include "net/cert/x509_util.h"
#include "net/cert/x509_util_win.h"
#include "net/ssl/ssl_platform_key_util.h"
@@ -34,17 +34,17 @@ namespace net {
namespace {
-using ScopedHCERTSTORE = crypto::ScopedCAPIHandle<
+using ScopedHCERTSTOREWithChecks = base::ScopedGeneric<
HCERTSTORE,
- crypto::CAPIDestroyerWithFlags<HCERTSTORE,
- CertCloseStore,
- CERT_CLOSE_STORE_CHECK_FLAG>>;
+ crypto::CAPITraitsWithFlags<HCERTSTORE,
+ CertCloseStore,
+ CERT_CLOSE_STORE_CHECK_FLAG>>;
class ClientCertIdentityWin : public ClientCertIdentity {
public:
ClientCertIdentityWin(
scoped_refptr<net::X509Certificate> cert,
- ScopedPCCERT_CONTEXT cert_context,
+ crypto::ScopedPCCERT_CONTEXT cert_context,
scoped_refptr<base::SingleThreadTaskRunner> key_task_runner)
: ClientCertIdentity(std::move(cert)),
cert_context_(std::move(cert_context)),
@@ -60,7 +60,7 @@ class ClientCertIdentityWin : public ClientCertIdentity {
}
private:
- ScopedPCCERT_CONTEXT cert_context_;
+ crypto::ScopedPCCERT_CONTEXT cert_context_;
scoped_refptr<base::SingleThreadTaskRunner> key_task_runner_;
};
@@ -153,7 +153,7 @@ ClientCertIdentityList GetClientCertsImpl(HCERTSTORE cert_store,
PCCERT_CONTEXT cert_context =
chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
// Copy the certificate, so that it is valid after |cert_store| is closed.
- ScopedPCCERT_CONTEXT cert_context2;
+ crypto::ScopedPCCERT_CONTEXT cert_context2;
PCCERT_CONTEXT raw = nullptr;
BOOL ok = CertAddCertificateContextToStore(
nullptr, cert_context, CERT_STORE_ADD_USE_EXISTING, &raw);
@@ -164,7 +164,7 @@ ClientCertIdentityList GetClientCertsImpl(HCERTSTORE cert_store,
cert_context2.reset(raw);
// Grab the intermediates, if any.
- std::vector<ScopedPCCERT_CONTEXT> intermediates_storage;
+ std::vector<crypto::ScopedPCCERT_CONTEXT> intermediates_storage;
std::vector<PCCERT_CONTEXT> intermediates;
for (DWORD i = 1; i < chain_context->rgpChain[0]->cElement; ++i) {
PCCERT_CONTEXT chain_intermediate =
@@ -215,15 +215,15 @@ ClientCertIdentityList GetClientCertsImpl(HCERTSTORE cert_store,
} // namespace
-ClientCertStoreWin::ClientCertStoreWin() {}
+ClientCertStoreWin::ClientCertStoreWin() = default;
ClientCertStoreWin::ClientCertStoreWin(
- base::RepeatingCallback<HCERTSTORE()> cert_store_callback)
+ base::RepeatingCallback<crypto::ScopedHCERTSTORE()> cert_store_callback)
: cert_store_callback_(std::move(cert_store_callback)) {
DCHECK(!cert_store_callback_.is_null());
}
-ClientCertStoreWin::~ClientCertStoreWin() {}
+ClientCertStoreWin::~ClientCertStoreWin() = default;
void ClientCertStoreWin::GetClientCerts(const SSLCertRequestInfo& request,
ClientCertListCallback callback) {
@@ -239,31 +239,34 @@ void ClientCertStoreWin::GetClientCerts(const SSLCertRequestInfo& request,
// static
ClientCertIdentityList ClientCertStoreWin::GetClientCertsWithCertStore(
const SSLCertRequestInfo& request,
- const base::RepeatingCallback<HCERTSTORE()>& cert_store_callback) {
- ScopedHCERTSTORE cert_store;
+ const base::RepeatingCallback<crypto::ScopedHCERTSTORE()>&
+ cert_store_callback) {
+ ScopedHCERTSTOREWithChecks cert_store;
if (cert_store_callback.is_null()) {
// Always open a new instance of the "MY" store, to ensure that there
// are no previously cached certificates being reused after they're
// no longer available (some smartcard providers fail to update the "MY"
- // store handles and instead interpose CertOpenSystemStore).
+ // store handles and instead interpose CertOpenSystemStore). To help confirm
+ // this, use `ScopedHCERTSTOREWithChecks` and `CERT_CLOSE_STORE_CHECK_FLAG`
+ // to DCHECK that `cert_store` is not inadvertently ref-counted.
cert_store.reset(CertOpenSystemStore(NULL, L"MY"));
} else {
- cert_store.reset(cert_store_callback.Run());
+ cert_store.reset(cert_store_callback.Run().release());
}
- if (!cert_store) {
+ if (!cert_store.is_valid()) {
PLOG(ERROR) << "Could not open certificate store: ";
return ClientCertIdentityList();
}
- return GetClientCertsImpl(cert_store, request);
+ return GetClientCertsImpl(cert_store.get(), request);
}
bool ClientCertStoreWin::SelectClientCertsForTesting(
const CertificateList& input_certs,
const SSLCertRequestInfo& request,
ClientCertIdentityList* selected_identities) {
- ScopedHCERTSTORE test_store(
+ ScopedHCERTSTOREWithChecks test_store(
CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, nullptr));
- if (!test_store)
+ if (!test_store.is_valid())
return false;
// Add available certificates to the test store.
@@ -271,7 +274,7 @@ bool ClientCertStoreWin::SelectClientCertsForTesting(
// Add the certificate to the test store.
PCCERT_CONTEXT cert = nullptr;
if (!CertAddEncodedCertificateToStore(
- test_store, X509_ASN_ENCODING,
+ test_store.get(), X509_ASN_ENCODING,
reinterpret_cast<const BYTE*>(
CRYPTO_BUFFER_data(input_cert->cert_buffer())),
base::checked_cast<DWORD>(
@@ -280,7 +283,7 @@ bool ClientCertStoreWin::SelectClientCertsForTesting(
return false;
}
// Hold the reference to the certificate (since we requested a copy).
- ScopedPCCERT_CONTEXT scoped_cert(cert);
+ crypto::ScopedPCCERT_CONTEXT scoped_cert(cert);
// Add dummy private key data to the certificate - otherwise the certificate
// would be discarded by the filtering routines.
diff --git a/chromium/net/ssl/client_cert_store_win.h b/chromium/net/ssl/client_cert_store_win.h
index 44d6c647983..6dac9386845 100644
--- a/chromium/net/ssl/client_cert_store_win.h
+++ b/chromium/net/ssl/client_cert_store_win.h
@@ -8,6 +8,7 @@
#include "base/callback.h"
#include "base/macros.h"
#include "base/win/wincrypt_shim.h"
+#include "crypto/scoped_capi_types.h"
#include "net/base/net_export.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
@@ -20,10 +21,9 @@ class NET_EXPORT ClientCertStoreWin : public ClientCertStore {
ClientCertStoreWin();
// Calls |cert_store_callback| on the platform key thread to determine the
- // certificate store. ClientCertStoreWin takes ownership of the resulting
- // |HCERTSTORE| and closes it when the operation is finished.
+ // certificate store.
explicit ClientCertStoreWin(
- base::RepeatingCallback<HCERTSTORE()> cert_store_callback);
+ base::RepeatingCallback<crypto::ScopedHCERTSTORE()> cert_store_callback);
~ClientCertStoreWin() override;
@@ -39,7 +39,8 @@ class NET_EXPORT ClientCertStoreWin : public ClientCertStore {
// Opens the cert store and uses it to lookup the client certs.
static ClientCertIdentityList GetClientCertsWithCertStore(
const SSLCertRequestInfo& request,
- const base::RepeatingCallback<HCERTSTORE()>& cert_store_callback);
+ const base::RepeatingCallback<crypto::ScopedHCERTSTORE()>&
+ cert_store_callback);
// A hook for testing. Filters |input_certs| using the logic being used to
// filter the system store when GetClientCerts() is called.
@@ -49,7 +50,7 @@ class NET_EXPORT ClientCertStoreWin : public ClientCertStore {
const SSLCertRequestInfo& cert_request_info,
ClientCertIdentityList* selected_identities);
- base::RepeatingCallback<HCERTSTORE()> cert_store_callback_;
+ base::RepeatingCallback<crypto::ScopedHCERTSTORE()> cert_store_callback_;
DISALLOW_COPY_AND_ASSIGN(ClientCertStoreWin);
};
diff --git a/chromium/net/ssl/ssl_cipher_suite_names.cc b/chromium/net/ssl/ssl_cipher_suite_names.cc
index fb852b7d005..8a539db77d6 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names.cc
+++ b/chromium/net/ssl/ssl_cipher_suite_names.cc
@@ -4,6 +4,8 @@
#include "net/ssl/ssl_cipher_suite_names.h"
+#include <ostream>
+
#include "base/notreached.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc b/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
index 3f4bceb3307..f0964d503c2 100644
--- a/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
+++ b/chromium/net/ssl/ssl_cipher_suite_names_unittest.cc
@@ -4,7 +4,7 @@
#include "net/ssl/ssl_cipher_suite_names.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/ssl/ssl_connection_status_flags.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/boringssl/src/include/openssl/ssl.h"
diff --git a/chromium/net/ssl/ssl_client_auth_cache.h b/chromium/net/ssl/ssl_client_auth_cache.h
index a380ea7d6f3..facbc5f997f 100644
--- a/chromium/net/ssl/ssl_client_auth_cache.h
+++ b/chromium/net/ssl/ssl_client_auth_cache.h
@@ -6,7 +6,6 @@
#define NET_SSL_SSL_CLIENT_AUTH_CACHE_H_
#include <map>
-#include <string>
#include <utility>
#include "base/compiler_specific.h"
diff --git a/chromium/net/ssl/ssl_config.h b/chromium/net/ssl/ssl_config.h
index 18c5af92a77..c3dd24f8dd7 100644
--- a/chromium/net/ssl/ssl_config.h
+++ b/chromium/net/ssl/ssl_config.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "base/containers/flat_map.h"
#include "base/memory/ref_counted.h"
#include "net/base/net_export.h"
#include "net/base/network_isolation_key.h"
diff --git a/chromium/net/ssl/ssl_config_service.h b/chromium/net/ssl/ssl_config_service.h
index cc2b73f2e8d..4909ebe3614 100644
--- a/chromium/net/ssl/ssl_config_service.h
+++ b/chromium/net/ssl/ssl_config_service.h
@@ -48,6 +48,9 @@ struct NET_EXPORT SSLContextConfig {
bool cecpq2_enabled = true;
// If false, disables 3DES cipher suites in TLS connections.
+ //
+ // TODO(https://crbug.com/1203442): Disable this by default, once the change
+ // has successfully shipped in Chrome 93.
bool triple_des_enabled = true;
// ADDING MORE HERE? Don't forget to update |SSLContextConfigsAreEqual|.
diff --git a/chromium/net/ssl/ssl_platform_key_win.cc b/chromium/net/ssl/ssl_platform_key_win.cc
index 04a6b11bab5..64b43e6e0b5 100644
--- a/chromium/net/ssl/ssl_platform_key_win.cc
+++ b/chromium/net/ssl/ssl_platform_key_win.cc
@@ -50,12 +50,12 @@ std::string GetCAPIProviderName(HCRYPTPROV provider) {
class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate {
public:
// Takes ownership of |provider|.
- SSLPlatformKeyCAPI(HCRYPTPROV provider, DWORD key_spec)
- : provider_name_(GetCAPIProviderName(provider)),
- provider_(provider),
+ SSLPlatformKeyCAPI(crypto::ScopedHCRYPTPROV provider, DWORD key_spec)
+ : provider_name_(GetCAPIProviderName(provider.get())),
+ provider_(std::move(provider)),
key_spec_(key_spec) {}
- ~SSLPlatformKeyCAPI() override {}
+ ~SSLPlatformKeyCAPI() override = default;
std::string GetProviderName() override { return "CAPI: " + provider_name_; }
@@ -65,8 +65,10 @@ class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate {
// Prioritize SHA-1, but if the server doesn't advertise it, leave the other
// algorithms enabled to try.
return {
- SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA256,
- SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA512,
+ SSL_SIGN_RSA_PKCS1_SHA1,
+ SSL_SIGN_RSA_PKCS1_SHA256,
+ SSL_SIGN_RSA_PKCS1_SHA384,
+ SSL_SIGN_RSA_PKCS1_SHA512,
};
}
@@ -104,7 +106,9 @@ class SSLPlatformKeyCAPI : public ThreadedSSLPrivateKey::Delegate {
}
crypto::ScopedHCRYPTHASH hash_handle;
- if (!CryptCreateHash(provider_, hash_alg, 0, 0, hash_handle.receive())) {
+ if (!CryptCreateHash(
+ provider_.get(), hash_alg, 0, 0,
+ crypto::ScopedHCRYPTHASH::Receiver(hash_handle).get())) {
PLOG(ERROR) << "CreateCreateHash failed";
return ERR_SSL_CLIENT_AUTH_SIGNATURE_FAILED;
}
@@ -167,7 +171,7 @@ class ScopedNCRYPT_PROV_HANDLE {
NCRYPT_PROV_HANDLE prov_ = 0;
};
-std::string GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
+std::wstring GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
ScopedNCRYPT_PROV_HANDLE prov;
DWORD prov_len = 0;
SECURITY_STATUS status = NCryptGetProperty(
@@ -175,7 +179,7 @@ std::string GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
reinterpret_cast<BYTE*>(prov.InitializeInto()),
sizeof(*prov.InitializeInto()), &prov_len, NCRYPT_SILENT_FLAG);
if (FAILED(status)) {
- return "(error getting provider)";
+ return L"(error getting provider)";
}
DCHECK_EQ(sizeof(NCRYPT_PROV_HANDLE), prov_len);
@@ -186,14 +190,15 @@ std::string GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
status = NCryptGetProperty(prov.get(), NCRYPT_NAME_PROPERTY, nullptr, 0,
&name_len, NCRYPT_SILENT_FLAG);
if (FAILED(status) || name_len % sizeof(wchar_t) != 0) {
- return "(error getting provider name)";
+ return L"(error getting provider name)";
}
- std::vector<wchar_t> name(name_len / sizeof(wchar_t));
+ std::vector<wchar_t> name;
+ name.reserve(name_len / sizeof(wchar_t));
status = NCryptGetProperty(
prov.get(), NCRYPT_NAME_PROPERTY, reinterpret_cast<BYTE*>(name.data()),
name.size() * sizeof(wchar_t), &name_len, NCRYPT_SILENT_FLAG);
if (FAILED(status)) {
- return "(error getting provider name)";
+ return L"(error getting provider name)";
}
name.resize(name_len / sizeof(wchar_t));
@@ -203,7 +208,7 @@ std::string GetCNGProviderName(NCRYPT_KEY_HANDLE key) {
if (nul != name.end()) {
name.erase(nul, name.end());
}
- return base::WideToUTF8(base::WStringPiece(name.data(), name.size()));
+ return std::wstring(name.begin(), name.end());
}
class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
@@ -217,23 +222,53 @@ class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
~SSLPlatformKeyCNG() override { NCryptFreeObject(key_); }
- std::string GetProviderName() override { return "CNG: " + provider_name_; }
+ std::string GetProviderName() override {
+ return "CNG: " + base::WideToUTF8(provider_name_);
+ }
std::vector<uint16_t> GetAlgorithmPreferences() override {
+ // Per TLS 1.3 (RFC 8446), the RSA-PSS code points in TLS correspond to
+ // RSA-PSS with salt length equal to the digest length. TPM 2.0's
+ // TPM_ALG_RSAPSS algorithm, however, uses the maximum possible salt length.
+ // The TPM provider will fail signing requests for other salt lengths and
+ // thus cannot generate TLS-compatible PSS signatures.
+ //
+ // However, as of TPM revision 1.16, TPMs which follow FIPS 186-4 will
+ // instead interpret TPM_ALG_RSAPSS using salt length equal to the digest
+ // length. Those TPMs can generate TLS-compatible PSS signatures. As a
+ // result, if this is a TPM-based key, we only report PSS as supported if
+ // the salt length will match the digest length.
+ bool supports_pss = true;
+ if (provider_name_ == MS_PLATFORM_KEY_STORAGE_PROVIDER) {
+ DWORD salt_size = 0;
+ DWORD size_of_salt_size = sizeof(salt_size);
+ HRESULT status =
+ NCryptGetProperty(key_, NCRYPT_PCP_PSS_SALT_SIZE_PROPERTY,
+ reinterpret_cast<PBYTE>(&salt_size),
+ size_of_salt_size, &size_of_salt_size, 0);
+ if (FAILED(status) || salt_size != NCRYPT_TPM_PSS_SALT_SIZE_HASHSIZE) {
+ supports_pss = false;
+ }
+ }
// If this is an under 1024-bit RSA key, conservatively prefer to sign SHA-1
// hashes. Older Estonian ID cards can only sign SHA-1 hashes. Prioritize
// SHA-1, but if the server doesn't advertise it, leave the other algorithms
// enabled to try.
if (type_ == EVP_PKEY_RSA && max_length_ <= 1024 / 8) {
- return {
- SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA256,
- SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA512,
- // 1024-bit keys are too small for SSL_SIGN_RSA_PSS_SHA512.
- SSL_SIGN_RSA_PSS_SHA256, SSL_SIGN_RSA_PSS_SHA384,
+ std::vector<uint16_t> ret = {
+ SSL_SIGN_RSA_PKCS1_SHA1,
+ SSL_SIGN_RSA_PKCS1_SHA256,
+ SSL_SIGN_RSA_PKCS1_SHA384,
+ SSL_SIGN_RSA_PKCS1_SHA512,
};
+ if (supports_pss) {
+ // 1024-bit keys are too small for SSL_SIGN_RSA_PSS_SHA512.
+ ret.push_back(SSL_SIGN_RSA_PSS_SHA256);
+ ret.push_back(SSL_SIGN_RSA_PSS_SHA384);
+ }
+ return ret;
}
- return SSLPrivateKey::DefaultAlgorithmPreferences(type_,
- true /* supports PSS */);
+ return SSLPrivateKey::DefaultAlgorithmPreferences(type_, supports_pss);
}
Error Sign(uint16_t algorithm,
@@ -336,7 +371,7 @@ class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
}
private:
- std::string provider_name_;
+ std::wstring provider_name_;
NCRYPT_KEY_HANDLE key_;
int type_;
size_t max_length_;
@@ -348,10 +383,10 @@ class SSLPlatformKeyCNG : public ThreadedSSLPrivateKey::Delegate {
scoped_refptr<SSLPrivateKey> WrapCAPIPrivateKey(
const X509Certificate* certificate,
- HCRYPTPROV prov,
+ crypto::ScopedHCRYPTPROV prov,
DWORD key_spec) {
return base::MakeRefCounted<ThreadedSSLPrivateKey>(
- std::make_unique<SSLPlatformKeyCAPI>(prov, key_spec),
+ std::make_unique<SSLPlatformKeyCAPI>(std::move(prov), key_spec),
GetSSLPlatformKeyTaskRunner());
}
@@ -394,7 +429,8 @@ scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
if (key_spec == CERT_NCRYPT_KEY_SPEC) {
return WrapCNGPrivateKey(certificate, prov_or_key);
} else {
- return WrapCAPIPrivateKey(certificate, prov_or_key, key_spec);
+ return WrapCAPIPrivateKey(certificate,
+ crypto::ScopedHCRYPTPROV(prov_or_key), key_spec);
}
}
diff --git a/chromium/net/ssl/ssl_platform_key_win.h b/chromium/net/ssl/ssl_platform_key_win.h
index 70e70613bee..299ac853535 100644
--- a/chromium/net/ssl/ssl_platform_key_win.h
+++ b/chromium/net/ssl/ssl_platform_key_win.h
@@ -12,6 +12,7 @@
#include "base/memory/ref_counted.h"
#include "base/win/wincrypt_shim.h"
+#include "crypto/scoped_capi_types.h"
#include "net/base/net_export.h"
namespace net {
@@ -26,10 +27,10 @@ scoped_refptr<SSLPrivateKey> FetchClientCertPrivateKey(
PCCERT_CONTEXT cert_context);
// Returns an SSLPrivateKey backed by |prov| and |key_spec|, which must
-// correspond to |certificate|'s public key. Takes ownership of |prov|.
+// correspond to |certificate|'s public key.
NET_EXPORT_PRIVATE scoped_refptr<SSLPrivateKey> WrapCAPIPrivateKey(
const X509Certificate* certificate,
- HCRYPTPROV prov,
+ crypto::ScopedHCRYPTPROV prov,
DWORD key_spec);
// Returns an SSLPrivateKey backed by |key|, which must correspond to
diff --git a/chromium/net/ssl/ssl_platform_key_win_unittest.cc b/chromium/net/ssl/ssl_platform_key_win_unittest.cc
index 083bb905e54..bd943cfe743 100644
--- a/chromium/net/ssl/ssl_platform_key_win_unittest.cc
+++ b/chromium/net/ssl/ssl_platform_key_win_unittest.cc
@@ -289,7 +289,8 @@ TEST(SSLPlatformKeyCAPITest, KeyMatches) {
// Import the key into CAPI. Use CRYPT_VERIFYCONTEXT for an ephemeral key.
crypto::ScopedHCRYPTPROV prov;
ASSERT_NE(FALSE,
- CryptAcquireContext(prov.receive(), nullptr, nullptr, PROV_RSA_AES,
+ CryptAcquireContext(crypto::ScopedHCRYPTPROV::Receiver(prov).get(),
+ nullptr, nullptr, PROV_RSA_AES,
CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
<< GetLastError();
@@ -297,15 +298,16 @@ TEST(SSLPlatformKeyCAPITest, KeyMatches) {
ASSERT_TRUE(PKCS8ToBLOBForCAPI(pkcs8, &blob));
crypto::ScopedHCRYPTKEY hcryptkey;
- ASSERT_NE(FALSE, CryptImportKey(prov.get(), blob.data(), blob.size(),
- 0 /* hPubKey */, 0 /* dwFlags */,
- hcryptkey.receive()))
+ ASSERT_NE(FALSE,
+ CryptImportKey(prov.get(), blob.data(), blob.size(),
+ 0 /* hPubKey */, 0 /* dwFlags */,
+ crypto::ScopedHCRYPTKEY::Receiver(hcryptkey).get()))
<< GetLastError();
// Release |hcryptkey| so it does not outlive |prov|.
hcryptkey.reset();
scoped_refptr<SSLPrivateKey> key =
- WrapCAPIPrivateKey(cert.get(), prov.release(), AT_SIGNATURE);
+ WrapCAPIPrivateKey(cert.get(), std::move(prov), AT_SIGNATURE);
ASSERT_TRUE(key);
std::vector<uint16_t> expected = {
diff --git a/chromium/net/test/android/javatests/src/org/chromium/net/test/OWNERS b/chromium/net/test/android/javatests/src/org/chromium/net/test/OWNERS
index 89442abe190..8f094e0099e 100644
--- a/chromium/net/test/android/javatests/src/org/chromium/net/test/OWNERS
+++ b/chromium/net/test/android/javatests/src/org/chromium/net/test/OWNERS
@@ -1,2 +1,2 @@
per-file *.aidl=set noparent
-per-file *.aidl=file://ipc/SECURITY_OWNERS \ No newline at end of file
+per-file *.aidl=file://ipc/SECURITY_OWNERS
diff --git a/chromium/net/test/cert_test_util.cc b/chromium/net/test/cert_test_util.cc
index 415d685b414..911433155bc 100644
--- a/chromium/net/test/cert_test_util.cc
+++ b/chromium/net/test/cert_test_util.cc
@@ -14,17 +14,15 @@
namespace net {
-CertificateList CreateCertificateListFromFile(
- const base::FilePath& certs_dir,
- const std::string& cert_file,
- int format) {
+CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir,
+ base::StringPiece cert_file,
+ int format) {
base::FilePath cert_path = certs_dir.AppendASCII(cert_file);
std::string cert_data;
if (!base::ReadFileToString(cert_path, &cert_data))
return CertificateList();
- return X509Certificate::CreateCertificateListFromBytes(cert_data.data(),
- cert_data.size(),
- format);
+ return X509Certificate::CreateCertificateListFromBytes(
+ base::as_bytes(base::make_span(cert_data)), format);
}
::testing::AssertionResult LoadCertificateFiles(
@@ -46,7 +44,7 @@ CertificateList CreateCertificateListFromFile(
scoped_refptr<X509Certificate> CreateCertificateChainFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file,
+ base::StringPiece cert_file,
int format) {
CertificateList certs = CreateCertificateListFromFile(
certs_dir, cert_file, format);
@@ -64,7 +62,7 @@ scoped_refptr<X509Certificate> CreateCertificateChainFromFile(
scoped_refptr<X509Certificate> ImportCertFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file) {
+ base::StringPiece cert_file) {
base::ScopedAllowBlockingForTesting allow_blocking;
base::FilePath cert_path = certs_dir.AppendASCII(cert_file);
std::string cert_data;
@@ -73,7 +71,8 @@ scoped_refptr<X509Certificate> ImportCertFromFile(
CertificateList certs_in_file =
X509Certificate::CreateCertificateListFromBytes(
- cert_data.data(), cert_data.size(), X509Certificate::FORMAT_AUTO);
+ base::as_bytes(base::make_span(cert_data)),
+ X509Certificate::FORMAT_AUTO);
if (certs_in_file.empty())
return nullptr;
return certs_in_file[0];
diff --git a/chromium/net/test/cert_test_util.h b/chromium/net/test/cert_test_util.h
index 9085fded217..aebaaf14615 100644
--- a/chromium/net/test/cert_test_util.h
+++ b/chromium/net/test/cert_test_util.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/memory/ref_counted.h"
+#include "base/strings/string_piece.h"
#include "net/cert/x509_cert_types.h"
#include "net/cert/x509_certificate.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -35,7 +36,7 @@ class EVRootCAMetadata;
// must contain a PKCS#8 PrivateKeyInfo in DER encoding. Returns true on success
// and false on failure.
bool ImportSensitiveKeyFromFile(const base::FilePath& dir,
- const std::string& key_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot);
bool ImportClientCertToSlot(CERTCertificate* cert, PK11SlotInfo* slot);
@@ -46,30 +47,30 @@ ScopedCERTCertificate ImportClientCertToSlot(
scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
const base::FilePath& dir,
- const std::string& cert_filename,
- const std::string& key_filename,
+ base::StringPiece cert_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot,
ScopedCERTCertificate* nss_cert);
scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
const base::FilePath& dir,
- const std::string& cert_filename,
- const std::string& key_filename,
+ base::StringPiece cert_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot);
ScopedCERTCertificate ImportCERTCertificateFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file);
+ base::StringPiece cert_file);
ScopedCERTCertificateList CreateCERTCertificateListFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file,
+ base::StringPiece cert_file,
int format);
#endif
// Imports all of the certificates in |cert_file|, a file in |certs_dir|, into a
// CertificateList.
CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir,
- const std::string& cert_file,
+ base::StringPiece cert_file,
int format);
// Imports all the certificates given a list of filenames, and assigns the
@@ -85,15 +86,16 @@ CertificateList CreateCertificateListFromFile(const base::FilePath& certs_dir,
// intermediate certificates.
scoped_refptr<X509Certificate> CreateCertificateChainFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file,
+ base::StringPiece cert_file,
int format);
// Imports a single certificate from |cert_file|.
// |certs_dir| represents the test certificates directory. |cert_file| is the
// name of the certificate file. If cert_file contains multiple certificates,
// the first certificate found will be returned.
-scoped_refptr<X509Certificate> ImportCertFromFile(const base::FilePath& certs_dir,
- const std::string& cert_file);
+scoped_refptr<X509Certificate> ImportCertFromFile(
+ const base::FilePath& certs_dir,
+ base::StringPiece cert_file);
// ScopedTestEVPolicy causes certificates marked with |policy|, issued from a
// root with the given fingerprint, to be treated as EV. |policy| is expressed
diff --git a/chromium/net/test/cert_test_util_nss.cc b/chromium/net/test/cert_test_util_nss.cc
index 096285d0963..466363ab8b0 100644
--- a/chromium/net/test/cert_test_util_nss.cc
+++ b/chromium/net/test/cert_test_util_nss.cc
@@ -28,7 +28,7 @@
namespace net {
bool ImportSensitiveKeyFromFile(const base::FilePath& dir,
- const std::string& key_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot) {
base::FilePath key_path = dir.AppendASCII(key_filename);
std::string key_pkcs8;
@@ -143,8 +143,8 @@ ScopedCERTCertificate ImportClientCertToSlot(
scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
const base::FilePath& dir,
- const std::string& cert_filename,
- const std::string& key_filename,
+ base::StringPiece cert_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot,
ScopedCERTCertificate* nss_cert) {
if (!ImportSensitiveKeyFromFile(dir, key_filename, slot)) {
@@ -171,8 +171,8 @@ scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
const base::FilePath& dir,
- const std::string& cert_filename,
- const std::string& key_filename,
+ base::StringPiece cert_filename,
+ base::StringPiece key_filename,
PK11SlotInfo* slot) {
ScopedCERTCertificate nss_cert;
return ImportClientCertAndKeyFromFile(dir, cert_filename, key_filename, slot,
@@ -181,7 +181,7 @@ scoped_refptr<X509Certificate> ImportClientCertAndKeyFromFile(
ScopedCERTCertificate ImportCERTCertificateFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file) {
+ base::StringPiece cert_file) {
scoped_refptr<X509Certificate> cert =
ImportCertFromFile(certs_dir, cert_file);
if (!cert)
@@ -191,7 +191,7 @@ ScopedCERTCertificate ImportCERTCertificateFromFile(
ScopedCERTCertificateList CreateCERTCertificateListFromFile(
const base::FilePath& certs_dir,
- const std::string& cert_file,
+ base::StringPiece cert_file,
int format) {
CertificateList certs =
CreateCertificateListFromFile(certs_dir, cert_file, format);
diff --git a/chromium/net/test/embedded_test_server/controllable_http_response.h b/chromium/net/test/embedded_test_server/controllable_http_response.h
index 41fa34a8687..c04da5cf113 100644
--- a/chromium/net/test/embedded_test_server/controllable_http_response.h
+++ b/chromium/net/test/embedded_test_server/controllable_http_response.h
@@ -30,7 +30,7 @@ namespace test_server {
// multiple ControllableHttpResponses for the same path, they're used in the
// order they were created.
//
-// If |relative_url_is_prefix| is true, |relative_url| is only compared agaisnt
+// If |relative_url_is_prefix| is true, |relative_url| is only compared against
// the start of the URL being requested, which allows matching against (possibly
// variable) query strings, for instance.
class ControllableHttpResponse {
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.cc b/chromium/net/test/embedded_test_server/embedded_test_server.cc
index 870af991aee..cd552c91ac7 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.cc
@@ -47,9 +47,11 @@
#include "net/test/embedded_test_server/request_handler_util.h"
#include "net/test/revocation_builder.h"
#include "net/test/test_data_directory.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "third_party/boringssl/src/include/openssl/bytestring.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
#include "third_party/boringssl/src/include/openssl/rsa.h"
+#include "url/origin.h"
namespace net {
namespace test_server {
@@ -697,6 +699,13 @@ GURL EmbeddedTestServer::GetURL(
return local_url.ReplaceComponents(replace_host);
}
+url::Origin EmbeddedTestServer::GetOrigin(
+ const absl::optional<std::string>& hostname) const {
+ if (hostname)
+ return url::Origin::Create(GetURL(*hostname, "/"));
+ return url::Origin::Create(base_url_);
+}
+
bool EmbeddedTestServer::GetAddressList(AddressList* address_list) const {
*address_list = AddressList(local_endpoint_);
return true;
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server.h b/chromium/net/test/embedded_test_server/embedded_test_server.h
index 396f3b1f02a..870f675e8d8 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server.h
@@ -29,7 +29,9 @@
#include "net/socket/stream_socket.h"
#include "net/socket/tcp_server_socket.h"
#include "net/ssl/ssl_server_config.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace net {
@@ -382,6 +384,12 @@ class EmbeddedTestServer {
GURL GetURL(const std::string& hostname,
const std::string& relative_url) const;
+ // Convenience function equivalent to calling url::Origin::Create(base_url()).
+ // Will use the GetURL() variant that takes a hostname as the base URL, if
+ // `hostname` is non-null.
+ url::Origin GetOrigin(
+ const absl::optional<std::string>& hostname = absl::nullopt) const;
+
// Returns the address list needed to connect to the server.
bool GetAddressList(AddressList* address_list) const WARN_UNUSED_RESULT;
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server_connection_listener.h b/chromium/net/test/embedded_test_server/embedded_test_server_connection_listener.h
index 89422d02a83..d07dca7e420 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server_connection_listener.h
+++ b/chromium/net/test/embedded_test_server/embedded_test_server_connection_listener.h
@@ -26,8 +26,9 @@ class EmbeddedTestServerConnectionListener {
// Notified when the EmbeddedTestServer has completed a request and response
// successfully on |socket|. The listener can take |socket| to manually handle
- // further traffic on it (for example, if doing a proxy tunnel), otherwise
- // |socket| is destroyed.
+ // further traffic on it (for example, if doing a proxy tunnel). Not called if
+ // the socket has already been closed by the remote side, since it can't be
+ // used to convey data if that happens.
virtual void OnResponseCompletedSuccessfully(
std::unique_ptr<StreamSocket> socket) {}
diff --git a/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc b/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
index 5be3eb0d5d4..e90cef342a4 100644
--- a/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
+++ b/chromium/net/test/embedded_test_server/embedded_test_server_unittest.cc
@@ -121,6 +121,7 @@ class EmbeddedTestServerTest
void SetUp() override {
server_ = std::make_unique<EmbeddedTestServer>(GetParam());
+ server_->AddDefaultHandlers();
server_->SetConnectionListener(&connection_listener_);
}
@@ -325,13 +326,24 @@ TEST_P(EmbeddedTestServerTest, ConnectionListenerRead) {
EXPECT_TRUE(connection_listener_.DidReadFromSocket());
}
-TEST_P(EmbeddedTestServerTest, ConnectionListenerComplete) {
+// TODO(http://crbug.com/1166868): Flaky on ChromeOS.
+#if defined(OS_CHROMEOS)
+#define MAYBE_ConnectionListenerComplete DISABLED_ConnectionListenerComplete
+#else
+#define MAYBE_ConnectionListenerComplete ConnectionListenerComplete
+#endif
+TEST_P(EmbeddedTestServerTest, MAYBE_ConnectionListenerComplete) {
ASSERT_TRUE(server_->Start());
TestDelegate delegate;
- std::unique_ptr<URLRequest> request(
- context_.CreateRequest(server_->GetURL("/non-existent"), DEFAULT_PRIORITY,
- &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
+ // Need to send a Keep-Alive response header since the EmbeddedTestServer only
+ // invokes OnResponseCompletedSuccessfully() if the socket is still open, and
+ // the network stack will close the socket if not reuable, resulting in
+ // potentially racilly closing the socket before
+ // OnResponseCompletedSuccessfully() is invoked.
+ std::unique_ptr<URLRequest> request(context_.CreateRequest(
+ server_->GetURL("/set-header?Connection: Keep-Alive"), DEFAULT_PRIORITY,
+ &delegate, TRAFFIC_ANNOTATION_FOR_TESTS));
request->Start();
delegate.RunUntilComplete();
diff --git a/chromium/net/test/gtest_util.h b/chromium/net/test/gtest_util.h
index af852923dda..ea1ef8633f3 100644
--- a/chromium/net/test/gtest_util.h
+++ b/chromium/net/test/gtest_util.h
@@ -48,6 +48,9 @@ class StringPieceHasSubstrMatcher {
public:
explicit StringPieceHasSubstrMatcher(const std::string& substring)
: substring_(substring) {}
+ StringPieceHasSubstrMatcher(const StringPieceHasSubstrMatcher&) = default;
+ StringPieceHasSubstrMatcher& operator=(const StringPieceHasSubstrMatcher&) =
+ default;
bool MatchAndExplain(base::StringPiece s,
::testing::MatchResultListener* listener) const {
@@ -64,9 +67,7 @@ class StringPieceHasSubstrMatcher {
}
private:
- const std::string substring_;
-
- DISALLOW_ASSIGN(StringPieceHasSubstrMatcher);
+ std::string substring_;
};
// Internal implementation for the EXPECT_DFATAL and ASSERT_DFATAL
diff --git a/chromium/net/test/net_test_suite.cc b/chromium/net/test/net_test_suite.cc
index e5ef64c36b4..e702a2662cf 100644
--- a/chromium/net/test/net_test_suite.cc
+++ b/chromium/net/test/net_test_suite.cc
@@ -7,10 +7,32 @@
#include "base/check_op.h"
#include "net/base/network_change_notifier.h"
#include "net/http/http_stream_factory.h"
+#include "net/quic/platform/impl/quic_test_flags_utils.h"
#include "net/spdy/spdy_session.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
+class NetUnitTestEventListener : public testing::EmptyTestEventListener {
+ public:
+ NetUnitTestEventListener() = default;
+ NetUnitTestEventListener(const NetUnitTestEventListener&) = delete;
+ NetUnitTestEventListener& operator=(const NetUnitTestEventListener&) = delete;
+ ~NetUnitTestEventListener() override = default;
+
+ void OnTestStart(const testing::TestInfo& test_info) override {
+ QuicFlagChecker checker;
+ DCHECK(!quic_flags_saver_);
+ quic_flags_saver_ = std::make_unique<QuicFlagSaverImpl>();
+ }
+
+ void OnTestEnd(const testing::TestInfo& test_info) override {
+ quic_flags_saver_.reset();
+ }
+
+ private:
+ std::unique_ptr<QuicFlagSaverImpl> quic_flags_saver_;
+};
+
NetTestSuite* g_current_net_test_suite = nullptr;
} // namespace
@@ -28,6 +50,10 @@ NetTestSuite::~NetTestSuite() {
void NetTestSuite::Initialize() {
TestSuite::Initialize();
InitializeTestThread();
+
+ testing::TestEventListeners& listeners =
+ testing::UnitTest::GetInstance()->listeners();
+ listeners.Append(new NetUnitTestEventListener());
}
void NetTestSuite::Shutdown() {
diff --git a/chromium/net/test/quic_simple_test_server.cc b/chromium/net/test/quic_simple_test_server.cc
index e0183b611da..5c855e3176e 100644
--- a/chromium/net/test/quic_simple_test_server.cc
+++ b/chromium/net/test/quic_simple_test_server.cc
@@ -60,14 +60,18 @@ int g_quic_server_port = 0;
namespace net {
-const std::string QuicSimpleTestServer::GetDomain() {
+std::string const QuicSimpleTestServer::GetDomain() {
return kTestServerDomain;
}
-const std::string QuicSimpleTestServer::GetHost() {
+std::string const QuicSimpleTestServer::GetHost() {
return kTestServerHost;
}
+HostPortPair const QuicSimpleTestServer::GetHostPort() {
+ return HostPortPair(kTestServerHost, GetPort());
+}
+
GURL QuicSimpleTestServer::GetFileURL(const std::string& file_path) {
return GURL("https://test.example.com:" + base::NumberToString(GetPort()))
.Resolve(file_path);
@@ -78,39 +82,39 @@ GURL QuicSimpleTestServer::GetHelloURL() {
return GURL("https://test.example.com").Resolve(kHelloPath);
}
-const std::string QuicSimpleTestServer::GetStatusHeaderName() {
+std::string const QuicSimpleTestServer::GetStatusHeaderName() {
return kStatusHeader;
}
// Hello Url returns response with HTTP/2 headers and trailers.
-const std::string QuicSimpleTestServer::GetHelloPath() {
+std::string const QuicSimpleTestServer::GetHelloPath() {
return kHelloPath;
}
-const std::string QuicSimpleTestServer::GetHelloBodyValue() {
+std::string const QuicSimpleTestServer::GetHelloBodyValue() {
return kHelloBodyValue;
}
-const std::string QuicSimpleTestServer::GetHelloStatus() {
+std::string const QuicSimpleTestServer::GetHelloStatus() {
return kHelloStatus;
}
-const std::string QuicSimpleTestServer::GetHelloHeaderName() {
+std::string const QuicSimpleTestServer::GetHelloHeaderName() {
return kHelloHeaderName;
}
-const std::string QuicSimpleTestServer::GetHelloHeaderValue() {
+std::string const QuicSimpleTestServer::GetHelloHeaderValue() {
return kHelloHeaderValue;
}
-const std::string QuicSimpleTestServer::GetCombinedHeaderName() {
+std::string const QuicSimpleTestServer::GetCombinedHeaderName() {
return kCombinedHeaderName;
}
-const std::string QuicSimpleTestServer::GetHelloTrailerName() {
+std::string const QuicSimpleTestServer::GetHelloTrailerName() {
return kHelloTrailerName;
}
-const std::string QuicSimpleTestServer::GetHelloTrailerValue() {
+std::string const QuicSimpleTestServer::GetHelloTrailerValue() {
return kHelloTrailerValue;
}
@@ -120,19 +124,19 @@ GURL QuicSimpleTestServer::GetSimpleURL() {
return GURL("https://test.example.com").Resolve(kSimplePath);
}
-const std::string QuicSimpleTestServer::GetSimpleBodyValue() {
+std::string const QuicSimpleTestServer::GetSimpleBodyValue() {
return kSimpleBodyValue;
}
-const std::string QuicSimpleTestServer::GetSimpleStatus() {
+std::string const QuicSimpleTestServer::GetSimpleStatus() {
return kSimpleStatus;
}
-const std::string QuicSimpleTestServer::GetSimpleHeaderName() {
+std::string const QuicSimpleTestServer::GetSimpleHeaderName() {
return kSimpleHeaderName;
}
-const std::string QuicSimpleTestServer::GetSimpleHeaderValue() {
+std::string const QuicSimpleTestServer::GetSimpleHeaderValue() {
return kSimpleHeaderValue;
}
diff --git a/chromium/net/test/quic_simple_test_server.h b/chromium/net/test/quic_simple_test_server.h
index 0c32a9ba868..90b4da62669 100644
--- a/chromium/net/test/quic_simple_test_server.h
+++ b/chromium/net/test/quic_simple_test_server.h
@@ -8,6 +8,7 @@
#include <string>
#include <vector>
+#include "net/base/host_port_pair.h"
#include "net/third_party/quiche/src/spdy/core/spdy_header_block.h"
#include "url/gurl.h"
@@ -30,39 +31,39 @@ class QuicSimpleTestServer {
const std::vector<spdy::Http2HeaderBlock>& early_hints);
// Returns example.com
- static const std::string GetDomain();
+ static std::string const GetDomain();
// Returns test.example.com
- static const std::string GetHost();
+ static std::string const GetHost();
// Returns port number of the server.
static int GetPort();
// Returns test.example.com:port
- static const std::string GetHostPort();
+ static HostPortPair const GetHostPort();
// Returns URL with host, port and file path, for example
// https://test.example.com:12345/{file_path}
static GURL GetFileURL(const std::string& file_path);
- static const std::string GetStatusHeaderName();
+ static std::string const GetStatusHeaderName();
// Server returns response with HTTP/2 headers and trailers. Does not include
// |port| as it is resolved differently: https://test.example.com/hello.txt
static GURL GetHelloURL();
- static const std::string GetHelloPath();
- static const std::string GetHelloBodyValue();
- static const std::string GetHelloStatus();
- static const std::string GetHelloHeaderName();
- static const std::string GetHelloHeaderValue();
- static const std::string GetCombinedHeaderName();
- static const std::string GetHelloTrailerName();
- static const std::string GetHelloTrailerValue();
+ static std::string const GetHelloPath();
+ static std::string const GetHelloBodyValue();
+ static std::string const GetHelloStatus();
+ static std::string const GetHelloHeaderName();
+ static std::string const GetHelloHeaderValue();
+ static std::string const GetCombinedHeaderName();
+ static std::string const GetHelloTrailerName();
+ static std::string const GetHelloTrailerValue();
// Server returns response without HTTP/2 trailers.
// https://test.example.com/simple.txt
static GURL GetSimpleURL();
- static const std::string GetSimpleBodyValue();
- static const std::string GetSimpleStatus();
- static const std::string GetSimpleHeaderName();
- static const std::string GetSimpleHeaderValue();
+ static std::string const GetSimpleBodyValue();
+ static std::string const GetSimpleStatus();
+ static std::string const GetSimpleHeaderName();
+ static std::string const GetSimpleHeaderValue();
};
} // namespace net
diff --git a/chromium/net/test/spawned_test_server/base_test_server.cc b/chromium/net/test/spawned_test_server/base_test_server.cc
index cfcf0dc08d6..9caaf0ad501 100644
--- a/chromium/net/test/spawned_test_server/base_test_server.cc
+++ b/chromium/net/test/spawned_test_server/base_test_server.cc
@@ -336,7 +336,7 @@ scoped_refptr<X509Certificate> BaseTestServer::GetCertificate() const {
CertificateList certs_in_file =
X509Certificate::CreateCertificateListFromBytes(
- cert_data.data(), cert_data.size(),
+ base::as_bytes(base::make_span(cert_data)),
X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
if (certs_in_file.empty())
return nullptr;
diff --git a/chromium/net/test/spawned_test_server/local_test_server.cc b/chromium/net/test/spawned_test_server/local_test_server.cc
index a389fe582d7..8cbb9dac9ee 100644
--- a/chromium/net/test/spawned_test_server/local_test_server.cc
+++ b/chromium/net/test/spawned_test_server/local_test_server.cc
@@ -205,7 +205,7 @@ bool LocalTestServer::AddCommandLineArguments(
// Add arguments from a list.
if (value.is_list()) {
const base::ListValue* list = nullptr;
- if (!value.GetAsList(&list) || !list || list->empty())
+ if (!value.GetAsList(&list) || !list || list->GetList().empty())
return false;
for (const auto& entry : list->GetList()) {
if (!AppendArgumentFromJSONValue(key, entry, command_line))
diff --git a/chromium/net/test/spawned_test_server/local_test_server.h b/chromium/net/test/spawned_test_server/local_test_server.h
index a9dc1afc476..74622a83bd8 100644
--- a/chromium/net/test/spawned_test_server/local_test_server.h
+++ b/chromium/net/test/spawned_test_server/local_test_server.h
@@ -5,7 +5,6 @@
#ifndef NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_
#define NET_TEST_SPAWNED_TEST_SERVER_LOCAL_TEST_SERVER_H_
-#include <string>
#include <vector>
#include "base/files/file_util.h"
diff --git a/chromium/net/test/spawned_test_server/remote_test_server.cc b/chromium/net/test/spawned_test_server/remote_test_server.cc
index 61ff349540a..b10f9e7aeeb 100644
--- a/chromium/net/test/spawned_test_server/remote_test_server.cc
+++ b/chromium/net/test/spawned_test_server/remote_test_server.cc
@@ -116,7 +116,7 @@ bool RemoteTestServer::StartInBackground() {
if (!GenerateArguments(&arguments_dict))
return false;
- arguments_dict.Set("on-remote-server", std::make_unique<base::Value>());
+ arguments_dict.SetKey("on-remote-server", base::Value());
// Append the 'server-type' argument which is used by spawner server to
// pass right server type to Python test server.
diff --git a/chromium/net/test/test_data_directory.cc b/chromium/net/test/test_data_directory.cc
index b6a79541b34..80540f3c1ae 100644
--- a/chromium/net/test/test_data_directory.cc
+++ b/chromium/net/test/test_data_directory.cc
@@ -12,9 +12,12 @@ namespace net {
namespace {
-// Net data directory, relative to source root.
+// Net directory, relative to source root.
+const base::FilePath::CharType kNetRelativePath[] = FILE_PATH_LITERAL("net");
+
+// Net data directory, relative to net directory.
const base::FilePath::CharType kNetDataRelativePath[] =
- FILE_PATH_LITERAL("net/data");
+ FILE_PATH_LITERAL("data");
// Test certificates directory, relative to kNetDataRelativePath.
const base::FilePath::CharType kCertificateDataSubPath[] =
@@ -22,14 +25,18 @@ const base::FilePath::CharType kCertificateDataSubPath[] =
} // namespace
-base::FilePath GetTestNetDataDirectory() {
+base::FilePath GetTestNetDirectory() {
base::FilePath src_root;
{
base::ScopedAllowBlockingForTesting allow_blocking;
base::PathService::Get(base::DIR_SOURCE_ROOT, &src_root);
}
- return src_root.Append(kNetDataRelativePath);
+ return src_root.Append(kNetRelativePath);
+}
+
+base::FilePath GetTestNetDataDirectory() {
+ return GetTestNetDirectory().Append(kNetDataRelativePath);
}
base::FilePath GetTestCertsDirectory() {
diff --git a/chromium/net/test/test_data_directory.h b/chromium/net/test/test_data_directory.h
index f7ab7ee9ccd..7d5711cbf15 100644
--- a/chromium/net/test/test_data_directory.h
+++ b/chromium/net/test/test_data_directory.h
@@ -9,6 +9,10 @@
namespace net {
+// Returns the FilePath object representing the absolute path of //net in the
+// source tree.
+base::FilePath GetTestNetDirectory();
+
// Returns the FilePath object representing the absolute path in the source
// tree that contains net data files.
base::FilePath GetTestNetDataDirectory();
diff --git a/chromium/net/test/url_request/url_request_failed_job.cc b/chromium/net/test/url_request/url_request_failed_job.cc
index 09bc1532fdd..d9f77cc1a74 100644
--- a/chromium/net/test/url_request/url_request_failed_job.cc
+++ b/chromium/net/test/url_request/url_request_failed_job.cc
@@ -6,9 +6,9 @@
#include "base/bind.h"
#include "base/check_op.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/net_errors.h"
diff --git a/chromium/net/third_party/nss/README.chromium b/chromium/net/third_party/nss/README.chromium
index 87108826e11..65586d86f03 100644
--- a/chromium/net/third_party/nss/README.chromium
+++ b/chromium/net/third_party/nss/README.chromium
@@ -4,14 +4,14 @@ Version: 3.23 RTM
Security Critical: Yes
License: MPL 2
License File: LICENSE
-CPEPrefix: cpe:/a:mozilla:nss:3.23
-This directory includes a file derived from NSS's libssl, from the hg repo at:
+This directory includes a single function that was historically derived from
+NSS's libssl, from the hg repo at hg tag NSS_3_23_RTM:
https://hg.mozilla.org/projects/nss
-The snapshot was updated to the hg tag: NSS_3_23_RTM
+The CPEPrefix field is intentionally omitted because this code no longer shares
+fate with NSS. This is derived code, not than a vendored dependency.
Local Modifications:
-Files are forked from Mozilla's because of the heavy adaptations necessary.
-Differences are using Chromium libraries instead of Mozilla's, matching the
-Chromium style, and returning the certificate chain built.
+The function has been rewritten using Chromium's libraries and Chromium's
+certificate verifier.
diff --git a/chromium/net/third_party/quiche/BUILD.gn b/chromium/net/third_party/quiche/BUILD.gn
index 41d2dfff1d9..eb544f93d1c 100644
--- a/chromium/net/third_party/quiche/BUILD.gn
+++ b/chromium/net/third_party/quiche/BUILD.gn
@@ -31,17 +31,22 @@ source_set("quiche") {
sources = [
"overrides/quiche_platform_impl/quic_mutex_impl.cc",
"overrides/quiche_platform_impl/quic_mutex_impl.h",
+ "overrides/quiche_platform_impl/quiche_bug_tracker_impl.h",
"overrides/quiche_platform_impl/quiche_export_impl.h",
"overrides/quiche_platform_impl/quiche_logging_impl.h",
+ "overrides/quiche_platform_impl/quiche_thread_local_impl.h",
"overrides/quiche_platform_impl/quiche_time_utils_impl.cc",
"overrides/quiche_platform_impl/quiche_time_utils_impl.h",
+ "src/common/platform/api/quiche_bug_tracker.h",
"src/common/platform/api/quiche_export.h",
"src/common/platform/api/quiche_flag_utils.h",
"src/common/platform/api/quiche_flags.h",
"src/common/platform/api/quiche_logging.h",
"src/common/platform/api/quiche_prefetch.h",
+ "src/common/platform/api/quiche_thread_local.h",
"src/common/platform/api/quiche_time_utils.h",
"src/common/platform/default/quiche_platform_impl/quiche_prefetch_impl.h",
+ "src/common/print_elements.h",
"src/common/quiche_circular_deque.h",
"src/common/quiche_data_reader.cc",
"src/common/quiche_data_reader.h",
@@ -140,13 +145,10 @@ source_set("quiche") {
"src/http2/http2_structures.cc",
"src/http2/http2_structures.h",
"src/http2/platform/api/http2_bug_tracker.h",
- "src/http2/platform/api/http2_containers.h",
- "src/http2/platform/api/http2_estimate_memory_usage.h",
"src/http2/platform/api/http2_flag_utils.h",
"src/http2/platform/api/http2_flags.h",
"src/http2/platform/api/http2_logging.h",
"src/http2/platform/api/http2_macros.h",
- "src/http2/platform/api/http2_string_utils.h",
"src/quic/core/congestion_control/bandwidth_sampler.cc",
"src/quic/core/congestion_control/bandwidth_sampler.h",
"src/quic/core/congestion_control/bbr2_drain.cc",
@@ -433,6 +435,8 @@ source_set("quiche") {
"src/quic/core/quic_config.h",
"src/quic/core/quic_connection.cc",
"src/quic/core/quic_connection.h",
+ "src/quic/core/quic_connection_context.cc",
+ "src/quic/core/quic_connection_context.h",
"src/quic/core/quic_connection_id.cc",
"src/quic/core/quic_connection_id.h",
"src/quic/core/quic_connection_id_manager.cc",
@@ -463,6 +467,7 @@ source_set("quiche") {
"src/quic/core/quic_datagram_queue.h",
"src/quic/core/quic_error_codes.cc",
"src/quic/core/quic_error_codes.h",
+ "src/quic/core/quic_flags_list.h",
"src/quic/core/quic_flow_controller.cc",
"src/quic/core/quic_flow_controller.h",
"src/quic/core/quic_framer.cc",
@@ -552,11 +557,8 @@ source_set("quiche") {
"src/quic/platform/api/quic_client_stats.h",
"src/quic/platform/api/quic_containers.h",
"src/quic/platform/api/quic_error_code_wrappers.h",
- "src/quic/platform/api/quic_estimate_memory_usage.h",
"src/quic/platform/api/quic_export.h",
"src/quic/platform/api/quic_exported_stats.h",
- "src/quic/platform/api/quic_file_utils.cc",
- "src/quic/platform/api/quic_file_utils.h",
"src/quic/platform/api/quic_flag_utils.h",
"src/quic/platform/api/quic_flags.h",
"src/quic/platform/api/quic_hostname_utils.cc",
@@ -566,7 +568,6 @@ source_set("quiche") {
"src/quic/platform/api/quic_ip_address.h",
"src/quic/platform/api/quic_ip_address_family.h",
"src/quic/platform/api/quic_logging.h",
- "src/quic/platform/api/quic_map_util.h",
"src/quic/platform/api/quic_mem_slice.h",
"src/quic/platform/api/quic_mem_slice_span.h",
"src/quic/platform/api/quic_mem_slice_storage.h",
@@ -633,8 +634,6 @@ source_set("quiche") {
"src/spdy/core/spdy_simple_arena.cc",
"src/spdy/core/spdy_simple_arena.h",
"src/spdy/core/zero_copy_output_buffer.h",
- "src/spdy/platform/api/spdy_containers.h",
- "src/spdy/platform/api/spdy_estimate_memory_usage.h",
]
deps = [ "//net:net_deps" ]
@@ -859,6 +858,7 @@ source_set("quiche_test_tools_core") {
testonly = true
sources = [
"src/common/platform/api/quiche_test.h",
+ "src/common/platform/api/quiche_test_helpers.h",
"src/common/test_tools/quiche_test_utils.cc",
"src/common/test_tools/quiche_test_utils.h",
]
@@ -869,6 +869,17 @@ source_set("quiche_test_tools_core") {
]
}
+source_set("quiche_file_utils") {
+ sources = [
+ "src/common/platform/api/quiche_file_utils.cc",
+ "src/common/platform/api/quiche_file_utils.h",
+ "src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc",
+ "src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h",
+ ]
+ configs += [ ":quiche_config" ]
+ deps = [ "//base" ]
+}
+
source_set("quic_test_tools_core") {
testonly = true
sources = [
@@ -1005,6 +1016,7 @@ source_set("quic_test_tools_core") {
]
deps = [
+ ":quiche_file_utils",
"//base",
"//crypto:test_support",
"//net",
@@ -1100,6 +1112,7 @@ source_set("simple_quic_tools_core") {
"src/quic/tools/simple_ticket_crypter.h",
]
deps = [
+ ":quiche_file_utils",
"//base",
"//base/third_party/dynamic_annotations",
"//net",
@@ -1136,6 +1149,7 @@ if (!is_ios) {
executable("quic_packet_printer") {
sources = [ "src/quic/tools/quic_packet_printer_bin.cc" ]
deps = [
+ ":quiche_file_utils",
"//base",
"//build/win:default_exe_manifest",
"//net",
@@ -1185,6 +1199,8 @@ if (!is_ios) {
source_set("quiche_tests") {
testonly = true
sources = [
+ # TODO(bnc): Include in tests after test data files are added to QUICHE.
+ # "src/common/platform/api/quiche_file_utils_test.cc",
"src/common/platform/api/quiche_time_utils_test.cc",
"src/common/quiche_circular_deque_test.cc",
"src/common/quiche_data_writer_test.cc",
@@ -1312,6 +1328,7 @@ source_set("quiche_tests") {
"src/quic/core/frames/quic_frames_test.cc",
"src/quic/core/http/http_decoder_test.cc",
"src/quic/core/http/http_encoder_test.cc",
+ "src/quic/core/http/http_frames_test.cc",
"src/quic/core/http/quic_client_promised_info_test.cc",
"src/quic/core/http/quic_client_push_promise_index_test.cc",
"src/quic/core/http/quic_header_list_test.cc",
@@ -1351,6 +1368,7 @@ source_set("quiche_tests") {
"src/quic/core/quic_chaos_protector_test.cc",
"src/quic/core/quic_coalesced_packet_test.cc",
"src/quic/core/quic_config_test.cc",
+ "src/quic/core/quic_connection_context_test.cc",
"src/quic/core/quic_connection_id_manager_test.cc",
"src/quic/core/quic_connection_id_test.cc",
"src/quic/core/quic_connection_test.cc",
@@ -1400,9 +1418,9 @@ source_set("quiche_tests") {
"src/quic/core/quic_versions_test.cc",
"src/quic/core/quic_write_blocked_list_test.cc",
"src/quic/core/tls_chlo_extractor_test.cc",
+ "src/quic/core/tls_client_handshaker_test.cc",
"src/quic/core/uber_quic_stream_id_manager_test.cc",
"src/quic/core/uber_received_packet_manager_test.cc",
- "src/quic/platform/api/quic_containers_test.cc",
"src/quic/platform/api/quic_hostname_utils_test.cc",
"src/quic/platform/api/quic_ip_address_test.cc",
"src/quic/platform/api/quic_mem_slice_span_test.cc",
@@ -1455,6 +1473,7 @@ source_set("quiche_tests") {
]
deps = [
+ ":quiche_file_utils",
"//net",
"//net:quic_test_tools",
"//net:quiche_test_tools",
diff --git a/chromium/net/quiche/common/platform/impl/quiche_bug_tracker_impl.h b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_bug_tracker_impl.h
index c5198a19b4c..5ae25a09c77 100644
--- a/chromium/net/quiche/common/platform/impl/quiche_bug_tracker_impl.h
+++ b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_bug_tracker_impl.h
@@ -1,8 +1,8 @@
// Copyright (c) 2016 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
-#define NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
+#ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
+#define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
@@ -17,4 +17,4 @@
#define QUICHE_PEER_BUG_IF_V2_IMPL(bug_id, condition) \
QUIC_LOG_IF(ERROR, condition)
-#endif // NET_QUICHE_COMMON_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
+#endif // NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
diff --git a/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h
index 8ff5e27f8ee..326ed930701 100644
--- a/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h
+++ b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_logging_impl.h
@@ -5,6 +5,8 @@
#ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_
#define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_LOGGING_IMPL_H_
+#include <vector>
+
#include "base/check_op.h"
#include "base/logging.h"
#include "base/notreached.h"
diff --git a/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_thread_local_impl.h b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_thread_local_impl.h
new file mode 100644
index 00000000000..8be2972e5b6
--- /dev/null
+++ b/chromium/net/third_party/quiche/overrides/quiche_platform_impl/quiche_thread_local_impl.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
+#define NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
+
+#include "base/no_destructor.h"
+#include "base/threading/thread_local.h"
+
+#define DEFINE_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, type) \
+ struct QuicheThreadLocalPointer_##name { \
+ static ::base::ThreadLocalPointer<type>* Instance() { \
+ static ::base::NoDestructor<::base::ThreadLocalPointer<type>> instance; \
+ return instance.get(); \
+ } \
+ static type* Get() { return Instance()->Get(); } \
+ static void Set(type* ptr) { Instance()->Set(ptr); } \
+ }
+
+#define GET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name) \
+ QuicheThreadLocalPointer_##name::Get()
+
+#define SET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, value) \
+ QuicheThreadLocalPointer_##name::Set(value)
+
+#endif // NET_THIRD_PARTY_QUICHE_OVERRIDES_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/CONTRIBUTING.md b/chromium/net/third_party/quiche/src/CONTRIBUTING.md
index 07824e04d4f..d8c6e48b7be 100644
--- a/chromium/net/third_party/quiche/src/CONTRIBUTING.md
+++ b/chromium/net/third_party/quiche/src/CONTRIBUTING.md
@@ -20,12 +20,13 @@ again.
The QUICHE repository is currently not set up to accept pull requests directly.
If you would like to make a contribution, please follow these steps:
-1. Sign the Contributor License Agreement (see above).
-2. Create a Gerrit pull request at <https://quiche-review.googlesource.com>.
-3. Email a link to your pull request to <quiche-contribution@google.com>.
-4. An engineer will review your pull request and merge it internally.
+1. Sign the Contributor License Agreement (see above).
+2. Create a Gerrit pull request at <https://quiche-review.googlesource.com>, or
+ a GitHub pull request at <https://github.com/google/quiche/pulls>.
+3. Email a link to your pull request to <quiche-contribution@google.com>.
+4. An engineer will review your pull request and merge it internally.
## Community Guidelines
-This project follows [Google's Open Source Community
-Guidelines](https://opensource.google.com/conduct/).
+This project follows
+[Google's Open Source Community Guidelines](https://opensource.google.com/conduct/).
diff --git a/chromium/net/third_party/quiche/src/README.md b/chromium/net/third_party/quiche/src/README.md
index 0c441923f54..60f24da2b09 100644
--- a/chromium/net/third_party/quiche/src/README.md
+++ b/chromium/net/third_party/quiche/src/README.md
@@ -1,8 +1,28 @@
# QUICHE
-QUICHE (QUIC, Http/2, Etc) is Google's implementation of QUIC and related
-protocols. It powers Chromium as well as Google's QUIC servers and some other
-projects. QUICHE is only supported on little-endian platforms.
+QUICHE stands for QUIC, Http/2, Etc. It is Google's production-ready
+implementation of QUIC, HTTP/2, HTTP/3, and related protocols and tools. It
+powers Google's servers, Chromium, Envoy, and other projects. It is actively
+developed and maintained.
-Code can be viewed in CodeSearch in Quiche and is imported into
-[Chromium](https://source.chromium.org/chromium/chromium/src/+/master:net/third_party/quiche/src).
+There are two public QUICHE repositories. Either one may be used by embedders,
+as they are automatically kept in sync:
+
+* https://quiche.googlesource.com/quiche
+* https://github.com/google/quiche
+
+To embed QUICHE in your project, platform APIs need to be implemented and build
+files need to be created. Note that it is on the QUICHE team's roadmap to
+include default implementation for all platform APIs and to open-source build
+files. In the meanwhile, take a look at open source embedders like Chromium and
+Envoy to get started:
+
+* Platform implementations in Chromium:
+ + [quic/platform](https://source.chromium.org/chromium/chromium/src/+/main:net/net/quic/platform/impl/)
+ + [http2/platform](https://source.chromium.org/chromium/chromium/src/+/main:net/net/http2/platform/impl/)
+ + [quiche/common/platform](https://source.chromium.org/chromium/chromium/src/+/main:net/quiche/net/quiche/common/platform/impl/)
+* [Build file in Chromium](https://source.chromium.org/chromium/chromium/src/+/main:net/third_party/quiche/BUILD.gn)
+* [Platform implementations in Envoy](https://github.com/envoyproxy/envoy/tree/master/source/common/quic/platform)
+* [Build file in Envoy](https://github.com/envoyproxy/envoy/blob/main/bazel/external/quiche.BUILD)
+
+QUICHE is only supported on little-endian platforms.
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h
index 0e8e456209a..27ac0d20948 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_bug_tracker.h
@@ -5,7 +5,7 @@
#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
#define QUICHE_COMMON_PLATFORM_API_QUICHE_BUG_TRACKER_H_
-#include "net/quiche/common/platform/impl/quiche_bug_tracker_impl.h"
+#include "quiche_platform_impl/quiche_bug_tracker_impl.h"
#define QUICHE_BUG QUICHE_BUG_IMPL
#define QUICHE_BUG_IF QUICHE_BUG_IF_IMPL
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.cc b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.cc
new file mode 100644
index 00000000000..fc0c189382e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.cc
@@ -0,0 +1,51 @@
+#include "common/platform/api/quiche_file_utils.h"
+
+#include "quiche_platform_impl/quiche_file_utils_impl.h"
+
+namespace quiche {
+
+std::string JoinPath(absl::string_view a, absl::string_view b) {
+ return JoinPathImpl(a, b);
+}
+
+absl::optional<std::string> ReadFileContents(absl::string_view file) {
+ return ReadFileContentsImpl(file);
+}
+
+bool EnumerateDirectory(absl::string_view path,
+ std::vector<std::string>& directories,
+ std::vector<std::string>& files) {
+ return EnumerateDirectoryImpl(path, directories, files);
+}
+
+bool EnumerateDirectoryRecursivelyInner(absl::string_view path,
+ int recursion_limit,
+ std::vector<std::string>& files) {
+ if (recursion_limit < 0) {
+ return false;
+ }
+
+ std::vector<std::string> local_files;
+ std::vector<std::string> directories;
+ if (!EnumerateDirectory(path, directories, local_files)) {
+ return false;
+ }
+ for (const std::string& directory : directories) {
+ if (!EnumerateDirectoryRecursivelyInner(JoinPath(path, directory),
+ recursion_limit - 1, files)) {
+ return false;
+ }
+ }
+ for (const std::string& file : local_files) {
+ files.push_back(JoinPath(path, file));
+ }
+ return true;
+}
+
+bool EnumerateDirectoryRecursively(absl::string_view path,
+ std::vector<std::string>& files) {
+ constexpr int kRecursionLimit = 20;
+ return EnumerateDirectoryRecursivelyInner(path, kRecursionLimit, files);
+}
+
+} // namespace quiche
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.h
new file mode 100644
index 00000000000..47723d19e92
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils.h
@@ -0,0 +1,40 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This header contains basic filesystem functions for use in unit tests and CLI
+// tools. Note that those are not 100% suitable for production use, as in, they
+// might be prone to race conditions and not always handle non-ASCII filenames
+// correctly.
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace quiche {
+
+// Join two paths in a platform-specific way. Returns |a| if |b| is empty, and
+// vice versa.
+std::string JoinPath(absl::string_view a, absl::string_view b);
+
+// Reads the entire file into the memory.
+absl::optional<std::string> ReadFileContents(absl::string_view file);
+
+// Lists all files and directories in the directory specified by |path|. Returns
+// true on success, false on failure.
+bool EnumerateDirectory(absl::string_view path,
+ std::vector<std::string>& directories,
+ std::vector<std::string>& files);
+
+// Recursively enumerates all of the files in the directory and all of the
+// internal subdirectories. Has a fairly small recursion limit.
+bool EnumerateDirectoryRecursively(absl::string_view path,
+ std::vector<std::string>& files);
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_FILE_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils_test.cc b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils_test.cc
new file mode 100644
index 00000000000..ddf1a4000b1
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_file_utils_test.cc
@@ -0,0 +1,86 @@
+#include "common/platform/api/quiche_file_utils.h"
+
+#include <vector>
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/strip.h"
+#include "absl/types/optional.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace quiche {
+namespace test {
+namespace {
+
+using testing::UnorderedElementsAre;
+using testing::UnorderedElementsAreArray;
+
+TEST(QuicheFileUtilsTest, ReadFileContents) {
+ std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+ "/platform/api/testdir/testfile");
+ absl::optional<std::string> contents = ReadFileContents(path);
+ ASSERT_TRUE(contents.has_value());
+ EXPECT_EQ(*contents, "This is a test file.");
+}
+
+TEST(QuicheFileUtilsTest, ReadFileContentsFileNotFound) {
+ std::string path =
+ absl::StrCat(QuicheGetCommonSourcePath(),
+ "/platform/api/testdir/file-that-does-not-exist");
+ absl::optional<std::string> contents = ReadFileContents(path);
+ EXPECT_FALSE(contents.has_value());
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectory) {
+ std::string path =
+ absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir");
+ std::vector<std::string> dirs;
+ std::vector<std::string> files;
+ bool success = EnumerateDirectory(path, dirs, files);
+ EXPECT_TRUE(success);
+ EXPECT_THAT(files, UnorderedElementsAre("testfile", "README.md"));
+ EXPECT_THAT(dirs, UnorderedElementsAre("a"));
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryNoSuchDirectory) {
+ std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+ "/platform/api/testdir/no-such-directory");
+ std::vector<std::string> dirs;
+ std::vector<std::string> files;
+ bool success = EnumerateDirectory(path, dirs, files);
+ EXPECT_FALSE(success);
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryNotADirectory) {
+ std::string path = absl::StrCat(QuicheGetCommonSourcePath(),
+ "/platform/api/testdir/testfile");
+ std::vector<std::string> dirs;
+ std::vector<std::string> files;
+ bool success = EnumerateDirectory(path, dirs, files);
+ EXPECT_FALSE(success);
+}
+
+TEST(QuicheFileUtilsTest, EnumerateDirectoryRecursively) {
+ std::vector<std::string> expected_paths = {"a/b/c/d/e", "a/subdir/testfile",
+ "a/z", "testfile", "README.md"};
+
+ std::string root_path =
+ absl::StrCat(QuicheGetCommonSourcePath(), "/platform/api/testdir");
+ for (std::string& path : expected_paths) {
+ // For Windows, use Windows path separators.
+ if (JoinPath("a", "b") == "a\\b") {
+ absl::c_replace(path, '/', '\\');
+ }
+
+ path = JoinPath(root_path, path);
+ }
+
+ std::vector<std::string> files;
+ bool success = EnumerateDirectoryRecursively(root_path, files);
+ EXPECT_TRUE(success);
+ EXPECT_THAT(files, UnorderedElementsAreArray(expected_paths));
+}
+
+} // namespace
+} // namespace test
+} // namespace quiche
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
index 1af25df1ea5..efec6384db3 100644
--- a/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_test.h
@@ -12,6 +12,18 @@ using QuicheTest = quiche::test::QuicheTest;
template <class T>
using QuicheTestWithParam = quiche::test::QuicheTestWithParamImpl<T>;
+namespace quiche {
+namespace test {
+
+// Returns the path to quiche/common directory where the test data could be
+// located.
+inline std::string QuicheGetCommonSourcePath() {
+ return QuicheGetCommonSourcePathImpl();
+}
+
+} // namespace test
+} // namespace quiche
+
#define EXPECT_QUICHE_DEBUG_DEATH(condition, message) \
EXPECT_QUICHE_DEBUG_DEATH_IMPL(condition, message)
diff --git a/chromium/net/third_party/quiche/src/common/platform/api/quiche_thread_local.h b/chromium/net/third_party/quiche/src/common/platform/api/quiche_thread_local.h
new file mode 100644
index 00000000000..c2d58e1dd5e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/api/quiche_thread_local.h
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
+#define QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
+
+#include "quiche_platform_impl/quiche_thread_local_impl.h"
+
+// Define a thread local |type*| with |name|. Conceptually, this is a
+//
+// static thread_local type* name = nullptr;
+//
+// It is wrapped in a macro because the thread_local keyword is banned from
+// Chromium.
+#define DEFINE_QUICHE_THREAD_LOCAL_POINTER(name, type) \
+ DEFINE_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, type)
+
+// Get the value of |name| for the current thread.
+#define GET_QUICHE_THREAD_LOCAL_POINTER(name) \
+ GET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name)
+
+// Set the |value| of |name| for the current thread.
+#define SET_QUICHE_THREAD_LOCAL_POINTER(name, value) \
+ SET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, value)
+
+#endif // QUICHE_COMMON_PLATFORM_API_QUICHE_THREAD_LOCAL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_bug_tracker_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_bug_tracker_impl.h
new file mode 100644
index 00000000000..de164aac15e
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_bug_tracker_impl.h
@@ -0,0 +1,15 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
+#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
+
+#include "common/platform/api/quiche_logging.h"
+
+#define QUICHE_BUG_IMPL(b) QUICHE_LOG(DFATAL)
+#define QUICHE_BUG_IF_IMPL(b, condition) QUICHE_LOG_IF(DFATAL, condition)
+#define QUICHE_PEER_BUG_IMPL(b) QUICHE_LOG(DFATAL)
+#define QUICHE_PEER_BUG_IF_IMPL(b, condition) QUICHE_LOG_IF(DFATAL, condition)
+
+#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_BUG_TRACKER_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_containers_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_containers_impl.h
deleted file mode 100644
index 2e18dd7a2f8..00000000000
--- a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_containers_impl.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_CONTAINERS_IMPL_H_
-#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_CONTAINERS_IMPL_H_
-
-#include <deque>
-
-namespace quiche {
-
-// Represents a double-ended queue which may be backed by a list or a flat
-// circular buffer.
-//
-// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename T>
-using QuicheDequeImpl = std::deque<T>;
-
-} // namespace quiche
-
-#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_CONTAINERS_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_estimate_memory_usage_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_estimate_memory_usage_impl.h
deleted file mode 100644
index 59087a725eb..00000000000
--- a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_estimate_memory_usage_impl.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2021 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_ESTIMATE_MEMORY_USAGE_IMPL_H_
-#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_ESTIMATE_MEMORY_USAGE_IMPL_H_
-
-#include <cstddef>
-
-namespace quiche {
-
-// No-op implementation.
-template <class T>
-size_t QuicheEstimateMemoryUsageImpl(const T& /*object*/) {
- return 0;
-}
-
-} // namespace quiche
-
-#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_ESTIMATE_MEMORY_USAGE_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc
new file mode 100644
index 00000000000..65965b222d5
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.cc
@@ -0,0 +1,182 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quiche_platform_impl/quiche_file_utils_impl.h"
+
+#if defined(_WIN32)
+#include <windows.h>
+#else
+#include <dirent.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif // defined(_WIN32)
+
+#include <fstream>
+#include <ios>
+#include <iostream>
+
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/types/optional.h"
+
+namespace quiche {
+
+#if defined(_WIN32)
+std::string JoinPathImpl(absl::string_view a, absl::string_view b) {
+ if (a.empty()) {
+ return std::string(b);
+ }
+ if (b.empty()) {
+ return std::string(a);
+ }
+ // Win32 actually provides two different APIs for combining paths; one of them
+ // has issues that could potentially lead to buffer overflow, and another is
+ // not supported in Windows 7, which is why we're doing it manually.
+ a = absl::StripSuffix(a, "/");
+ a = absl::StripSuffix(a, "\\");
+ return absl::StrCat(a, "\\", b);
+}
+#else
+std::string JoinPathImpl(absl::string_view a, absl::string_view b) {
+ if (a.empty()) {
+ return std::string(b);
+ }
+ if (b.empty()) {
+ return std::string(a);
+ }
+ return absl::StrCat(absl::StripSuffix(a, "/"), "/", b);
+}
+#endif // defined(_WIN32)
+
+absl::optional<std::string> ReadFileContentsImpl(absl::string_view file) {
+ std::ifstream input_file(std::string{file}, std::ios::binary);
+ if (!input_file || !input_file.is_open()) {
+ return absl::nullopt;
+ }
+
+ input_file.seekg(0, std::ios_base::end);
+ auto file_size = input_file.tellg();
+ if (!input_file) {
+ return absl::nullopt;
+ }
+ input_file.seekg(0, std::ios_base::beg);
+
+ std::string output;
+ output.resize(file_size);
+ input_file.read(&output[0], file_size);
+ if (!input_file) {
+ return absl::nullopt;
+ }
+
+ return output;
+}
+
+#if defined(_WIN32)
+
+class ScopedDir {
+ public:
+ ScopedDir(HANDLE dir) : dir_(dir) {}
+ ~ScopedDir() {
+ if (dir_ != INVALID_HANDLE_VALUE) {
+ // The API documentation explicitly says that CloseHandle() should not be
+ // used on directory search handles.
+ FindClose(dir_);
+ dir_ = INVALID_HANDLE_VALUE;
+ }
+ }
+
+ HANDLE get() { return dir_; }
+
+ private:
+ HANDLE dir_;
+};
+
+bool EnumerateDirectoryImpl(absl::string_view path,
+ std::vector<std::string>& directories,
+ std::vector<std::string>& files) {
+ std::string path_owned(path);
+
+ // Explicitly check that the directory we are trying to search is in fact a
+ // directory.
+ DWORD attributes = GetFileAttributesA(path_owned.c_str());
+ if (attributes == INVALID_FILE_ATTRIBUTES) {
+ return false;
+ }
+ if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
+ return false;
+ }
+
+ std::string search_path = JoinPathImpl(path, "*");
+ WIN32_FIND_DATAA file_data;
+ ScopedDir dir(FindFirstFileA(search_path.c_str(), &file_data));
+ if (dir.get() == INVALID_HANDLE_VALUE) {
+ return GetLastError() == ERROR_FILE_NOT_FOUND;
+ }
+ do {
+ std::string filename(file_data.cFileName);
+ if (filename == "." || filename == "..") {
+ continue;
+ }
+ if ((file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
+ directories.push_back(std::move(filename));
+ } else {
+ files.push_back(std::move(filename));
+ }
+ } while (FindNextFileA(dir.get(), &file_data));
+ return GetLastError() == ERROR_NO_MORE_FILES;
+}
+
+#else // defined(_WIN32)
+
+class ScopedDir {
+ public:
+ ScopedDir(DIR* dir) : dir_(dir) {}
+ ~ScopedDir() {
+ if (dir_ != nullptr) {
+ closedir(dir_);
+ dir_ = nullptr;
+ }
+ }
+
+ DIR* get() { return dir_; }
+
+ private:
+ DIR* dir_;
+};
+
+bool EnumerateDirectoryImpl(absl::string_view path,
+ std::vector<std::string>& directories,
+ std::vector<std::string>& files) {
+ std::string path_owned(path);
+ ScopedDir dir(opendir(path_owned.c_str()));
+ if (dir.get() == nullptr) {
+ return false;
+ }
+
+ dirent* entry;
+ while ((entry = readdir(dir.get()))) {
+ const std::string filename(entry->d_name);
+ if (filename == "." || filename == "..") {
+ continue;
+ }
+
+ const std::string entry_path = JoinPathImpl(path, filename);
+ struct stat stat_entry;
+ if (stat(entry_path.c_str(), &stat_entry) != 0) {
+ return false;
+ }
+ if (S_ISREG(stat_entry.st_mode)) {
+ files.push_back(std::move(filename));
+ } else if (S_ISDIR(stat_entry.st_mode)) {
+ directories.push_back(std::move(filename));
+ }
+ }
+ return true;
+}
+
+#endif // defined(_WIN32)
+
+} // namespace quiche
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h
new file mode 100644
index 00000000000..ad5ff1a9084
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_file_utils_impl.h
@@ -0,0 +1,26 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_FILE_UTILS_IMPL_H_
+#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_FILE_UTILS_IMPL_H_
+
+#include <string>
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+
+namespace quiche {
+
+std::string JoinPathImpl(absl::string_view a, absl::string_view b);
+
+absl::optional<std::string> ReadFileContentsImpl(absl::string_view file);
+
+bool EnumerateDirectoryImpl(absl::string_view path,
+ std::vector<std::string>& directories,
+ std::vector<std::string>& files);
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_FILE_UTILS_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_thread_local_impl.h b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_thread_local_impl.h
new file mode 100644
index 00000000000..5ebea4c5bfb
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/platform/default/quiche_platform_impl/quiche_thread_local_impl.h
@@ -0,0 +1,24 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
+#define QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
+
+#define DEFINE_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, type) \
+ struct QuicheThreadLocalPointer_##name { \
+ static type** Instance() { \
+ static thread_local type* instance = nullptr; \
+ return &instance; \
+ } \
+ static type* Get() { return *Instance(); } \
+ static void Set(type* ptr) { *Instance() = ptr; } \
+ }
+
+#define GET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name) \
+ QuicheThreadLocalPointer_##name::Get()
+
+#define SET_QUICHE_THREAD_LOCAL_POINTER_IMPL(name, value) \
+ QuicheThreadLocalPointer_##name::Set(value)
+
+#endif // QUICHE_COMMON_PLATFORM_DEFAULT_QUICHE_PLATFORM_IMPL_QUICHE_THREAD_LOCAL_IMPL_H_
diff --git a/chromium/net/third_party/quiche/src/common/print_elements.h b/chromium/net/third_party/quiche/src/common/print_elements.h
new file mode 100644
index 00000000000..f241a4b9509
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/common/print_elements.h
@@ -0,0 +1,35 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_COMMON_PRINT_ELEMENTS_H_
+#define QUICHE_COMMON_PRINT_ELEMENTS_H_
+
+#include <ostream>
+#include <sstream>
+#include <string>
+
+#include "common/platform/api/quiche_export.h"
+
+namespace quiche {
+
+// Print elements of any iterable container that has cbegin() and cend() methods
+// and the elements have operator<<(ostream) override.
+template <typename T>
+QUICHE_EXPORT_PRIVATE inline std::string PrintElements(const T& container) {
+ std::stringstream debug_string;
+ debug_string << "{";
+ auto it = container.cbegin();
+ debug_string << *it;
+ ++it;
+ while (it != container.cend()) {
+ debug_string << ", " << *it;
+ ++it;
+ }
+ debug_string << "}";
+ return debug_string.str();
+}
+
+} // namespace quiche
+
+#endif // QUICHE_COMMON_PRINT_ELEMENTS_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc
index eaf4b6169d2..4381749d430 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.cc
@@ -36,14 +36,63 @@ struct nghttp2_session_callbacks {
namespace http2 {
namespace adapter {
+CallbackVisitor::CallbackVisitor(Perspective perspective,
+ const nghttp2_session_callbacks& callbacks,
+ void* user_data)
+ : perspective_(perspective),
+ callbacks_(MakeCallbacksPtr(nullptr)),
+ user_data_(user_data) {
+ nghttp2_session_callbacks* c;
+ nghttp2_session_callbacks_new(&c);
+ *c = callbacks;
+ callbacks_ = MakeCallbacksPtr(c);
+}
+
+ssize_t CallbackVisitor::OnReadyToSend(absl::string_view serialized) {
+ if (!callbacks_->send_callback) {
+ return kSendError;
+ }
+ ssize_t result = callbacks_->send_callback(
+ nullptr, ToUint8Ptr(serialized.data()), serialized.size(), 0, user_data_);
+ QUICHE_VLOG(1) << "CallbackVisitor::OnReadyToSend returning " << result;
+ if (result > 0) {
+ return result;
+ } else if (result == NGHTTP2_ERR_WOULDBLOCK) {
+ return kSendBlocked;
+ } else {
+ return kSendError;
+ }
+}
+
void CallbackVisitor::OnConnectionError() {
- QUICHE_LOG(FATAL) << "Not implemented";
+ QUICHE_LOG(ERROR) << "OnConnectionError not implemented";
}
void CallbackVisitor::OnFrameHeader(Http2StreamId stream_id,
size_t length,
uint8_t type,
uint8_t flags) {
+ QUICHE_VLOG(1) << "CallbackVisitor::OnFrameHeader(stream_id: " << stream_id
+ << ", len: " << length << ", type: " << int(type)
+ << ", flags: " << int(flags) << ")";
+ if (static_cast<FrameType>(type) == FrameType::CONTINUATION) {
+ // Treat CONTINUATION as HEADERS
+ QUICHE_DCHECK_EQ(current_frame_.hd.stream_id, stream_id);
+ current_frame_.hd.length += length;
+ current_frame_.hd.flags |= flags;
+ QUICHE_DLOG_IF(ERROR, length == 0) << "Empty CONTINUATION!";
+ // Still need to deliver the CONTINUATION to the begin frame callback.
+ nghttp2_frame_hd hd;
+ memset(&hd, 0, sizeof(hd));
+ hd.stream_id = stream_id;
+ hd.length = length;
+ hd.type = type;
+ hd.flags = flags;
+ if (callbacks_->on_begin_frame_callback) {
+ callbacks_->on_begin_frame_callback(nullptr, &hd, user_data_);
+ }
+ return;
+ }
// The general strategy is to clear |current_frame_| at the start of a new
// frame, accumulate frame information from the various callback events, then
// invoke the on_frame_recv_callback() with the accumulated frame data.
@@ -52,7 +101,10 @@ void CallbackVisitor::OnFrameHeader(Http2StreamId stream_id,
current_frame_.hd.length = length;
current_frame_.hd.type = type;
current_frame_.hd.flags = flags;
- callbacks_->on_begin_frame_callback(nullptr, &current_frame_.hd, user_data_);
+ if (callbacks_->on_begin_frame_callback) {
+ callbacks_->on_begin_frame_callback(nullptr, &current_frame_.hd,
+ user_data_);
+ }
}
void CallbackVisitor::OnSettingsStart() {}
@@ -64,106 +116,147 @@ void CallbackVisitor::OnSetting(Http2Setting setting) {
void CallbackVisitor::OnSettingsEnd() {
current_frame_.settings.niv = settings_.size();
current_frame_.settings.iv = settings_.data();
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ QUICHE_VLOG(1) << "OnSettingsEnd, received settings of size "
+ << current_frame_.settings.niv;
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
settings_.clear();
}
void CallbackVisitor::OnSettingsAck() {
// ACK is part of the flags, which were set in OnFrameHeader().
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
}
-void CallbackVisitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
- auto it = stream_map_.find(stream_id);
- if (it == stream_map_.end()) {
- auto p = stream_map_.insert({stream_id, absl::make_unique<StreamInfo>()});
- it = p.first;
- }
+bool CallbackVisitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
+ auto it = GetStreamInfo(stream_id);
if (it->second->received_headers) {
// At least one headers frame has already been received.
+ QUICHE_VLOG(1)
+ << "Headers already received for stream " << stream_id
+ << ", these are trailers or headers following a 100 response";
current_frame_.headers.cat = NGHTTP2_HCAT_HEADERS;
} else {
switch (perspective_) {
case Perspective::kClient:
+ QUICHE_VLOG(1) << "First headers at the client for stream " << stream_id
+ << "; these are response headers";
current_frame_.headers.cat = NGHTTP2_HCAT_RESPONSE;
break;
case Perspective::kServer:
+ QUICHE_VLOG(1) << "First headers at the server for stream " << stream_id
+ << "; these are request headers";
current_frame_.headers.cat = NGHTTP2_HCAT_REQUEST;
break;
}
}
- callbacks_->on_begin_headers_callback(nullptr, &current_frame_, user_data_);
it->second->received_headers = true;
+ if (callbacks_->on_begin_headers_callback) {
+ const int result = callbacks_->on_begin_headers_callback(
+ nullptr, &current_frame_, user_data_);
+ return result == 0;
+ }
+ return true;
}
-void CallbackVisitor::OnHeaderForStream(Http2StreamId stream_id,
- absl::string_view name,
- absl::string_view value) {
- callbacks_->on_header_callback(
- nullptr, &current_frame_, ToUint8Ptr(name.data()), name.size(),
- ToUint8Ptr(value.data()), value.size(), NGHTTP2_NV_FLAG_NONE, user_data_);
+Http2VisitorInterface::OnHeaderResult CallbackVisitor::OnHeaderForStream(
+ Http2StreamId /*stream_id*/, absl::string_view name,
+ absl::string_view value) {
+ if (callbacks_->on_header_callback) {
+ const int result = callbacks_->on_header_callback(
+ nullptr, &current_frame_, ToUint8Ptr(name.data()), name.size(),
+ ToUint8Ptr(value.data()), value.size(), NGHTTP2_NV_FLAG_NONE,
+ user_data_);
+ if (result == 0) {
+ return HEADER_OK;
+ } else if (result == NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE) {
+ return HEADER_RST_STREAM;
+ } else {
+ // Assume NGHTTP2_ERR_CALLBACK_FAILURE.
+ return HEADER_CONNECTION_ERROR;
+ }
+ }
+ return HEADER_OK;
}
-void CallbackVisitor::OnEndHeadersForStream(Http2StreamId stream_id) {
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+void CallbackVisitor::OnEndHeadersForStream(Http2StreamId /*stream_id*/) {
+ if (callbacks_->on_frame_recv_callback) {
+ const int result = callbacks_->on_frame_recv_callback(
+ nullptr, &current_frame_, user_data_);
+ QUICHE_DCHECK_EQ(0, result);
+ }
}
-void CallbackVisitor::OnBeginDataForStream(Http2StreamId stream_id,
+void CallbackVisitor::OnBeginDataForStream(Http2StreamId /*stream_id*/,
size_t payload_length) {
// TODO(b/181586191): Interpret padding, subtract padding from
// |remaining_data_|.
remaining_data_ = payload_length;
- if (remaining_data_ == 0) {
+ if (remaining_data_ == 0 && callbacks_->on_frame_recv_callback) {
callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
}
}
void CallbackVisitor::OnDataForStream(Http2StreamId stream_id,
absl::string_view data) {
- callbacks_->on_data_chunk_recv_callback(nullptr, current_frame_.hd.flags,
- stream_id, ToUint8Ptr(data.data()),
- data.size(), user_data_);
+ if (callbacks_->on_data_chunk_recv_callback) {
+ callbacks_->on_data_chunk_recv_callback(nullptr, current_frame_.hd.flags,
+ stream_id, ToUint8Ptr(data.data()),
+ data.size(), user_data_);
+ }
remaining_data_ -= data.size();
- if (remaining_data_ == 0) {
+ if (remaining_data_ == 0 && callbacks_->on_frame_recv_callback) {
callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
}
}
-void CallbackVisitor::OnEndStream(Http2StreamId stream_id) {}
+void CallbackVisitor::OnEndStream(Http2StreamId /*stream_id*/) {}
-void CallbackVisitor::OnRstStream(Http2StreamId stream_id,
+void CallbackVisitor::OnRstStream(Http2StreamId /*stream_id*/,
Http2ErrorCode error_code) {
current_frame_.rst_stream.error_code = static_cast<uint32_t>(error_code);
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
}
void CallbackVisitor::OnCloseStream(Http2StreamId stream_id,
Http2ErrorCode error_code) {
- callbacks_->on_stream_close_callback(
- nullptr, stream_id, static_cast<uint32_t>(error_code), user_data_);
+ if (callbacks_->on_stream_close_callback) {
+ QUICHE_VLOG(1) << "OnCloseStream(stream_id: " << stream_id
+ << ", error_code: " << int(error_code) << ")";
+ callbacks_->on_stream_close_callback(
+ nullptr, stream_id, static_cast<uint32_t>(error_code), user_data_);
+ }
}
-void CallbackVisitor::OnPriorityForStream(Http2StreamId stream_id,
+void CallbackVisitor::OnPriorityForStream(Http2StreamId /*stream_id*/,
Http2StreamId parent_stream_id,
- int weight,
- bool exclusive) {
+ int weight, bool exclusive) {
current_frame_.priority.pri_spec.stream_id = parent_stream_id;
current_frame_.priority.pri_spec.weight = weight;
current_frame_.priority.pri_spec.exclusive = exclusive;
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
}
-void CallbackVisitor::OnPing(Http2PingId ping_id, bool is_ack) {
+void CallbackVisitor::OnPing(Http2PingId ping_id, bool /*is_ack*/) {
uint64_t network_order_opaque_data =
quiche::QuicheEndian::HostToNet64(ping_id);
std::memcpy(current_frame_.ping.opaque_data, &network_order_opaque_data,
sizeof(network_order_opaque_data));
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
}
-void CallbackVisitor::OnPushPromiseForStream(Http2StreamId stream_id,
- Http2StreamId promised_stream_id) {
- QUICHE_LOG(FATAL) << "Not implemented";
+void CallbackVisitor::OnPushPromiseForStream(
+ Http2StreamId /*stream_id*/, Http2StreamId /*promised_stream_id*/) {
+ QUICHE_LOG(DFATAL) << "Not implemented";
}
void CallbackVisitor::OnGoAway(Http2StreamId last_accepted_stream_id,
@@ -173,42 +266,173 @@ void CallbackVisitor::OnGoAway(Http2StreamId last_accepted_stream_id,
current_frame_.goaway.error_code = static_cast<uint32_t>(error_code);
current_frame_.goaway.opaque_data = ToUint8Ptr(opaque_data.data());
current_frame_.goaway.opaque_data_len = opaque_data.size();
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
}
-void CallbackVisitor::OnWindowUpdate(Http2StreamId stream_id,
+void CallbackVisitor::OnWindowUpdate(Http2StreamId /*stream_id*/,
int window_increment) {
current_frame_.window_update.window_size_increment = window_increment;
- callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
+}
+
+void CallbackVisitor::PopulateFrame(nghttp2_frame& frame, uint8_t frame_type,
+ Http2StreamId stream_id, size_t length,
+ uint8_t flags, uint32_t error_code,
+ bool sent_headers) {
+ frame.hd.type = frame_type;
+ frame.hd.stream_id = stream_id;
+ frame.hd.length = length;
+ frame.hd.flags = flags;
+ const FrameType frame_type_enum = static_cast<FrameType>(frame_type);
+ if (frame_type_enum == FrameType::HEADERS) {
+ if (sent_headers) {
+ frame.headers.cat = NGHTTP2_HCAT_HEADERS;
+ } else {
+ switch (perspective_) {
+ case Perspective::kClient:
+ QUICHE_VLOG(1) << "First headers sent by the client for stream "
+ << stream_id << "; these are request headers";
+ frame.headers.cat = NGHTTP2_HCAT_REQUEST;
+ break;
+ case Perspective::kServer:
+ QUICHE_VLOG(1) << "First headers sent by the server for stream "
+ << stream_id << "; these are response headers";
+ frame.headers.cat = NGHTTP2_HCAT_RESPONSE;
+ break;
+ }
+ }
+ } else if (frame_type_enum == FrameType::RST_STREAM) {
+ frame.rst_stream.error_code = error_code;
+ } else if (frame_type_enum == FrameType::GOAWAY) {
+ frame.goaway.error_code = error_code;
+ }
}
-void CallbackVisitor::OnReadyToSendDataForStream(Http2StreamId stream_id,
- char* destination_buffer,
- size_t length,
- ssize_t* written,
- bool* end_stream) {
- QUICHE_LOG(FATAL) << "Not implemented";
+int CallbackVisitor::OnBeforeFrameSent(uint8_t frame_type,
+ Http2StreamId stream_id, size_t length,
+ uint8_t flags) {
+ if (callbacks_->before_frame_send_callback) {
+ QUICHE_VLOG(1) << "OnBeforeFrameSent(type=" << int(frame_type)
+ << ", stream_id=" << stream_id << ", length=" << length
+ << ", flags=" << int(flags) << ")";
+ nghttp2_frame frame;
+ auto it = GetStreamInfo(stream_id);
+ // The implementation of the before_frame_send_callback doesn't look at the
+ // error code, so for now it's populated with 0.
+ PopulateFrame(frame, frame_type, stream_id, length, flags, /*error_code=*/0,
+ it->second->before_sent_headers);
+ it->second->before_sent_headers = true;
+ return callbacks_->before_frame_send_callback(nullptr, &frame, user_data_);
+ }
+ return 0;
+}
+
+int CallbackVisitor::OnFrameSent(uint8_t frame_type, Http2StreamId stream_id,
+ size_t length, uint8_t flags,
+ uint32_t error_code) {
+ if (callbacks_->on_frame_send_callback) {
+ QUICHE_VLOG(1) << "OnFrameSent(type=" << int(frame_type)
+ << ", stream_id=" << stream_id << ", length=" << length
+ << ", flags=" << int(flags) << ", error_code=" << error_code
+ << ")";
+ nghttp2_frame frame;
+ auto it = GetStreamInfo(stream_id);
+ PopulateFrame(frame, frame_type, stream_id, length, flags, error_code,
+ it->second->sent_headers);
+ it->second->sent_headers = true;
+ return callbacks_->on_frame_send_callback(nullptr, &frame, user_data_);
+ }
+ return 0;
+}
+
+void CallbackVisitor::OnReadyToSendDataForStream(Http2StreamId /*stream_id*/,
+ char* /*destination_buffer*/,
+ size_t /*length*/,
+ ssize_t* /*written*/,
+ bool* /*end_stream*/) {
+ QUICHE_LOG(DFATAL) << "Not implemented";
+}
+
+bool CallbackVisitor::OnInvalidFrame(Http2StreamId stream_id, int error_code) {
+ QUICHE_VLOG(1) << "OnInvalidFrame(" << stream_id << ", " << error_code << ")";
+ QUICHE_DCHECK_EQ(stream_id, current_frame_.hd.stream_id);
+ if (callbacks_->on_invalid_frame_recv_callback) {
+ return 0 == callbacks_->on_invalid_frame_recv_callback(
+ nullptr, &current_frame_, error_code, user_data_);
+ }
+ return true;
}
void CallbackVisitor::OnReadyToSendMetadataForStream(Http2StreamId stream_id,
char* buffer,
size_t length,
ssize_t* written) {
- QUICHE_LOG(FATAL) << "Not implemented";
+ if (callbacks_->pack_extension_callback) {
+ nghttp2_frame frame;
+ frame.hd.type = kMetadataFrameType;
+ frame.hd.stream_id = stream_id;
+ frame.hd.flags = 0;
+ frame.hd.length = 0;
+ *written = callbacks_->pack_extension_callback(nullptr, ToUint8Ptr(buffer),
+ length, &frame, user_data_);
+ }
+ QUICHE_VLOG(1) << "OnReadyToSendMetadataForStream(stream_id=" << stream_id
+ << ", length=" << length << ", written=" << *written << ")";
}
void CallbackVisitor::OnBeginMetadataForStream(Http2StreamId stream_id,
size_t payload_length) {
- QUICHE_LOG(FATAL) << "Not implemented";
+ QUICHE_VLOG(1) << "OnBeginMetadataForStream(stream_id=" << stream_id
+ << ", payload_length=" << payload_length << ")";
}
void CallbackVisitor::OnMetadataForStream(Http2StreamId stream_id,
absl::string_view metadata) {
- QUICHE_LOG(FATAL) << "Not implemented";
+ QUICHE_VLOG(1) << "OnMetadataForStream(stream_id=" << stream_id
+ << ", len=" << metadata.size() << ")";
+ if (callbacks_->on_extension_chunk_recv_callback) {
+ int result = callbacks_->on_extension_chunk_recv_callback(
+ nullptr, &current_frame_.hd, ToUint8Ptr(metadata.data()),
+ metadata.size(), user_data_);
+ QUICHE_DCHECK_EQ(0, result);
+ }
+}
+
+bool CallbackVisitor::OnMetadataEndForStream(Http2StreamId stream_id) {
+ QUICHE_LOG_IF(DFATAL, current_frame_.hd.flags != kMetadataEndFlag);
+ QUICHE_VLOG(1) << "OnMetadataEndForStream(stream_id=" << stream_id << ")";
+ if (callbacks_->unpack_extension_callback) {
+ void* payload;
+ int result = callbacks_->unpack_extension_callback(
+ nullptr, &payload, &current_frame_.hd, user_data_);
+ if (callbacks_->on_frame_recv_callback) {
+ current_frame_.ext.payload = payload;
+ callbacks_->on_frame_recv_callback(nullptr, &current_frame_, user_data_);
+ }
+ return (result == 0);
+ }
+ return true;
}
-void CallbackVisitor::OnMetadataEndForStream(Http2StreamId stream_id) {
- QUICHE_LOG(FATAL) << "Not implemented";
+void CallbackVisitor::OnErrorDebug(absl::string_view message) {
+ if (callbacks_->error_callback2) {
+ callbacks_->error_callback2(nullptr, -1, message.data(), message.size(),
+ user_data_);
+ }
+}
+
+CallbackVisitor::StreamInfoMap::iterator CallbackVisitor::GetStreamInfo(
+ Http2StreamId stream_id) {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ auto p = stream_map_.insert({stream_id, absl::make_unique<StreamInfo>()});
+ it = p.first;
+ }
+ return it;
}
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h
index 94746bf8edb..b5afc83a103 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor.h
@@ -8,21 +8,20 @@
#include "http2/adapter/http2_visitor_interface.h"
#include "http2/adapter/nghttp2_util.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
// This visitor implementation accepts a set of nghttp2 callbacks and a "user
// data" pointer, and invokes the callbacks according to HTTP/2 events received.
-class CallbackVisitor : public Http2VisitorInterface {
+class QUICHE_EXPORT_PRIVATE CallbackVisitor : public Http2VisitorInterface {
public:
explicit CallbackVisitor(Perspective perspective,
- nghttp2_session_callbacks_unique_ptr callbacks,
- void* user_data)
- : perspective_(perspective),
- callbacks_(std::move(callbacks)),
- user_data_(user_data) {}
+ const nghttp2_session_callbacks& callbacks,
+ void* user_data);
+ ssize_t OnReadyToSend(absl::string_view serialized) override;
void OnConnectionError() override;
void OnFrameHeader(Http2StreamId stream_id,
size_t length,
@@ -32,10 +31,10 @@ class CallbackVisitor : public Http2VisitorInterface {
void OnSetting(Http2Setting setting) override;
void OnSettingsEnd() override;
void OnSettingsAck() override;
- void OnBeginHeadersForStream(Http2StreamId stream_id) override;
- void OnHeaderForStream(Http2StreamId stream_id,
- absl::string_view name,
- absl::string_view value) override;
+ bool OnBeginHeadersForStream(Http2StreamId stream_id) override;
+ OnHeaderResult OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) override;
void OnEndHeadersForStream(Http2StreamId stream_id) override;
void OnBeginDataForStream(Http2StreamId stream_id,
size_t payload_length) override;
@@ -56,11 +55,16 @@ class CallbackVisitor : public Http2VisitorInterface {
Http2ErrorCode error_code,
absl::string_view opaque_data) override;
void OnWindowUpdate(Http2StreamId stream_id, int window_increment) override;
+ int OnBeforeFrameSent(uint8_t frame_type, Http2StreamId stream_id,
+ size_t length, uint8_t flags) override;
+ int OnFrameSent(uint8_t frame_type, Http2StreamId stream_id, size_t length,
+ uint8_t flags, uint32_t error_code) override;
void OnReadyToSendDataForStream(Http2StreamId stream_id,
char* destination_buffer,
size_t length,
ssize_t* written,
bool* end_stream) override;
+ bool OnInvalidFrame(Http2StreamId stream_id, int error_code) override;
void OnReadyToSendMetadataForStream(Http2StreamId stream_id,
char* buffer,
size_t length,
@@ -69,9 +73,25 @@ class CallbackVisitor : public Http2VisitorInterface {
size_t payload_length) override;
void OnMetadataForStream(Http2StreamId stream_id,
absl::string_view metadata) override;
- void OnMetadataEndForStream(Http2StreamId stream_id) override;
+ bool OnMetadataEndForStream(Http2StreamId stream_id) override;
+ void OnErrorDebug(absl::string_view message) override;
private:
+ struct QUICHE_EXPORT_PRIVATE StreamInfo {
+ bool before_sent_headers = false;
+ bool sent_headers = false;
+ bool received_headers = false;
+ };
+
+ using StreamInfoMap =
+ absl::flat_hash_map<Http2StreamId, std::unique_ptr<StreamInfo>>;
+
+ void PopulateFrame(nghttp2_frame& frame, uint8_t frame_type,
+ Http2StreamId stream_id, size_t length, uint8_t flags,
+ uint32_t error_code, bool sent_headers);
+ // Creates the StreamInfoMap entry if it doesn't exist.
+ StreamInfoMap::iterator GetStreamInfo(Http2StreamId stream_id);
+
Perspective perspective_;
nghttp2_session_callbacks_unique_ptr callbacks_;
void* user_data_;
@@ -80,10 +100,7 @@ class CallbackVisitor : public Http2VisitorInterface {
std::vector<nghttp2_settings_entry> settings_;
size_t remaining_data_ = 0;
- struct StreamInfo {
- bool received_headers = false;
- };
- absl::flat_hash_map<Http2StreamId, std::unique_ptr<StreamInfo>> stream_map_;
+ StreamInfoMap stream_map_;
};
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc
index 4dfcb5fcddb..2cb31ed24f4 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/callback_visitor_test.cc
@@ -1,6 +1,7 @@
#include "http2/adapter/callback_visitor.h"
#include "http2/adapter/mock_nghttp2_callbacks.h"
+#include "http2/adapter/nghttp2_test_utils.h"
#include "http2/adapter/test_utils.h"
#include "common/platform/api/quiche_test.h"
@@ -21,13 +22,14 @@ enum FrameType {
PING,
GOAWAY,
WINDOW_UPDATE,
+ CONTINUATION,
};
// Tests connection-level events.
TEST(ClientCallbackVisitorUnitTest, ConnectionFrames) {
testing::StrictMock<MockNghttp2Callbacks> callbacks;
CallbackVisitor visitor(Perspective::kClient,
- MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+ *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
testing::InSequence seq;
@@ -73,7 +75,7 @@ TEST(ClientCallbackVisitorUnitTest, ConnectionFrames) {
TEST(ClientCallbackVisitorUnitTest, StreamFrames) {
testing::StrictMock<MockNghttp2Callbacks> callbacks;
CallbackVisitor visitor(Perspective::kClient,
- MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+ *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
testing::InSequence seq;
@@ -153,12 +155,69 @@ TEST(ClientCallbackVisitorUnitTest, StreamFrames) {
EXPECT_CALL(callbacks, OnStreamClose(5, NGHTTP2_REFUSED_STREAM));
visitor.OnCloseStream(5, Http2ErrorCode::REFUSED_STREAM);
+
+ // Metadata events
+ constexpr size_t kMetadataBufferSize = 256;
+ char metadata_dest[kMetadataBufferSize];
+ ssize_t written = 0;
+
+ const absl::string_view kExampleFrame = "This is supposed to be metadata.";
+ EXPECT_CALL(
+ callbacks,
+ OnPackExtension(_, kMetadataBufferSize,
+ Field(&nghttp2_frame::hd,
+ HasFrameHeaderRef(7, kMetadataFrameType, _))))
+ .WillOnce(testing::Invoke(
+ [kExampleFrame](uint8_t* buf, size_t /*len*/,
+ const nghttp2_frame* /*frame*/) -> ssize_t {
+ std::memcpy(buf, kExampleFrame.data(), kExampleFrame.size());
+ return kExampleFrame.size();
+ }));
+ visitor.OnReadyToSendMetadataForStream(7, metadata_dest, kMetadataBufferSize,
+ &written);
+ ASSERT_EQ(written, kExampleFrame.size());
+ EXPECT_EQ(absl::string_view(metadata_dest, written), kExampleFrame);
+}
+
+TEST(ClientCallbackVisitorUnitTest, HeadersWithContinuation) {
+ testing::StrictMock<MockNghttp2Callbacks> callbacks;
+ CallbackVisitor visitor(Perspective::kClient,
+ *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+
+ testing::InSequence seq;
+
+ // HEADERS on stream 1
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, HEADERS, 0x0)));
+ visitor.OnFrameHeader(1, 23, HEADERS, 0x0);
+
+ EXPECT_CALL(callbacks,
+ OnBeginHeaders(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
+ visitor.OnBeginHeadersForStream(1);
+
+ EXPECT_CALL(callbacks, OnHeader(_, ":status", "200", _));
+ visitor.OnHeaderForStream(1, ":status", "200");
+
+ EXPECT_CALL(callbacks, OnHeader(_, "server", "my-fake-server", _));
+ visitor.OnHeaderForStream(1, "server", "my-fake-server");
+
+ EXPECT_CALL(callbacks, OnBeginFrame(HasFrameHeader(1, CONTINUATION, 0x4)));
+ visitor.OnFrameHeader(1, 23, CONTINUATION, 0x4);
+
+ EXPECT_CALL(callbacks,
+ OnHeader(_, "date", "Tue, 6 Apr 2021 12:54:01 GMT", _));
+ visitor.OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT");
+
+ EXPECT_CALL(callbacks, OnHeader(_, "trailer", "x-server-status", _));
+ visitor.OnHeaderForStream(1, "trailer", "x-server-status");
+
+ EXPECT_CALL(callbacks, OnFrameRecv(IsHeaders(1, _, NGHTTP2_HCAT_RESPONSE)));
+ visitor.OnEndHeadersForStream(1);
}
TEST(ServerCallbackVisitorUnitTest, ConnectionFrames) {
testing::StrictMock<MockNghttp2Callbacks> callbacks;
CallbackVisitor visitor(Perspective::kServer,
- MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+ *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
testing::InSequence seq;
@@ -196,7 +255,7 @@ TEST(ServerCallbackVisitorUnitTest, ConnectionFrames) {
TEST(ServerCallbackVisitorUnitTest, StreamFrames) {
testing::StrictMock<MockNghttp2Callbacks> callbacks;
CallbackVisitor visitor(Perspective::kServer,
- MockNghttp2Callbacks::GetCallbacks(), &callbacks);
+ *MockNghttp2Callbacks::GetCallbacks(), &callbacks);
testing::InSequence seq;
@@ -252,6 +311,28 @@ TEST(ServerCallbackVisitorUnitTest, StreamFrames) {
EXPECT_CALL(callbacks, OnStreamClose(3, NGHTTP2_INTERNAL_ERROR));
visitor.OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR);
+
+ // Metadata events
+ constexpr size_t kMetadataBufferSize = 256;
+ char metadata_dest[kMetadataBufferSize];
+ ssize_t written = 0;
+
+ const absl::string_view kExampleFrame = "This is supposed to be metadata.";
+ EXPECT_CALL(
+ callbacks,
+ OnPackExtension(_, kMetadataBufferSize,
+ Field(&nghttp2_frame::hd,
+ HasFrameHeaderRef(5, kMetadataFrameType, _))))
+ .WillOnce(testing::Invoke(
+ [kExampleFrame](uint8_t* buf, size_t /*len*/,
+ const nghttp2_frame* /*frame*/) -> ssize_t {
+ std::memcpy(buf, kExampleFrame.data(), kExampleFrame.size());
+ return kExampleFrame.size();
+ }));
+ visitor.OnReadyToSendMetadataForStream(5, metadata_dest, kMetadataBufferSize,
+ &written);
+ ASSERT_EQ(written, kExampleFrame.size());
+ EXPECT_EQ(absl::string_view(metadata_dest, written), kExampleFrame);
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc b/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc
deleted file mode 100644
index 13f89d28581..00000000000
--- a/chromium/net/third_party/quiche/src/http2/adapter/data_source.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-#include "http2/adapter/data_source.h"
-
-namespace http2 {
-namespace adapter {
-
-StringDataSource::StringDataSource(std::string data)
- : data_(std::move(data)), remaining_(data_) {
- state_ = remaining_.empty() ? DONE : READY;
-}
-
-absl::string_view StringDataSource::NextData() const {
- return remaining_;
-}
-
-void StringDataSource::Consume(size_t bytes) {
- remaining_.remove_prefix(std::min(bytes, remaining_.size()));
- if (remaining_.empty()) {
- state_ = DONE;
- }
-}
-
-} // namespace adapter
-} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source.h b/chromium/net/third_party/quiche/src/http2/adapter/data_source.h
index e170104a597..d86714148c3 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/data_source.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/data_source.h
@@ -2,49 +2,46 @@
#define QUICHE_HTTP2_ADAPTER_DATA_SOURCE_H_
#include <string>
+#include <utility>
#include "absl/strings/string_view.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
-// Represents a HTTP message body.
-class DataSource {
+// Represents a source of DATA frames for transmission to the peer.
+class QUICHE_EXPORT_PRIVATE DataFrameSource {
public:
- virtual ~DataSource() {}
+ virtual ~DataFrameSource() {}
- enum State {
- // The source is not done, but cannot currently provide more data.
- NOT_READY,
- // The source can provide more data.
- READY,
- // The source is done.
- DONE,
- };
+ enum : ssize_t { kBlocked = 0, kError = -1 };
- State state() const { return state_; }
+ // Returns the number of bytes to send in the next DATA frame, and whether
+ // this frame indicates the end of the data. Returns {kBlocked, false} if
+ // blocked, {kError, false} on error.
+ virtual std::pair<ssize_t, bool> SelectPayloadLength(size_t max_length) = 0;
- // The next range of data provided by this data source.
- virtual absl::string_view NextData() const = 0;
+ // This method is called with a frame header and a payload length to send. The
+ // source should send or buffer the entire frame and return true, or return
+ // false without sending or buffering anything.
+ virtual bool Send(absl::string_view frame_header, size_t payload_length) = 0;
- // Indicates that |bytes| bytes have been consumed by the caller.
- virtual void Consume(size_t bytes) = 0;
-
- protected:
- State state_ = NOT_READY;
+ // If true, the end of this data source indicates the end of the stream.
+ // Otherwise, this data will be followed by trailers.
+ virtual bool send_fin() const = 0;
};
-// A simple implementation constructible from a string_view or std::string.
-class StringDataSource : public DataSource {
+// Represents a source of metadata frames for transmission to the peer.
+class QUICHE_EXPORT_PRIVATE MetadataSource {
public:
- explicit StringDataSource(std::string data);
-
- absl::string_view NextData() const override;
- void Consume(size_t bytes) override;
+ virtual ~MetadataSource() {}
- private:
- const std::string data_;
- absl::string_view remaining_;
+ // This method is called with a destination buffer and length. It should
+ // return the number of payload bytes copied to |dest|, or a negative integer
+ // to indicate an error, as well as a boolean indicating whether the metadata
+ // has been completely copied.
+ virtual std::pair<ssize_t, bool> Pack(uint8_t* dest, size_t dest_len) = 0;
};
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc
deleted file mode 100644
index c290124b430..00000000000
--- a/chromium/net/third_party/quiche/src/http2/adapter/data_source_test.cc
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "http2/adapter/data_source.h"
-
-#include "common/platform/api/quiche_test.h"
-
-namespace http2 {
-namespace adapter {
-namespace test {
-namespace {
-
-TEST(StringDataSourceTest, EmptyString) {
- StringDataSource source("");
-
- EXPECT_EQ(source.state(), DataSource::DONE);
- EXPECT_THAT(source.NextData(), testing::IsEmpty());
-}
-
-TEST(StringDataSourceTest, PartialConsume) {
- StringDataSource source("I'm a HTTP message body. Really!");
-
- EXPECT_EQ(source.state(), DataSource::READY);
- EXPECT_THAT(source.NextData(), testing::Not(testing::IsEmpty()));
- source.Consume(6);
- EXPECT_EQ(source.state(), DataSource::READY);
- EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
-
- source.Consume(0);
- EXPECT_EQ(source.state(), DataSource::READY);
- EXPECT_THAT(source.NextData(), testing::StartsWith("HTTP"));
-
- // Consumes more than the remaining bytes available.
- source.Consume(50);
- EXPECT_THAT(source.NextData(), testing::IsEmpty())
- << "next data: " << source.NextData();
- EXPECT_EQ(source.state(), DataSource::DONE);
-}
-
-} // namespace
-} // namespace test
-} // namespace adapter
-} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
index ef2ae0a5baf..789be98ae3b 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_adapter.h
@@ -4,9 +4,11 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
#include "absl/types/span.h"
+#include "http2/adapter/data_source.h"
#include "http2/adapter/http2_protocol.h"
#include "http2/adapter/http2_session.h"
#include "http2/adapter/http2_visitor_interface.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
@@ -17,11 +19,13 @@ namespace adapter {
// invokes corresponding callbacks on its passed-in Http2VisitorInterface.
// Http2Adapter is a base class shared between client-side and server-side
// implementations.
-class Http2Adapter {
+class QUICHE_EXPORT_PRIVATE Http2Adapter {
public:
Http2Adapter(const Http2Adapter&) = delete;
Http2Adapter& operator=(const Http2Adapter&) = delete;
+ virtual bool IsServerSession() const = 0;
+
// Processes the incoming |bytes| as HTTP/2 and invokes callbacks on the
// |visitor_| as appropriate.
virtual ssize_t ProcessBytes(absl::string_view bytes) = 0;
@@ -36,17 +40,15 @@ class Http2Adapter {
int weight,
bool exclusive) = 0;
- // Submits a PING on the connection. Note that nghttp2 automatically submits
- // PING acks upon receiving non-ack PINGs from the peer, so callers only use
- // this method to originate PINGs. See nghttp2_option_set_no_auto_ping_ack().
+ // Submits a PING on the connection.
virtual void SubmitPing(Http2PingId ping_id) = 0;
+ // Starts a graceful shutdown. A no-op for clients.
+ virtual void SubmitShutdownNotice() = 0;
+
// Submits a GOAWAY on the connection. Note that |last_accepted_stream_id|
- // refers to stream IDs initiated by the peer. For client-side, this last
- // stream ID must be even (or 0); for server-side, this last stream ID must be
- // odd (or 0). To submit a GOAWAY with |last_accepted_stream_id| with the
- // maximum stream ID, signaling imminent connection termination, call
- // SubmitShutdownNotice() instead (though this is only possible server-side).
+ // refers to stream IDs initiated by the peer. For a server sending this
+ // frame, this last stream ID must be odd (or 0).
virtual void SubmitGoAway(Http2StreamId last_accepted_stream_id,
Http2ErrorCode error_code,
absl::string_view opaque_data) = 0;
@@ -56,27 +58,85 @@ class Http2Adapter {
virtual void SubmitWindowUpdate(Http2StreamId stream_id,
int window_increment) = 0;
- // Submits a METADATA frame for the given stream (a |stream_id| of 0 indicates
- // connection-level METADATA). If |fin|, the frame will also have the
- // END_METADATA flag set.
- virtual void SubmitMetadata(Http2StreamId stream_id, bool fin) = 0;
+ // Submits a RST_STREAM for the given |stream_id| and |error_code|.
+ virtual void SubmitRst(Http2StreamId stream_id,
+ Http2ErrorCode error_code) = 0;
+
+ // Submits a sequence of METADATA frames for the given stream. A |stream_id|
+ // of 0 indicates connection-level METADATA.
+ virtual void SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source) = 0;
+
+ // Invokes the visitor's OnReadyToSend() method for serialized frame data.
+ // Returns 0 on success.
+ virtual int Send() = 0;
+
+ // Returns the connection-level flow control window advertised by the peer.
+ virtual int GetSendWindowSize() const = 0;
- // Returns serialized bytes for writing to the wire.
- // Writes should be submitted to Http2Adapter first, so that Http2Adapter
- // has data to serialize and return in this method.
- virtual std::string GetBytesToWrite(absl::optional<size_t> max_bytes) = 0;
+ // Returns the stream-level flow control window advertised by the peer.
+ virtual int GetStreamSendWindowSize(Http2StreamId stream_id) const = 0;
- // Returns the connection-level flow control window for the peer.
- virtual int GetPeerConnectionWindow() const = 0;
+ // Returns the current upper bound on the flow control receive window for this
+ // stream. This value does not account for data received from the peer.
+ virtual int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const = 0;
+
+ // Returns the amount of data a peer could send on a given stream. This is
+ // the outstanding stream receive window.
+ virtual int GetStreamReceiveWindowSize(Http2StreamId stream_id) const = 0;
+
+ // Returns the total amount of data a peer could send on the connection. This
+ // is the outstanding connection receive window.
+ virtual int GetReceiveWindowSize() const = 0;
+
+ // Returns the size of the HPACK encoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ virtual int GetHpackEncoderDynamicTableSize() const = 0;
+
+ // Returns the size of the HPACK decoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ virtual int GetHpackDecoderDynamicTableSize() const = 0;
+
+ // Gets the highest stream ID value seen in a frame received by this endpoint.
+ // This method is only guaranteed to work for server endpoints.
+ virtual Http2StreamId GetHighestReceivedStreamId() const = 0;
// Marks the given amount of data as consumed for the given stream, which
- // enables the nghttp2 layer to trigger WINDOW_UPDATEs as appropriate.
+ // enables the implementation layer to send WINDOW_UPDATEs as appropriate.
virtual void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) = 0;
- // Submits a RST_STREAM for the given stream.
- virtual void SubmitRst(Http2StreamId stream_id,
- Http2ErrorCode error_code) = 0;
+ // Returns the assigned stream ID if the operation succeeds. Otherwise,
+ // returns a negative integer indicating an error code. |data_source| may be
+ // nullptr if the request does not have a body.
+ virtual int32_t SubmitRequest(absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source,
+ void* user_data) = 0;
+
+ // Returns 0 on success. |data_source| may be nullptr if the response does not
+ // have a body.
+ virtual int SubmitResponse(Http2StreamId stream_id,
+ absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) = 0;
+
+ // Queues trailers to be sent after any outstanding data on the stream with ID
+ // |stream_id|. Returns 0 on success.
+ virtual int SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) = 0;
+
+ // Sets a user data pointer for the given stream. Can be called after
+ // SubmitRequest/SubmitResponse, or after receiving any frame for a given
+ // stream.
+ virtual void SetStreamUserData(Http2StreamId stream_id, void* user_data) = 0;
+
+ // Returns nullptr if the stream does not exist, or if stream user data has
+ // not been set.
+ virtual void* GetStreamUserData(Http2StreamId stream_id) = 0;
+
+ // Resumes a stream that was previously blocked (for example, due to
+ // DataFrameSource::SelectPayloadLength() returning kBlocked). Returns true if
+ // the stream was successfully resumed.
+ virtual bool ResumeStream(Http2StreamId stream_id) = 0;
protected:
// Subclasses should expose a public factory method for constructing and
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
index 8d59aeedda0..dc0a57acac5 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.cc
@@ -12,6 +12,10 @@ const char kHttp2AuthorityPseudoHeader[] = ":authority";
const char kHttp2PathPseudoHeader[] = ":path";
const char kHttp2StatusPseudoHeader[] = ":status";
+const uint8_t kMetadataFrameType = 0x4d;
+const uint8_t kMetadataEndFlag = 0x04;
+const uint16_t kMetadataExtensionId = 0x4d44;
+
std::pair<absl::string_view, bool> GetStringView(const HeaderRep& rep) {
if (absl::holds_alternative<absl::string_view>(rep)) {
return std::make_pair(absl::get<absl::string_view>(rep), true);
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
index 1e1dd39a21a..9f72fbe9d05 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_protocol.h
@@ -5,10 +5,10 @@
#include <string>
#include <utility>
-#include "base/integral_types.h"
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "absl/types/variant.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
@@ -34,7 +34,7 @@ std::pair<absl::string_view, bool> GetStringView(const HeaderRep& rep);
using Header = std::pair<HeaderRep, HeaderRep>;
// Represents an HTTP/2 SETTINGS key-value parameter.
-struct Http2Setting {
+struct QUICHE_EXPORT_PRIVATE Http2Setting {
Http2SettingsId id;
uint32_t value;
};
@@ -50,17 +50,40 @@ const Http2StreamId kConnectionStreamId = 0;
// 7540 Section 6.5.2 (SETTINGS_MAX_FRAME_SIZE).
const int kDefaultFramePayloadSizeLimit = 16 * 1024;
-// The default value for the initial stream flow control window size, according
-// to RFC 7540 Section 6.9.2.
-const int kDefaultInitialStreamWindowSize = 64 * 1024 - 1;
+// The default value for the initial stream and connection flow control window
+// size, according to RFC 7540 Section 6.9.2.
+const int kInitialFlowControlWindowSize = 64 * 1024 - 1;
// The pseudo-header fields as specified in RFC 7540 Section 8.1.2.3 (request)
// and Section 8.1.2.4 (response).
-ABSL_CONST_INIT extern const char kHttp2MethodPseudoHeader[];
-ABSL_CONST_INIT extern const char kHttp2SchemePseudoHeader[];
-ABSL_CONST_INIT extern const char kHttp2AuthorityPseudoHeader[];
-ABSL_CONST_INIT extern const char kHttp2PathPseudoHeader[];
-ABSL_CONST_INIT extern const char kHttp2StatusPseudoHeader[];
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const char
+ kHttp2MethodPseudoHeader[];
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const char
+ kHttp2SchemePseudoHeader[];
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const char
+ kHttp2AuthorityPseudoHeader[];
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const char
+ kHttp2PathPseudoHeader[];
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const char
+ kHttp2StatusPseudoHeader[];
+
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const uint8_t kMetadataFrameType;
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const uint8_t kMetadataEndFlag;
+ABSL_CONST_INIT QUICHE_EXPORT_PRIVATE extern const uint16_t
+ kMetadataExtensionId;
+
+enum class FrameType : uint8_t {
+ DATA = 0x0,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+ CONTINUATION,
+};
// HTTP/2 error codes as specified in RFC 7540 Section 7.
enum class Http2ErrorCode {
@@ -94,7 +117,8 @@ enum Http2KnownSettingsId : Http2SettingsId {
INITIAL_WINDOW_SIZE = 0x4,
MAX_FRAME_SIZE = 0x5,
MAX_HEADER_LIST_SIZE = 0x6,
- MAX_SETTING = MAX_HEADER_LIST_SIZE
+ ENABLE_CONNECT_PROTOCOL = 0x8, // See RFC 8441
+ MAX_SETTING = ENABLE_CONNECT_PROTOCOL
};
// Returns a human-readable string representation of the given SETTINGS |id| for
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
index 0a6321c0ccc..3b57d8f1aba 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_session.h
@@ -5,14 +5,15 @@
#include "absl/strings/string_view.h"
#include "http2/adapter/http2_protocol.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
-struct Http2SessionCallbacks {};
+struct QUICHE_EXPORT_PRIVATE Http2SessionCallbacks {};
// A class to represent the state of a single HTTP/2 connection.
-class Http2Session {
+class QUICHE_EXPORT_PRIVATE Http2Session {
public:
Http2Session() = default;
virtual ~Http2Session() {}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
index 3ace28b2ce9..88e9a49e6e4 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_util.h
@@ -2,13 +2,16 @@
#define QUICHE_HTTP2_ADAPTER_HTTP2_UTIL_H_
#include "http2/adapter/http2_protocol.h"
+#include "common/platform/api/quiche_export.h"
#include "spdy/core/spdy_protocol.h"
namespace http2 {
namespace adapter {
-spdy::SpdyErrorCode TranslateErrorCode(Http2ErrorCode code);
-Http2ErrorCode TranslateErrorCode(spdy::SpdyErrorCode code);
+QUICHE_EXPORT_PRIVATE spdy::SpdyErrorCode TranslateErrorCode(
+ Http2ErrorCode code);
+QUICHE_EXPORT_PRIVATE Http2ErrorCode
+TranslateErrorCode(spdy::SpdyErrorCode code);
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h b/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
index 12729e75651..292021a23f4 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/http2_visitor_interface.h
@@ -5,6 +5,7 @@
#include "absl/strings/string_view.h"
#include "http2/adapter/http2_protocol.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
@@ -44,20 +45,24 @@ namespace adapter {
// - OnCloseStream()
//
// More details are at RFC 7540 (go/http2spec).
-class Http2VisitorInterface {
+class QUICHE_EXPORT_PRIVATE Http2VisitorInterface {
public:
Http2VisitorInterface(const Http2VisitorInterface&) = delete;
Http2VisitorInterface& operator=(const Http2VisitorInterface&) = delete;
virtual ~Http2VisitorInterface() = default;
+ static const ssize_t kSendBlocked = 0;
+ static const ssize_t kSendError = -1;
+ // Called when there are serialized frames to send. Should return how many
+ // bytes were actually sent. May return kSendBlocked or kSendError.
+ virtual ssize_t OnReadyToSend(absl::string_view serialized) = 0;
+
// Called when a connection-level processing error has been encountered.
virtual void OnConnectionError() = 0;
// Called when the header for a frame is received.
- virtual void OnFrameHeader(Http2StreamId stream_id,
- size_t length,
- uint8_t type,
- uint8_t flags) {}
+ virtual void OnFrameHeader(Http2StreamId /*stream_id*/, size_t /*length*/,
+ uint8_t /*type*/, uint8_t /*flags*/) {}
// Called when a non-ack SETTINGS frame is received.
virtual void OnSettingsStart() = 0;
@@ -72,15 +77,28 @@ class Http2VisitorInterface {
virtual void OnSettingsAck() = 0;
// Called when the connection receives the header block for a HEADERS frame on
- // a stream but has not yet parsed individual headers.
- virtual void OnBeginHeadersForStream(Http2StreamId stream_id) = 0;
+ // a stream but has not yet parsed individual headers. Returns false if a
+ // fatal error has occurred.
+ virtual bool OnBeginHeadersForStream(Http2StreamId stream_id) = 0;
// Called when the connection receives the header |key| and |value| for a
// stream. The HTTP/2 pseudo-headers defined in RFC 7540 Sections 8.1.2.3 and
// 8.1.2.4 are also conveyed in this callback. This method is called after
- // OnBeginHeadersForStream().
- virtual void OnHeaderForStream(Http2StreamId stream_id, absl::string_view key,
- absl::string_view value) = 0;
+ // OnBeginHeadersForStream(). May return HEADER_RST_STREAM to indicate the
+ // header block should be rejected. This will cause the library to queue a
+ // RST_STREAM frame, which will have a default error code of INTERNAL_ERROR.
+ // The visitor implementation may choose to queue a RST_STREAM with a
+ // different error code instead, which should be done before returning
+ // HEADER_RST_STREAM. Returning HEADER_CONNECTION_ERROR will lead to a
+ // non-recoverable error on the connection.
+ enum OnHeaderResult {
+ HEADER_OK,
+ HEADER_CONNECTION_ERROR,
+ HEADER_RST_STREAM,
+ };
+ virtual OnHeaderResult OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view key,
+ absl::string_view value) = 0;
// Called when the connection has received the complete header block for a
// logical HEADERS frame on a stream (which may contain CONTINUATION frames,
@@ -133,6 +151,18 @@ class Http2VisitorInterface {
virtual void OnWindowUpdate(Http2StreamId stream_id,
int window_increment) = 0;
+ // Called immediately before a frame of the given type is sent. Should return
+ // 0 on success.
+ virtual int OnBeforeFrameSent(uint8_t frame_type, Http2StreamId stream_id,
+ size_t length, uint8_t flags) = 0;
+
+ // Called immediately after a frame of the given type is sent. Should return 0
+ // on success. |error_code| is only populated for RST_STREAM and GOAWAY frame
+ // types.
+ virtual int OnFrameSent(uint8_t frame_type, Http2StreamId stream_id,
+ size_t length, uint8_t flags,
+ uint32_t error_code) = 0;
+
// Called when the connection is ready to send data for a stream. The
// implementation should write at most |length| bytes of the data payload to
// the |destination_buffer| and set |end_stream| to true IFF there will be no
@@ -144,6 +174,12 @@ class Http2VisitorInterface {
ssize_t* written,
bool* end_stream) = 0;
+ // Called when the connection receives an invalid frame. |error_code| is a
+ // negative integer error code generated by the library. A return value of
+ // false will result in the connection entering an error state, with no
+ // further frame processing possible.
+ virtual bool OnInvalidFrame(Http2StreamId stream_id, int error_code) = 0;
+
// Called when the connection is ready to write metadata for |stream_id| to
// the wire. The implementation should write at most |length| bytes of the
// serialized metadata payload to the |buffer| and set |written| to the number
@@ -155,6 +191,7 @@ class Http2VisitorInterface {
// Called when the connection receives the beginning of a METADATA frame
// (which may itself be the middle of a logical metadata block). The metadata
// payload will be provided via subsequent calls to OnMetadataForStream().
+ // TODO(birenroy): Consider removing this unnecessary method.
virtual void OnBeginMetadataForStream(Http2StreamId stream_id,
size_t payload_length) = 0;
@@ -165,7 +202,11 @@ class Http2VisitorInterface {
// Called when the connection has finished receiving a logical metadata block
// for a stream. Note that there may be multiple metadata blocks for a stream.
- virtual void OnMetadataEndForStream(Http2StreamId stream_id) = 0;
+ // Returns false if there was an error unpacking the metadata payload.
+ virtual bool OnMetadataEndForStream(Http2StreamId stream_id) = 0;
+
+ // Invoked with an error message from the application.
+ virtual void OnErrorDebug(absl::string_view message) = 0;
protected:
Http2VisitorInterface() = default;
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
index 171d40f443f..3daa8053962 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_http2_visitor.h
@@ -2,6 +2,7 @@
#define QUICHE_HTTP2_ADAPTER_MOCK_HTTP2_VISITOR_INTERFACE_H_
#include "http2/adapter/http2_visitor_interface.h"
+#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -9,10 +10,20 @@ namespace adapter {
namespace test {
// A mock visitor class, for use in tests.
-class MockHttp2Visitor : public Http2VisitorInterface {
+class QUICHE_NO_EXPORT MockHttp2Visitor : public Http2VisitorInterface {
public:
- MockHttp2Visitor() = default;
-
+ MockHttp2Visitor() {
+ ON_CALL(*this, OnBeginHeadersForStream)
+ .WillByDefault(testing::Return(true));
+ ON_CALL(*this, OnHeaderForStream).WillByDefault(testing::Return(HEADER_OK));
+ ON_CALL(*this, OnInvalidFrame).WillByDefault(testing::Return(true));
+ ON_CALL(*this, OnMetadataEndForStream).WillByDefault(testing::Return(true));
+ }
+
+ MOCK_METHOD(ssize_t,
+ OnReadyToSend,
+ (absl::string_view serialized),
+ (override));
MOCK_METHOD(void, OnConnectionError, (), (override));
MOCK_METHOD(
void,
@@ -23,15 +34,11 @@ class MockHttp2Visitor : public Http2VisitorInterface {
MOCK_METHOD(void, OnSetting, (Http2Setting setting), (override));
MOCK_METHOD(void, OnSettingsEnd, (), (override));
MOCK_METHOD(void, OnSettingsAck, (), (override));
- MOCK_METHOD(void,
- OnBeginHeadersForStream,
- (Http2StreamId stream_id),
+ MOCK_METHOD(bool, OnBeginHeadersForStream, (Http2StreamId stream_id),
(override));
- MOCK_METHOD(void,
- OnHeaderForStream,
- (Http2StreamId stream_id,
- absl::string_view key,
+ MOCK_METHOD(OnHeaderResult, OnHeaderForStream,
+ (Http2StreamId stream_id, absl::string_view key,
absl::string_view value),
(override));
@@ -89,6 +96,19 @@ class MockHttp2Visitor : public Http2VisitorInterface {
(Http2StreamId stream_id, int window_increment),
(override));
+ MOCK_METHOD(int, OnBeforeFrameSent,
+ (uint8_t frame_type, Http2StreamId stream_id, size_t length,
+ uint8_t flags),
+ (override));
+
+ MOCK_METHOD(int, OnFrameSent,
+ (uint8_t frame_type, Http2StreamId stream_id, size_t length,
+ uint8_t flags, uint32_t error_code),
+ (override));
+
+ MOCK_METHOD(bool, OnInvalidFrame, (Http2StreamId stream_id, int error_code),
+ (override));
+
MOCK_METHOD(void,
OnReadyToSendDataForStream,
(Http2StreamId stream_id,
@@ -114,10 +134,10 @@ class MockHttp2Visitor : public Http2VisitorInterface {
(Http2StreamId stream_id, absl::string_view metadata),
(override));
- MOCK_METHOD(void,
- OnMetadataEndForStream,
- (Http2StreamId stream_id),
+ MOCK_METHOD(bool, OnMetadataEndForStream, (Http2StreamId stream_id),
(override));
+
+ MOCK_METHOD(void, OnErrorDebug, (absl::string_view message), (override));
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc
index 4699a371add..4243347e758 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.cc
@@ -109,12 +109,19 @@ nghttp2_session_callbacks_unique_ptr MockNghttp2Callbacks::GetCallbacks() {
nghttp2_session_callbacks_set_error_callback2(
callbacks,
- [](nghttp2_session* session, int lib_error_code, const char* msg,
+ [](nghttp2_session* /*session*/, int lib_error_code, const char* msg,
size_t len, void* user_data) -> int {
return static_cast<MockNghttp2Callbacks*>(user_data)->OnErrorCallback2(
lib_error_code, msg, len);
});
+ nghttp2_session_callbacks_set_pack_extension_callback(
+ callbacks,
+ [](nghttp2_session*, uint8_t* buf, size_t len, const nghttp2_frame* frame,
+ void* user_data) -> ssize_t {
+ return static_cast<MockNghttp2Callbacks*>(user_data)->OnPackExtension(
+ buf, len, frame);
+ });
return MakeCallbacksPtr(callbacks);
}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h
index e2794575c8d..08d15be7d7d 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/mock_nghttp2_callbacks.h
@@ -4,6 +4,7 @@
#include "absl/strings/string_view.h"
#include "http2/adapter/nghttp2_util.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -12,7 +13,7 @@ namespace test {
// This class provides a set of mock nghttp2 callbacks for use in unit test
// expectations.
-class MockNghttp2Callbacks {
+class QUICHE_NO_EXPORT MockNghttp2Callbacks {
public:
MockNghttp2Callbacks() = default;
@@ -71,6 +72,9 @@ class MockNghttp2Callbacks {
OnErrorCallback2,
(int lib_error_code, const char* msg, size_t len),
());
+
+ MOCK_METHOD(ssize_t, OnPackExtension,
+ (uint8_t * buf, size_t len, const nghttp2_frame* frame), ());
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc
index 878c040ef72..9b444a3243d 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.cc
@@ -4,6 +4,7 @@
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "http2/adapter/nghttp2_callbacks.h"
+#include "http2/adapter/nghttp2_data_provider.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
#include "common/platform/api/quiche_logging.h"
#include "common/quiche_endian.h"
@@ -13,20 +14,26 @@ namespace adapter {
/* static */
std::unique_ptr<NgHttp2Adapter> NgHttp2Adapter::CreateClientAdapter(
- Http2VisitorInterface& visitor) {
- auto adapter = new NgHttp2Adapter(visitor, Perspective::kClient);
+ Http2VisitorInterface& visitor, const nghttp2_option* options) {
+ auto adapter = new NgHttp2Adapter(visitor, Perspective::kClient, options);
adapter->Initialize();
return absl::WrapUnique(adapter);
}
/* static */
std::unique_ptr<NgHttp2Adapter> NgHttp2Adapter::CreateServerAdapter(
- Http2VisitorInterface& visitor) {
- auto adapter = new NgHttp2Adapter(visitor, Perspective::kServer);
+ Http2VisitorInterface& visitor, const nghttp2_option* options) {
+ auto adapter = new NgHttp2Adapter(visitor, Perspective::kServer, options);
adapter->Initialize();
return absl::WrapUnique(adapter);
}
+bool NgHttp2Adapter::IsServerSession() const {
+ int result = nghttp2_session_check_server_session(session_->raw_ptr());
+ QUICHE_DCHECK_EQ(perspective_ == Perspective::kServer, result > 0);
+ return result > 0;
+}
+
ssize_t NgHttp2Adapter::ProcessBytes(absl::string_view bytes) {
const ssize_t processed_bytes = session_->ProcessBytes(bytes);
if (processed_bytes < 0) {
@@ -64,6 +71,10 @@ void NgHttp2Adapter::SubmitPing(Http2PingId ping_id) {
nghttp2_submit_ping(session_->raw_ptr(), NGHTTP2_FLAG_NONE, opaque_data);
}
+void NgHttp2Adapter::SubmitShutdownNotice() {
+ nghttp2_submit_shutdown_notice(session_->raw_ptr());
+}
+
void NgHttp2Adapter::SubmitGoAway(Http2StreamId last_accepted_stream_id,
Http2ErrorCode error_code,
absl::string_view opaque_data) {
@@ -79,32 +90,55 @@ void NgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
stream_id, window_increment);
}
-void NgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id,
- bool end_metadata) {
+void NgHttp2Adapter::SubmitMetadata(
+ Http2StreamId /*stream_id*/, std::unique_ptr<MetadataSource> /*source*/) {
QUICHE_LOG(DFATAL) << "Not implemented";
}
-std::string NgHttp2Adapter::GetBytesToWrite(absl::optional<size_t> max_bytes) {
- ssize_t num_bytes = 0;
- std::string result;
- do {
- const uint8_t* data = nullptr;
- num_bytes = nghttp2_session_mem_send(session_->raw_ptr(), &data);
- if (num_bytes > 0) {
- absl::StrAppend(
- &result,
- absl::string_view(reinterpret_cast<const char*>(data), num_bytes));
- } else if (num_bytes < 0) {
- visitor_.OnConnectionError();
- }
- } while (num_bytes > 0);
+int NgHttp2Adapter::Send() {
+ const int result = nghttp2_session_send(session_->raw_ptr());
+ if (result != 0) {
+ QUICHE_VLOG(1) << "nghttp2_session_send returned " << result;
+ visitor_.OnConnectionError();
+ }
return result;
}
-int NgHttp2Adapter::GetPeerConnectionWindow() const {
+int NgHttp2Adapter::GetSendWindowSize() const {
return session_->GetRemoteWindowSize();
}
+int NgHttp2Adapter::GetStreamSendWindowSize(Http2StreamId stream_id) const {
+ return nghttp2_session_get_stream_remote_window_size(session_->raw_ptr(),
+ stream_id);
+}
+
+int NgHttp2Adapter::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+ return nghttp2_session_get_stream_effective_local_window_size(
+ session_->raw_ptr(), stream_id);
+}
+
+int NgHttp2Adapter::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
+ return nghttp2_session_get_stream_local_window_size(session_->raw_ptr(),
+ stream_id);
+}
+
+int NgHttp2Adapter::GetReceiveWindowSize() const {
+ return nghttp2_session_get_local_window_size(session_->raw_ptr());
+}
+
+int NgHttp2Adapter::GetHpackEncoderDynamicTableSize() const {
+ return nghttp2_session_get_hd_deflate_dynamic_table_size(session_->raw_ptr());
+}
+
+int NgHttp2Adapter::GetHpackDecoderDynamicTableSize() const {
+ return nghttp2_session_get_hd_inflate_dynamic_table_size(session_->raw_ptr());
+}
+
+Http2StreamId NgHttp2Adapter::GetHighestReceivedStreamId() const {
+ return nghttp2_session_get_last_proc_stream_id(session_->raw_ptr());
+}
+
void NgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) {
int rc = session_->Consume(stream_id, num_bytes);
@@ -125,24 +159,96 @@ void NgHttp2Adapter::SubmitRst(Http2StreamId stream_id,
}
}
+int32_t NgHttp2Adapter::SubmitRequest(
+ absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source, void* stream_user_data) {
+ auto nvs = GetNghttp2Nvs(headers);
+ std::unique_ptr<nghttp2_data_provider> provider =
+ MakeDataProvider(data_source.get());
+
+ int32_t stream_id =
+ nghttp2_submit_request(session_->raw_ptr(), nullptr, nvs.data(),
+ nvs.size(), provider.get(), stream_user_data);
+ // TODO(birenroy): clean up data source on stream close
+ sources_.emplace(stream_id, std::move(data_source));
+ QUICHE_VLOG(1) << "Submitted request with " << nvs.size()
+ << " request headers and user data " << stream_user_data
+ << "; resulted in stream " << stream_id;
+ return stream_id;
+}
+
+int NgHttp2Adapter::SubmitResponse(
+ Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) {
+ auto nvs = GetNghttp2Nvs(headers);
+ std::unique_ptr<nghttp2_data_provider> provider =
+ MakeDataProvider(data_source.get());
+
+ // TODO(birenroy): clean up data source on stream close
+ sources_.emplace(stream_id, std::move(data_source));
+
+ int result = nghttp2_submit_response(session_->raw_ptr(), stream_id,
+ nvs.data(), nvs.size(), provider.get());
+ QUICHE_VLOG(1) << "Submitted response with " << nvs.size()
+ << " response headers; result = " << result;
+ return result;
+}
+
+int NgHttp2Adapter::SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) {
+ auto nvs = GetNghttp2Nvs(trailers);
+ int result = nghttp2_submit_trailer(session_->raw_ptr(), stream_id,
+ nvs.data(), nvs.size());
+ QUICHE_VLOG(1) << "Submitted trailers with " << nvs.size()
+ << " response trailers; result = " << result;
+ return result;
+}
+
+void NgHttp2Adapter::SetStreamUserData(Http2StreamId stream_id,
+ void* stream_user_data) {
+ nghttp2_session_set_stream_user_data(session_->raw_ptr(), stream_id,
+ stream_user_data);
+}
+
+void* NgHttp2Adapter::GetStreamUserData(Http2StreamId stream_id) {
+ return nghttp2_session_get_stream_user_data(session_->raw_ptr(), stream_id);
+}
+
+bool NgHttp2Adapter::ResumeStream(Http2StreamId stream_id) {
+ return 0 == nghttp2_session_resume_data(session_->raw_ptr(), stream_id);
+}
+
NgHttp2Adapter::NgHttp2Adapter(Http2VisitorInterface& visitor,
- Perspective perspective)
- : Http2Adapter(visitor), visitor_(visitor), perspective_(perspective) {}
+ Perspective perspective,
+ const nghttp2_option* options)
+ : Http2Adapter(visitor),
+ visitor_(visitor),
+ options_(options),
+ perspective_(perspective) {}
NgHttp2Adapter::~NgHttp2Adapter() {}
void NgHttp2Adapter::Initialize() {
- nghttp2_option* options;
- nghttp2_option_new(&options);
- // Set some common options for compatibility.
- nghttp2_option_set_no_closed_streams(options, 1);
- nghttp2_option_set_no_auto_window_update(options, 1);
- nghttp2_option_set_max_send_header_block_length(options, 0x2000000);
- nghttp2_option_set_max_outbound_ack(options, 10000);
-
- session_ =
- absl::make_unique<NgHttp2Session>(perspective_, callbacks::Create(),
- options, static_cast<void*>(&visitor_));
+ nghttp2_option* owned_options = nullptr;
+ if (options_ == nullptr) {
+ nghttp2_option_new(&owned_options);
+ // Set some common options for compatibility.
+ nghttp2_option_set_no_closed_streams(owned_options, 1);
+ nghttp2_option_set_no_auto_window_update(owned_options, 1);
+ nghttp2_option_set_max_send_header_block_length(owned_options, 0x2000000);
+ nghttp2_option_set_max_outbound_ack(owned_options, 10000);
+ nghttp2_option_set_user_recv_extension_type(owned_options,
+ kMetadataFrameType);
+ options_ = owned_options;
+ }
+
+ session_ = absl::make_unique<NgHttp2Session>(perspective_,
+ callbacks::Create(), options_,
+ static_cast<void*>(&visitor_));
+ if (owned_options != nullptr) {
+ nghttp2_option_del(owned_options);
+ }
+ options_ = nullptr;
}
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h
index 13c2ffcc3f4..151f9a7ae5a 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter.h
@@ -1,35 +1,34 @@
#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_ADAPTER_H_
#define QUICHE_HTTP2_ADAPTER_NGHTTP2_ADAPTER_H_
+#include "absl/container/flat_hash_map.h"
#include "http2/adapter/http2_adapter.h"
#include "http2/adapter/http2_protocol.h"
#include "http2/adapter/nghttp2_session.h"
#include "http2/adapter/nghttp2_util.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
-class NgHttp2Adapter : public Http2Adapter {
+class QUICHE_EXPORT_PRIVATE NgHttp2Adapter : public Http2Adapter {
public:
~NgHttp2Adapter() override;
- // Creates an adapter that functions as a client.
+ // Creates an adapter that functions as a client. Does not take ownership of
+ // |options|.
static std::unique_ptr<NgHttp2Adapter> CreateClientAdapter(
- Http2VisitorInterface& visitor);
+ Http2VisitorInterface& visitor, const nghttp2_option* options = nullptr);
- // Creates an adapter that functions as a server.
+ // Creates an adapter that functions as a server. Does not take ownership of
+ // |options|.
static std::unique_ptr<NgHttp2Adapter> CreateServerAdapter(
- Http2VisitorInterface& visitor);
+ Http2VisitorInterface& visitor, const nghttp2_option* options = nullptr);
- // Processes the incoming |bytes| as HTTP/2 and invokes callbacks on the
- // |visitor_| as appropriate.
- ssize_t ProcessBytes(absl::string_view bytes) override;
+ bool IsServerSession() const override;
- // Submits the |settings| to be written to the peer, e.g., as part of the
- // HTTP/2 connection preface.
+ ssize_t ProcessBytes(absl::string_view bytes) override;
void SubmitSettings(absl::Span<const Http2Setting> settings) override;
-
- // Submits a PRIORITY frame for the given stream.
void SubmitPriorityForStream(Http2StreamId stream_id,
Http2StreamId parent_stream_id,
int weight,
@@ -40,47 +39,58 @@ class NgHttp2Adapter : public Http2Adapter {
// this method to originate PINGs. See nghttp2_option_set_no_auto_ping_ack().
void SubmitPing(Http2PingId ping_id) override;
- // Submits a GOAWAY on the connection. Note that |last_accepted_stream_id|
- // refers to stream IDs initiated by the peer. For client-side, this last
- // stream ID must be even (or 0); for server-side, this last stream ID must be
- // odd (or 0).
- // TODO(birenroy): Add a graceful shutdown behavior to the API.
+ void SubmitShutdownNotice() override;
void SubmitGoAway(Http2StreamId last_accepted_stream_id,
Http2ErrorCode error_code,
absl::string_view opaque_data) override;
- // Submits a WINDOW_UPDATE for the given stream (a |stream_id| of 0 indicates
- // a connection-level WINDOW_UPDATE).
void SubmitWindowUpdate(Http2StreamId stream_id,
int window_increment) override;
- // Submits a METADATA frame for the given stream (a |stream_id| of 0 indicates
- // connection-level METADATA). If |end_metadata|, the frame will also have the
- // END_METADATA flag set.
- void SubmitMetadata(Http2StreamId stream_id, bool end_metadata) override;
+ void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+
+ void SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source) override;
+
+ int Send() override;
+
+ int GetSendWindowSize() const override;
+ int GetStreamSendWindowSize(Http2StreamId stream_id) const override;
- // Returns serialized bytes for writing to the wire. Writes should be
- // submitted to Nghttp2Adapter first, so that Nghttp2Adapter has data to
- // serialize and return in this method.
- std::string GetBytesToWrite(absl::optional<size_t> max_bytes) override;
+ int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const override;
+ int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
+ int GetReceiveWindowSize() const override;
- // Returns the connection-level flow control window for the peer.
- int GetPeerConnectionWindow() const override;
+ int GetHpackEncoderDynamicTableSize() const override;
+ int GetHpackDecoderDynamicTableSize() const override;
+
+ Http2StreamId GetHighestReceivedStreamId() const override;
- // Marks the given amount of data as consumed for the given stream, which
- // enables the nghttp2 layer to trigger WINDOW_UPDATEs as appropriate.
void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) override;
- // Submits a RST_STREAM with the desired |error_code|.
- void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+ int32_t SubmitRequest(absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source,
+ void* user_data) override;
+
+ int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) override;
+
+ int SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) override;
+
+ void SetStreamUserData(Http2StreamId stream_id, void* user_data) override;
+ void* GetStreamUserData(Http2StreamId stream_id) override;
+
+ bool ResumeStream(Http2StreamId stream_id) override;
// TODO(b/181586191): Temporary accessor until equivalent functionality is
// available in this adapter class.
NgHttp2Session& session() { return *session_; }
private:
- NgHttp2Adapter(Http2VisitorInterface& visitor, Perspective perspective);
+ NgHttp2Adapter(Http2VisitorInterface& visitor, Perspective perspective,
+ const nghttp2_option* options);
// Performs any necessary initialization of the underlying HTTP/2 session,
// such as preparing initial SETTINGS.
@@ -88,7 +98,10 @@ class NgHttp2Adapter : public Http2Adapter {
std::unique_ptr<NgHttp2Session> session_;
Http2VisitorInterface& visitor_;
+ const nghttp2_option* options_;
Perspective perspective_;
+
+ absl::flat_hash_map<int32_t, std::unique_ptr<DataFrameSource>> sources_;
};
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc
index 3aec115dbeb..785e476c94d 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_adapter_test.cc
@@ -1,6 +1,7 @@
#include "http2/adapter/nghttp2_adapter.h"
#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/nghttp2_test_utils.h"
#include "http2/adapter/test_frame_sequence.h"
#include "http2/adapter/test_utils.h"
#include "common/platform/api/quiche_test.h"
@@ -22,21 +23,46 @@ enum FrameType {
PING,
GOAWAY,
WINDOW_UPDATE,
+ CONTINUATION,
};
+// This send callback assumes |source|'s pointer is a TestDataSource, and
+// |user_data| is a Http2VisitorInterface.
+int TestSendCallback(nghttp2_session*, nghttp2_frame* /*frame*/,
+ const uint8_t* framehd, size_t length,
+ nghttp2_data_source* source, void* user_data) {
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ // Send the frame header via the visitor.
+ ssize_t result = visitor->OnReadyToSend(ToStringView(framehd, 9));
+ if (result == 0) {
+ return NGHTTP2_ERR_WOULDBLOCK;
+ }
+ auto* test_source = static_cast<TestDataSource*>(source->ptr);
+ absl::string_view payload = test_source->ReadNext(length);
+ // Send the frame payload via the visitor.
+ visitor->OnReadyToSend(payload);
+ return 0;
+}
+
TEST(NgHttp2AdapterTest, ClientConstruction) {
testing::StrictMock<MockHttp2Visitor> visitor;
auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
ASSERT_NE(nullptr, adapter);
EXPECT_TRUE(adapter->session().want_read());
EXPECT_FALSE(adapter->session().want_write());
+ EXPECT_FALSE(adapter->IsServerSession());
}
TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
- testing::StrictMock<MockHttp2Visitor> visitor;
+ DataSavingVisitor visitor;
auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
- std::string serialized = adapter->GetBytesToWrite(absl::nullopt);
- EXPECT_THAT(serialized, testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(),
+ testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+ visitor.Clear();
+
+ EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
const std::string initial_frames = TestFrameSequence()
.ServerPreface()
@@ -58,56 +84,95 @@ TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
const ssize_t initial_result = adapter->ProcessBytes(initial_frames);
EXPECT_EQ(initial_frames.size(), initial_result);
- EXPECT_EQ(adapter->GetPeerConnectionWindow(),
- kDefaultInitialStreamWindowSize + 1000);
+ EXPECT_EQ(adapter->GetSendWindowSize(), kInitialFlowControlWindowSize + 1000);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
+
+ result = adapter->Send();
// Some bytes should have been serialized.
- serialized = adapter->GetBytesToWrite(absl::nullopt);
- EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
- spdy::SpdyFrameType::PING}));
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING}));
+ visitor.Clear();
const std::vector<const Header> headers1 =
ToHeaders({{":method", "GET"},
{":scheme", "http"},
{":authority", "example.com"},
{":path", "/this/is/request/one"}});
- const auto nvs1 = GetNghttp2Nvs(headers1);
const std::vector<const Header> headers2 =
ToHeaders({{":method", "GET"},
{":scheme", "http"},
{":authority", "example.com"},
{":path", "/this/is/request/two"}});
- const auto nvs2 = GetNghttp2Nvs(headers2);
const std::vector<const Header> headers3 =
ToHeaders({{":method", "GET"},
{":scheme", "http"},
{":authority", "example.com"},
{":path", "/this/is/request/three"}});
- const auto nvs3 = GetNghttp2Nvs(headers3);
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const char* kSentinel3 = "arbitrary pointer 3";
const int32_t stream_id1 =
- nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs1.data(),
- nvs1.size(), nullptr, nullptr);
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
ASSERT_GT(stream_id1, 0);
QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
- const int32_t stream_id2 =
- nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs2.data(),
- nvs2.size(), nullptr, nullptr);
+ const int32_t stream_id2 = adapter->SubmitRequest(headers2, nullptr, nullptr);
ASSERT_GT(stream_id2, 0);
QUICHE_LOG(INFO) << "Created stream: " << stream_id2;
const int32_t stream_id3 =
- nghttp2_submit_request(adapter->session().raw_ptr(), nullptr, nvs3.data(),
- nvs3.size(), nullptr, nullptr);
+ adapter->SubmitRequest(headers3, nullptr, const_cast<char*>(kSentinel3));
ASSERT_GT(stream_id3, 0);
QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
- serialized = adapter->GetBytesToWrite(absl::nullopt);
- EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS,
- spdy::SpdyFrameType::HEADERS,
- spdy::SpdyFrameType::HEADERS}));
+ const char* kSentinel2 = "arbitrary pointer 2";
+ adapter->SetStreamUserData(stream_id2, const_cast<char*>(kSentinel2));
+ adapter->SetStreamUserData(stream_id3, nullptr);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id2, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id2, _, 0x5, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id3, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id3, _, 0x5, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ // All streams are active and have not yet received any data, so the receive
+ // window should be at the initial value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id1));
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id2));
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id3));
+
+ // Upper bound on the flow control receive window should be the initial value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowLimit(stream_id1));
+
+ // Connection has not yet received any data.
+ EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
+
+ EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
+
+ EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(stream_id1));
+ EXPECT_EQ(kSentinel2, adapter->GetStreamUserData(stream_id2));
+ EXPECT_EQ(nullptr, adapter->GetStreamUserData(stream_id3));
+
+ EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
const std::string stream_frames =
TestFrameSequence()
@@ -140,6 +205,29 @@ TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
EXPECT_EQ(stream_frames.size(), stream_result);
+ // First stream has received some data.
+ EXPECT_GT(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id1));
+ // Second stream was closed.
+ EXPECT_EQ(-1, adapter->GetStreamReceiveWindowSize(stream_id2));
+ // Third stream has not received any data.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id3));
+
+ // Connection window should be the same as the first stream.
+ EXPECT_EQ(adapter->GetReceiveWindowSize(),
+ adapter->GetStreamReceiveWindowSize(stream_id1));
+
+ // Upper bound on the flow control receive window should still be the initial
+ // value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowLimit(stream_id1));
+
+ EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
+
+ // Should be 3, but this method only works for server adapters.
+ EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
+
// Even though the client recieved a GOAWAY, streams 1 and 5 are still active.
EXPECT_TRUE(adapter->session().want_read());
@@ -154,14 +242,801 @@ TEST(NgHttp2AdapterTest, ClientHandlesFrames) {
.Data(1, "", true)
.RstStream(5, Http2ErrorCode::REFUSED_STREAM)
.Serialize());
+
+ // Should be 5, but this method only works for server adapters.
+ EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
+
// After receiving END_STREAM for 1 and RST_STREAM for 5, the session no
// longer expects reads.
EXPECT_FALSE(adapter->session().want_read());
// Client will not have anything else to write.
EXPECT_FALSE(adapter->session().want_write());
- serialized = adapter->GetBytesToWrite(absl::nullopt);
- EXPECT_THAT(serialized, testing::IsEmpty());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), testing::IsEmpty());
+}
+
+TEST(NgHttp2AdapterTest, ClientHandlesTrailers) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Headers(1, {{"final-status", "A-OK"}},
+ /*fin=*/true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "final-status", "A-OK"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(NgHttp2AdapterTest, ClientHandlesMetadata) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Metadata(0, "Example connection metadata")
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Metadata(1, "Example stream metadata")
+ .Data(1, "This is the response body.", true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnEndStream(1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(NgHttp2AdapterTest, ClientHandlesInvalidTrailers) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Headers(1, {{":bad-status", "9000"}},
+ /*fin=*/true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(
+ visitor,
+ OnErrorDebug("Invalid HTTP header field was received: frame type: 1, "
+ "stream: 1, name: [:bad-status], value: [9000]"));
+ EXPECT_CALL(visitor, OnInvalidFrame(1, -531));
+
+ // Bad status trailer will cause a PROTOCOL_ERROR. The header is never
+ // delivered in an OnHeaderForStream callback.
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, stream_id1, 4, 0x0, 1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
+}
+
+TEST(NgHttp2AdapterTest, ClientRstStreamWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
+ .WillOnce(testing::DoAll(
+ testing::InvokeWithoutArgs([&adapter]() {
+ adapter->SubmitRst(1, Http2ErrorCode::REFUSED_STREAM);
+ }),
+ testing::Return(Http2VisitorInterface::HEADER_RST_STREAM)));
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
+ EXPECT_CALL(visitor,
+ OnFrameSent(RST_STREAM, stream_id1, 4, 0x0,
+ static_cast<int>(Http2ErrorCode::REFUSED_STREAM)));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::REFUSED_STREAM));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
+}
+
+TEST(NgHttp2AdapterTest, ClientConnectionErrorWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
+ .WillOnce(
+ testing::Return(Http2VisitorInterface::HEADER_CONNECTION_ERROR));
+ EXPECT_CALL(visitor, OnConnectionError());
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(-902 /* NGHTTP2_ERR_CALLBACK_FAILURE */, stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(NgHttp2AdapterTest, ClientRejectsHeaders) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1))
+ .WillOnce(testing::Return(false));
+ // Rejecting headers leads to a connection error.
+ EXPECT_CALL(visitor, OnConnectionError());
+
+ const ssize_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(NGHTTP2_ERR_CALLBACK_FAILURE, stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(NgHttp2AdapterTest, ClientSubmitRequest) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ // Client preface does not appear to include the mandatory SETTINGS frame.
+ EXPECT_THAT(visitor.data(),
+ testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+ visitor.Clear();
+
+ const std::string initial_frames =
+ TestFrameSequence().ServerPreface().Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ const ssize_t initial_result = adapter->ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
+ EXPECT_FALSE(adapter->session().want_write());
+ const char* kSentinel = "";
+ const absl::string_view kBody = "This is an example request body.";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ body1->AppendPayload(kBody);
+ body1->EndData();
+ int stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel));
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(stream_id));
+ EXPECT_EQ(kInitialFlowControlWindowSize, adapter->GetReceiveWindowSize());
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowLimit(stream_id));
+
+ EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
+
+ // Some data was sent, so the remaining send window size should be less than
+ // the default.
+ EXPECT_LT(adapter->GetStreamSendWindowSize(stream_id),
+ kInitialFlowControlWindowSize);
+ EXPECT_GT(adapter->GetStreamSendWindowSize(stream_id), 0);
+ // Send window for a nonexistent stream is not available.
+ EXPECT_EQ(-1, adapter->GetStreamSendWindowSize(stream_id + 2));
+
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ nullptr, nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+ const char* kSentinel2 = "arbitrary pointer 2";
+ EXPECT_EQ(nullptr, adapter->GetStreamUserData(stream_id));
+ adapter->SetStreamUserData(stream_id, const_cast<char*>(kSentinel2));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+
+ EXPECT_EQ(kSentinel2, adapter->GetStreamUserData(stream_id));
+
+ // No data was sent (just HEADERS), so the remaining send window size should
+ // still be the default.
+ EXPECT_EQ(adapter->GetStreamSendWindowSize(stream_id),
+ kInitialFlowControlWindowSize);
+}
+
+// This is really a test of the MakeZeroCopyDataFrameSource adapter, but I
+// wasn't sure where else to put it.
+TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProvider) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ // Client preface does not appear to include the mandatory SETTINGS frame.
+ EXPECT_THAT(visitor.data(),
+ testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+ visitor.Clear();
+
+ const std::string initial_frames =
+ TestFrameSequence().ServerPreface().Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ const ssize_t initial_result = adapter->ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_FALSE(adapter->session().want_write());
+ const absl::string_view kBody = "This is an example request body.";
+ // This test will use TestDataSource as the source of the body payload data.
+ TestDataSource body1{kBody};
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+ nghttp2_send_data_callback send_callback = &TestSendCallback;
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
+ int stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(frame_source), nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ EXPECT_FALSE(adapter->session().want_write());
+}
+
+// This test verifies how nghttp2 behaves when a data source becomes
+// read-blocked.
+TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProviderAndReadBlock) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ const absl::string_view kBody = "This is an example request body.";
+ // This test will use TestDataSource as the source of the body payload data.
+ TestDataSource body1{kBody};
+ body1.set_is_data_available(false);
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+ nghttp2_send_data_callback send_callback = &TestSendCallback;
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
+ int stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(frame_source), nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ // Client preface does not appear to include the mandatory SETTINGS frame.
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // Resume the deferred stream.
+ body1.set_is_data_available(true);
+ EXPECT_TRUE(adapter->ResumeStream(stream_id));
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::DATA}));
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // Stream data is done, so this stream cannot be resumed.
+ EXPECT_FALSE(adapter->ResumeStream(stream_id));
+ EXPECT_FALSE(adapter->session().want_write());
+}
+
+// This test verifies how nghttp2 behaves when a data source is read block, then
+// ends with an empty DATA frame.
+TEST(NgHttp2AdapterTest, ClientSubmitRequestEmptyDataWithFin) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ const absl::string_view kEmptyBody = "";
+ // This test will use TestDataSource as the source of the body payload data.
+ TestDataSource body1{kEmptyBody};
+ body1.set_is_data_available(false);
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+ nghttp2_send_data_callback send_callback = &TestSendCallback;
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
+ int stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(frame_source), nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ // Client preface does not appear to include the mandatory SETTINGS frame.
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // Resume the deferred stream.
+ body1.set_is_data_available(true);
+ EXPECT_TRUE(adapter->ResumeStream(stream_id));
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 0, 0x1, 0));
+
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::DATA}));
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // Stream data is done, so this stream cannot be resumed.
+ EXPECT_FALSE(adapter->ResumeStream(stream_id));
+ EXPECT_FALSE(adapter->session().want_write());
+}
+
+// This test verifies how nghttp2 behaves when a connection becomes
+// write-blocked.
+TEST(NgHttp2AdapterTest, ClientSubmitRequestWithDataProviderAndWriteBlock) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateClientAdapter(visitor);
+
+ const absl::string_view kBody = "This is an example request body.";
+ // This test will use TestDataSource as the source of the body payload data.
+ TestDataSource body1{kBody};
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+ nghttp2_send_data_callback send_callback = &TestSendCallback;
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &visitor, std::move(send_callback));
+ int stream_id =
+ adapter->SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(frame_source), nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ visitor.set_is_write_blocked(true);
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), testing::IsEmpty());
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ visitor.set_is_write_blocked(false);
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+
+ // Client preface does not appear to include the mandatory SETTINGS frame.
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_FALSE(adapter->session().want_write());
}
TEST(NgHttp2AdapterTest, ServerConstruction) {
@@ -170,12 +1045,16 @@ TEST(NgHttp2AdapterTest, ServerConstruction) {
ASSERT_NE(nullptr, adapter);
EXPECT_TRUE(adapter->session().want_read());
EXPECT_FALSE(adapter->session().want_write());
+ EXPECT_TRUE(adapter->IsServerSession());
}
TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
- testing::StrictMock<MockHttp2Visitor> visitor;
+ DataSavingVisitor visitor;
auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_EQ(0, adapter->GetHighestReceivedStreamId());
+ EXPECT_EQ(0, adapter->GetHpackDecoderDynamicTableSize());
+
const std::string frames = TestFrameSequence()
.ClientPreface()
.Ping(42)
@@ -199,6 +1078,8 @@ TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
.Serialize();
testing::InSequence s;
+ const char* kSentinel1 = "arbitrary pointer 1";
+
// Client preface (empty SETTINGS)
EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
EXPECT_CALL(visitor, OnSettingsStart());
@@ -214,7 +1095,10 @@ TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
- EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1))
+ .WillOnce(testing::InvokeWithoutArgs([&adapter, kSentinel1]() {
+ adapter->SetStreamUserData(1, const_cast<char*>(kSentinel1));
+ }));
EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
@@ -237,16 +1121,506 @@ TEST(NgHttp2AdapterTest, ServerHandlesFrames) {
const ssize_t result = adapter->ProcessBytes(frames);
EXPECT_EQ(frames.size(), result);
- EXPECT_EQ(adapter->GetPeerConnectionWindow(),
- kDefaultInitialStreamWindowSize + 1000);
+ EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(1));
+
+ EXPECT_GT(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowSize(1));
+ EXPECT_EQ(adapter->GetStreamReceiveWindowSize(1),
+ adapter->GetReceiveWindowSize());
+ // Upper bound should still be the original value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ adapter->GetStreamReceiveWindowLimit(1));
+
+ EXPECT_GT(adapter->GetHpackDecoderDynamicTableSize(), 0);
+
+ // Because stream 3 has already been closed, it's not possible to set user
+ // data.
+ const char* kSentinel3 = "another arbitrary pointer";
+ adapter->SetStreamUserData(3, const_cast<char*>(kSentinel3));
+ EXPECT_EQ(nullptr, adapter->GetStreamUserData(3));
+
+ EXPECT_EQ(3, adapter->GetHighestReceivedStreamId());
+
+ EXPECT_EQ(adapter->GetSendWindowSize(), kInitialFlowControlWindowSize + 1000);
EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x1, 0));
+
+ int send_result = adapter->Send();
// Some bytes should have been serialized.
- std::string serialized = adapter->GetBytesToWrite(absl::nullopt);
+ EXPECT_EQ(0, send_result);
// SETTINGS ack, two PING acks.
- EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
- spdy::SpdyFrameType::PING,
- spdy::SpdyFrameType::PING}));
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::PING,
+ spdy::SpdyFrameType::PING}));
+}
+
+TEST(NgHttp2AdapterTest, ServerErrorWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"},
+ {"accept", "some bogus value!"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .WindowUpdate(0, 2000)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "some bogus value!"))
+ .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
+ // DATA frame is not delivered to the visitor.
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 2000));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
+ EXPECT_CALL(visitor,
+ OnFrameSent(RST_STREAM, 1, 4, 0x0,
+ static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::INTERNAL_ERROR));
+
+ int send_result = adapter->Send();
+ // Some bytes should have been serialized.
+ EXPECT_EQ(0, send_result);
+ // SETTINGS ack
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
+}
+
+TEST(NgHttp2AdapterTest, ServerSubmitResponse) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1))
+ .WillOnce(testing::InvokeWithoutArgs([&adapter, kSentinel1]() {
+ adapter->SetStreamUserData(1, const_cast<char*>(kSentinel1));
+ }));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_EQ(1, adapter->GetHighestReceivedStreamId());
+
+ // Server will want to send a SETTINGS ack.
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ int send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_EQ(0, adapter->GetHpackEncoderDynamicTableSize());
+
+ EXPECT_FALSE(adapter->session().want_write());
+ const absl::string_view kBody = "This is an example response body.";
+ // A data fin is not sent so that the stream remains open, and the flow
+ // control state can be verified.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload(kBody);
+ int submit_result = adapter->SubmitResponse(
+ 1,
+ ToHeaders({{":status", "404"},
+ {"x-comment", "I have no idea what you're talking about."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ // Stream user data should have been set successfully after receiving headers.
+ EXPECT_EQ(kSentinel1, adapter->GetStreamUserData(1));
+ adapter->SetStreamUserData(1, nullptr);
+ EXPECT_EQ(nullptr, adapter->GetStreamUserData(1));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // Some data was sent, so the remaining send window size should be less than
+ // the default.
+ EXPECT_LT(adapter->GetStreamSendWindowSize(1), kInitialFlowControlWindowSize);
+ EXPECT_GT(adapter->GetStreamSendWindowSize(1), 0);
+ // Send window for a nonexistent stream is not available.
+ EXPECT_EQ(adapter->GetStreamSendWindowSize(3), -1);
+
+ EXPECT_GT(adapter->GetHpackEncoderDynamicTableSize(), 0);
+}
+
+// Should also test: client attempts shutdown, server attempts shutdown after an
+// explicit GOAWAY.
+TEST(NgHttp2AdapterTest, ServerSendsShutdown) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ adapter->SubmitShutdownNotice();
+
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
+
+ int send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::GOAWAY}));
+}
+
+TEST(NgHttp2AdapterTest, ServerSendsTrailers) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ // Server will want to send a SETTINGS ack.
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ int send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_FALSE(adapter->session().want_write());
+ const absl::string_view kBody = "This is an example response body.";
+
+ // The body source must indicate that the end of the body is not the end of
+ // the stream.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload(kBody);
+ body1->EndData();
+ int submit_result = adapter->SubmitResponse(
+ 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // The body source has been exhausted by the call to Send() above.
+ int trailer_result = adapter->SubmitTrailer(
+ 1, ToHeaders({{"final-status", "a-ok"},
+ {"x-comment", "trailers sure are cool"}}));
+ ASSERT_EQ(trailer_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+}
+
+TEST(NgHttp2AdapterTest, ClientSendsContinuation) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true,
+ /*add_continuation=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 1));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+}
+
+TEST(NgHttp2AdapterTest, ClientSendsMetadataWithContinuation) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames =
+ TestFrameSequence()
+ .ClientPreface()
+ .Metadata(0, "Example connection metadata in multiple frames", true)
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false,
+ /*add_continuation=*/true)
+ .Metadata(1,
+ "Some stream metadata that's also sent in multiple frames",
+ true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Metadata on stream 0
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ // Metadata on stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+ EXPECT_EQ(TestFrameSequence::MetadataBlockForPayload(
+ "Example connection metadata in multiple frames"),
+ absl::StrJoin(visitor.GetMetadata(0), ""));
+ EXPECT_EQ(TestFrameSequence::MetadataBlockForPayload(
+ "Some stream metadata that's also sent in multiple frames"),
+ absl::StrJoin(visitor.GetMetadata(1), ""));
+}
+
+TEST(NgHttp2AdapterTest, ServerSendsInvalidTrailers) {
+ DataSavingVisitor visitor;
+ auto adapter = NgHttp2Adapter::CreateServerAdapter(visitor);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const ssize_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ const absl::string_view kBody = "This is an example response body.";
+
+ // The body source must indicate that the end of the body is not the end of
+ // the stream.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload(kBody);
+ body1->EndData();
+ int submit_result = adapter->SubmitResponse(
+ 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ int send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // The body source has been exhausted by the call to Send() above.
+ int trailer_result =
+ adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
+ ASSERT_EQ(trailer_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
index 8774873c95f..4a2221ea2ee 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.cc
@@ -6,6 +6,7 @@
#include "absl/strings/string_view.h"
#include "http2/adapter/http2_protocol.h"
#include "http2/adapter/http2_visitor_interface.h"
+#include "http2/adapter/nghttp2_data_provider.h"
#include "http2/adapter/nghttp2_util.h"
#include "third_party/nghttp2/nghttp2.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
@@ -16,14 +17,33 @@ namespace http2 {
namespace adapter {
namespace callbacks {
+ssize_t OnReadyToSend(nghttp2_session* /* session */, const uint8_t* data,
+ size_t length, int flags, void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ const ssize_t result = visitor->OnReadyToSend(ToStringView(data, length));
+ QUICHE_VLOG(1) << "OnReadyToSend(length=" << length << ", flags=" << flags
+ << ") returning " << result;
+ if (result > 0) {
+ return result;
+ } else if (result == Http2VisitorInterface::kSendBlocked) {
+ return -504; // NGHTTP2_ERR_WOULDBLOCK
+ } else {
+ return -902; // NGHTTP2_ERR_CALLBACK_FAILURE
+ }
+}
+
int OnBeginFrame(nghttp2_session* /* session */,
const nghttp2_frame_hd* header,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
visitor->OnFrameHeader(header->stream_id, header->length, header->type,
header->flags);
if (header->type == NGHTTP2_DATA) {
visitor->OnBeginDataForStream(header->stream_id, header->length);
+ } else if (header->type == kMetadataFrameType) {
+ visitor->OnBeginMetadataForStream(header->stream_id, header->length);
}
return 0;
}
@@ -31,10 +51,9 @@ int OnBeginFrame(nghttp2_session* /* session */,
int OnFrameReceived(nghttp2_session* /* session */,
const nghttp2_frame* frame,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
const Http2StreamId stream_id = frame->hd.stream_id;
- QUICHE_VLOG(2) << "Frame " << static_cast<int>(frame->hd.type)
- << " for stream " << stream_id;
switch (frame->hd.type) {
// The beginning of the DATA frame is handled in OnBeginFrame(), and the
// beginning of the header block is handled in client/server-specific
@@ -71,7 +90,7 @@ int OnFrameReceived(nghttp2_session* /* session */,
visitor->OnSettingsAck();
} else {
visitor->OnSettingsStart();
- for (int i = 0; i < frame->settings.niv; ++i) {
+ for (size_t i = 0; i < frame->settings.niv; ++i) {
nghttp2_settings_entry entry = frame->settings.iv[i];
// The nghttp2_settings_entry uses int32_t for the ID; we must cast.
visitor->OnSetting(Http2Setting{
@@ -129,29 +148,67 @@ int OnFrameReceived(nghttp2_session* /* session */,
int OnBeginHeaders(nghttp2_session* /* session */,
const nghttp2_frame* frame,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
- visitor->OnBeginHeadersForStream(frame->hd.stream_id);
- return 0;
+ const bool result = visitor->OnBeginHeadersForStream(frame->hd.stream_id);
+ return result ? 0 : NGHTTP2_ERR_CALLBACK_FAILURE;
}
-int OnHeader(nghttp2_session* /* session */,
- const nghttp2_frame* frame,
- nghttp2_rcbuf* name,
- nghttp2_rcbuf* value,
- uint8_t flags,
+int OnHeader(nghttp2_session* /* session */, const nghttp2_frame* frame,
+ nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t /*flags*/,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
- visitor->OnHeaderForStream(frame->hd.stream_id, ToStringView(name),
- ToStringView(value));
- return 0;
+ const Http2VisitorInterface::OnHeaderResult result =
+ visitor->OnHeaderForStream(frame->hd.stream_id, ToStringView(name),
+ ToStringView(value));
+ switch (result) {
+ case Http2VisitorInterface::HEADER_OK:
+ return 0;
+ case Http2VisitorInterface::HEADER_CONNECTION_ERROR:
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ case Http2VisitorInterface::HEADER_RST_STREAM:
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
}
-int OnDataChunk(nghttp2_session* /* session */,
- uint8_t flags,
- Http2StreamId stream_id,
- const uint8_t* data,
- size_t len,
+int OnBeforeFrameSent(nghttp2_session* /* session */,
+ const nghttp2_frame* frame, void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ LogBeforeSend(*frame);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ return visitor->OnBeforeFrameSent(frame->hd.type, frame->hd.stream_id,
+ frame->hd.length, frame->hd.flags);
+}
+
+int OnFrameSent(nghttp2_session* /* session */, const nghttp2_frame* frame,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ uint32_t error_code = 0;
+ if (frame->hd.type == NGHTTP2_RST_STREAM) {
+ error_code = frame->rst_stream.error_code;
+ } else if (frame->hd.type == NGHTTP2_GOAWAY) {
+ error_code = frame->goaway.error_code;
+ }
+ return visitor->OnFrameSent(frame->hd.type, frame->hd.stream_id,
+ frame->hd.length, frame->hd.flags, error_code);
+}
+
+int OnInvalidFrameReceived(nghttp2_session* /* session */,
+ const nghttp2_frame* frame, int lib_error_code,
+ void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ const bool result =
+ visitor->OnInvalidFrame(frame->hd.stream_id, lib_error_code);
+ return result ? 0 : NGHTTP2_ERR_CALLBACK_FAILURE;
+}
+
+int OnDataChunk(nghttp2_session* /* session */, uint8_t /*flags*/,
+ Http2StreamId stream_id, const uint8_t* data, size_t len,
+ void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
visitor->OnDataForStream(
stream_id, absl::string_view(reinterpret_cast<const char*>(data), len));
@@ -162,34 +219,63 @@ int OnStreamClosed(nghttp2_session* /* session */,
Http2StreamId stream_id,
uint32_t error_code,
void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
visitor->OnCloseStream(stream_id, ToHttp2ErrorCode(error_code));
return 0;
}
-ssize_t OnReadyToReadDataForStream(nghttp2_session* /* session */,
- Http2StreamId stream_id,
- uint8_t* dest_buffer,
- size_t max_length,
- uint32_t* data_flags,
- nghttp2_data_source* source,
- void* user_data) {
- auto* visitor = static_cast<Http2VisitorInterface*>(source->ptr);
- ssize_t bytes_to_send = 0;
- bool end_stream = false;
- visitor->OnReadyToSendDataForStream(stream_id,
- reinterpret_cast<char*>(dest_buffer),
- max_length, &bytes_to_send, &end_stream);
- if (bytes_to_send >= 0 && end_stream) {
- *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+int OnExtensionChunkReceived(nghttp2_session* /*session*/,
+ const nghttp2_frame_hd* hd, const uint8_t* data,
+ size_t len, void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ if (hd->type != kMetadataFrameType) {
+ QUICHE_LOG(ERROR) << "Unexpected frame type: "
+ << static_cast<int>(hd->type);
+ return NGHTTP2_ERR_CANCEL;
+ }
+ visitor->OnMetadataForStream(hd->stream_id, ToStringView(data, len));
+ return 0;
+}
+
+int OnUnpackExtensionCallback(nghttp2_session* /*session*/, void** /*payload*/,
+ const nghttp2_frame_hd* hd, void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ if (hd->flags == kMetadataEndFlag) {
+ const bool result = visitor->OnMetadataEndForStream(hd->stream_id);
+ if (!result) {
+ return NGHTTP2_ERR_CALLBACK_FAILURE;
+ }
}
- return bytes_to_send;
+ return 0;
+}
+
+ssize_t OnPackExtensionCallback(nghttp2_session* /*session*/, uint8_t* buf,
+ size_t len, const nghttp2_frame* frame,
+ void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ ssize_t written = 0;
+ visitor->OnReadyToSendMetadataForStream(
+ frame->hd.stream_id, reinterpret_cast<char*>(buf), len, &written);
+ return written;
+}
+
+int OnError(nghttp2_session* /*session*/, int /*lib_error_code*/,
+ const char* msg, size_t len, void* user_data) {
+ QUICHE_CHECK_NE(user_data, nullptr);
+ auto* visitor = static_cast<Http2VisitorInterface*>(user_data);
+ visitor->OnErrorDebug(absl::string_view(msg, len));
+ return 0;
}
nghttp2_session_callbacks_unique_ptr Create() {
nghttp2_session_callbacks* callbacks;
nghttp2_session_callbacks_new(&callbacks);
+ nghttp2_session_callbacks_set_send_callback(callbacks, &OnReadyToSend);
nghttp2_session_callbacks_set_on_begin_frame_callback(callbacks,
&OnBeginFrame);
nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks,
@@ -201,6 +287,21 @@ nghttp2_session_callbacks_unique_ptr Create() {
&OnDataChunk);
nghttp2_session_callbacks_set_on_stream_close_callback(callbacks,
&OnStreamClosed);
+ nghttp2_session_callbacks_set_before_frame_send_callback(callbacks,
+ &OnBeforeFrameSent);
+ nghttp2_session_callbacks_set_on_frame_send_callback(callbacks, &OnFrameSent);
+ nghttp2_session_callbacks_set_on_invalid_frame_recv_callback(
+ callbacks, &OnInvalidFrameReceived);
+ nghttp2_session_callbacks_set_error_callback2(callbacks, &OnError);
+ // on_frame_not_send_callback <- just ignored
+ nghttp2_session_callbacks_set_send_data_callback(
+ callbacks, &DataFrameSourceSendCallback);
+ nghttp2_session_callbacks_set_pack_extension_callback(
+ callbacks, &OnPackExtensionCallback);
+ nghttp2_session_callbacks_set_unpack_extension_callback(
+ callbacks, &OnUnpackExtensionCallback);
+ nghttp2_session_callbacks_set_on_extension_chunk_recv_callback(
+ callbacks, &OnExtensionChunkReceived);
return MakeCallbacksPtr(callbacks);
}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
index 5fbaee041c5..696b6847509 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_callbacks.h
@@ -13,6 +13,13 @@ namespace callbacks {
// beginning of its lifetime. It is expected that |user_data| holds an
// Http2VisitorInterface.
+// Callback once the library is ready to send serialized frames.
+ssize_t OnReadyToSend(nghttp2_session* session,
+ const uint8_t* data,
+ size_t length,
+ int flags,
+ void* user_data);
+
// Callback once a frame header has been received.
int OnBeginFrame(nghttp2_session* session, const nghttp2_frame_hd* header,
void* user_data);
@@ -31,7 +38,19 @@ int OnHeader(nghttp2_session* session, const nghttp2_frame* frame,
nghttp2_rcbuf* name, nghttp2_rcbuf* value, uint8_t flags,
void* user_data);
-// Callback once a chunk of data (from a DATA frame payload) has been received.
+// Invoked immediately before sending a frame.
+int OnBeforeFrameSent(nghttp2_session* session, const nghttp2_frame* frame,
+ void* user_data);
+
+// Invoked immediately after a frame is sent.
+int OnFrameSent(nghttp2_session* session, const nghttp2_frame* frame,
+ void* user_data);
+
+// Invoked when an invalid frame is received.
+int OnInvalidFrameReceived(nghttp2_session* session, const nghttp2_frame* frame,
+ int lib_error_code, void* user_data);
+
+// Invoked when a chunk of data (from a DATA frame payload) has been received.
int OnDataChunk(nghttp2_session* session, uint8_t flags,
Http2StreamId stream_id, const uint8_t* data, size_t len,
void* user_data);
@@ -40,13 +59,25 @@ int OnDataChunk(nghttp2_session* session, uint8_t flags,
int OnStreamClosed(nghttp2_session* session, Http2StreamId stream_id,
uint32_t error_code, void* user_data);
-// Callback once nghttp2 is ready to read data from |source| into |dest_buffer|.
-ssize_t OnReadyToReadDataForStream(nghttp2_session* session,
- Http2StreamId stream_id,
- uint8_t* dest_buffer, size_t max_length,
- uint32_t* data_flags,
- nghttp2_data_source* source,
- void* user_data);
+// Invoked when nghttp2 has a chunk of extension frame data to pass to the
+// application.
+int OnExtensionChunkReceived(nghttp2_session* session,
+ const nghttp2_frame_hd* hd, const uint8_t* data,
+ size_t len, void* user_data);
+
+// Invoked when nghttp2 wants the application to unpack an extension payload.
+int OnUnpackExtensionCallback(nghttp2_session* session, void** payload,
+ const nghttp2_frame_hd* hd, void* user_data);
+
+// Invoked when nghttp2 is ready to pack an extension payload. Returns the
+// number of bytes serialized to |buf|.
+ssize_t OnPackExtensionCallback(nghttp2_session* session, uint8_t* buf,
+ size_t len, const nghttp2_frame* frame,
+ void* user_data);
+
+// Invoked when the library has an error message to deliver.
+int OnError(nghttp2_session* session, int lib_error_code, const char* msg,
+ size_t len, void* user_data);
nghttp2_session_callbacks_unique_ptr Create();
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.cc
new file mode 100644
index 00000000000..200aa67ae29
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.cc
@@ -0,0 +1,63 @@
+#include "http2/adapter/nghttp2_data_provider.h"
+
+#include "http2/adapter/http2_visitor_interface.h"
+#include "http2/adapter/nghttp2_util.h"
+
+namespace http2 {
+namespace adapter {
+namespace callbacks {
+
+namespace {
+const size_t kFrameHeaderSize = 9;
+}
+
+ssize_t DataFrameSourceReadCallback(nghttp2_session* /* session */,
+ int32_t /* stream_id */,
+ uint8_t* /* buf */,
+ size_t length,
+ uint32_t* data_flags,
+ nghttp2_data_source* source,
+ void* /* user_data */) {
+ *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
+ auto* frame_source = static_cast<DataFrameSource*>(source->ptr);
+ auto [result_length, done] = frame_source->SelectPayloadLength(length);
+ if (result_length == 0 && !done) {
+ return NGHTTP2_ERR_DEFERRED;
+ } else if (result_length == DataFrameSource::kError) {
+ return NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
+ }
+ if (done) {
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+ }
+ if (!frame_source->send_fin()) {
+ *data_flags |= NGHTTP2_DATA_FLAG_NO_END_STREAM;
+ }
+ return result_length;
+}
+
+int DataFrameSourceSendCallback(nghttp2_session* /* session */,
+ nghttp2_frame* /* frame */,
+ const uint8_t* framehd,
+ size_t length,
+ nghttp2_data_source* source,
+ void* /* user_data */) {
+ auto* frame_source = static_cast<DataFrameSource*>(source->ptr);
+ frame_source->Send(ToStringView(framehd, kFrameHeaderSize), length);
+ return 0;
+}
+
+} // namespace callbacks
+
+std::unique_ptr<nghttp2_data_provider> MakeDataProvider(
+ DataFrameSource* source) {
+ if (source == nullptr) {
+ return nullptr;
+ }
+ auto provider = absl::make_unique<nghttp2_data_provider>();
+ provider->source.ptr = source;
+ provider->read_callback = &callbacks::DataFrameSourceReadCallback;
+ return provider;
+}
+
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.h
new file mode 100644
index 00000000000..241bab91cdd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider.h
@@ -0,0 +1,37 @@
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_DATA_PROVIDER_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_DATA_PROVIDER_H_
+
+#include "http2/adapter/data_source.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+
+namespace http2 {
+namespace adapter {
+namespace callbacks {
+
+// Assumes |source| is a DataFrameSource.
+ssize_t DataFrameSourceReadCallback(nghttp2_session* /*session */,
+ int32_t /* stream_id */,
+ uint8_t* /* buf */,
+ size_t length,
+ uint32_t* data_flags,
+ nghttp2_data_source* source,
+ void* /* user_data */);
+
+int DataFrameSourceSendCallback(nghttp2_session* /* session */,
+ nghttp2_frame* /* frame */,
+ const uint8_t* framehd,
+ size_t length,
+ nghttp2_data_source* source,
+ void* /* user_data */);
+
+} // namespace callbacks
+
+// Transforms a DataFrameSource into a nghttp2_data_provider. Does not take
+// ownership of |source|. Returns nullptr if |source| is nullptr.
+std::unique_ptr<nghttp2_data_provider> MakeDataProvider(
+ DataFrameSource* source);
+
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_DATA_PROVIDER_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider_test.cc
new file mode 100644
index 00000000000..af8d98187f2
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_data_provider_test.cc
@@ -0,0 +1,117 @@
+#include "http2/adapter/nghttp2_data_provider.h"
+
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+const size_t kFrameHeaderSize = 9;
+
+// Verifies that a nghttp2_data_provider derived from a DataFrameSource works
+// correctly with nghttp2-style callbacks when the amount of data read is less
+// than what the source provides.
+TEST(DataProviderTest, ReadLessThanSourceProvides) {
+ DataSavingVisitor visitor;
+ TestDataFrameSource source(visitor, true);
+ source.AppendPayload("Example payload");
+ source.EndData();
+ auto provider = MakeDataProvider(&source);
+ uint32_t data_flags = 0;
+ const int32_t kStreamId = 1;
+ const size_t kReadLength = 10;
+ // Read callback selects a payload length given an upper bound.
+ ssize_t result =
+ provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
+ &data_flags, &provider->source, nullptr);
+ ASSERT_EQ(kReadLength, result);
+ EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY, data_flags);
+
+ const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ // Sends the frame header and some payload bytes.
+ int send_result = callbacks::DataFrameSourceSendCallback(
+ nullptr, nullptr, framehd, result, &provider->source, nullptr);
+ EXPECT_EQ(0, send_result);
+ // Data accepted by the visitor includes a frame header and kReadLength bytes
+ // of payload.
+ EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kReadLength);
+}
+
+// Verifies that a nghttp2_data_provider derived from a DataFrameSource works
+// correctly with nghttp2-style callbacks when the amount of data read is more
+// than what the source provides.
+TEST(DataProviderTest, ReadMoreThanSourceProvides) {
+ DataSavingVisitor visitor;
+ const absl::string_view kPayload = "Example payload";
+ TestDataFrameSource source(visitor, true);
+ source.AppendPayload(kPayload);
+ source.EndData();
+ auto provider = MakeDataProvider(&source);
+ uint32_t data_flags = 0;
+ const int32_t kStreamId = 1;
+ const size_t kReadLength = 30;
+ // Read callback selects a payload length given an upper bound.
+ ssize_t result =
+ provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
+ &data_flags, &provider->source, nullptr);
+ ASSERT_EQ(kPayload.size(), result);
+ EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags);
+
+ const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ // Sends the frame header and some payload bytes.
+ int send_result = callbacks::DataFrameSourceSendCallback(
+ nullptr, nullptr, framehd, result, &provider->source, nullptr);
+ EXPECT_EQ(0, send_result);
+ // Data accepted by the visitor includes a frame header and the entire
+ // payload.
+ EXPECT_EQ(visitor.data().size(), kFrameHeaderSize + kPayload.size());
+}
+
+// Verifies that a nghttp2_data_provider derived from a DataFrameSource works
+// correctly with nghttp2-style callbacks when the source is blocked.
+TEST(DataProviderTest, ReadFromBlockedSource) {
+ DataSavingVisitor visitor;
+ // Source has no payload, but also no fin, so it's blocked.
+ TestDataFrameSource source(visitor, false);
+ auto provider = MakeDataProvider(&source);
+ uint32_t data_flags = 0;
+ const int32_t kStreamId = 1;
+ const size_t kReadLength = 10;
+ ssize_t result =
+ provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
+ &data_flags, &provider->source, nullptr);
+ // Read operation is deferred, since the source is blocked.
+ EXPECT_EQ(NGHTTP2_ERR_DEFERRED, result);
+}
+
+// Verifies that a nghttp2_data_provider derived from a DataFrameSource works
+// correctly with nghttp2-style callbacks when the source provides only fin and
+// no data.
+TEST(DataProviderTest, ReadFromZeroLengthSource) {
+ DataSavingVisitor visitor;
+ // Empty payload and fin=true indicates the source is done.
+ TestDataFrameSource source(visitor, true);
+ source.EndData();
+ auto provider = MakeDataProvider(&source);
+ uint32_t data_flags = 0;
+ const int32_t kStreamId = 1;
+ const size_t kReadLength = 10;
+ ssize_t result =
+ provider->read_callback(nullptr, kStreamId, nullptr, kReadLength,
+ &data_flags, &provider->source, nullptr);
+ ASSERT_EQ(0, result);
+ EXPECT_EQ(NGHTTP2_DATA_FLAG_NO_COPY | NGHTTP2_DATA_FLAG_EOF, data_flags);
+
+ const uint8_t framehd[kFrameHeaderSize] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
+ int send_result = callbacks::DataFrameSourceSendCallback(
+ nullptr, nullptr, framehd, result, &provider->source, nullptr);
+ EXPECT_EQ(0, send_result);
+ // Data accepted by the visitor includes a frame header with fin and zero
+ // bytes of payload.
+ EXPECT_EQ(visitor.data().size(), kFrameHeaderSize);
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc
index d434b06e0f5..9868958bc67 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.cc
@@ -4,35 +4,21 @@
namespace http2 {
namespace adapter {
-namespace {
-
-void DeleteOptions(nghttp2_option* options) {
- if (options) {
- nghttp2_option_del(options);
- }
-}
-
-} // namespace
NgHttp2Session::NgHttp2Session(Perspective perspective,
nghttp2_session_callbacks_unique_ptr callbacks,
- nghttp2_option* options,
- void* userdata)
- : session_(MakeSessionPtr(nullptr)),
- options_(options, DeleteOptions),
- perspective_(perspective) {
+ const nghttp2_option* options, void* userdata)
+ : session_(MakeSessionPtr(nullptr)), perspective_(perspective) {
nghttp2_session* session;
switch (perspective) {
case Perspective::kClient:
- nghttp2_session_client_new2(&session, callbacks.get(), userdata,
- options_.get());
+ nghttp2_session_client_new2(&session, callbacks.get(), userdata, options);
break;
case Perspective::kServer:
- nghttp2_session_server_new2(&session, callbacks.get(), userdata,
- options_.get());
+ nghttp2_session_server_new2(&session, callbacks.get(), userdata, options);
break;
}
- session_.reset(session);
+ session_ = MakeSessionPtr(session);
}
NgHttp2Session::~NgHttp2Session() {
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h
index d446a07c75b..4339875588c 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session.h
@@ -4,18 +4,18 @@
#include "http2/adapter/http2_session.h"
#include "http2/adapter/nghttp2_util.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
// A C++ wrapper around common nghttp2_session operations.
-class NgHttp2Session : public Http2Session {
+class QUICHE_EXPORT_PRIVATE NgHttp2Session : public Http2Session {
public:
- // Takes ownership of |options|.
+ // Does not take ownership of |options|.
NgHttp2Session(Perspective perspective,
nghttp2_session_callbacks_unique_ptr callbacks,
- nghttp2_option* options,
- void* userdata);
+ const nghttp2_option* options, void* userdata);
~NgHttp2Session() override;
ssize_t ProcessBytes(absl::string_view bytes) override;
@@ -29,10 +29,7 @@ class NgHttp2Session : public Http2Session {
nghttp2_session* raw_ptr() const { return session_.get(); }
private:
- using OptionsDeleter = void (&)(nghttp2_option*);
-
nghttp2_session_unique_ptr session_;
- std::unique_ptr<nghttp2_option, OptionsDeleter> options_;
Perspective perspective_;
};
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc
index 169d2f20dd0..487843bcc52 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_session_test.cc
@@ -26,47 +26,36 @@ enum FrameType {
WINDOW_UPDATE,
};
-ssize_t SaveSessionOutput(nghttp2_session* /* session*/,
- const uint8_t* data,
- size_t length,
- int /* flags */,
- void* user_data) {
- auto visitor = static_cast<DataSavingVisitor*>(user_data);
- visitor->Save(ToStringView(data, length));
- return length;
-}
-
class NgHttp2SessionTest : public testing::Test {
public:
- nghttp2_option* CreateOptions() {
- nghttp2_option* options;
- nghttp2_option_new(&options);
- nghttp2_option_set_no_auto_window_update(options, 1);
- return options;
+ void SetUp() override {
+ nghttp2_option_new(&options_);
+ nghttp2_option_set_no_auto_window_update(options_, 1);
}
+ void TearDown() override { nghttp2_option_del(options_); }
+
nghttp2_session_callbacks_unique_ptr CreateCallbacks() {
nghttp2_session_callbacks_unique_ptr callbacks = callbacks::Create();
- nghttp2_session_callbacks_set_send_callback(callbacks.get(),
- &SaveSessionOutput);
return callbacks;
}
DataSavingVisitor visitor_;
+ nghttp2_option* options_ = nullptr;
};
TEST_F(NgHttp2SessionTest, ClientConstruction) {
- NgHttp2Session session(Perspective::kClient, CreateCallbacks(),
- CreateOptions(), &visitor_);
+ NgHttp2Session session(Perspective::kClient, CreateCallbacks(), options_,
+ &visitor_);
EXPECT_TRUE(session.want_read());
EXPECT_FALSE(session.want_write());
- EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
EXPECT_NE(session.raw_ptr(), nullptr);
}
TEST_F(NgHttp2SessionTest, ClientHandlesFrames) {
- NgHttp2Session session(Perspective::kClient, CreateCallbacks(),
- CreateOptions(), &visitor_);
+ NgHttp2Session session(Perspective::kClient, CreateCallbacks(), options_,
+ &visitor_);
ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
ASSERT_GT(visitor_.data().size(), 0);
@@ -92,7 +81,13 @@ TEST_F(NgHttp2SessionTest, ClientHandlesFrames) {
EXPECT_EQ(initial_frames.size(), initial_result);
EXPECT_EQ(session.GetRemoteWindowSize(),
- kDefaultInitialStreamWindowSize + 1000);
+ kInitialFlowControlWindowSize + 1000);
+
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor_, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor_, OnFrameSent(PING, 0, 8, 0x1, 0));
+
ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
// Some bytes should have been serialized.
absl::string_view serialized = visitor_.data();
@@ -139,6 +134,13 @@ TEST_F(NgHttp2SessionTest, ClientHandlesFrames) {
ASSERT_GT(stream_id3, 0);
QUICHE_LOG(INFO) << "Created stream: " << stream_id3;
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor_, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(HEADERS, 3, _, 0x5));
+ EXPECT_CALL(visitor_, OnFrameSent(HEADERS, 3, _, 0x5, 0));
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(HEADERS, 5, _, 0x5));
+ EXPECT_CALL(visitor_, OnFrameSent(HEADERS, 5, _, 0x5, 0));
+
ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
serialized = visitor_.data();
EXPECT_THAT(serialized, EqualsFrames({spdy::SpdyFrameType::HEADERS,
@@ -203,17 +205,17 @@ TEST_F(NgHttp2SessionTest, ClientHandlesFrames) {
}
TEST_F(NgHttp2SessionTest, ServerConstruction) {
- NgHttp2Session session(Perspective::kServer, CreateCallbacks(),
- CreateOptions(), &visitor_);
+ NgHttp2Session session(Perspective::kServer, CreateCallbacks(), options_,
+ &visitor_);
EXPECT_TRUE(session.want_read());
EXPECT_FALSE(session.want_write());
- EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
EXPECT_NE(session.raw_ptr(), nullptr);
}
TEST_F(NgHttp2SessionTest, ServerHandlesFrames) {
- NgHttp2Session session(Perspective::kServer, CreateCallbacks(),
- CreateOptions(), &visitor_);
+ NgHttp2Session session(Perspective::kServer, CreateCallbacks(), options_,
+ &visitor_);
const std::string frames = TestFrameSequence()
.ClientPreface()
@@ -277,7 +279,14 @@ TEST_F(NgHttp2SessionTest, ServerHandlesFrames) {
EXPECT_EQ(frames.size(), result);
EXPECT_EQ(session.GetRemoteWindowSize(),
- kDefaultInitialStreamWindowSize + 1000);
+ kInitialFlowControlWindowSize + 1000);
+
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor_, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor_, OnFrameSent(PING, 0, 8, 0x1, 0));
+ EXPECT_CALL(visitor_, OnBeforeFrameSent(PING, 0, 8, 0x1));
+ EXPECT_CALL(visitor_, OnFrameSent(PING, 0, 8, 0x1, 0));
EXPECT_TRUE(session.want_write());
ASSERT_EQ(0, nghttp2_session_send(session.raw_ptr()));
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test.cc
new file mode 100644
index 00000000000..0b977dc1815
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test.cc
@@ -0,0 +1,205 @@
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+
+#include "absl/strings/str_cat.h"
+#include "http2/adapter/mock_nghttp2_callbacks.h"
+#include "http2/adapter/nghttp2_test_utils.h"
+#include "http2/adapter/nghttp2_util.h"
+#include "http2/adapter/test_frame_sequence.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+};
+
+nghttp2_option* GetOptions() {
+ nghttp2_option* options;
+ nghttp2_option_new(&options);
+ // Set some common options for compatibility.
+ nghttp2_option_set_no_closed_streams(options, 1);
+ nghttp2_option_set_no_auto_window_update(options, 1);
+ nghttp2_option_set_max_send_header_block_length(options, 0x2000000);
+ nghttp2_option_set_max_outbound_ack(options, 10000);
+ return options;
+}
+
+class Nghttp2Test : public testing::Test {
+ public:
+ Nghttp2Test() : session_(MakeSessionPtr(nullptr)) {}
+
+ void SetUp() override { InitializeSession(); }
+
+ virtual Perspective GetPerspective() = 0;
+
+ void InitializeSession() {
+ auto nghttp2_callbacks = MockNghttp2Callbacks::GetCallbacks();
+ nghttp2_option* options = GetOptions();
+ nghttp2_session* ptr;
+ if (GetPerspective() == Perspective::kClient) {
+ nghttp2_session_client_new2(&ptr, nghttp2_callbacks.get(),
+ &mock_callbacks_, options);
+ } else {
+ nghttp2_session_server_new2(&ptr, nghttp2_callbacks.get(),
+ &mock_callbacks_, options);
+ }
+ nghttp2_option_del(options);
+
+ // Sets up the Send() callback to append to |serialized_|.
+ EXPECT_CALL(mock_callbacks_, Send(_, _, _))
+ .WillRepeatedly(
+ [this](const uint8_t* data, size_t length, int /*flags*/) {
+ absl::StrAppend(&serialized_, ToStringView(data, length));
+ return length;
+ });
+ // Sets up the SendData() callback to fetch and append data from a
+ // TestDataSource.
+ EXPECT_CALL(mock_callbacks_, SendData(_, _, _, _))
+ .WillRepeatedly([this](nghttp2_frame* /*frame*/, const uint8_t* framehd,
+ size_t length, nghttp2_data_source* source) {
+ QUICHE_LOG(INFO) << "Appending frame header and " << length
+ << " bytes of data";
+ auto* s = static_cast<TestDataSource*>(source->ptr);
+ absl::StrAppend(&serialized_, ToStringView(framehd, 9),
+ s->ReadNext(length));
+ return 0;
+ });
+ session_ = MakeSessionPtr(ptr);
+ }
+
+ testing::StrictMock<MockNghttp2Callbacks> mock_callbacks_;
+ nghttp2_session_unique_ptr session_;
+ std::string serialized_;
+};
+
+class Nghttp2ClientTest : public Nghttp2Test {
+ public:
+ Perspective GetPerspective() override { return Perspective::kClient; }
+};
+
+// Verifies nghttp2 behavior when acting as a client.
+TEST_F(Nghttp2ClientTest, ClientReceivesUnexpectedHeaders) {
+ const std::string initial_frames = TestFrameSequence()
+ .ServerPreface()
+ .Ping(42)
+ .WindowUpdate(0, 1000)
+ .Serialize();
+
+ testing::InSequence seq;
+ EXPECT_CALL(mock_callbacks_, OnBeginFrame(HasFrameHeader(0, SETTINGS, 0)));
+ EXPECT_CALL(mock_callbacks_, OnFrameRecv(IsSettings(testing::IsEmpty())));
+ EXPECT_CALL(mock_callbacks_, OnBeginFrame(HasFrameHeader(0, PING, 0)));
+ EXPECT_CALL(mock_callbacks_, OnFrameRecv(IsPing(42)));
+ EXPECT_CALL(mock_callbacks_,
+ OnBeginFrame(HasFrameHeader(0, WINDOW_UPDATE, 0)));
+ EXPECT_CALL(mock_callbacks_, OnFrameRecv(IsWindowUpdate(1000)));
+
+ ssize_t result = nghttp2_session_mem_recv(
+ session_.get(), ToUint8Ptr(initial_frames.data()), initial_frames.size());
+ ASSERT_EQ(result, initial_frames.size());
+
+ const std::string unexpected_stream_frames =
+ TestFrameSequence()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
+ .GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
+ .Serialize();
+
+ EXPECT_CALL(mock_callbacks_, OnBeginFrame(HasFrameHeader(1, HEADERS, _)));
+ EXPECT_CALL(mock_callbacks_, OnInvalidFrameRecv(IsHeaders(1, _, _), _));
+ // No events from the DATA, RST_STREAM or GOAWAY.
+
+ nghttp2_session_mem_recv(session_.get(),
+ ToUint8Ptr(unexpected_stream_frames.data()),
+ unexpected_stream_frames.size());
+}
+
+// Tests the request-sending behavior of nghttp2 when acting as a client.
+TEST_F(Nghttp2ClientTest, ClientSendsRequest) {
+ int result = nghttp2_session_send(session_.get());
+ ASSERT_EQ(result, 0);
+
+ EXPECT_THAT(serialized_, testing::StrEq(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized_.clear();
+
+ const std::string initial_frames =
+ TestFrameSequence().ServerPreface().Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(mock_callbacks_, OnBeginFrame(HasFrameHeader(0, SETTINGS, 0)));
+ EXPECT_CALL(mock_callbacks_, OnFrameRecv(IsSettings(testing::IsEmpty())));
+
+ ssize_t recv_result = nghttp2_session_mem_recv(
+ session_.get(), ToUint8Ptr(initial_frames.data()), initial_frames.size());
+ EXPECT_EQ(initial_frames.size(), recv_result);
+
+ // Client wants to send a SETTINGS ack.
+ EXPECT_CALL(mock_callbacks_, BeforeFrameSend(IsSettings(testing::IsEmpty())));
+ EXPECT_CALL(mock_callbacks_, OnFrameSend(IsSettings(testing::IsEmpty())));
+ EXPECT_TRUE(nghttp2_session_want_write(session_.get()));
+ result = nghttp2_session_send(session_.get());
+ EXPECT_THAT(serialized_, EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+ serialized_.clear();
+
+ EXPECT_FALSE(nghttp2_session_want_write(session_.get()));
+
+ // The following sets up the client request.
+ std::vector<std::pair<absl::string_view, absl::string_view>> headers = {
+ {":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}};
+ std::vector<nghttp2_nv> nvs;
+ for (const auto& h : headers) {
+ nvs.push_back({.name = ToUint8Ptr(h.first.data()),
+ .value = ToUint8Ptr(h.second.data()),
+ .namelen = h.first.size(),
+ .valuelen = h.second.size()});
+ }
+ const absl::string_view kBody = "This is an example request body.";
+ TestDataSource source{kBody};
+ nghttp2_data_provider provider = source.MakeDataProvider();
+ // After submitting the request, the client will want to write.
+ int stream_id =
+ nghttp2_submit_request(session_.get(), nullptr /* pri_spec */, nvs.data(),
+ nvs.size(), &provider, nullptr /* stream_data */);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(nghttp2_session_want_write(session_.get()));
+
+ // We expect that the client will want to write HEADERS, then DATA.
+ EXPECT_CALL(mock_callbacks_, BeforeFrameSend(IsHeaders(stream_id, _, _)));
+ EXPECT_CALL(mock_callbacks_, OnFrameSend(IsHeaders(stream_id, _, _)));
+ EXPECT_CALL(mock_callbacks_, OnFrameSend(IsData(stream_id, kBody.size(), _)));
+ nghttp2_session_send(session_.get());
+ EXPECT_THAT(serialized_, EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(serialized_, testing::HasSubstr(kBody));
+
+ // Once the request is flushed, the client no longer wants to write.
+ EXPECT_FALSE(nghttp2_session_want_write(session_.get()));
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.cc
new file mode 100644
index 00000000000..d9a04f27772
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.cc
@@ -0,0 +1,454 @@
+#include "http2/adapter/nghttp2_test_utils.h"
+
+#include "http2/adapter/nghttp2_util.h"
+#include "common/quiche_endian.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+namespace {
+
+// Custom gMock matcher, used to implement HasFrameHeader().
+class FrameHeaderMatcher {
+ public:
+ FrameHeaderMatcher(int32_t streamid, uint8_t type,
+ const testing::Matcher<int> flags)
+ : stream_id_(streamid), type_(type), flags_(flags) {}
+
+ bool Match(const nghttp2_frame_hd& frame,
+ testing::MatchResultListener* listener) const {
+ bool matched = true;
+ if (stream_id_ != frame.stream_id) {
+ *listener << "; expected stream " << stream_id_ << ", saw "
+ << frame.stream_id;
+ matched = false;
+ }
+ if (type_ != frame.type) {
+ *listener << "; expected frame type " << type_ << ", saw "
+ << static_cast<int>(frame.type);
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame.flags, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const {
+ *os << "contains a frame header with stream " << stream_id_ << ", type "
+ << type_ << ", ";
+ flags_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const {
+ *os << "does not contain a frame header with stream " << stream_id_
+ << ", type " << type_ << ", ";
+ flags_.DescribeNegationTo(os);
+ }
+
+ private:
+ const int32_t stream_id_;
+ const int type_;
+ const testing::Matcher<int> flags_;
+};
+
+class PointerToFrameHeaderMatcher
+ : public FrameHeaderMatcher,
+ public testing::MatcherInterface<const nghttp2_frame_hd*> {
+ public:
+ PointerToFrameHeaderMatcher(int32_t streamid, uint8_t type,
+ const testing::Matcher<int> flags)
+ : FrameHeaderMatcher(streamid, type, flags) {}
+
+ bool MatchAndExplain(const nghttp2_frame_hd* frame,
+ testing::MatchResultListener* listener) const override {
+ return FrameHeaderMatcher::Match(*frame, listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ FrameHeaderMatcher::DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ FrameHeaderMatcher::DescribeNegationTo(os);
+ }
+};
+
+class ReferenceToFrameHeaderMatcher
+ : public FrameHeaderMatcher,
+ public testing::MatcherInterface<const nghttp2_frame_hd&> {
+ public:
+ ReferenceToFrameHeaderMatcher(int32_t streamid, uint8_t type,
+ const testing::Matcher<int> flags)
+ : FrameHeaderMatcher(streamid, type, flags) {}
+
+ bool MatchAndExplain(const nghttp2_frame_hd& frame,
+ testing::MatchResultListener* listener) const override {
+ return FrameHeaderMatcher::Match(frame, listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ FrameHeaderMatcher::DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ FrameHeaderMatcher::DescribeNegationTo(os);
+ }
+};
+
+class DataMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ DataMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length,
+ const testing::Matcher<int> flags)
+ : stream_id_(stream_id), length_(length), flags_(flags) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_DATA) {
+ *listener << "; expected DATA frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!length_.MatchAndExplain(frame->hd.length, listener)) {
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a DATA frame, ";
+ stream_id_.DescribeTo(os);
+ length_.DescribeTo(os);
+ flags_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a DATA frame, ";
+ stream_id_.DescribeNegationTo(os);
+ length_.DescribeNegationTo(os);
+ flags_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<size_t> length_;
+ const testing::Matcher<int> flags_;
+};
+
+class HeadersMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ HeadersMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags,
+ const testing::Matcher<int> category)
+ : stream_id_(stream_id), flags_(flags), category_(category) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_HEADERS) {
+ *listener << "; expected HEADERS frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
+ matched = false;
+ }
+ if (!category_.MatchAndExplain(frame->headers.cat, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a HEADERS frame, ";
+ stream_id_.DescribeTo(os);
+ flags_.DescribeTo(os);
+ category_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a HEADERS frame, ";
+ stream_id_.DescribeNegationTo(os);
+ flags_.DescribeNegationTo(os);
+ category_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<int> flags_;
+ const testing::Matcher<int> category_;
+};
+
+class RstStreamMatcher
+ : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ RstStreamMatcher(const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code)
+ : stream_id_(stream_id), error_code_(error_code) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_RST_STREAM) {
+ *listener << "; expected RST_STREAM frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
+ matched = false;
+ }
+ if (!error_code_.MatchAndExplain(frame->rst_stream.error_code, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a RST_STREAM frame, ";
+ stream_id_.DescribeTo(os);
+ error_code_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a RST_STREAM frame, ";
+ stream_id_.DescribeNegationTo(os);
+ error_code_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> stream_id_;
+ const testing::Matcher<uint32_t> error_code_;
+};
+
+class SettingsMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ SettingsMatcher(const testing::Matcher<std::vector<Http2Setting>> values)
+ : values_(values) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_SETTINGS) {
+ *listener << "; expected SETTINGS frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ std::vector<Http2Setting> settings;
+ settings.reserve(frame->settings.niv);
+ for (size_t i = 0; i < frame->settings.niv; ++i) {
+ const auto& p = frame->settings.iv[i];
+ settings.push_back({static_cast<uint16_t>(p.settings_id), p.value});
+ }
+ return values_.MatchAndExplain(settings, listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a SETTINGS frame, ";
+ values_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a SETTINGS frame, ";
+ values_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<std::vector<Http2Setting>> values_;
+};
+
+class PingMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ PingMatcher(const testing::Matcher<uint64_t> id, bool is_ack)
+ : id_(id), is_ack_(is_ack) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_PING) {
+ *listener << "; expected PING frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ bool frame_ack = frame->hd.flags & NGHTTP2_FLAG_ACK;
+ if (is_ack_ != frame_ack) {
+ *listener << "; expected is_ack=" << is_ack_ << ", saw " << frame_ack;
+ matched = false;
+ }
+ uint64_t data;
+ std::memcpy(&data, frame->ping.opaque_data, sizeof(data));
+ data = quiche::QuicheEndian::HostToNet64(data);
+ if (!id_.MatchAndExplain(data, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a PING frame, ";
+ id_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a PING frame, ";
+ id_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint64_t> id_;
+ const bool is_ack_;
+};
+
+class GoAwayMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ GoAwayMatcher(const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data)
+ : last_stream_id_(last_stream_id),
+ error_code_(error_code),
+ opaque_data_(opaque_data) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_GOAWAY) {
+ *listener << "; expected GOAWAY frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ bool matched = true;
+ if (!last_stream_id_.MatchAndExplain(frame->goaway.last_stream_id,
+ listener)) {
+ matched = false;
+ }
+ if (!error_code_.MatchAndExplain(frame->goaway.error_code, listener)) {
+ matched = false;
+ }
+ auto opaque_data =
+ ToStringView(frame->goaway.opaque_data, frame->goaway.opaque_data_len);
+ if (!opaque_data_.MatchAndExplain(opaque_data, listener)) {
+ matched = false;
+ }
+ return matched;
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a GOAWAY frame, ";
+ last_stream_id_.DescribeTo(os);
+ error_code_.DescribeTo(os);
+ opaque_data_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a GOAWAY frame, ";
+ last_stream_id_.DescribeNegationTo(os);
+ error_code_.DescribeNegationTo(os);
+ opaque_data_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> last_stream_id_;
+ const testing::Matcher<uint32_t> error_code_;
+ const testing::Matcher<absl::string_view> opaque_data_;
+};
+
+class WindowUpdateMatcher
+ : public testing::MatcherInterface<const nghttp2_frame*> {
+ public:
+ WindowUpdateMatcher(const testing::Matcher<uint32_t> delta) : delta_(delta) {}
+
+ bool MatchAndExplain(const nghttp2_frame* frame,
+ testing::MatchResultListener* listener) const override {
+ if (frame->hd.type != NGHTTP2_WINDOW_UPDATE) {
+ *listener << "; expected WINDOW_UPDATE frame, saw frame of type "
+ << static_cast<int>(frame->hd.type);
+ return false;
+ }
+ return delta_.MatchAndExplain(frame->window_update.window_size_increment,
+ listener);
+ }
+
+ void DescribeTo(std::ostream* os) const override {
+ *os << "contains a WINDOW_UPDATE frame, ";
+ delta_.DescribeTo(os);
+ }
+
+ void DescribeNegationTo(std::ostream* os) const override {
+ *os << "does not contain a WINDOW_UPDATE frame, ";
+ delta_.DescribeNegationTo(os);
+ }
+
+ private:
+ const testing::Matcher<uint32_t> delta_;
+};
+
+} // namespace
+
+testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
+ uint32_t streamid, uint8_t type, const testing::Matcher<int> flags) {
+ return MakeMatcher(new PointerToFrameHeaderMatcher(streamid, type, flags));
+}
+
+testing::Matcher<const nghttp2_frame_hd&> HasFrameHeaderRef(
+ uint32_t streamid, uint8_t type, const testing::Matcher<int> flags) {
+ return MakeMatcher(new ReferenceToFrameHeaderMatcher(streamid, type, flags));
+}
+
+testing::Matcher<const nghttp2_frame*> IsData(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length, const testing::Matcher<int> flags) {
+ return MakeMatcher(new DataMatcher(stream_id, length, flags));
+}
+
+testing::Matcher<const nghttp2_frame*> IsHeaders(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags, const testing::Matcher<int> category) {
+ return MakeMatcher(new HeadersMatcher(stream_id, flags, category));
+}
+
+testing::Matcher<const nghttp2_frame*> IsRstStream(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code) {
+ return MakeMatcher(new RstStreamMatcher(stream_id, error_code));
+}
+
+testing::Matcher<const nghttp2_frame*> IsSettings(
+ const testing::Matcher<std::vector<Http2Setting>> values) {
+ return MakeMatcher(new SettingsMatcher(values));
+}
+
+testing::Matcher<const nghttp2_frame*> IsPing(
+ const testing::Matcher<uint64_t> id) {
+ return MakeMatcher(new PingMatcher(id, false));
+}
+
+testing::Matcher<const nghttp2_frame*> IsPingAck(
+ const testing::Matcher<uint64_t> id) {
+ return MakeMatcher(new PingMatcher(id, true));
+}
+
+testing::Matcher<const nghttp2_frame*> IsGoAway(
+ const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data) {
+ return MakeMatcher(
+ new GoAwayMatcher(last_stream_id, error_code, opaque_data));
+}
+
+testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
+ const testing::Matcher<uint32_t> delta) {
+ return MakeMatcher(new WindowUpdateMatcher(delta));
+}
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.h
new file mode 100644
index 00000000000..9b772ffda63
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_test_utils.h
@@ -0,0 +1,99 @@
+#ifndef QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_
+#define QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_
+
+#include <vector>
+
+#include "absl/strings/string_view.h"
+#include "http2/adapter/http2_protocol.h"
+#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_export.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+
+// A simple class that can easily be adapted to act as a nghttp2_data_source.
+class QUICHE_NO_EXPORT TestDataSource {
+ public:
+ explicit TestDataSource(absl::string_view data) : data_(std::string(data)) {}
+
+ absl::string_view ReadNext(size_t size) {
+ const size_t to_send = std::min(size, remaining_.size());
+ auto ret = remaining_.substr(0, to_send);
+ remaining_.remove_prefix(to_send);
+ return ret;
+ }
+
+ size_t SelectPayloadLength(size_t max_length) {
+ return std::min(max_length, remaining_.size());
+ }
+
+ nghttp2_data_provider MakeDataProvider() {
+ return nghttp2_data_provider{
+ .source = {.ptr = this},
+ .read_callback = [](nghttp2_session*, int32_t, uint8_t*, size_t length,
+ uint32_t* data_flags, nghttp2_data_source* source,
+ void*) -> ssize_t {
+ *data_flags |= NGHTTP2_DATA_FLAG_NO_COPY;
+ auto* s = static_cast<TestDataSource*>(source->ptr);
+ if (!s->is_data_available()) {
+ return NGHTTP2_ERR_DEFERRED;
+ }
+ const ssize_t ret = s->SelectPayloadLength(length);
+ if (ret < static_cast<ssize_t>(length)) {
+ *data_flags |= NGHTTP2_DATA_FLAG_EOF;
+ }
+ return ret;
+ }};
+ }
+
+ bool is_data_available() const { return is_data_available_; }
+ void set_is_data_available(bool value) { is_data_available_ = value; }
+
+ private:
+ const std::string data_;
+ absl::string_view remaining_ = data_;
+ bool is_data_available_ = true;
+};
+
+// Matchers for nghttp2 data types.
+testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
+ uint32_t streamid, uint8_t type, const testing::Matcher<int> flags);
+testing::Matcher<const nghttp2_frame_hd&> HasFrameHeaderRef(
+ uint32_t streamid, uint8_t type, const testing::Matcher<int> flags);
+
+testing::Matcher<const nghttp2_frame*> IsData(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<size_t> length, const testing::Matcher<int> flags);
+
+testing::Matcher<const nghttp2_frame*> IsHeaders(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<int> flags, const testing::Matcher<int> category);
+
+testing::Matcher<const nghttp2_frame*> IsRstStream(
+ const testing::Matcher<uint32_t> stream_id,
+ const testing::Matcher<uint32_t> error_code);
+
+testing::Matcher<const nghttp2_frame*> IsSettings(
+ const testing::Matcher<std::vector<Http2Setting>> values);
+
+testing::Matcher<const nghttp2_frame*> IsPing(
+ const testing::Matcher<uint64_t> id);
+
+testing::Matcher<const nghttp2_frame*> IsPingAck(
+ const testing::Matcher<uint64_t> id);
+
+testing::Matcher<const nghttp2_frame*> IsGoAway(
+ const testing::Matcher<uint32_t> last_stream_id,
+ const testing::Matcher<uint32_t> error_code,
+ const testing::Matcher<absl::string_view> opaque_data);
+
+testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
+ const testing::Matcher<uint32_t> delta);
+
+} // namespace test
+} // namespace adapter
+} // namespace http2
+
+#endif // QUICHE_HTTP2_ADAPTER_NGHTTP2_TEST_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
index 8d23a55278a..efb811fc35c 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.cc
@@ -2,10 +2,13 @@
#include <cstdint>
+#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
#include "http2/adapter/http2_protocol.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
#include "common/platform/api/quiche_logging.h"
+#include "common/quiche_endian.h"
namespace http2 {
namespace adapter {
@@ -28,11 +31,11 @@ void DeleteSession(nghttp2_session* session) {
nghttp2_session_callbacks_unique_ptr MakeCallbacksPtr(
nghttp2_session_callbacks* callbacks) {
- return nghttp2_session_callbacks_unique_ptr(callbacks, DeleteCallbacks);
+ return nghttp2_session_callbacks_unique_ptr(callbacks, &DeleteCallbacks);
}
nghttp2_session_unique_ptr MakeSessionPtr(nghttp2_session* session) {
- return nghttp2_session_unique_ptr(session, DeleteSession);
+ return nghttp2_session_unique_ptr(session, &DeleteSession);
}
uint8_t* ToUint8Ptr(char* str) { return reinterpret_cast<uint8_t*>(str); }
@@ -56,7 +59,8 @@ absl::string_view ToStringView(const uint8_t* pointer, size_t length) {
std::vector<nghttp2_nv> GetNghttp2Nvs(absl::Span<const Header> headers) {
const int num_headers = headers.size();
- auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers);
+ std::vector<nghttp2_nv> nghttp2_nvs;
+ nghttp2_nvs.reserve(num_headers);
for (int i = 0; i < num_headers; ++i) {
nghttp2_nv header;
uint8_t flags = NGHTTP2_NV_FLAG_NONE;
@@ -85,7 +89,8 @@ std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
absl::string_view response_code) {
// Allocate enough for all headers and also the :status pseudoheader.
const int num_headers = headers.size();
- auto nghttp2_nvs = std::vector<nghttp2_nv>(num_headers + 1);
+ std::vector<nghttp2_nv> nghttp2_nvs;
+ nghttp2_nvs.reserve(num_headers + 1);
// Add the :status pseudoheader first.
nghttp2_nv status;
@@ -97,7 +102,7 @@ std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
nghttp2_nvs.push_back(std::move(status));
// Add the remaining headers.
- for (const auto header_pair : headers) {
+ for (const auto& header_pair : headers) {
nghttp2_nv header;
header.name = ToUint8Ptr(header_pair.first.data());
header.namelen = header_pair.first.size();
@@ -117,5 +122,148 @@ Http2ErrorCode ToHttp2ErrorCode(uint32_t wire_error_code) {
return static_cast<Http2ErrorCode>(wire_error_code);
}
+class Nghttp2DataFrameSource : public DataFrameSource {
+ public:
+ Nghttp2DataFrameSource(nghttp2_data_provider provider,
+ nghttp2_send_data_callback send_data,
+ void* user_data)
+ : provider_(std::move(provider)),
+ send_data_(std::move(send_data)),
+ user_data_(user_data) {}
+
+ std::pair<ssize_t, bool> SelectPayloadLength(size_t max_length) override {
+ const int32_t stream_id = 0;
+ uint32_t data_flags = 0;
+ QUICHE_LOG(INFO) << "Invoking read callback";
+ ssize_t result = provider_.read_callback(
+ nullptr /* session */, stream_id, nullptr /* buf */, max_length,
+ &data_flags, &provider_.source, nullptr /* user_data */);
+ if (result == NGHTTP2_ERR_DEFERRED) {
+ return {kBlocked, false};
+ } else if (result < 0) {
+ return {kError, false};
+ } else if ((data_flags & NGHTTP2_DATA_FLAG_NO_COPY) == 0) {
+ QUICHE_LOG(ERROR) << "Source did not use the zero-copy API!";
+ return {kError, false};
+ } else {
+ if (data_flags & NGHTTP2_DATA_FLAG_NO_END_STREAM) {
+ send_fin_ = false;
+ }
+ const bool eof = data_flags & NGHTTP2_DATA_FLAG_EOF;
+ return {result, eof};
+ }
+ }
+
+ bool Send(absl::string_view frame_header, size_t payload_length) override {
+ nghttp2_frame frame;
+ frame.hd.type = 0;
+ frame.hd.length = payload_length;
+ frame.hd.flags = 0;
+ frame.hd.stream_id = 0;
+ frame.data.padlen = 0;
+ const int result = send_data_(
+ nullptr /* session */, &frame, ToUint8Ptr(frame_header.data()),
+ payload_length, &provider_.source, user_data_);
+ QUICHE_LOG_IF(ERROR, result < 0 && result != NGHTTP2_ERR_WOULDBLOCK)
+ << "Unexpected error code from send: " << result;
+ return result == 0;
+ }
+
+ bool send_fin() const override { return send_fin_; }
+
+ private:
+ nghttp2_data_provider provider_;
+ nghttp2_send_data_callback send_data_;
+ void* user_data_;
+ bool send_fin_ = true;
+};
+
+std::unique_ptr<DataFrameSource> MakeZeroCopyDataFrameSource(
+ nghttp2_data_provider provider,
+ void* user_data,
+ nghttp2_send_data_callback send_data) {
+ return absl::make_unique<Nghttp2DataFrameSource>(
+ std::move(provider), std::move(send_data), user_data);
+}
+
+absl::string_view ErrorString(uint32_t error_code) {
+ return Http2ErrorCodeToString(static_cast<Http2ErrorCode>(error_code));
+}
+
+size_t PaddingLength(uint8_t flags, size_t padlen) {
+ return (flags & 0x8 ? 1 : 0) + padlen;
+}
+
+struct NvFormatter {
+ void operator()(std::string* out, const nghttp2_nv& nv) {
+ absl::StrAppend(out, ToStringView(nv.name, nv.namelen), ": ",
+ ToStringView(nv.value, nv.valuelen));
+ }
+};
+
+std::string NvsAsString(nghttp2_nv* nva, size_t nvlen) {
+ return absl::StrJoin(absl::MakeConstSpan(nva, nvlen), ", ", NvFormatter());
+}
+
+#define HTTP2_FRAME_SEND_LOG QUICHE_VLOG(1)
+
+void LogBeforeSend(const nghttp2_frame& frame) {
+ switch (static_cast<FrameType>(frame.hd.type)) {
+ case FrameType::DATA:
+ HTTP2_FRAME_SEND_LOG << "Sending DATA on stream " << frame.hd.stream_id
+ << " with length "
+ << frame.hd.length - PaddingLength(frame.hd.flags,
+ frame.data.padlen)
+ << " and padding "
+ << PaddingLength(frame.hd.flags, frame.data.padlen);
+ break;
+ case FrameType::HEADERS:
+ HTTP2_FRAME_SEND_LOG << "Sending HEADERS on stream " << frame.hd.stream_id
+ << " with headers ["
+ << NvsAsString(frame.headers.nva,
+ frame.headers.nvlen)
+ << "]";
+ break;
+ case FrameType::PRIORITY:
+ HTTP2_FRAME_SEND_LOG << "Sending PRIORITY";
+ break;
+ case FrameType::RST_STREAM:
+ HTTP2_FRAME_SEND_LOG << "Sending RST_STREAM on stream "
+ << frame.hd.stream_id << " with error code "
+ << ErrorString(frame.rst_stream.error_code);
+ break;
+ case FrameType::SETTINGS:
+ HTTP2_FRAME_SEND_LOG << "Sending SETTINGS with " << frame.settings.niv
+ << " entries, is_ack: " << (frame.hd.flags & 0x01);
+ break;
+ case FrameType::PUSH_PROMISE:
+ HTTP2_FRAME_SEND_LOG << "Sending PUSH_PROMISE";
+ break;
+ case FrameType::PING: {
+ Http2PingId ping_id;
+ std::memcpy(&ping_id, frame.ping.opaque_data, sizeof(Http2PingId));
+ HTTP2_FRAME_SEND_LOG << "Sending PING with unique_id "
+ << quiche::QuicheEndian::NetToHost64(ping_id)
+ << ", is_ack: " << (frame.hd.flags & 0x01);
+ break;
+ }
+ case FrameType::GOAWAY:
+ HTTP2_FRAME_SEND_LOG << "Sending GOAWAY with last_stream: "
+ << frame.goaway.last_stream_id << " and error "
+ << ErrorString(frame.goaway.error_code);
+ break;
+ case FrameType::WINDOW_UPDATE:
+ HTTP2_FRAME_SEND_LOG << "Sending WINDOW_UPDATE on stream "
+ << frame.hd.stream_id << " with update delta "
+ << frame.window_update.window_size_increment;
+ break;
+ case FrameType::CONTINUATION:
+ HTTP2_FRAME_SEND_LOG << "Sending CONTINUATION, which is unexpected";
+ break;
+ }
+}
+
+#undef HTTP2_FRAME_SEND_LOG
+
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
index e2c3e7a37c7..78d4702a3c5 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util.h
@@ -8,6 +8,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
+#include "http2/adapter/data_source.h"
#include "http2/adapter/http2_protocol.h"
#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
#include "spdy/core/spdy_header_block.h"
@@ -20,8 +21,8 @@ inline constexpr int kStreamCallbackFailureStatus =
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE;
inline constexpr int kCancelStatus = NGHTTP2_ERR_CANCEL;
-using CallbacksDeleter = void (&)(nghttp2_session_callbacks*);
-using SessionDeleter = void (&)(nghttp2_session*);
+using CallbacksDeleter = void (*)(nghttp2_session_callbacks*);
+using SessionDeleter = void (*)(nghttp2_session*);
using nghttp2_session_callbacks_unique_ptr =
std::unique_ptr<nghttp2_session_callbacks, CallbacksDeleter>;
@@ -55,6 +56,16 @@ std::vector<nghttp2_nv> GetResponseNghttp2Nvs(
// based on the RFC 7540 Section 7 suggestion.
Http2ErrorCode ToHttp2ErrorCode(uint32_t wire_error_code);
+// Transforms a nghttp2_data_provider into a DataFrameSource. Assumes that
+// |provider| uses the zero-copy nghttp2_data_source_read_callback API. Unsafe
+// otherwise.
+std::unique_ptr<DataFrameSource> MakeZeroCopyDataFrameSource(
+ nghttp2_data_provider provider,
+ void* user_data,
+ nghttp2_send_data_callback send_data);
+
+void LogBeforeSend(const nghttp2_frame& frame);
+
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util_test.cc
new file mode 100644
index 00000000000..1ec00ba32ec
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/http2/adapter/nghttp2_util_test.cc
@@ -0,0 +1,109 @@
+#include "http2/adapter/nghttp2_util.h"
+
+#include "http2/adapter/nghttp2_test_utils.h"
+#include "http2/adapter/test_utils.h"
+#include "common/platform/api/quiche_test.h"
+
+namespace http2 {
+namespace adapter {
+namespace test {
+namespace {
+
+// This send callback assumes |source|'s pointer is a TestDataSource, and
+// |user_data| is a std::string.
+int FakeSendCallback(nghttp2_session*, nghttp2_frame* /*frame*/,
+ const uint8_t* framehd, size_t length,
+ nghttp2_data_source* source, void* user_data) {
+ auto* dest = static_cast<std::string*>(user_data);
+ // Appends the frame header to the string.
+ absl::StrAppend(dest, ToStringView(framehd, 9));
+ auto* test_source = static_cast<TestDataSource*>(source->ptr);
+ absl::string_view payload = test_source->ReadNext(length);
+ // Appends the frame payload to the string.
+ absl::StrAppend(dest, payload);
+ return 0;
+}
+
+TEST(MakeZeroCopyDataFrameSource, EmptyPayload) {
+ std::string result;
+
+ const absl::string_view kEmptyBody = "";
+ TestDataSource body1{kEmptyBody};
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
+ auto [length, eof] = frame_source->SelectPayloadLength(100);
+ EXPECT_EQ(length, 0);
+ EXPECT_TRUE(eof);
+ frame_source->Send("ninebytes", 0);
+ EXPECT_EQ(result, "ninebytes");
+}
+
+TEST(MakeZeroCopyDataFrameSource, ShortPayload) {
+ std::string result;
+
+ const absl::string_view kShortBody =
+ "<html><head><title>Example Page!</title></head>"
+ "<body><div><span><table><tr><th><blink>Wow!!"
+ "</blink></th></tr></table></span></div></body>"
+ "</html>";
+ TestDataSource body1{kShortBody};
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
+ auto [length, eof] = frame_source->SelectPayloadLength(200);
+ EXPECT_EQ(length, kShortBody.size());
+ EXPECT_TRUE(eof);
+ frame_source->Send("ninebytes", length);
+ EXPECT_EQ(result, absl::StrCat("ninebytes", kShortBody));
+}
+
+TEST(MakeZeroCopyDataFrameSource, MultiFramePayload) {
+ std::string result;
+
+ const absl::string_view kShortBody =
+ "<html><head><title>Example Page!</title></head>"
+ "<body><div><span><table><tr><th><blink>Wow!!"
+ "</blink></th></tr></table></span></div></body>"
+ "</html>";
+ TestDataSource body1{kShortBody};
+ // The TestDataSource is wrapped in the nghttp2_data_provider data type.
+ nghttp2_data_provider provider = body1.MakeDataProvider();
+
+ // This call transforms it back into a DataFrameSource, which is compatible
+ // with the Http2Adapter API.
+ std::unique_ptr<DataFrameSource> frame_source =
+ MakeZeroCopyDataFrameSource(provider, &result, FakeSendCallback);
+ auto ret = frame_source->SelectPayloadLength(50);
+ EXPECT_EQ(ret.first, 50);
+ EXPECT_FALSE(ret.second);
+ frame_source->Send("ninebyte1", ret.first);
+
+ ret = frame_source->SelectPayloadLength(50);
+ EXPECT_EQ(ret.first, 50);
+ EXPECT_FALSE(ret.second);
+ frame_source->Send("ninebyte2", ret.first);
+
+ ret = frame_source->SelectPayloadLength(50);
+ EXPECT_EQ(ret.first, 44);
+ EXPECT_TRUE(ret.second);
+ frame_source->Send("ninebyte3", ret.first);
+
+ EXPECT_EQ(result,
+ "ninebyte1<html><head><title>Example Page!</title></head><bo"
+ "ninebyte2dy><div><span><table><tr><th><blink>Wow!!</blink><"
+ "ninebyte3/th></tr></table></span></div></body></html>");
+}
+
+} // namespace
+} // namespace test
+} // namespace adapter
+} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
index 9f287facb9f..27f011ec62f 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.cc
@@ -30,6 +30,10 @@ std::unique_ptr<OgHttp2Adapter> OgHttp2Adapter::Create(
OgHttp2Adapter::~OgHttp2Adapter() {}
+bool OgHttp2Adapter::IsServerSession() const {
+ return session_->IsServerSession();
+}
+
ssize_t OgHttp2Adapter::ProcessBytes(absl::string_view bytes) {
return session_->ProcessBytes(bytes);
}
@@ -54,6 +58,10 @@ void OgHttp2Adapter::SubmitPing(Http2PingId ping_id) {
session_->EnqueueFrame(absl::make_unique<SpdyPingIR>(ping_id));
}
+void OgHttp2Adapter::SubmitShutdownNotice() {
+ session_->StartGracefulShutdown();
+}
+
void OgHttp2Adapter::SubmitGoAway(Http2StreamId last_accepted_stream_id,
Http2ErrorCode error_code,
absl::string_view opaque_data) {
@@ -67,18 +75,45 @@ void OgHttp2Adapter::SubmitWindowUpdate(Http2StreamId stream_id,
absl::make_unique<SpdyWindowUpdateIR>(stream_id, window_increment));
}
-void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id, bool fin) {
- QUICHE_BUG(oghttp2_submit_metadata) << "Not implemented";
+void OgHttp2Adapter::SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source) {
+ session_->SubmitMetadata(stream_id, std::move(source));
}
-std::string OgHttp2Adapter::GetBytesToWrite(absl::optional<size_t> max_bytes) {
- return session_->GetBytesToWrite(max_bytes);
-}
+int OgHttp2Adapter::Send() { return session_->Send(); }
-int OgHttp2Adapter::GetPeerConnectionWindow() const {
+int OgHttp2Adapter::GetSendWindowSize() const {
return session_->GetRemoteWindowSize();
}
+int OgHttp2Adapter::GetStreamSendWindowSize(Http2StreamId stream_id) const {
+ return session_->GetStreamSendWindowSize(stream_id);
+}
+
+int OgHttp2Adapter::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+ return session_->GetStreamReceiveWindowLimit(stream_id);
+}
+
+int OgHttp2Adapter::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
+ return session_->GetStreamReceiveWindowSize(stream_id);
+}
+
+int OgHttp2Adapter::GetReceiveWindowSize() const {
+ return session_->GetReceiveWindowSize();
+}
+
+int OgHttp2Adapter::GetHpackEncoderDynamicTableSize() const {
+ return session_->GetHpackEncoderDynamicTableSize();
+}
+
+int OgHttp2Adapter::GetHpackDecoderDynamicTableSize() const {
+ return session_->GetHpackDecoderDynamicTableSize();
+}
+
+Http2StreamId OgHttp2Adapter::GetHighestReceivedStreamId() const {
+ return session_->GetHighestReceivedStreamId();
+}
+
void OgHttp2Adapter::MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) {
session_->Consume(stream_id, num_bytes);
@@ -90,6 +125,36 @@ void OgHttp2Adapter::SubmitRst(Http2StreamId stream_id,
stream_id, TranslateErrorCode(error_code)));
}
+int32_t OgHttp2Adapter::SubmitRequest(
+ absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source, void* user_data) {
+ return session_->SubmitRequest(headers, std::move(data_source), user_data);
+}
+
+int OgHttp2Adapter::SubmitResponse(
+ Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) {
+ return session_->SubmitResponse(stream_id, headers, std::move(data_source));
+}
+
+int OgHttp2Adapter::SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) {
+ return session_->SubmitTrailer(stream_id, trailers);
+}
+
+void OgHttp2Adapter::SetStreamUserData(Http2StreamId stream_id,
+ void* user_data) {
+ session_->SetStreamUserData(stream_id, user_data);
+}
+
+void* OgHttp2Adapter::GetStreamUserData(Http2StreamId stream_id) {
+ return session_->GetStreamUserData(stream_id);
+}
+
+bool OgHttp2Adapter::ResumeStream(Http2StreamId stream_id) {
+ return session_->ResumeStream(stream_id);
+}
+
const Http2Session& OgHttp2Adapter::session() const {
return *session_;
}
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
index 572ba04e9fc..9c7bad3c575 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter.h
@@ -6,11 +6,12 @@
#include "http2/adapter/http2_adapter.h"
#include "http2/adapter/http2_session.h"
#include "http2/adapter/oghttp2_session.h"
+#include "common/platform/api/quiche_export.h"
namespace http2 {
namespace adapter {
-class OgHttp2Adapter : public Http2Adapter {
+class QUICHE_EXPORT_PRIVATE OgHttp2Adapter : public Http2Adapter {
public:
using Options = OgHttp2Session::Options;
static std::unique_ptr<OgHttp2Adapter> Create(Http2VisitorInterface& visitor,
@@ -19,6 +20,7 @@ class OgHttp2Adapter : public Http2Adapter {
~OgHttp2Adapter();
// From Http2Adapter.
+ bool IsServerSession() const override;
ssize_t ProcessBytes(absl::string_view bytes) override;
void SubmitSettings(absl::Span<const Http2Setting> settings) override;
void SubmitPriorityForStream(Http2StreamId stream_id,
@@ -26,17 +28,38 @@ class OgHttp2Adapter : public Http2Adapter {
int weight,
bool exclusive) override;
void SubmitPing(Http2PingId ping_id) override;
+ void SubmitShutdownNotice() override;
void SubmitGoAway(Http2StreamId last_accepted_stream_id,
Http2ErrorCode error_code,
absl::string_view opaque_data) override;
void SubmitWindowUpdate(Http2StreamId stream_id,
int window_increment) override;
- void SubmitMetadata(Http2StreamId stream_id, bool fin) override;
- std::string GetBytesToWrite(absl::optional<size_t> max_bytes) override;
- int GetPeerConnectionWindow() const override;
+ void SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source) override;
+ int Send() override;
+ int GetSendWindowSize() const override;
+ int GetStreamSendWindowSize(Http2StreamId stream_id) const override;
+ int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const override;
+ int GetStreamReceiveWindowSize(Http2StreamId stream_id) const override;
+ int GetReceiveWindowSize() const override;
+ int GetHpackEncoderDynamicTableSize() const override;
+ int GetHpackDecoderDynamicTableSize() const override;
+ Http2StreamId GetHighestReceivedStreamId() const override;
void MarkDataConsumedForStream(Http2StreamId stream_id,
size_t num_bytes) override;
void SubmitRst(Http2StreamId stream_id, Http2ErrorCode error_code) override;
+ int32_t SubmitRequest(absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source,
+ void* user_data) override;
+ int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) override;
+
+ int SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) override;
+
+ void SetStreamUserData(Http2StreamId stream_id, void* user_data) override;
+ void* GetStreamUserData(Http2StreamId stream_id) override;
+ bool ResumeStream(Http2StreamId stream_id) override;
const Http2Session& session() const;
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
index 4c849f6fd6d..03b45df6aa9 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_adapter_test.cc
@@ -1,6 +1,8 @@
#include "http2/adapter/oghttp2_adapter.h"
+#include "absl/strings/str_join.h"
#include "http2/adapter/mock_http2_visitor.h"
+#include "http2/adapter/oghttp2_util.h"
#include "http2/adapter/test_frame_sequence.h"
#include "http2/adapter/test_utils.h"
#include "common/platform/api/quiche_test.h"
@@ -11,6 +13,23 @@ namespace adapter {
namespace test {
namespace {
+using testing::_;
+
+enum FrameType {
+ DATA,
+ HEADERS,
+ PRIORITY,
+ RST_STREAM,
+ SETTINGS,
+ PUSH_PROMISE,
+ PING,
+ GOAWAY,
+ WINDOW_UPDATE,
+ CONTINUATION,
+};
+
+using spdy::SpdyFrameType;
+
class OgHttp2AdapterTest : public testing::Test {
protected:
void SetUp() override {
@@ -18,10 +37,14 @@ class OgHttp2AdapterTest : public testing::Test {
adapter_ = OgHttp2Adapter::Create(http2_visitor_, options);
}
- testing::StrictMock<MockHttp2Visitor> http2_visitor_;
+ DataSavingVisitor http2_visitor_;
std::unique_ptr<OgHttp2Adapter> adapter_;
};
+TEST_F(OgHttp2AdapterTest, IsServerSession) {
+ EXPECT_TRUE(adapter_->IsServerSession());
+}
+
TEST_F(OgHttp2AdapterTest, ProcessBytes) {
testing::InSequence seq;
EXPECT_CALL(http2_visitor_, OnFrameHeader(0, 0, 4, 0));
@@ -33,13 +56,527 @@ TEST_F(OgHttp2AdapterTest, ProcessBytes) {
TestFrameSequence().ClientPreface().Ping(17).Serialize());
}
+TEST(OgHttp2AdapterClientTest, ClientHandlesTrailers) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Headers(1, {{"final-status", "A-OK"}},
+ /*fin=*/true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "final-status", "A-OK"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2AdapterClientTest, ClientHandlesMetadata) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Metadata(0, "Example connection metadata")
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Metadata(1, "Example stream metadata")
+ .Data(1, "This is the response body.", true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 1));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnEndStream(1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2AdapterClientTest, ClientRstStreamWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
+ .WillOnce(testing::DoAll(
+ testing::InvokeWithoutArgs([&adapter]() {
+ adapter->SubmitRst(1, Http2ErrorCode::REFUSED_STREAM);
+ }),
+ testing::Return(Http2VisitorInterface::HEADER_RST_STREAM)));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
+ EXPECT_CALL(visitor,
+ OnFrameSent(RST_STREAM, stream_id1, 4, 0x0,
+ static_cast<int>(Http2ErrorCode::REFUSED_STREAM)));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
+}
+
+TEST(OgHttp2AdapterClientTest, ClientConnectionErrorWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"))
+ .WillOnce(
+ testing::Return(Http2VisitorInterface::HEADER_CONNECTION_ERROR));
+ EXPECT_CALL(visitor, OnConnectionError());
+ // Note: OgHttp2Adapter continues processing bytes until the input is
+ // complete.
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2AdapterClientTest, ClientRejectsHeaders) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1))
+ .WillOnce(testing::Return(false));
+ // Rejecting headers leads to a connection error.
+ EXPECT_CALL(visitor, OnConnectionError());
+ // Note: OgHttp2Adapter continues processing bytes until the input is
+ // complete.
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_result, stream_frames.size());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS}));
+}
+
+// TODO(birenroy): Validate headers and re-enable this test. The library should
+// invoke OnErrorDebug() with an error message for the invalid header. The
+// library should also invoke OnInvalidFrame() for the invalid HEADERS frame.
+TEST(OgHttp2AdapterClientTest, DISABLED_ClientHandlesInvalidTrailers) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kClient};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ testing::InSequence s;
+
+ const std::vector<const Header> headers1 =
+ ToHeaders({{":method", "GET"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}});
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ const int32_t stream_id1 =
+ adapter->SubmitRequest(headers1, nullptr, const_cast<char*>(kSentinel1));
+ ASSERT_GT(stream_id1, 0);
+ QUICHE_LOG(INFO) << "Created stream: " << stream_id1;
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id1, _, 0x5, 0));
+
+ int result = adapter->Send();
+ EXPECT_EQ(0, result);
+ absl::string_view data = visitor.data();
+ EXPECT_THAT(data, testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ data.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(data, EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS}));
+ visitor.Clear();
+
+ const std::string stream_frames =
+ TestFrameSequence()
+ .ServerPreface()
+ .Headers(1,
+ {{":status", "200"},
+ {"server", "my-fake-server"},
+ {"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
+ /*fin=*/false)
+ .Data(1, "This is the response body.")
+ .Headers(1, {{":bad-status", "9000"}},
+ /*fin=*/true)
+ .Serialize();
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor,
+ OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+
+ // Bad status trailer will cause a PROTOCOL_ERROR. The header is never
+ // delivered in an OnHeaderForStream callback.
+
+ const size_t stream_result = adapter->ProcessBytes(stream_frames);
+ EXPECT_EQ(stream_frames.size(), stream_result);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, stream_id1, 4, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(RST_STREAM, stream_id1, 4, 0x0, 1));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::PROTOCOL_ERROR));
+
+ EXPECT_TRUE(adapter->session().want_write());
+ result = adapter->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
+}
+
TEST_F(OgHttp2AdapterTest, SubmitMetadata) {
- EXPECT_QUICHE_BUG(adapter_->SubmitMetadata(3, true), "Not implemented");
+ auto source = absl::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
+ {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
+ adapter_->SubmitMetadata(1, std::move(source));
+ EXPECT_TRUE(adapter_->session().want_write());
+
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(kMetadataFrameType, 1, _, 0x4));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(kMetadataFrameType, 1, _, 0x4, 0));
+
+ int result = adapter_->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(
+ http2_visitor_.data(),
+ EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ static_cast<spdy::SpdyFrameType>(kMetadataFrameType)}));
+ EXPECT_FALSE(adapter_->session().want_write());
+}
+
+TEST_F(OgHttp2AdapterTest, SubmitConnectionMetadata) {
+ auto source = absl::make_unique<TestMetadataSource>(ToHeaderBlock(ToHeaders(
+ {{"query-cost", "is too darn high"}, {"secret-sauce", "hollandaise"}})));
+ adapter_->SubmitMetadata(0, std::move(source));
+ EXPECT_TRUE(adapter_->session().want_write());
+
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(kMetadataFrameType, 0, _, 0x4));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(kMetadataFrameType, 0, _, 0x4, 0));
+
+ int result = adapter_->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(
+ http2_visitor_.data(),
+ EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ static_cast<spdy::SpdyFrameType>(kMetadataFrameType)}));
+ EXPECT_FALSE(adapter_->session().want_write());
}
-TEST_F(OgHttp2AdapterTest, GetPeerConnectionWindow) {
- const int peer_window = adapter_->GetPeerConnectionWindow();
- EXPECT_GT(peer_window, 0);
+TEST_F(OgHttp2AdapterTest, GetSendWindowSize) {
+ const int peer_window = adapter_->GetSendWindowSize();
+ EXPECT_EQ(peer_window, kInitialFlowControlWindowSize);
}
TEST_F(OgHttp2AdapterTest, MarkDataConsumedForStream) {
@@ -62,12 +599,27 @@ TEST_F(OgHttp2AdapterTest, TestSerialize) {
adapter_->SubmitWindowUpdate(3, 127);
EXPECT_TRUE(adapter_->session().want_write());
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(PRIORITY, 3, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(PRIORITY, 3, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(RST_STREAM, 3, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(RST_STREAM, 3, _, 0x0, 0x8));
+ EXPECT_CALL(http2_visitor_, OnCloseStream(3, Http2ErrorCode::NO_ERROR));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(PING, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(PING, 0, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(WINDOW_UPDATE, 3, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(WINDOW_UPDATE, 3, _, 0x0, 0));
+
+ int result = adapter_->Send();
+ EXPECT_EQ(0, result);
EXPECT_THAT(
- adapter_->GetBytesToWrite(absl::nullopt),
- EqualsFrames(
- {spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::PRIORITY,
- spdy::SpdyFrameType::RST_STREAM, spdy::SpdyFrameType::PING,
- spdy::SpdyFrameType::GOAWAY, spdy::SpdyFrameType::WINDOW_UPDATE}));
+ http2_visitor_.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PRIORITY,
+ SpdyFrameType::RST_STREAM, SpdyFrameType::PING,
+ SpdyFrameType::GOAWAY, SpdyFrameType::WINDOW_UPDATE}));
EXPECT_FALSE(adapter_->session().want_write());
}
@@ -80,14 +632,271 @@ TEST_F(OgHttp2AdapterTest, TestPartialSerialize) {
adapter_->SubmitPing(42);
EXPECT_TRUE(adapter_->session().want_write());
- const std::string first_part = adapter_->GetBytesToWrite(10);
+ http2_visitor_.set_send_limit(20);
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ int result = adapter_->Send();
+ EXPECT_EQ(0, result);
+ EXPECT_TRUE(adapter_->session().want_write());
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
+ result = adapter_->Send();
+ EXPECT_EQ(0, result);
EXPECT_TRUE(adapter_->session().want_write());
- const std::string second_part = adapter_->GetBytesToWrite(absl::nullopt);
+ EXPECT_CALL(http2_visitor_, OnBeforeFrameSent(PING, 0, _, 0x0));
+ EXPECT_CALL(http2_visitor_, OnFrameSent(PING, 0, _, 0x0, 0));
+ result = adapter_->Send();
+ EXPECT_EQ(0, result);
EXPECT_FALSE(adapter_->session().want_write());
- EXPECT_THAT(
- absl::StrCat(first_part, second_part),
- EqualsFrames({spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::GOAWAY,
- spdy::SpdyFrameType::PING}));
+ EXPECT_THAT(http2_visitor_.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::GOAWAY,
+ SpdyFrameType::PING}));
+}
+
+TEST(OgHttp2AdapterServerTest, ClientSendsContinuation) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true,
+ /*add_continuation=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 1));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+}
+
+TEST(OgHttp2AdapterServerTest, ClientSendsMetadataWithContinuation) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames =
+ TestFrameSequence()
+ .ClientPreface()
+ .Metadata(0, "Example connection metadata in multiple frames", true)
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/false,
+ /*add_continuation=*/true)
+ .Metadata(1,
+ "Some stream metadata that's also sent in multiple frames",
+ true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Metadata on stream 0
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 0));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnFrameHeader(0, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(0, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(0));
+
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 0));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, CONTINUATION, 4));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ // Metadata on stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 0));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, kMetadataFrameType, 4));
+ EXPECT_CALL(visitor, OnBeginMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataForStream(1, _));
+ EXPECT_CALL(visitor, OnMetadataEndForStream(1));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+ EXPECT_EQ(TestFrameSequence::MetadataBlockForPayload(
+ "Example connection metadata in multiple frames"),
+ absl::StrJoin(visitor.GetMetadata(0), ""));
+ EXPECT_EQ(TestFrameSequence::MetadataBlockForPayload(
+ "Some stream metadata that's also sent in multiple frames"),
+ absl::StrJoin(visitor.GetMetadata(1), ""));
+}
+
+TEST(OgHttp2AdapterServerTest, ServerSendsInvalidTrailers) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+ EXPECT_FALSE(adapter->session().want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ const absl::string_view kBody = "This is an example response body.";
+
+ // The body source must indicate that the end of the body is not the end of
+ // the stream.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload(kBody);
+ body1->EndData();
+ int submit_result = adapter->SubmitResponse(
+ 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ int send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames(
+ {spdy::SpdyFrameType::SETTINGS, spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::HEADERS, spdy::SpdyFrameType::DATA}));
+ EXPECT_THAT(visitor.data(), testing::HasSubstr(kBody));
+ visitor.Clear();
+ EXPECT_FALSE(adapter->session().want_write());
+
+ // The body source has been exhausted by the call to Send() above.
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+ int trailer_result =
+ adapter->SubmitTrailer(1, ToHeaders({{":final-status", "a-ok"}}));
+ ASSERT_EQ(trailer_result, 0);
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+
+ send_result = adapter->Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+}
+
+TEST(OgHttp2AdapterServerTest, ServerErrorWhileHandlingHeaders) {
+ DataSavingVisitor visitor;
+ OgHttp2Adapter::Options options{.perspective = Perspective::kServer};
+ auto adapter = OgHttp2Adapter::Create(visitor, options);
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "POST"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"},
+ {"accept", "some bogus value!"}},
+ /*fin=*/false)
+ .WindowUpdate(1, 2000)
+ .Data(1, "This is the request body.")
+ .WindowUpdate(0, 2000)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "POST"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, "accept", "some bogus value!"))
+ .WillOnce(testing::Return(Http2VisitorInterface::HEADER_RST_STREAM));
+ EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(1, _));
+ EXPECT_CALL(visitor, OnDataForStream(1, "This is the request body."));
+ EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
+ EXPECT_CALL(visitor, OnWindowUpdate(0, 2000));
+
+ const size_t result = adapter->ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_TRUE(adapter->session().want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, 0, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, 0, 0x1, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(RST_STREAM, 1, 4, 0x0));
+ EXPECT_CALL(visitor,
+ OnFrameSent(RST_STREAM, 1, 4, 0x0,
+ static_cast<int>(Http2ErrorCode::INTERNAL_ERROR)));
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ int send_result = adapter->Send();
+ // Some bytes should have been serialized.
+ EXPECT_EQ(0, send_result);
+ // SETTINGS ack
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::RST_STREAM}));
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
index 2222fed4b6b..3a32b2e70ea 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.cc
@@ -1,29 +1,150 @@
#include "http2/adapter/oghttp2_session.h"
+#include <tuple>
+
#include "absl/strings/escaping.h"
+#include "http2/adapter/oghttp2_util.h"
namespace http2 {
namespace adapter {
+namespace {
+
+const size_t kMaxMetadataFrameSize = 16384;
+
+// TODO(birenroy): Consider incorporating spdy::FlagsSerializionVisitor here.
+class FrameAttributeCollector : public spdy::SpdyFrameVisitor {
+ public:
+ FrameAttributeCollector() = default;
+ void VisitData(const spdy::SpdyDataIR& data) override {
+ frame_type_ = static_cast<uint8_t>(data.frame_type());
+ stream_id_ = data.stream_id();
+ length_ =
+ data.data_len() + (data.padded() ? 1 : 0) + data.padding_payload_len();
+ flags_ = (data.fin() ? 0x1 : 0) | (data.padded() ? 0x8 : 0);
+ }
+ void VisitHeaders(const spdy::SpdyHeadersIR& headers) override {
+ frame_type_ = static_cast<uint8_t>(headers.frame_type());
+ stream_id_ = headers.stream_id();
+ length_ = headers.size() - spdy::kFrameHeaderSize;
+ flags_ = 0x4 | (headers.fin() ? 0x1 : 0) | (headers.padded() ? 0x8 : 0) |
+ (headers.has_priority() ? 0x20 : 0);
+ }
+ void VisitPriority(const spdy::SpdyPriorityIR& priority) override {
+ frame_type_ = static_cast<uint8_t>(priority.frame_type());
+ frame_type_ = 2;
+ length_ = 5;
+ stream_id_ = priority.stream_id();
+ }
+ void VisitRstStream(const spdy::SpdyRstStreamIR& rst_stream) override {
+ frame_type_ = static_cast<uint8_t>(rst_stream.frame_type());
+ frame_type_ = 3;
+ length_ = 4;
+ stream_id_ = rst_stream.stream_id();
+ error_code_ = rst_stream.error_code();
+ }
+ void VisitSettings(const spdy::SpdySettingsIR& settings) override {
+ frame_type_ = static_cast<uint8_t>(settings.frame_type());
+ frame_type_ = 4;
+ length_ = 6 * settings.values().size();
+ flags_ = (settings.is_ack() ? 0x1 : 0);
+ }
+ void VisitPushPromise(const spdy::SpdyPushPromiseIR& push_promise) override {
+ frame_type_ = static_cast<uint8_t>(push_promise.frame_type());
+ frame_type_ = 5;
+ length_ = push_promise.size() - spdy::kFrameHeaderSize;
+ stream_id_ = push_promise.stream_id();
+ flags_ = (push_promise.padded() ? 0x8 : 0);
+ }
+ void VisitPing(const spdy::SpdyPingIR& ping) override {
+ frame_type_ = static_cast<uint8_t>(ping.frame_type());
+ frame_type_ = 6;
+ length_ = 8;
+ flags_ = (ping.is_ack() ? 0x1 : 0);
+ }
+ void VisitGoAway(const spdy::SpdyGoAwayIR& goaway) override {
+ frame_type_ = static_cast<uint8_t>(goaway.frame_type());
+ frame_type_ = 7;
+ length_ = goaway.size() - spdy::kFrameHeaderSize;
+ error_code_ = goaway.error_code();
+ }
+ void VisitWindowUpdate(
+ const spdy::SpdyWindowUpdateIR& window_update) override {
+ frame_type_ = static_cast<uint8_t>(window_update.frame_type());
+ frame_type_ = 8;
+ length_ = 4;
+ stream_id_ = window_update.stream_id();
+ }
+ void VisitContinuation(
+ const spdy::SpdyContinuationIR& continuation) override {
+ frame_type_ = static_cast<uint8_t>(continuation.frame_type());
+ stream_id_ = continuation.stream_id();
+ flags_ = continuation.end_headers() ? 0x4 : 0;
+ length_ = continuation.size() - spdy::kFrameHeaderSize;
+ }
+ void VisitUnknown(const spdy::SpdyUnknownIR& unknown) override {
+ frame_type_ = static_cast<uint8_t>(unknown.frame_type());
+ stream_id_ = unknown.stream_id();
+ flags_ = unknown.flags();
+ length_ = unknown.size() - spdy::kFrameHeaderSize;
+ }
+ void VisitAltSvc(const spdy::SpdyAltSvcIR& /*altsvc*/) override {}
+ void VisitPriorityUpdate(
+ const spdy::SpdyPriorityUpdateIR& /*priority_update*/) override {}
+ void VisitAcceptCh(const spdy::SpdyAcceptChIR& /*accept_ch*/) override {}
+
+ uint32_t stream_id() { return stream_id_; }
+ uint32_t length() { return length_; }
+ uint32_t error_code() { return error_code_; }
+ uint8_t frame_type() { return frame_type_; }
+ uint8_t flags() { return flags_; }
+
+ private:
+ uint32_t stream_id_ = 0;
+ uint32_t length_ = 0;
+ uint32_t error_code_ = 0;
+ uint8_t frame_type_ = 0;
+ uint8_t flags_ = 0;
+};
+
+} // namespace
+
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockStart() {
- visitor_.OnBeginHeadersForStream(stream_id_);
+ const bool status = visitor_.OnBeginHeadersForStream(stream_id_);
+ if (!status) {
+ result_ = Http2VisitorInterface::HEADER_CONNECTION_ERROR;
+ }
}
void OgHttp2Session::PassthroughHeadersHandler::OnHeader(
absl::string_view key,
absl::string_view value) {
- visitor_.OnHeaderForStream(stream_id_, key, value);
+ if (result_ == Http2VisitorInterface::HEADER_OK) {
+ result_ = visitor_.OnHeaderForStream(stream_id_, key, value);
+ }
}
void OgHttp2Session::PassthroughHeadersHandler::OnHeaderBlockEnd(
size_t /* uncompressed_header_bytes */,
size_t /* compressed_header_bytes */) {
- visitor_.OnEndHeadersForStream(stream_id_);
+ if (result_ == Http2VisitorInterface::HEADER_OK) {
+ visitor_.OnEndHeadersForStream(stream_id_);
+ } else {
+ session_.OnHeaderStatus(stream_id_, result_);
+ }
}
OgHttp2Session::OgHttp2Session(Http2VisitorInterface& visitor, Options options)
- : visitor_(visitor), headers_handler_(visitor), options_(options) {
+ : visitor_(visitor),
+ headers_handler_(*this, visitor),
+ connection_window_manager_(kInitialFlowControlWindowSize,
+ [this](size_t window_update_delta) {
+ SendWindowUpdate(kConnectionStreamId,
+ window_update_delta);
+ }),
+ options_(options) {
decoder_.set_visitor(this);
+ decoder_.set_extension_visitor(this);
if (options_.perspective == Perspective::kServer) {
remaining_preface_ = {spdy::kHttp2ConnectionHeaderPrefix,
spdy::kHttp2ConnectionHeaderPrefixSize};
@@ -32,6 +153,70 @@ OgHttp2Session::OgHttp2Session(Http2VisitorInterface& visitor, Options options)
OgHttp2Session::~OgHttp2Session() {}
+void OgHttp2Session::SetStreamUserData(Http2StreamId stream_id,
+ void* user_data) {
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ it->second.user_data = user_data;
+ }
+}
+
+void* OgHttp2Session::GetStreamUserData(Http2StreamId stream_id) {
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ return it->second.user_data;
+ }
+ return nullptr;
+}
+
+bool OgHttp2Session::ResumeStream(Http2StreamId stream_id) {
+ auto it = stream_map_.find(stream_id);
+ if (it->second.outbound_body == nullptr ||
+ !write_scheduler_.StreamRegistered(stream_id)) {
+ return false;
+ }
+ write_scheduler_.MarkStreamReady(stream_id, /*add_to_front=*/false);
+ return true;
+}
+
+int OgHttp2Session::GetStreamSendWindowSize(Http2StreamId stream_id) const {
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ return it->second.send_window;
+ }
+ return -1;
+}
+
+int OgHttp2Session::GetStreamReceiveWindowLimit(Http2StreamId stream_id) const {
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ return it->second.window_manager.WindowSizeLimit();
+ }
+ return -1;
+}
+
+int OgHttp2Session::GetStreamReceiveWindowSize(Http2StreamId stream_id) const {
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ return it->second.window_manager.CurrentWindowSize();
+ }
+ return -1;
+}
+
+int OgHttp2Session::GetReceiveWindowSize() const {
+ return connection_window_manager_.CurrentWindowSize();
+}
+
+int OgHttp2Session::GetHpackEncoderDynamicTableSize() const {
+ const spdy::HpackEncoder* encoder = framer_.GetHpackEncoder();
+ return encoder == nullptr ? 0 : encoder->GetDynamicTableSize();
+}
+
+int OgHttp2Session::GetHpackDecoderDynamicTableSize() const {
+ const spdy::HpackDecoderAdapter* decoder = decoder_.GetHpackDecoder();
+ return decoder == nullptr ? 0 : decoder->GetDynamicTableSize();
+}
+
ssize_t OgHttp2Session::ProcessBytes(absl::string_view bytes) {
ssize_t preface_consumed = 0;
if (!remaining_preface_.empty()) {
@@ -68,27 +253,317 @@ int OgHttp2Session::Consume(Http2StreamId stream_id, size_t num_bytes) {
} else {
it->second.window_manager.MarkDataFlushed(num_bytes);
}
+ connection_window_manager_.MarkDataFlushed(num_bytes);
return 0; // Remove?
}
+void OgHttp2Session::StartGracefulShutdown() {
+ if (options_.perspective == Perspective::kServer) {
+ if (!queued_goaway_) {
+ EnqueueFrame(absl::make_unique<spdy::SpdyGoAwayIR>(
+ std::numeric_limits<int32_t>::max(), spdy::ERROR_CODE_NO_ERROR,
+ "graceful_shutdown"));
+ }
+ } else {
+ QUICHE_LOG(ERROR) << "Graceful shutdown not needed for clients.";
+ }
+}
+
void OgHttp2Session::EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame) {
+ if (frame->frame_type() == spdy::SpdyFrameType::GOAWAY) {
+ queued_goaway_ = true;
+ } else if (frame->frame_type() == spdy::SpdyFrameType::RST_STREAM) {
+ streams_reset_.insert(frame->stream_id());
+ auto iter = stream_map_.find(frame->stream_id());
+ if (iter != stream_map_.end()) {
+ iter->second.half_closed_local = true;
+ }
+ }
frames_.push_back(std::move(frame));
}
-std::string OgHttp2Session::GetBytesToWrite(absl::optional<size_t> max_bytes) {
- const size_t serialized_max =
- max_bytes ? max_bytes.value() : std::numeric_limits<size_t>::max();
- std::string serialized = std::move(serialized_prefix_);
- while (serialized.size() < serialized_max && !frames_.empty()) {
- spdy::SpdySerializedFrame frame = framer_.SerializeFrame(*frames_.front());
- absl::StrAppend(&serialized, absl::string_view(frame));
- frames_.pop_front();
+int OgHttp2Session::Send() {
+ MaybeSetupPreface();
+ ssize_t result = std::numeric_limits<ssize_t>::max();
+ // Flush any serialized prefix.
+ while (result > 0 && !serialized_prefix_.empty()) {
+ result = visitor_.OnReadyToSend(serialized_prefix_);
+ if (result > 0) {
+ serialized_prefix_.erase(0, result);
+ }
+ }
+ if (!serialized_prefix_.empty()) {
+ return result < 0 ? result : 0;
+ }
+ bool continue_writing = SendQueuedFrames();
+ while (continue_writing && !connection_metadata_.empty()) {
+ continue_writing = SendMetadata(0, connection_metadata_);
+ }
+ // Wake streams for writes.
+ while (continue_writing && write_scheduler_.HasReadyStreams() &&
+ connection_send_window_ > 0) {
+ const Http2StreamId stream_id = write_scheduler_.PopNextReadyStream();
+ // TODO(birenroy): Add a return value to indicate write blockage, so streams
+ // aren't woken unnecessarily.
+ continue_writing = WriteForStream(stream_id);
+ }
+ if (continue_writing) {
+ SendQueuedFrames();
+ }
+ return 0;
+}
+
+bool OgHttp2Session::SendQueuedFrames() {
+ // Serialize and send frames in the queue.
+ while (!frames_.empty()) {
+ const auto& frame_ptr = frames_.front();
+ FrameAttributeCollector c;
+ frame_ptr->Visit(&c);
+ visitor_.OnBeforeFrameSent(c.frame_type(), c.stream_id(), c.length(),
+ c.flags());
+ spdy::SpdySerializedFrame frame = framer_.SerializeFrame(*frame_ptr);
+ const ssize_t result = visitor_.OnReadyToSend(absl::string_view(frame));
+ if (result < 0) {
+ visitor_.OnConnectionError();
+ return false;
+ } else if (result == 0) {
+ // Write blocked.
+ return false;
+ } else {
+ visitor_.OnFrameSent(c.frame_type(), c.stream_id(), c.length(), c.flags(),
+ c.error_code());
+ if (static_cast<FrameType>(c.frame_type()) == FrameType::RST_STREAM) {
+ // If this endpoint is resetting the stream, the stream should be
+ // closed. This endpoint is already aware of the outbound RST_STREAM and
+ // its error code, so close with NO_ERROR.
+ visitor_.OnCloseStream(c.stream_id(), Http2ErrorCode::NO_ERROR);
+ }
+
+ frames_.pop_front();
+ if (static_cast<size_t>(result) < frame.size()) {
+ // The frame was partially written, so the rest must be buffered.
+ serialized_prefix_.assign(frame.data() + result, frame.size() - result);
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+bool OgHttp2Session::WriteForStream(Http2StreamId stream_id) {
+ auto it = stream_map_.find(stream_id);
+ if (it == stream_map_.end()) {
+ QUICHE_LOG(ERROR) << "Can't find stream " << stream_id
+ << " which is ready to write!";
+ return true;
+ }
+ StreamState& state = it->second;
+ bool connection_can_write = true;
+ if (!state.outbound_metadata.empty()) {
+ connection_can_write = SendMetadata(stream_id, state.outbound_metadata);
+ }
+
+ if (state.outbound_body == nullptr) {
+ // No data to send, but there might be trailers.
+ if (state.trailers != nullptr) {
+ auto block_ptr = std::move(state.trailers);
+ if (state.half_closed_local) {
+ QUICHE_LOG(ERROR) << "Sent fin; can't send trailers.";
+ } else {
+ SendTrailers(stream_id, std::move(*block_ptr));
+ MaybeCloseWithRstStream(stream_id, state);
+ }
+ }
+ return true;
+ }
+ bool source_can_produce = true;
+ int32_t available_window = std::min(
+ std::min(connection_send_window_, state.send_window), max_frame_payload_);
+ while (connection_can_write && available_window > 0 &&
+ state.outbound_body != nullptr) {
+ ssize_t length;
+ bool end_data;
+ std::tie(length, end_data) =
+ state.outbound_body->SelectPayloadLength(available_window);
+ if (length == 0 && !end_data) {
+ source_can_produce = false;
+ break;
+ } else if (length == DataFrameSource::kError) {
+ source_can_produce = false;
+ visitor_.OnCloseStream(stream_id, Http2ErrorCode::INTERNAL_ERROR);
+ break;
+ }
+ const bool fin = end_data ? state.outbound_body->send_fin() : false;
+ if (length > 0 || fin) {
+ spdy::SpdyDataIR data(stream_id);
+ data.set_fin(fin);
+ data.SetDataShallow(length);
+ spdy::SpdySerializedFrame header =
+ spdy::SpdyFramer::SerializeDataFrameHeaderWithPaddingLengthField(
+ data);
+ QUICHE_DCHECK(serialized_prefix_.empty() && frames_.empty());
+ const bool success =
+ state.outbound_body->Send(absl::string_view(header), length);
+ if (!success) {
+ connection_can_write = false;
+ break;
+ }
+ visitor_.OnFrameSent(/* DATA */ 0, stream_id, length, fin ? 0x1 : 0x0, 0);
+ connection_send_window_ -= length;
+ state.send_window -= length;
+ available_window =
+ std::min(std::min(connection_send_window_, state.send_window),
+ max_frame_payload_);
+ }
+ if (end_data) {
+ bool sent_trailers = false;
+ if (state.trailers != nullptr) {
+ auto block_ptr = std::move(state.trailers);
+ if (fin) {
+ QUICHE_LOG(ERROR) << "Sent fin; can't send trailers.";
+ } else {
+ SendTrailers(stream_id, std::move(*block_ptr));
+ sent_trailers = true;
+ }
+ }
+ state.outbound_body = nullptr;
+ if (fin || sent_trailers) {
+ MaybeCloseWithRstStream(stream_id, state);
+ }
+ }
+ }
+ // If the stream still has data to send, it should be marked as ready in the
+ // write scheduler.
+ if (source_can_produce && state.send_window > 0 &&
+ state.outbound_body != nullptr) {
+ write_scheduler_.MarkStreamReady(stream_id, false);
+ }
+ // Streams can continue writing as long as the connection is not write-blocked
+ // and there is additional flow control quota available.
+ return connection_can_write && available_window > 0;
+}
+
+bool OgHttp2Session::SendMetadata(Http2StreamId stream_id,
+ OgHttp2Session::MetadataSequence& sequence) {
+ auto payload_buffer = absl::make_unique<uint8_t[]>(kMaxMetadataFrameSize);
+ while (!sequence.empty()) {
+ MetadataSource& source = *sequence.front();
+
+ ssize_t written;
+ bool end_metadata;
+ std::tie(written, end_metadata) =
+ source.Pack(payload_buffer.get(), kMaxMetadataFrameSize);
+ if (written < 0) {
+ // Did not touch the connection, so perhaps writes are still possible.
+ return true;
+ }
+ QUICHE_DCHECK_LE(static_cast<size_t>(written), kMaxMetadataFrameSize);
+ auto payload = absl::string_view(
+ reinterpret_cast<const char*>(payload_buffer.get()), written);
+ EnqueueFrame(absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id, kMetadataFrameType, end_metadata ? kMetadataEndFlag : 0u,
+ std::string(payload)));
+ if (end_metadata) {
+ sequence.erase(sequence.begin());
+ }
+ }
+ return SendQueuedFrames();
+}
+
+int32_t OgHttp2Session::SubmitRequest(
+ absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source, void* user_data) {
+ // TODO(birenroy): return an error for the incorrect perspective
+ const Http2StreamId stream_id = next_stream_id_;
+ next_stream_id_ += 2;
+ // Convert headers to header block, create headers frame.
+ auto frame =
+ absl::make_unique<spdy::SpdyHeadersIR>(stream_id, ToHeaderBlock(headers));
+ // Add data source and user data to stream state
+ auto iter = CreateStream(stream_id);
+ write_scheduler_.MarkStreamReady(stream_id, false);
+ if (data_source == nullptr) {
+ frame->set_fin(true);
+ iter->second.half_closed_local = true;
+ } else {
+ iter->second.outbound_body = std::move(data_source);
+ }
+ iter->second.user_data = user_data;
+ // Enqueue headers frame
+ EnqueueFrame(std::move(frame));
+ return stream_id;
+}
+
+int OgHttp2Session::SubmitResponse(
+ Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source) {
+ // TODO(birenroy): return an error for the incorrect perspective
+ auto iter = stream_map_.find(stream_id);
+ if (iter == stream_map_.end()) {
+ QUICHE_LOG(ERROR) << "Unable to find stream " << stream_id;
+ return -501; // NGHTTP2_ERR_INVALID_ARGUMENT
+ }
+ // Convert headers to header block, create headers frame
+ auto frame =
+ absl::make_unique<spdy::SpdyHeadersIR>(stream_id, ToHeaderBlock(headers));
+ if (data_source == nullptr) {
+ frame->set_fin(true);
+ if (iter->second.half_closed_remote) {
+ visitor_.OnCloseStream(stream_id, Http2ErrorCode::NO_ERROR);
+ }
+ // TODO(birenroy): the server adapter should probably delete stream state
+ // when calling visitor_.OnCloseStream.
+ } else {
+ // Add data source to stream state
+ iter->second.outbound_body = std::move(data_source);
+ write_scheduler_.MarkStreamReady(stream_id, false);
+ }
+ EnqueueFrame(std::move(frame));
+ return 0;
+}
+
+int OgHttp2Session::SubmitTrailer(Http2StreamId stream_id,
+ absl::Span<const Header> trailers) {
+ // TODO(birenroy): Reject trailers when acting as a client?
+ auto iter = stream_map_.find(stream_id);
+ if (iter == stream_map_.end()) {
+ QUICHE_LOG(ERROR) << "Unable to find stream " << stream_id;
+ return -501; // NGHTTP2_ERR_INVALID_ARGUMENT
+ }
+ StreamState& state = iter->second;
+ if (state.half_closed_local) {
+ QUICHE_LOG(ERROR) << "Stream " << stream_id << " is half closed (local)";
+ return -514; // NGHTTP2_ERR_INVALID_STREAM_STATE
}
- if (serialized.size() > serialized_max) {
- serialized_prefix_ = serialized.substr(serialized_max);
- serialized.resize(serialized_max);
+ if (state.trailers != nullptr) {
+ QUICHE_LOG(ERROR) << "Stream " << stream_id
+ << " already has trailers queued";
+ return -514; // NGHTTP2_ERR_INVALID_STREAM_STATE
+ }
+ if (state.outbound_body == nullptr) {
+ // Enqueue trailers immediately.
+ SendTrailers(stream_id, ToHeaderBlock(trailers));
+ MaybeCloseWithRstStream(stream_id, state);
+ } else {
+ QUICHE_LOG_IF(ERROR, state.outbound_body->send_fin())
+ << "DataFrameSource will send fin, preventing trailers!";
+ // Save trailers so they can be written once data is done.
+ state.trailers =
+ absl::make_unique<spdy::SpdyHeaderBlock>(ToHeaderBlock(trailers));
+ write_scheduler_.MarkStreamReady(stream_id, false);
+ }
+ return 0;
+}
+
+void OgHttp2Session::SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source) {
+ if (stream_id == 0) {
+ connection_metadata_.push_back(std::move(source));
+ } else {
+ auto iter = CreateStream(stream_id);
+ iter->second.outbound_metadata.push_back(std::move(source));
+ write_scheduler_.MarkStreamReady(stream_id, false);
}
- return serialized;
}
void OgHttp2Session::OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
@@ -103,32 +578,47 @@ void OgHttp2Session::OnCommonHeader(spdy::SpdyStreamId stream_id,
size_t length,
uint8_t type,
uint8_t flags) {
+ highest_received_stream_id_ = std::max(static_cast<Http2StreamId>(stream_id),
+ highest_received_stream_id_);
visitor_.OnFrameHeader(stream_id, length, type, flags);
}
void OgHttp2Session::OnDataFrameHeader(spdy::SpdyStreamId stream_id,
- size_t length,
- bool fin) {
+ size_t length, bool /*fin*/) {
visitor_.OnBeginDataForStream(stream_id, length);
}
void OgHttp2Session::OnStreamFrameData(spdy::SpdyStreamId stream_id,
const char* data,
size_t len) {
+ MarkDataBuffered(stream_id, len);
visitor_.OnDataForStream(stream_id, absl::string_view(data, len));
}
void OgHttp2Session::OnStreamEnd(spdy::SpdyStreamId stream_id) {
+ auto iter = stream_map_.find(stream_id);
+ if (iter != stream_map_.end()) {
+ iter->second.half_closed_remote = true;
+ }
visitor_.OnEndStream(stream_id);
+ if (iter != stream_map_.end() && iter->second.half_closed_local &&
+ options_.perspective == Perspective::kClient) {
+ // From the client's perspective, the stream can be closed if it's already
+ // half_closed_local.
+ visitor_.OnCloseStream(stream_id, Http2ErrorCode::NO_ERROR);
+ }
}
-void OgHttp2Session::OnStreamPadLength(spdy::SpdyStreamId /*stream_id*/,
- size_t /*value*/) {
- // TODO(181586191): handle padding
+void OgHttp2Session::OnStreamPadLength(spdy::SpdyStreamId stream_id,
+ size_t value) {
+ MarkDataBuffered(stream_id, 1 + value);
+ // TODO(181586191): Pass padding to the visitor?
}
-void OgHttp2Session::OnStreamPadding(spdy::SpdyStreamId stream_id, size_t len) {
- // TODO(181586191): handle padding
+void OgHttp2Session::OnStreamPadding(spdy::SpdyStreamId /*stream_id*/, size_t
+ /*len*/) {
+ // Flow control was accounted for in OnStreamPadLength().
+ // TODO(181586191): Pass padding to the visitor?
}
spdy::SpdyHeadersHandlerInterface* OgHttp2Session::OnHeaderFrameStart(
@@ -137,13 +627,21 @@ spdy::SpdyHeadersHandlerInterface* OgHttp2Session::OnHeaderFrameStart(
return &headers_handler_;
}
-void OgHttp2Session::OnHeaderFrameEnd(spdy::SpdyStreamId stream_id) {
+void OgHttp2Session::OnHeaderFrameEnd(spdy::SpdyStreamId /*stream_id*/) {
headers_handler_.set_stream_id(0);
}
void OgHttp2Session::OnRstStream(spdy::SpdyStreamId stream_id,
spdy::SpdyErrorCode error_code) {
+ auto iter = stream_map_.find(stream_id);
+ if (iter != stream_map_.end()) {
+ iter->second.half_closed_remote = true;
+ iter->second.outbound_body = nullptr;
+ write_scheduler_.UnregisterStream(stream_id);
+ }
visitor_.OnRstStream(stream_id, TranslateErrorCode(error_code));
+ // TODO(birenroy): Consider bundling "close stream" behavior into a dedicated
+ // method that also cleans up the stream map.
visitor_.OnCloseStream(stream_id, TranslateErrorCode(error_code));
}
@@ -153,10 +651,16 @@ void OgHttp2Session::OnSettings() {
void OgHttp2Session::OnSetting(spdy::SpdySettingsId id, uint32_t value) {
visitor_.OnSetting({id, value});
+ if (id == kMetadataExtensionId) {
+ peer_supports_metadata_ = (value != 0);
+ }
}
void OgHttp2Session::OnSettingsEnd() {
visitor_.OnSettingsEnd();
+ auto settings = absl::make_unique<spdy::SpdySettingsIR>();
+ settings->set_is_ack(true);
+ EnqueueFrame(std::move(settings));
}
void OgHttp2Session::OnSettingsAck() {
@@ -174,39 +678,46 @@ void OgHttp2Session::OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
"");
}
-bool OgHttp2Session::OnGoAwayFrameData(const char* goaway_data, size_t len) {
+bool OgHttp2Session::OnGoAwayFrameData(const char* /*goaway_data*/, size_t
+ /*len*/) {
// Opaque data is currently ignored.
return true;
}
void OgHttp2Session::OnHeaders(spdy::SpdyStreamId stream_id,
- bool has_priority,
- int weight,
- spdy::SpdyStreamId parent_stream_id,
- bool exclusive,
- bool fin,
- bool end) {}
+ bool /*has_priority*/, int /*weight*/,
+ spdy::SpdyStreamId /*parent_stream_id*/,
+ bool /*exclusive*/, bool /*fin*/, bool /*end*/) {
+ if (options_.perspective == Perspective::kServer) {
+ CreateStream(stream_id);
+ }
+}
void OgHttp2Session::OnWindowUpdate(spdy::SpdyStreamId stream_id,
int delta_window_size) {
if (stream_id == 0) {
- peer_window_ += delta_window_size;
+ connection_send_window_ += delta_window_size;
} else {
auto it = stream_map_.find(stream_id);
if (it == stream_map_.end()) {
QUICHE_VLOG(1) << "Stream " << stream_id << " not found!";
} else {
+ if (it->second.send_window == 0) {
+ // The stream was blocked on flow control.
+ write_scheduler_.MarkStreamReady(stream_id, false);
+ }
it->second.send_window += delta_window_size;
}
}
visitor_.OnWindowUpdate(stream_id, delta_window_size);
}
-void OgHttp2Session::OnPushPromise(spdy::SpdyStreamId stream_id,
- spdy::SpdyStreamId promised_stream_id,
- bool end) {}
+void OgHttp2Session::OnPushPromise(spdy::SpdyStreamId /*stream_id*/,
+ spdy::SpdyStreamId /*promised_stream_id*/,
+ bool /*end*/) {}
-void OgHttp2Session::OnContinuation(spdy::SpdyStreamId stream_id, bool end) {}
+void OgHttp2Session::OnContinuation(spdy::SpdyStreamId /*stream_id*/, bool
+ /*end*/) {}
void OgHttp2Session::OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
absl::string_view /*origin*/,
@@ -214,18 +725,141 @@ void OgHttp2Session::OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
AlternativeServiceVector& /*altsvc_vector*/) {
}
-void OgHttp2Session::OnPriority(spdy::SpdyStreamId stream_id,
- spdy::SpdyStreamId parent_stream_id,
- int weight,
- bool exclusive) {}
+void OgHttp2Session::OnPriority(spdy::SpdyStreamId /*stream_id*/,
+ spdy::SpdyStreamId /*parent_stream_id*/,
+ int /*weight*/, bool /*exclusive*/) {}
-void OgHttp2Session::OnPriorityUpdate(spdy::SpdyStreamId prioritized_stream_id,
- absl::string_view priority_field_value) {}
+void OgHttp2Session::OnPriorityUpdate(
+ spdy::SpdyStreamId /*prioritized_stream_id*/,
+ absl::string_view /*priority_field_value*/) {}
-bool OgHttp2Session::OnUnknownFrame(spdy::SpdyStreamId stream_id,
- uint8_t frame_type) {
+bool OgHttp2Session::OnUnknownFrame(spdy::SpdyStreamId /*stream_id*/,
+ uint8_t /*frame_type*/) {
return true;
}
+void OgHttp2Session::OnHeaderStatus(
+ Http2StreamId stream_id, Http2VisitorInterface::OnHeaderResult result) {
+ QUICHE_DCHECK_NE(result, Http2VisitorInterface::HEADER_OK);
+ if (result == Http2VisitorInterface::HEADER_RST_STREAM) {
+ auto it = streams_reset_.find(stream_id);
+ if (it == streams_reset_.end()) {
+ EnqueueFrame(absl::make_unique<spdy::SpdyRstStreamIR>(
+ stream_id, spdy::ERROR_CODE_INTERNAL_ERROR));
+ }
+ } else if (result == Http2VisitorInterface::HEADER_CONNECTION_ERROR) {
+ visitor_.OnConnectionError();
+ }
+}
+
+bool OgHttp2Session::OnFrameHeader(spdy::SpdyStreamId stream_id, size_t length,
+ uint8_t type, uint8_t flags) {
+ if (type == kMetadataFrameType) {
+ QUICHE_DCHECK_EQ(metadata_length_, 0u);
+ visitor_.OnBeginMetadataForStream(stream_id, length);
+ metadata_stream_id_ = stream_id;
+ metadata_length_ = length;
+ end_metadata_ = flags & kMetadataEndFlag;
+ return true;
+ } else {
+ QUICHE_DLOG(INFO) << "Unexpected frame type " << static_cast<int>(type)
+ << " received by the extension visitor.";
+ return false;
+ }
+}
+
+void OgHttp2Session::OnFramePayload(const char* data, size_t len) {
+ if (metadata_length_ > 0) {
+ QUICHE_DCHECK_LE(len, metadata_length_);
+ visitor_.OnMetadataForStream(metadata_stream_id_,
+ absl::string_view(data, len));
+ metadata_length_ -= len;
+ if (metadata_length_ == 0 && end_metadata_) {
+ visitor_.OnMetadataEndForStream(metadata_stream_id_);
+ metadata_stream_id_ = 0;
+ end_metadata_ = false;
+ }
+ } else {
+ QUICHE_DLOG(INFO) << "Unexpected metadata payload for stream "
+ << metadata_stream_id_;
+ }
+}
+
+void OgHttp2Session::MaybeSetupPreface() {
+ if (!queued_preface_) {
+ if (options_.perspective == Perspective::kClient) {
+ serialized_prefix_.assign(spdy::kHttp2ConnectionHeaderPrefix,
+ spdy::kHttp2ConnectionHeaderPrefixSize);
+ }
+ // First frame must be a non-ack SETTINGS.
+ if (frames_.empty() ||
+ frames_.front()->frame_type() != spdy::SpdyFrameType::SETTINGS ||
+ reinterpret_cast<spdy::SpdySettingsIR*>(frames_.front().get())
+ ->is_ack()) {
+ frames_.push_front(absl::make_unique<spdy::SpdySettingsIR>());
+ }
+ queued_preface_ = true;
+ }
+}
+
+void OgHttp2Session::SendWindowUpdate(Http2StreamId stream_id,
+ size_t update_delta) {
+ EnqueueFrame(
+ absl::make_unique<spdy::SpdyWindowUpdateIR>(stream_id, update_delta));
+}
+
+void OgHttp2Session::SendTrailers(Http2StreamId stream_id,
+ spdy::SpdyHeaderBlock trailers) {
+ auto frame =
+ absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(trailers));
+ frame->set_fin(true);
+ EnqueueFrame(std::move(frame));
+}
+
+void OgHttp2Session::MaybeCloseWithRstStream(Http2StreamId stream_id,
+ StreamState& state) {
+ state.half_closed_local = true;
+ if (options_.perspective == Perspective::kServer) {
+ if (state.half_closed_remote) {
+ visitor_.OnCloseStream(stream_id, Http2ErrorCode::NO_ERROR);
+ } else {
+ // Since the peer has not yet ended the stream, this endpoint should
+ // send a RST_STREAM NO_ERROR. See RFC 7540 Section 8.1.
+ EnqueueFrame(absl::make_unique<spdy::SpdyRstStreamIR>(
+ stream_id, spdy::SpdyErrorCode::ERROR_CODE_NO_ERROR));
+ // Enqueuing the RST_STREAM also invokes OnCloseStream.
+ }
+ // TODO(birenroy): the server adapter should probably delete stream state
+ // when calling visitor_.OnCloseStream.
+ }
+}
+
+void OgHttp2Session::MarkDataBuffered(Http2StreamId stream_id, size_t bytes) {
+ connection_window_manager_.MarkDataBuffered(bytes);
+ auto it = stream_map_.find(stream_id);
+ if (it != stream_map_.end()) {
+ it->second.window_manager.MarkDataBuffered(bytes);
+ }
+}
+
+OgHttp2Session::StreamStateMap::iterator OgHttp2Session::CreateStream(
+ Http2StreamId stream_id) {
+ WindowManager::WindowUpdateListener listener =
+ [this, stream_id](size_t window_update_delta) {
+ SendWindowUpdate(stream_id, window_update_delta);
+ };
+ absl::flat_hash_map<Http2StreamId, StreamState>::iterator iter;
+ bool inserted;
+ std::tie(iter, inserted) = stream_map_.try_emplace(
+ stream_id,
+ StreamState(stream_receive_window_limit_, std::move(listener)));
+ if (inserted) {
+ // Add the stream to the write scheduler.
+ const WriteScheduler::StreamPrecedenceType precedence(3);
+ write_scheduler_.RegisterStream(stream_id, precedence);
+ }
+ return iter;
+}
+
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
index b0bc28b7002..77b9da73c38 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session.h
@@ -3,11 +3,14 @@
#include <list>
+#include "http2/adapter/data_source.h"
#include "http2/adapter/http2_session.h"
#include "http2/adapter/http2_util.h"
#include "http2/adapter/http2_visitor_interface.h"
#include "http2/adapter/window_manager.h"
+#include "http2/core/priority_write_scheduler.h"
#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_export.h"
#include "spdy/core/http2_frame_decoder_adapter.h"
#include "spdy/core/spdy_framer.h"
@@ -15,33 +18,80 @@ namespace http2 {
namespace adapter {
// This class manages state associated with a single multiplexed HTTP/2 session.
-class OgHttp2Session : public Http2Session,
- public spdy::SpdyFramerVisitorInterface {
+class QUICHE_EXPORT_PRIVATE OgHttp2Session
+ : public Http2Session,
+ public spdy::SpdyFramerVisitorInterface,
+ public spdy::ExtensionVisitorInterface {
public:
- struct Options {
+ struct QUICHE_EXPORT_PRIVATE Options {
Perspective perspective = Perspective::kClient;
};
- OgHttp2Session(Http2VisitorInterface& visitor, Options /*options*/);
+ OgHttp2Session(Http2VisitorInterface& visitor, Options options);
~OgHttp2Session() override;
// Enqueues a frame for transmission to the peer.
void EnqueueFrame(std::unique_ptr<spdy::SpdyFrameIR> frame);
- // If |want_write()| returns true, this method will return a non-empty string
- // containing serialized HTTP/2 frames to write to the peer.
- std::string GetBytesToWrite(absl::optional<size_t> max_bytes);
+ // Starts a graceful shutdown sequence. No-op if a GOAWAY has already been
+ // sent.
+ void StartGracefulShutdown();
+
+ // Invokes the visitor's OnReadyToSend() method for serialized frame data.
+ int Send();
+
+ int32_t SubmitRequest(absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source,
+ void* user_data);
+ int SubmitResponse(Http2StreamId stream_id, absl::Span<const Header> headers,
+ std::unique_ptr<DataFrameSource> data_source);
+ int SubmitTrailer(Http2StreamId stream_id, absl::Span<const Header> trailers);
+ void SubmitMetadata(Http2StreamId stream_id,
+ std::unique_ptr<MetadataSource> source);
+
+ bool IsServerSession() const {
+ return options_.perspective == Perspective::kServer;
+ }
+ Http2StreamId GetHighestReceivedStreamId() const {
+ return highest_received_stream_id_;
+ }
+ void SetStreamUserData(Http2StreamId stream_id, void* user_data);
+ void* GetStreamUserData(Http2StreamId stream_id);
+
+ // Resumes a stream that was previously blocked. Returns true on success.
+ bool ResumeStream(Http2StreamId stream_id);
+
+ // Returns the peer's outstanding stream receive window for the given stream.
+ int GetStreamSendWindowSize(Http2StreamId stream_id) const;
+
+ // Returns the current upper bound on the flow control receive window for this
+ // stream.
+ int GetStreamReceiveWindowLimit(Http2StreamId stream_id) const;
+
+ // Returns the outstanding stream receive window, or -1 if the stream does not
+ // exist.
+ int GetStreamReceiveWindowSize(Http2StreamId stream_id) const;
+
+ // Returns the outstanding connection receive window.
+ int GetReceiveWindowSize() const;
+
+ // Returns the size of the HPACK encoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ int GetHpackEncoderDynamicTableSize() const;
+
+ // Returns the size of the HPACK decoder's dynamic table, including the
+ // per-entry overhead from the specification.
+ int GetHpackDecoderDynamicTableSize() const;
// From Http2Session.
ssize_t ProcessBytes(absl::string_view bytes) override;
int Consume(Http2StreamId stream_id, size_t num_bytes) override;
bool want_read() const override { return !received_goaway_; }
bool want_write() const override {
- return !frames_.empty() || !serialized_prefix_.empty();
- }
- int GetRemoteWindowSize() const override {
- return peer_window_;
+ return !frames_.empty() || !serialized_prefix_.empty() ||
+ write_scheduler_.HasReadyStreams() || !connection_metadata_.empty();
}
+ int GetRemoteWindowSize() const override { return connection_send_window_; }
// From SpdyFramerVisitorInterface
void OnError(http2::Http2DecoderAdapter::SpdyFramerError error,
@@ -72,7 +122,7 @@ class OgHttp2Session : public Http2Session,
void OnPing(spdy::SpdyPingId unique_id, bool is_ack) override;
void OnGoAway(spdy::SpdyStreamId last_accepted_stream_id,
spdy::SpdyErrorCode error_code) override;
- bool OnGoAwayFrameData(const char* goaway_data, size_t len);
+ bool OnGoAwayFrameData(const char* goaway_data, size_t len) override;
void OnHeaders(spdy::SpdyStreamId stream_id,
bool has_priority,
int weight,
@@ -86,10 +136,9 @@ class OgHttp2Session : public Http2Session,
spdy::SpdyStreamId promised_stream_id,
bool end) override;
void OnContinuation(spdy::SpdyStreamId stream_id, bool end) override;
- void OnAltSvc(spdy::SpdyStreamId /*stream_id*/,
- absl::string_view /*origin*/,
+ void OnAltSvc(spdy::SpdyStreamId /*stream_id*/, absl::string_view /*origin*/,
const spdy::SpdyAltSvcWireFormat::
- AlternativeServiceVector& /*altsvc_vector*/);
+ AlternativeServiceVector& /*altsvc_vector*/) override;
void OnPriority(spdy::SpdyStreamId stream_id,
spdy::SpdyStreamId parent_stream_id,
int weight,
@@ -99,40 +148,136 @@ class OgHttp2Session : public Http2Session,
bool OnUnknownFrame(spdy::SpdyStreamId stream_id,
uint8_t frame_type) override;
+ // Invoked when header processing encounters an invalid or otherwise
+ // problematic header.
+ void OnHeaderStatus(Http2StreamId stream_id,
+ Http2VisitorInterface::OnHeaderResult result);
+
+ // Returns true if a recognized extension frame is received.
+ bool OnFrameHeader(spdy::SpdyStreamId stream_id, size_t length, uint8_t type,
+ uint8_t flags) override;
+
+ // Handles the payload for a recognized extension frame.
+ void OnFramePayload(const char* data, size_t len) override;
+
private:
- struct StreamState {
+ using MetadataSequence = std::vector<std::unique_ptr<MetadataSource>>;
+ struct QUICHE_EXPORT_PRIVATE StreamState {
+ StreamState(int32_t stream_receive_window,
+ WindowManager::WindowUpdateListener listener)
+ : window_manager(stream_receive_window, std::move(listener)) {}
+
WindowManager window_manager;
- int32_t send_window = 65535;
+ std::unique_ptr<DataFrameSource> outbound_body;
+ MetadataSequence outbound_metadata;
+ std::unique_ptr<spdy::SpdyHeaderBlock> trailers;
+ void* user_data = nullptr;
+ int32_t send_window = kInitialFlowControlWindowSize;
bool half_closed_local = false;
bool half_closed_remote = false;
};
+ using StreamStateMap = absl::flat_hash_map<Http2StreamId, StreamState>;
- class PassthroughHeadersHandler : public spdy::SpdyHeadersHandlerInterface {
+ class QUICHE_EXPORT_PRIVATE PassthroughHeadersHandler
+ : public spdy::SpdyHeadersHandlerInterface {
public:
- explicit PassthroughHeadersHandler(Http2VisitorInterface& visitor)
- : visitor_(visitor) {}
- void set_stream_id(Http2StreamId stream_id) { stream_id_ = stream_id; }
+ explicit PassthroughHeadersHandler(OgHttp2Session& session,
+ Http2VisitorInterface& visitor)
+ : session_(session), visitor_(visitor) {}
+ void set_stream_id(Http2StreamId stream_id) {
+ stream_id_ = stream_id;
+ result_ = Http2VisitorInterface::HEADER_OK;
+ }
void OnHeaderBlockStart() override;
void OnHeader(absl::string_view key, absl::string_view value) override;
void OnHeaderBlockEnd(size_t /* uncompressed_header_bytes */,
size_t /* compressed_header_bytes */) override;
private:
+ OgHttp2Session& session_;
Http2VisitorInterface& visitor_;
Http2StreamId stream_id_ = 0;
+ Http2VisitorInterface::OnHeaderResult result_ =
+ Http2VisitorInterface::HEADER_OK;
};
+ // Queues the connection preface, if not already done.
+ void MaybeSetupPreface();
+
+ void SendWindowUpdate(Http2StreamId stream_id, size_t update_delta);
+
+ // Sends queued frames, returning true if all frames were flushed
+ // successfully.
+ bool SendQueuedFrames();
+
+ // Returns false if the connection is write-blocked (due to flow control or
+ // some other reason).
+ bool WriteForStream(Http2StreamId stream_id);
+
+ bool SendMetadata(Http2StreamId stream_id, MetadataSequence& sequence);
+
+ void SendTrailers(Http2StreamId stream_id, spdy::SpdyHeaderBlock trailers);
+
+ // Encapsulates the RST_STREAM NO_ERROR behavior described in RFC 7540
+ // Section 8.1.
+ void MaybeCloseWithRstStream(Http2StreamId stream_id, StreamState& state);
+
+ // Performs flow control accounting for data sent by the peer.
+ void MarkDataBuffered(Http2StreamId stream_id, size_t bytes);
+
+ // Creates a stream and returns an iterator pointing to it.
+ StreamStateMap::iterator CreateStream(Http2StreamId stream_id);
+
+ // Receives events when inbound frames are parsed.
Http2VisitorInterface& visitor_;
+
+ // Encodes outbound frames.
spdy::SpdyFramer framer_{spdy::SpdyFramer::ENABLE_COMPRESSION};
+
+ // Decodes inbound frames.
http2::Http2DecoderAdapter decoder_;
- absl::flat_hash_map<Http2StreamId, StreamState> stream_map_;
+
+ // Maintains the state of all streams known to this session.
+ StreamStateMap stream_map_;
+
+ // Maintains the queue of outbound frames, and any serialized bytes that have
+ // not yet been consumed.
std::list<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
- PassthroughHeadersHandler headers_handler_;
std::string serialized_prefix_;
+
+ // Maintains the set of streams ready to write data to the peer.
+ using WriteScheduler = PriorityWriteScheduler<Http2StreamId>;
+ WriteScheduler write_scheduler_;
+
+ // Delivers header name-value pairs to the visitor.
+ PassthroughHeadersHandler headers_handler_;
+
+ // Tracks the remaining client connection preface, in the case of a server
+ // session.
absl::string_view remaining_preface_;
- int peer_window_ = 65535;
+
+ WindowManager connection_window_manager_;
+
+ absl::flat_hash_set<Http2StreamId> streams_reset_;
+
+ MetadataSequence connection_metadata_;
+
+ Http2StreamId next_stream_id_ = 1;
+ Http2StreamId highest_received_stream_id_ = 0;
+ Http2StreamId metadata_stream_id_ = 0;
+ size_t metadata_length_ = 0;
+ int connection_send_window_ = kInitialFlowControlWindowSize;
+ // The initial flow control receive window size for any newly created streams.
+ int stream_receive_window_limit_ = kInitialFlowControlWindowSize;
+ int max_frame_payload_ = 16384;
Options options_;
bool received_goaway_ = false;
+ bool queued_preface_ = false;
+ bool peer_supports_metadata_ = false;
+ bool end_metadata_ = false;
+
+ // Replace this with a stream ID, for multiple GOAWAY support.
+ bool queued_goaway_ = false;
};
} // namespace adapter
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc
index ab155697d5d..3f24ea200ef 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_session_test.cc
@@ -2,6 +2,7 @@
#include "http2/adapter/mock_http2_visitor.h"
#include "http2/adapter/test_frame_sequence.h"
+#include "http2/adapter/test_utils.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -9,6 +10,7 @@ namespace adapter {
namespace test {
namespace {
+using spdy::SpdyFrameType;
using testing::_;
enum FrameType {
@@ -31,7 +33,9 @@ TEST(OgHttp2SessionTest, ClientConstruction) {
visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
EXPECT_TRUE(session.want_read());
EXPECT_FALSE(session.want_write());
- EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
+ EXPECT_FALSE(session.IsServerSession());
+ EXPECT_EQ(0, session.GetHighestReceivedStreamId());
}
TEST(OgHttp2SessionTest, ClientHandlesFrames) {
@@ -56,43 +60,433 @@ TEST(OgHttp2SessionTest, ClientHandlesFrames) {
EXPECT_CALL(visitor, OnFrameHeader(0, 4, WINDOW_UPDATE, 0));
EXPECT_CALL(visitor, OnWindowUpdate(0, 1000));
- const ssize_t initial_result = session.ProcessBytes(initial_frames);
+ const size_t initial_result = session.ProcessBytes(initial_frames);
EXPECT_EQ(initial_frames.size(), initial_result);
EXPECT_EQ(session.GetRemoteWindowSize(),
- kDefaultInitialStreamWindowSize + 1000);
+ kInitialFlowControlWindowSize + 1000);
+ EXPECT_EQ(0, session.GetHighestReceivedStreamId());
+
+ // Connection has not yet received any data.
+ EXPECT_EQ(kInitialFlowControlWindowSize, session.GetReceiveWindowSize());
+
+ EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
// Should OgHttp2Session require that streams 1 and 3 have been created?
+ // Submit a request to ensure the first stream is created.
+ const char* kSentinel1 = "arbitrary pointer 1";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ body1->AppendPayload("This is an example request body.");
+ body1->EndData();
+ int stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel1));
+ EXPECT_EQ(stream_id, 1);
+
const std::string stream_frames =
TestFrameSequence()
- .Headers(1,
+ .Headers(stream_id,
{{":status", "200"},
{"server", "my-fake-server"},
{"date", "Tue, 6 Apr 2021 12:54:01 GMT"}},
/*fin=*/false)
- .Data(1, "This is the response body.")
+ .Data(stream_id, "This is the response body.")
.RstStream(3, Http2ErrorCode::INTERNAL_ERROR)
.GoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, "calm down!!")
.Serialize();
- EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 4));
- EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
- EXPECT_CALL(visitor, OnHeaderForStream(1, ":status", "200"));
- EXPECT_CALL(visitor, OnHeaderForStream(1, "server", "my-fake-server"));
+ EXPECT_CALL(visitor, OnFrameHeader(stream_id, _, HEADERS, 4));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(stream_id));
+ EXPECT_CALL(visitor, OnHeaderForStream(stream_id, ":status", "200"));
EXPECT_CALL(visitor,
- OnHeaderForStream(1, "date", "Tue, 6 Apr 2021 12:54:01 GMT"));
- EXPECT_CALL(visitor, OnEndHeadersForStream(1));
- EXPECT_CALL(visitor, OnFrameHeader(1, 26, DATA, 0));
- EXPECT_CALL(visitor, OnBeginDataForStream(1, 26));
- EXPECT_CALL(visitor, OnDataForStream(1, "This is the response body."));
+ OnHeaderForStream(stream_id, "server", "my-fake-server"));
+ EXPECT_CALL(visitor, OnHeaderForStream(stream_id, "date",
+ "Tue, 6 Apr 2021 12:54:01 GMT"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(stream_id));
+ EXPECT_CALL(visitor, OnFrameHeader(stream_id, 26, DATA, 0));
+ EXPECT_CALL(visitor, OnBeginDataForStream(stream_id, 26));
+ EXPECT_CALL(visitor,
+ OnDataForStream(stream_id, "This is the response body."));
EXPECT_CALL(visitor, OnFrameHeader(3, 4, RST_STREAM, 0));
EXPECT_CALL(visitor, OnRstStream(3, Http2ErrorCode::INTERNAL_ERROR));
EXPECT_CALL(visitor, OnCloseStream(3, Http2ErrorCode::INTERNAL_ERROR));
EXPECT_CALL(visitor, OnFrameHeader(0, 19, GOAWAY, 0));
EXPECT_CALL(visitor, OnGoAway(5, Http2ErrorCode::ENHANCE_YOUR_CALM, ""));
- const ssize_t stream_result = session.ProcessBytes(stream_frames);
+ const size_t stream_result = session.ProcessBytes(stream_frames);
EXPECT_EQ(stream_frames.size(), stream_result);
+ EXPECT_EQ(3, session.GetHighestReceivedStreamId());
+
+ // The first stream is active and has received some data.
+ EXPECT_GT(kInitialFlowControlWindowSize,
+ session.GetStreamReceiveWindowSize(stream_id));
+ // Connection receive window is equivalent to the first stream's.
+ EXPECT_EQ(session.GetReceiveWindowSize(),
+ session.GetStreamReceiveWindowSize(stream_id));
+ // Receive window upper bound is still the initial value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ session.GetStreamReceiveWindowLimit(stream_id));
+
+ EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
+}
+
+// Verifies that a client session enqueues initial SETTINGS if Send() is called
+// before any frames are explicitly queued.
+TEST(OgHttp2SessionTest, ClientEnqueuesSettingsOnSend) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
+}
+
+// Verifies that a client session enqueues initial SETTINGS before whatever
+// frame type is passed to the first invocation of EnqueueFrame().
+TEST(OgHttp2SessionTest, ClientEnqueuesSettingsBeforeOtherFrame) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+ session.EnqueueFrame(absl::make_unique<spdy::SpdyPingIR>(42));
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, 8, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(PING, 0, 8, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized,
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
+}
+
+// Verifies that if the first call to EnqueueFrame() passes a SETTINGS frame,
+// the client session will not enqueue an additional SETTINGS frame.
+TEST(OgHttp2SessionTest, ClientEnqueuesSettingsOnce) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+ session.EnqueueFrame(absl::make_unique<spdy::SpdySettingsIR>());
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2SessionTest, ClientSubmitRequest) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+
+ EXPECT_FALSE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+
+ // Even though the user has not queued any frames for the session, it should
+ // still send the connection preface.
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ // Initial SETTINGS.
+ EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ const std::string initial_frames =
+ TestFrameSequence().ServerPreface().Serialize();
+ testing::InSequence s;
+
+ // Server preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+
+ const size_t initial_result = session.ProcessBytes(initial_frames);
+ EXPECT_EQ(initial_frames.size(), initial_result);
+
+ // Session will want to write a SETTINGS ack.
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ body1->AppendPayload("This is an example request body.");
+ body1->EndData();
+ int stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel1));
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(session.want_write());
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS,
+ spdy::SpdyFrameType::DATA}));
+ visitor.Clear();
+ EXPECT_FALSE(session.want_write());
+
+ // Some data was sent, so the remaining send window size should be less than
+ // the default.
+ EXPECT_LT(session.GetStreamSendWindowSize(stream_id),
+ kInitialFlowControlWindowSize);
+ EXPECT_GT(session.GetStreamSendWindowSize(stream_id), 0);
+ // Send window for a nonexistent stream is not available.
+ EXPECT_EQ(-1, session.GetStreamSendWindowSize(stream_id + 2));
+
+ EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
+
+ stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/two"}}),
+ nullptr, nullptr);
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(session.want_write());
+ const char* kSentinel2 = "arbitrary pointer 2";
+ EXPECT_EQ(nullptr, session.GetStreamUserData(stream_id));
+ session.SetStreamUserData(stream_id, const_cast<char*>(kSentinel2));
+ EXPECT_EQ(kSentinel2, session.GetStreamUserData(stream_id));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x5, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::HEADERS}));
+
+ // No data was sent (just HEADERS), so the remaining send window size should
+ // still be the default.
+ EXPECT_EQ(session.GetStreamSendWindowSize(stream_id),
+ kInitialFlowControlWindowSize);
+}
+
+// This test exercises the case where the client request body source is read
+// blocked.
+TEST(OgHttp2SessionTest, ClientSubmitRequestWithReadBlock) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ TestDataFrameSource* body_ref = body1.get();
+ int stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel1));
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(session.want_write());
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized,
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
+ // No data frame, as body1 was read blocked.
+ visitor.Clear();
+ EXPECT_FALSE(session.want_write());
+
+ body_ref->AppendPayload("This is an example request body.");
+ body_ref->EndData();
+ EXPECT_TRUE(session.ResumeStream(stream_id));
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
+ EXPECT_FALSE(session.want_write());
+
+ // Stream data is done, so this stream cannot be resumed.
+ EXPECT_FALSE(session.ResumeStream(stream_id));
+ EXPECT_FALSE(session.want_write());
+}
+
+// This test exercises the case where the client request body source is read
+// blocked, then ends with an empty DATA frame.
+TEST(OgHttp2SessionTest, ClientSubmitRequestEmptyDataWithFin) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ TestDataFrameSource* body_ref = body1.get();
+ int stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel1));
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(session.want_write());
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized,
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS}));
+ // No data frame, as body1 was read blocked.
+ visitor.Clear();
+ EXPECT_FALSE(session.want_write());
+
+ body_ref->EndData();
+ EXPECT_TRUE(session.ResumeStream(stream_id));
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, 0, 0x1, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::DATA}));
+ EXPECT_FALSE(session.want_write());
+
+ // Stream data is done, so this stream cannot be resumed.
+ EXPECT_FALSE(session.ResumeStream(stream_id));
+ EXPECT_FALSE(session.want_write());
+}
+
+// This test exercises the case where the connection to the peer is write
+// blocked.
+TEST(OgHttp2SessionTest, ClientSubmitRequestWithWriteBlock) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+ EXPECT_FALSE(session.want_write());
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, true);
+ body1->AppendPayload("This is an example request body.");
+ body1->EndData();
+ int stream_id =
+ session.SubmitRequest(ToHeaders({{":method", "POST"},
+ {":scheme", "http"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}}),
+ std::move(body1), const_cast<char*>(kSentinel1));
+ EXPECT_GT(stream_id, 0);
+ EXPECT_TRUE(session.want_write());
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(stream_id));
+ visitor.set_is_write_blocked(true);
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+
+ EXPECT_THAT(visitor.data(), testing::IsEmpty());
+ EXPECT_TRUE(session.want_write());
+ visitor.set_is_write_blocked(false);
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, stream_id, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, stream_id, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, stream_id, _, 0x1, 0));
+
+ result = session.Send();
+ EXPECT_EQ(0, result);
+
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized,
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::HEADERS,
+ SpdyFrameType::DATA}));
+ EXPECT_FALSE(session.want_write());
+}
+
+TEST(OgHttp2SessionTest, ClientStartShutdown) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kClient});
+
+ EXPECT_FALSE(session.want_write());
+
+ // No-op (except for logging) for a client implementation.
+ session.StartGracefulShutdown();
+ EXPECT_FALSE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+
+ absl::string_view serialized = visitor.data();
+ EXPECT_THAT(serialized,
+ testing::StartsWith(spdy::kHttp2ConnectionHeaderPrefix));
+ serialized.remove_prefix(strlen(spdy::kHttp2ConnectionHeaderPrefix));
+ EXPECT_THAT(serialized, EqualsFrames({SpdyFrameType::SETTINGS}));
}
TEST(OgHttp2SessionTest, ServerConstruction) {
@@ -101,14 +495,18 @@ TEST(OgHttp2SessionTest, ServerConstruction) {
visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
EXPECT_TRUE(session.want_read());
EXPECT_FALSE(session.want_write());
- EXPECT_EQ(session.GetRemoteWindowSize(), kDefaultInitialStreamWindowSize);
+ EXPECT_EQ(session.GetRemoteWindowSize(), kInitialFlowControlWindowSize);
+ EXPECT_TRUE(session.IsServerSession());
+ EXPECT_EQ(0, session.GetHighestReceivedStreamId());
}
TEST(OgHttp2SessionTest, ServerHandlesFrames) {
- testing::StrictMock<MockHttp2Visitor> visitor;
+ DataSavingVisitor visitor;
OgHttp2Session session(
visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+ EXPECT_EQ(0, session.GetHpackDecoderDynamicTableSize());
+
const std::string frames = TestFrameSequence()
.ClientPreface()
.Ping(42)
@@ -132,6 +530,8 @@ TEST(OgHttp2SessionTest, ServerHandlesFrames) {
.Serialize();
testing::InSequence s;
+ const char* kSentinel1 = "arbitrary pointer 1";
+
// Client preface (empty SETTINGS)
EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
EXPECT_CALL(visitor, OnSettingsStart());
@@ -147,7 +547,10 @@ TEST(OgHttp2SessionTest, ServerHandlesFrames) {
EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
- EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1))
+ .WillOnce(testing::InvokeWithoutArgs([&session, kSentinel1]() {
+ session.SetStreamUserData(1, const_cast<char*>(kSentinel1));
+ }));
EXPECT_CALL(visitor, OnFrameHeader(1, 4, WINDOW_UPDATE, 0));
EXPECT_CALL(visitor, OnWindowUpdate(1, 2000));
EXPECT_CALL(visitor, OnFrameHeader(1, 25, DATA, 0));
@@ -167,11 +570,410 @@ TEST(OgHttp2SessionTest, ServerHandlesFrames) {
EXPECT_CALL(visitor, OnFrameHeader(0, 8, PING, 0));
EXPECT_CALL(visitor, OnPing(47, false));
- const ssize_t result = session.ProcessBytes(frames);
+ const size_t result = session.ProcessBytes(frames);
EXPECT_EQ(frames.size(), result);
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(1));
+
+ // The first stream is active and has received some data.
+ EXPECT_GT(kInitialFlowControlWindowSize,
+ session.GetStreamReceiveWindowSize(1));
+ // Connection receive window is equivalent to the first stream's.
+ EXPECT_EQ(session.GetReceiveWindowSize(),
+ session.GetStreamReceiveWindowSize(1));
+ // Receive window upper bound is still the initial value.
+ EXPECT_EQ(kInitialFlowControlWindowSize,
+ session.GetStreamReceiveWindowLimit(1));
+
+ EXPECT_GT(session.GetHpackDecoderDynamicTableSize(), 0);
+
+ // TODO(birenroy): drop stream state when streams are closed. It should no
+ // longer be possible to set user data.
+ const char* kSentinel3 = "another arbitrary pointer";
+ session.SetStreamUserData(3, const_cast<char*>(kSentinel3));
+ EXPECT_EQ(kSentinel3, session.GetStreamUserData(3));
+
EXPECT_EQ(session.GetRemoteWindowSize(),
- kDefaultInitialStreamWindowSize + 1000);
+ kInitialFlowControlWindowSize + 1000);
+ EXPECT_EQ(3, session.GetHighestReceivedStreamId());
+
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ // Some bytes should have been serialized.
+ int send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ // Initial SETTINGS, SETTINGS ack.
+ // TODO(birenroy): automatically queue PING acks.
+ EXPECT_THAT(visitor.data(), EqualsFrames({spdy::SpdyFrameType::SETTINGS,
+ spdy::SpdyFrameType::SETTINGS}));
+}
+
+// Verifies that a server session enqueues initial SETTINGS before whatever
+// frame type is passed to the first invocation of EnqueueFrame().
+TEST(OgHttp2SessionTest, ServerEnqueuesSettingsBeforeOtherFrame) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+ EXPECT_FALSE(session.want_write());
+ session.EnqueueFrame(absl::make_unique<spdy::SpdyPingIR>(42));
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(PING, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(PING, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::PING}));
+}
+
+// Verifies that if the first call to EnqueueFrame() passes a SETTINGS frame,
+// the server session will not enqueue an additional SETTINGS frame.
+TEST(OgHttp2SessionTest, ServerEnqueuesSettingsOnce) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+ EXPECT_FALSE(session.want_write());
+ session.EnqueueFrame(absl::make_unique<spdy::SpdySettingsIR>());
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::SETTINGS}));
+}
+
+TEST(OgHttp2SessionTest, ServerSubmitResponse) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ EXPECT_FALSE(session.want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ const char* kSentinel1 = "arbitrary pointer 1";
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1))
+ .WillOnce(testing::InvokeWithoutArgs([&session, kSentinel1]() {
+ session.SetStreamUserData(1, const_cast<char*>(kSentinel1));
+ }));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ EXPECT_EQ(1, session.GetHighestReceivedStreamId());
+
+ EXPECT_EQ(0, session.GetHpackEncoderDynamicTableSize());
+
+ // Server will want to send initial SETTINGS, and a SETTINGS ack.
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ int send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_FALSE(session.want_write());
+ // A data fin is not sent so that the stream remains open, and the flow
+ // control state can be verified.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload("This is an example response body.");
+ int submit_result = session.SubmitResponse(
+ 1,
+ ToHeaders({{":status", "404"},
+ {"x-comment", "I have no idea what you're talking about."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(session.want_write());
+
+ // Stream user data should have been set successfully after receiving headers.
+ EXPECT_EQ(kSentinel1, session.GetStreamUserData(1));
+ session.SetStreamUserData(1, nullptr);
+ EXPECT_EQ(nullptr, session.GetStreamUserData(1));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
+ EXPECT_FALSE(session.want_write());
+
+ // Some data was sent, so the remaining send window size should be less than
+ // the default.
+ EXPECT_LT(session.GetStreamSendWindowSize(1), kInitialFlowControlWindowSize);
+ EXPECT_GT(session.GetStreamSendWindowSize(1), 0);
+ // Send window for a nonexistent stream is not available.
+ EXPECT_EQ(session.GetStreamSendWindowSize(3), -1);
+
+ EXPECT_GT(session.GetHpackEncoderDynamicTableSize(), 0);
+}
+
+TEST(OgHttp2SessionTest, ServerStartShutdown) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ EXPECT_FALSE(session.want_write());
+
+ session.StartGracefulShutdown();
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::GOAWAY}));
+}
+
+TEST(OgHttp2SessionTest, ServerStartShutdownAfterGoaway) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ EXPECT_FALSE(session.want_write());
+
+ auto goaway = absl::make_unique<spdy::SpdyGoAwayIR>(
+ 1, spdy::ERROR_CODE_NO_ERROR, "and don't come back!");
+ session.EnqueueFrame(std::move(goaway));
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(GOAWAY, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(GOAWAY, 0, _, 0x0, 0));
+
+ int result = session.Send();
+ EXPECT_EQ(0, result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::GOAWAY}));
+
+ // No-op, since a GOAWAY has previously been enqueued.
+ session.StartGracefulShutdown();
+ EXPECT_FALSE(session.want_write());
+}
+
+// Tests the case where the server queues trailers after the data stream is
+// exhausted.
+TEST(OgHttp2SessionTest, ServerSendsTrailers) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ EXPECT_FALSE(session.want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ // Server will want to send initial SETTINGS, and a SETTINGS ack.
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ int send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_FALSE(session.want_write());
+
+ // The body source must indicate that the end of the body is not the end of
+ // the stream.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload("This is an example response body.");
+ body1->EndData();
+ int submit_result = session.SubmitResponse(
+ 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA}));
+ visitor.Clear();
+ EXPECT_FALSE(session.want_write());
+
+ // The body source has been exhausted by the call to Send() above.
+ // TODO(birenroy): Fix this strange ordering.
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+ int trailer_result = session.SubmitTrailer(
+ 1, ToHeaders({{"final-status", "a-ok"},
+ {"x-comment", "trailers sure are cool"}}));
+ ASSERT_EQ(trailer_result, 0);
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+
+ send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(), EqualsFrames({SpdyFrameType::HEADERS}));
+}
+
+// Tests the case where the server queues trailers immediately after headers and
+// data, and before any writes have taken place.
+TEST(OgHttp2SessionTest, ServerQueuesTrailersWithResponse) {
+ DataSavingVisitor visitor;
+ OgHttp2Session session(
+ visitor, OgHttp2Session::Options{.perspective = Perspective::kServer});
+
+ EXPECT_FALSE(session.want_write());
+
+ const std::string frames = TestFrameSequence()
+ .ClientPreface()
+ .Headers(1,
+ {{":method", "GET"},
+ {":scheme", "https"},
+ {":authority", "example.com"},
+ {":path", "/this/is/request/one"}},
+ /*fin=*/true)
+ .Serialize();
+ testing::InSequence s;
+
+ // Client preface (empty SETTINGS)
+ EXPECT_CALL(visitor, OnFrameHeader(0, 0, SETTINGS, 0));
+ EXPECT_CALL(visitor, OnSettingsStart());
+ EXPECT_CALL(visitor, OnSettingsEnd());
+ // Stream 1
+ EXPECT_CALL(visitor, OnFrameHeader(1, _, HEADERS, 5));
+ EXPECT_CALL(visitor, OnBeginHeadersForStream(1));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":method", "GET"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":scheme", "https"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":authority", "example.com"));
+ EXPECT_CALL(visitor, OnHeaderForStream(1, ":path", "/this/is/request/one"));
+ EXPECT_CALL(visitor, OnEndHeadersForStream(1));
+ EXPECT_CALL(visitor, OnEndStream(1));
+
+ const size_t result = session.ProcessBytes(frames);
+ EXPECT_EQ(frames.size(), result);
+
+ // Server will want to send initial SETTINGS, and a SETTINGS ack.
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x0));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x0, 0));
+ EXPECT_CALL(visitor, OnBeforeFrameSent(SETTINGS, 0, _, 0x1));
+ EXPECT_CALL(visitor, OnFrameSent(SETTINGS, 0, _, 0x1, 0));
+
+ int send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::SETTINGS, SpdyFrameType::SETTINGS}));
+ visitor.Clear();
+
+ EXPECT_FALSE(session.want_write());
+
+ // The body source must indicate that the end of the body is not the end of
+ // the stream.
+ auto body1 = absl::make_unique<TestDataFrameSource>(visitor, false);
+ body1->AppendPayload("This is an example response body.");
+ body1->EndData();
+ int submit_result = session.SubmitResponse(
+ 1, ToHeaders({{":status", "200"}, {"x-comment", "Sure, sounds good."}}),
+ std::move(body1));
+ EXPECT_EQ(submit_result, 0);
+ EXPECT_TRUE(session.want_write());
+ // There has not been a call to Send() yet, so neither headers nor body have
+ // been written.
+ int trailer_result = session.SubmitTrailer(
+ 1, ToHeaders({{"final-status", "a-ok"},
+ {"x-comment", "trailers sure are cool"}}));
+ ASSERT_EQ(trailer_result, 0);
+ EXPECT_TRUE(session.want_write());
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x4));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x4, 0));
+ EXPECT_CALL(visitor, OnFrameSent(DATA, 1, _, 0x0, 0));
+
+ // TODO(birenroy): Fix this strange ordering.
+ EXPECT_CALL(visitor, OnCloseStream(1, Http2ErrorCode::NO_ERROR));
+
+ EXPECT_CALL(visitor, OnBeforeFrameSent(HEADERS, 1, _, 0x5));
+ EXPECT_CALL(visitor, OnFrameSent(HEADERS, 1, _, 0x5, 0));
+
+ send_result = session.Send();
+ EXPECT_EQ(0, send_result);
+ EXPECT_THAT(visitor.data(),
+ EqualsFrames({SpdyFrameType::HEADERS, SpdyFrameType::DATA,
+ SpdyFrameType::HEADERS}));
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h
index e222c96ccfd..3134ff7b004 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/oghttp2_util.h
@@ -3,12 +3,14 @@
#include "absl/types/span.h"
#include "http2/adapter/http2_protocol.h"
+#include "common/platform/api/quiche_export.h"
#include "spdy/core/spdy_header_block.h"
namespace http2 {
namespace adapter {
-spdy::SpdyHeaderBlock ToHeaderBlock(absl::Span<const Header> headers);
+QUICHE_EXPORT_PRIVATE spdy::SpdyHeaderBlock ToHeaderBlock(
+ absl::Span<const Header> headers);
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc
index 78ec423e25e..75f3749e62c 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.cc
@@ -7,6 +7,11 @@ namespace http2 {
namespace adapter {
namespace test {
+ssize_t RecordingHttp2Visitor::OnReadyToSend(absl::string_view serialized) {
+ events_.push_back(absl::StrFormat("OnReadyToSend %d", serialized.size()));
+ return serialized.size();
+}
+
void RecordingHttp2Visitor::OnConnectionError() {
events_.push_back("OnConnectionError");
}
@@ -36,15 +41,16 @@ void RecordingHttp2Visitor::OnSettingsAck() {
events_.push_back("OnSettingsAck");
}
-void RecordingHttp2Visitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
+bool RecordingHttp2Visitor::OnBeginHeadersForStream(Http2StreamId stream_id) {
events_.push_back(absl::StrFormat("OnBeginHeadersForStream %d", stream_id));
+ return true;
}
-void RecordingHttp2Visitor::OnHeaderForStream(Http2StreamId stream_id,
- absl::string_view name,
- absl::string_view value) {
+Http2VisitorInterface::OnHeaderResult RecordingHttp2Visitor::OnHeaderForStream(
+ Http2StreamId stream_id, absl::string_view name, absl::string_view value) {
events_.push_back(
absl::StrFormat("OnHeaderForStream %d %s %s", stream_id, name, value));
+ return HEADER_OK;
}
void RecordingHttp2Visitor::OnEndHeadersForStream(Http2StreamId stream_id) {
@@ -112,11 +118,32 @@ void RecordingHttp2Visitor::OnWindowUpdate(Http2StreamId stream_id,
absl::StrFormat("OnWindowUpdate %d %d", stream_id, window_increment));
}
-void RecordingHttp2Visitor::OnReadyToSendDataForStream(Http2StreamId stream_id,
- char* destination_buffer,
- size_t length,
- ssize_t* written,
- bool* end_stream) {
+int RecordingHttp2Visitor::OnBeforeFrameSent(uint8_t frame_type,
+ Http2StreamId stream_id,
+ size_t length, uint8_t flags) {
+ events_.push_back(absl::StrFormat("OnBeforeFrameSent %d %d %d %d", frame_type,
+ stream_id, length, flags));
+ return 0;
+}
+
+int RecordingHttp2Visitor::OnFrameSent(uint8_t frame_type,
+ Http2StreamId stream_id, size_t length,
+ uint8_t flags, uint32_t error_code) {
+ events_.push_back(absl::StrFormat("OnFrameSent %d %d %d %d %d", frame_type,
+ stream_id, length, flags, error_code));
+ return 0;
+}
+
+bool RecordingHttp2Visitor::OnInvalidFrame(Http2StreamId stream_id,
+ int error_code) {
+ events_.push_back(
+ absl::StrFormat("OnInvalidFrame %d %d", stream_id, error_code));
+ return true;
+}
+
+void RecordingHttp2Visitor::OnReadyToSendDataForStream(
+ Http2StreamId stream_id, char* /*destination_buffer*/, size_t length,
+ ssize_t* /*written*/, bool* /*end_stream*/) {
// TODO(b/181586191): Revisit this. The visitor is expected to write to the
// |destination_buffer| and set the other pointer values appropriately.
events_.push_back(
@@ -124,10 +151,8 @@ void RecordingHttp2Visitor::OnReadyToSendDataForStream(Http2StreamId stream_id,
}
void RecordingHttp2Visitor::OnReadyToSendMetadataForStream(
- Http2StreamId stream_id,
- char* buffer,
- size_t length,
- ssize_t* written) {
+ Http2StreamId stream_id, char* /*buffer*/, size_t length,
+ ssize_t* /*written*/) {
// TODO(b/181586191): Revisit this. The visitor is expected to write to the
// |buffer| and set *written appropriately.
events_.push_back(absl::StrFormat("OnReadyToSendMetadataForStream %d %d",
@@ -146,8 +171,13 @@ void RecordingHttp2Visitor::OnMetadataForStream(Http2StreamId stream_id,
absl::StrFormat("OnMetadataForStream %d %s", stream_id, metadata));
}
-void RecordingHttp2Visitor::OnMetadataEndForStream(Http2StreamId stream_id) {
+bool RecordingHttp2Visitor::OnMetadataEndForStream(Http2StreamId stream_id) {
events_.push_back(absl::StrFormat("OnMetadataEndForStream %d", stream_id));
+ return true;
+}
+
+void RecordingHttp2Visitor::OnErrorDebug(absl::string_view message) {
+ events_.push_back(absl::StrFormat("OnErrorDebug %s", message));
}
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h
index 452b45185cb..25b92935b35 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/recording_http2_visitor.h
@@ -5,6 +5,7 @@
#include <string>
#include "http2/adapter/http2_visitor_interface.h"
+#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
@@ -12,12 +13,13 @@ namespace adapter {
namespace test {
// A visitor implementation that records the sequence of callbacks it receives.
-class RecordingHttp2Visitor : public Http2VisitorInterface {
+class QUICHE_NO_EXPORT RecordingHttp2Visitor : public Http2VisitorInterface {
public:
using Event = std::string;
using EventSequence = std::list<Event>;
// From Http2VisitorInterface
+ ssize_t OnReadyToSend(absl::string_view serialized) override;
void OnConnectionError() override;
void OnFrameHeader(Http2StreamId stream_id,
size_t length,
@@ -27,10 +29,10 @@ class RecordingHttp2Visitor : public Http2VisitorInterface {
void OnSetting(Http2Setting setting) override;
void OnSettingsEnd() override;
void OnSettingsAck() override;
- void OnBeginHeadersForStream(Http2StreamId stream_id) override;
- void OnHeaderForStream(Http2StreamId stream_id,
- absl::string_view name,
- absl::string_view value) override;
+ bool OnBeginHeadersForStream(Http2StreamId stream_id) override;
+ OnHeaderResult OnHeaderForStream(Http2StreamId stream_id,
+ absl::string_view name,
+ absl::string_view value) override;
void OnEndHeadersForStream(Http2StreamId stream_id) override;
void OnBeginDataForStream(Http2StreamId stream_id,
size_t payload_length) override;
@@ -51,6 +53,11 @@ class RecordingHttp2Visitor : public Http2VisitorInterface {
Http2ErrorCode error_code,
absl::string_view opaque_data) override;
void OnWindowUpdate(Http2StreamId stream_id, int window_increment) override;
+ int OnBeforeFrameSent(uint8_t frame_type, Http2StreamId stream_id,
+ size_t length, uint8_t flags) override;
+ int OnFrameSent(uint8_t frame_type, Http2StreamId stream_id, size_t length,
+ uint8_t flags, uint32_t error_code) override;
+ bool OnInvalidFrame(Http2StreamId stream_id, int error_code) override;
void OnReadyToSendDataForStream(Http2StreamId stream_id,
char* destination_buffer,
size_t length,
@@ -64,7 +71,8 @@ class RecordingHttp2Visitor : public Http2VisitorInterface {
size_t payload_length) override;
void OnMetadataForStream(Http2StreamId stream_id,
absl::string_view metadata) override;
- void OnMetadataEndForStream(Http2StreamId stream_id) override;
+ bool OnMetadataEndForStream(Http2StreamId stream_id) override;
+ void OnErrorDebug(absl::string_view message) override;
const EventSequence& GetEventSequence() const { return events_; }
void Clear() { events_.clear(); }
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
index 7be368ea6a5..bb1517d3d73 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.cc
@@ -2,6 +2,7 @@
#include "http2/adapter/http2_util.h"
#include "http2/adapter/oghttp2_util.h"
+#include "spdy/core/hpack/hpack_encoder.h"
#include "spdy/core/spdy_framer.h"
namespace http2 {
@@ -11,8 +12,9 @@ namespace test {
std::vector<const Header> ToHeaders(
absl::Span<const std::pair<absl::string_view, absl::string_view>> headers) {
std::vector<const Header> out;
- for (auto [name, value] : headers) {
- out.push_back(std::make_pair(HeaderRep(name), HeaderRep(value)));
+ for (const auto& header : headers) {
+ out.push_back(
+ std::make_pair(HeaderRep(header.first), HeaderRep(header.second)));
}
return out;
}
@@ -88,24 +90,45 @@ TestFrameSequence& TestFrameSequence::GoAway(Http2StreamId last_good_stream_id,
TestFrameSequence& TestFrameSequence::Headers(
Http2StreamId stream_id,
absl::Span<const std::pair<absl::string_view, absl::string_view>> headers,
- bool fin) {
- return Headers(stream_id, ToHeaders(headers), fin);
+ bool fin, bool add_continuation) {
+ return Headers(stream_id, ToHeaders(headers), fin, add_continuation);
}
TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
spdy::Http2HeaderBlock block,
- bool fin) {
- auto headers =
- absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(block));
- headers->set_fin(fin);
- frames_.push_back(std::move(headers));
+ bool fin, bool add_continuation) {
+ if (add_continuation) {
+ // The normal intermediate representations don't allow you to represent a
+ // nonterminal HEADERS frame explicitly, so we'll need to use
+ // SpdyUnknownIRs. For simplicity, and in order not to mess up HPACK state,
+ // the payload will be uncompressed.
+ std::string encoded_block;
+ spdy::HpackEncoder encoder;
+ encoder.DisableCompression();
+ encoder.EncodeHeaderSet(block, &encoded_block);
+ const size_t pos = encoded_block.size() / 2;
+ const uint8_t flags = fin ? 0x1 : 0x0;
+ frames_.push_back(absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id, static_cast<uint8_t>(spdy::SpdyFrameType::HEADERS), flags,
+ encoded_block.substr(0, pos)));
+
+ auto continuation = absl::make_unique<spdy::SpdyContinuationIR>(stream_id);
+ continuation->set_end_headers(true);
+ continuation->take_encoding(encoded_block.substr(pos));
+ frames_.push_back(std::move(continuation));
+ } else {
+ auto headers =
+ absl::make_unique<spdy::SpdyHeadersIR>(stream_id, std::move(block));
+ headers->set_fin(fin);
+ frames_.push_back(std::move(headers));
+ }
return *this;
}
TestFrameSequence& TestFrameSequence::Headers(Http2StreamId stream_id,
absl::Span<const Header> headers,
- bool fin) {
- return Headers(stream_id, ToHeaderBlock(headers), fin);
+ bool fin, bool add_continuation) {
+ return Headers(stream_id, ToHeaderBlock(headers), fin, add_continuation);
}
TestFrameSequence& TestFrameSequence::WindowUpdate(Http2StreamId stream_id,
@@ -124,6 +147,25 @@ TestFrameSequence& TestFrameSequence::Priority(Http2StreamId stream_id,
return *this;
}
+TestFrameSequence& TestFrameSequence::Metadata(Http2StreamId stream_id,
+ absl::string_view payload,
+ bool multiple_frames) {
+ const std::string encoded_payload = MetadataBlockForPayload(payload);
+ if (multiple_frames) {
+ const size_t pos = encoded_payload.size() / 2;
+ frames_.push_back(absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id, kMetadataFrameType, 0, encoded_payload.substr(0, pos)));
+ frames_.push_back(absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id, kMetadataFrameType, kMetadataEndFlag,
+ encoded_payload.substr(pos)));
+ } else {
+ frames_.push_back(absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id, kMetadataFrameType, kMetadataEndFlag,
+ std::move(encoded_payload)));
+ }
+ return *this;
+}
+
std::string TestFrameSequence::Serialize() {
std::string result;
if (!preface_.empty()) {
@@ -137,6 +179,18 @@ std::string TestFrameSequence::Serialize() {
return result;
}
+std::string TestFrameSequence::MetadataBlockForPayload(
+ absl::string_view payload) {
+ // Encode the payload using a header block.
+ spdy::SpdyHeaderBlock block;
+ block["example-payload"] = payload;
+ spdy::HpackEncoder encoder;
+ encoder.DisableCompression();
+ std::string encoded_payload;
+ encoder.EncodeHeaderSet(block, &encoded_payload);
+ return encoded_payload;
+}
+
} // namespace test
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
index cc5e8b5ff57..99740d38f9e 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_frame_sequence.h
@@ -6,16 +6,17 @@
#include <vector>
#include "http2/adapter/http2_protocol.h"
+#include "common/platform/api/quiche_export.h"
#include "spdy/core/spdy_protocol.h"
namespace http2 {
namespace adapter {
namespace test {
-std::vector<const Header> ToHeaders(
+std::vector<const Header> QUICHE_NO_EXPORT ToHeaders(
absl::Span<const std::pair<absl::string_view, absl::string_view>> headers);
-class TestFrameSequence {
+class QUICHE_NO_EXPORT TestFrameSequence {
public:
TestFrameSequence() = default;
@@ -36,21 +37,26 @@ class TestFrameSequence {
TestFrameSequence& Headers(
Http2StreamId stream_id,
absl::Span<const std::pair<absl::string_view, absl::string_view>> headers,
- bool fin = false);
+ bool fin = false, bool add_continuation = false);
TestFrameSequence& Headers(Http2StreamId stream_id,
- spdy::Http2HeaderBlock block,
- bool fin = false);
+ spdy::Http2HeaderBlock block, bool fin = false,
+ bool add_continuation = false);
TestFrameSequence& Headers(Http2StreamId stream_id,
- absl::Span<const Header> headers,
- bool fin = false);
+ absl::Span<const Header> headers, bool fin = false,
+ bool add_continuation = false);
TestFrameSequence& WindowUpdate(Http2StreamId stream_id, int32_t delta);
TestFrameSequence& Priority(Http2StreamId stream_id,
Http2StreamId parent_stream_id,
int weight,
bool exclusive);
+ TestFrameSequence& Metadata(Http2StreamId stream_id,
+ absl::string_view payload,
+ bool multiple_frames = false);
std::string Serialize();
+ static std::string MetadataBlockForPayload(absl::string_view);
+
private:
std::string preface_;
std::vector<std::unique_ptr<spdy::SpdyFrameIR>> frames_;
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
index 315a28f0717..b8acddbb87f 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.cc
@@ -1,28 +1,123 @@
#include "http2/adapter/test_utils.h"
-#include "http2/adapter/nghttp2_util.h"
+#include <ostream>
+
+#include "absl/strings/str_format.h"
#include "common/quiche_endian.h"
+#include "spdy/core/hpack/hpack_encoder.h"
#include "spdy/core/spdy_frame_reader.h"
namespace http2 {
namespace adapter {
namespace test {
+
+TestDataFrameSource::TestDataFrameSource(Http2VisitorInterface& visitor,
+ bool has_fin)
+ : visitor_(visitor), has_fin_(has_fin) {}
+
+void TestDataFrameSource::AppendPayload(absl::string_view payload) {
+ QUICHE_CHECK(!end_data_);
+ if (!payload.empty()) {
+ payload_fragments_.push_back(std::string(payload));
+ current_fragment_ = payload_fragments_.front();
+ }
+}
+
+void TestDataFrameSource::EndData() { end_data_ = true; }
+
+std::pair<ssize_t, bool> TestDataFrameSource::SelectPayloadLength(
+ size_t max_length) {
+ // The stream is done if there's no more data, or if |max_length| is at least
+ // as large as the remaining data.
+ const bool end_data = end_data_ && (current_fragment_.empty() ||
+ (payload_fragments_.size() == 1 &&
+ max_length >= current_fragment_.size()));
+ const ssize_t length = std::min(max_length, current_fragment_.size());
+ return {length, end_data};
+}
+
+bool TestDataFrameSource::Send(absl::string_view frame_header,
+ size_t payload_length) {
+ QUICHE_LOG_IF(DFATAL, payload_length > current_fragment_.size())
+ << "payload_length: " << payload_length
+ << " current_fragment_size: " << current_fragment_.size();
+ const std::string concatenated =
+ absl::StrCat(frame_header, current_fragment_.substr(0, payload_length));
+ const ssize_t result = visitor_.OnReadyToSend(concatenated);
+ if (result < 0) {
+ // Write encountered error.
+ visitor_.OnConnectionError();
+ current_fragment_ = {};
+ payload_fragments_.clear();
+ return false;
+ } else if (result == 0) {
+ // Write blocked.
+ return false;
+ } else if (static_cast<const size_t>(result) < concatenated.size()) {
+ // Probably need to handle this better within this test class.
+ QUICHE_LOG(DFATAL)
+ << "DATA frame not fully flushed. Connection will be corrupt!";
+ visitor_.OnConnectionError();
+ current_fragment_ = {};
+ payload_fragments_.clear();
+ return false;
+ }
+ if (payload_length > 0) {
+ current_fragment_.remove_prefix(payload_length);
+ }
+ if (current_fragment_.empty() && !payload_fragments_.empty()) {
+ payload_fragments_.erase(payload_fragments_.begin());
+ if (!payload_fragments_.empty()) {
+ current_fragment_ = payload_fragments_.front();
+ }
+ }
+ return true;
+}
+
+std::string EncodeHeaders(const spdy::SpdyHeaderBlock& entries) {
+ spdy::HpackEncoder encoder;
+ encoder.DisableCompression();
+ std::string result;
+ QUICHE_CHECK(encoder.EncodeHeaderSet(entries, &result));
+ return result;
+}
+
+TestMetadataSource::TestMetadataSource(const spdy::SpdyHeaderBlock& entries)
+ : encoded_entries_(EncodeHeaders(entries)) {
+ remaining_ = encoded_entries_;
+}
+
+std::pair<ssize_t, bool> TestMetadataSource::Pack(uint8_t* dest,
+ size_t dest_len) {
+ const size_t copied = std::min(dest_len, remaining_.size());
+ std::memcpy(dest, remaining_.data(), copied);
+ remaining_.remove_prefix(copied);
+ return std::make_pair(copied, remaining_.empty());
+}
+
namespace {
using TypeAndOptionalLength =
std::pair<spdy::SpdyFrameType, absl::optional<size_t>>;
-std::vector<std::pair<const char*, std::string>> LogFriendly(
+std::ostream& operator<<(
+ std::ostream& os,
const std::vector<TypeAndOptionalLength>& types_and_lengths) {
- std::vector<std::pair<const char*, std::string>> out;
- out.reserve(types_and_lengths.size());
- for (const auto type_and_length : types_and_lengths) {
- out.push_back({spdy::FrameTypeToString(type_and_length.first),
- type_and_length.second
- ? absl::StrCat(type_and_length.second.value())
- : "<unspecified>"});
+ for (const auto& type_and_length : types_and_lengths) {
+ os << "(" << spdy::FrameTypeToString(type_and_length.first) << ", "
+ << (type_and_length.second ? absl::StrCat(type_and_length.second.value())
+ : "<unspecified>")
+ << ") ";
+ }
+ return os;
+}
+
+std::string FrameTypeToString(uint8_t frame_type) {
+ if (spdy::IsDefinedFrameType(frame_type)) {
+ return spdy::FrameTypeToString(spdy::ParseFrameType(frame_type));
+ } else {
+ return absl::StrFormat("0x%x", static_cast<int>(frame_type));
}
- return out;
}
// Custom gMock matcher, used to implement EqualsFrames().
@@ -75,16 +170,8 @@ class SpdyControlFrameMatcher
return false;
}
- if (!spdy::IsDefinedFrameType(raw_type)) {
- *listener << "; expected type " << FrameTypeToString(expected_type)
- << " but raw type " << static_cast<int>(raw_type)
- << " is not a defined frame type!";
- return false;
- }
-
- spdy::SpdyFrameType actual_type = spdy::ParseFrameType(raw_type);
- if (actual_type != expected_type) {
- *listener << "; actual type: " << FrameTypeToString(actual_type)
+ if (raw_type != static_cast<uint8_t>(expected_type)) {
+ *listener << "; actual type: " << FrameTypeToString(raw_type)
<< " but expected type: " << FrameTypeToString(expected_type);
return false;
}
@@ -96,358 +183,18 @@ class SpdyControlFrameMatcher
void DescribeTo(std::ostream* os) const override {
*os << "Data contains frames of types in sequence "
- << LogFriendly(expected_types_and_lengths_);
+ << expected_types_and_lengths_;
}
void DescribeNegationTo(std::ostream* os) const override {
*os << "Data does not contain frames of types in sequence "
- << LogFriendly(expected_types_and_lengths_);
+ << expected_types_and_lengths_;
}
private:
const std::vector<TypeAndOptionalLength> expected_types_and_lengths_;
};
-// Custom gMock matcher, used to implement HasFrameHeader().
-class FrameHeaderMatcher
- : public testing::MatcherInterface<const nghttp2_frame_hd*> {
- public:
- FrameHeaderMatcher(int32_t streamid,
- uint8_t type,
- const testing::Matcher<int> flags)
- : stream_id_(streamid), type_(type), flags_(flags) {}
-
- bool MatchAndExplain(const nghttp2_frame_hd* frame,
- testing::MatchResultListener* listener) const override {
- bool matched = true;
- if (stream_id_ != frame->stream_id) {
- *listener << "; expected stream " << stream_id_ << ", saw "
- << frame->stream_id;
- matched = false;
- }
- if (type_ != frame->type) {
- *listener << "; expected frame type " << type_ << ", saw "
- << static_cast<int>(frame->type);
- matched = false;
- }
- if (!flags_.MatchAndExplain(frame->flags, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a frame header with stream " << stream_id_ << ", type "
- << type_ << ", ";
- flags_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a frame header with stream " << stream_id_
- << ", type " << type_ << ", ";
- flags_.DescribeNegationTo(os);
- }
-
- private:
- const int32_t stream_id_;
- const int type_;
- const testing::Matcher<int> flags_;
-};
-
-class DataMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- DataMatcher(const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<size_t> length,
- const testing::Matcher<int> flags)
- : stream_id_(stream_id), length_(length), flags_(flags) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_DATA) {
- *listener << "; expected DATA frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- bool matched = true;
- if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
- matched = false;
- }
- if (!length_.MatchAndExplain(frame->hd.length, listener)) {
- matched = false;
- }
- if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a DATA frame, ";
- stream_id_.DescribeTo(os);
- length_.DescribeTo(os);
- flags_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a DATA frame, ";
- stream_id_.DescribeNegationTo(os);
- length_.DescribeNegationTo(os);
- flags_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint32_t> stream_id_;
- const testing::Matcher<size_t> length_;
- const testing::Matcher<int> flags_;
-};
-
-class HeadersMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- HeadersMatcher(const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<int> flags,
- const testing::Matcher<int> category)
- : stream_id_(stream_id), flags_(flags), category_(category) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_HEADERS) {
- *listener << "; expected HEADERS frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- bool matched = true;
- if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
- matched = false;
- }
- if (!flags_.MatchAndExplain(frame->hd.flags, listener)) {
- matched = false;
- }
- if (!category_.MatchAndExplain(frame->headers.cat, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a HEADERS frame, ";
- stream_id_.DescribeTo(os);
- flags_.DescribeTo(os);
- category_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a HEADERS frame, ";
- stream_id_.DescribeNegationTo(os);
- flags_.DescribeNegationTo(os);
- category_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint32_t> stream_id_;
- const testing::Matcher<int> flags_;
- const testing::Matcher<int> category_;
-};
-
-class RstStreamMatcher
- : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- RstStreamMatcher(const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<uint32_t> error_code)
- : stream_id_(stream_id), error_code_(error_code) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_RST_STREAM) {
- *listener << "; expected RST_STREAM frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- bool matched = true;
- if (!stream_id_.MatchAndExplain(frame->hd.stream_id, listener)) {
- matched = false;
- }
- if (!error_code_.MatchAndExplain(frame->rst_stream.error_code, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a RST_STREAM frame, ";
- stream_id_.DescribeTo(os);
- error_code_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a RST_STREAM frame, ";
- stream_id_.DescribeNegationTo(os);
- error_code_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint32_t> stream_id_;
- const testing::Matcher<uint32_t> error_code_;
-};
-
-class SettingsMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- SettingsMatcher(const testing::Matcher<std::vector<Http2Setting>> values)
- : values_(values) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_SETTINGS) {
- *listener << "; expected SETTINGS frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- std::vector<Http2Setting> settings;
- settings.reserve(frame->settings.niv);
- for (int i = 0; i < frame->settings.niv; ++i) {
- const auto& p = frame->settings.iv[i];
- settings.push_back({static_cast<uint16_t>(p.settings_id), p.value});
- }
- return values_.MatchAndExplain(settings, listener);
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a SETTINGS frame, ";
- values_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a SETTINGS frame, ";
- values_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<std::vector<Http2Setting>> values_;
-};
-
-class PingMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- PingMatcher(const testing::Matcher<uint64_t> id, bool is_ack)
- : id_(id), is_ack_(is_ack) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_PING) {
- *listener << "; expected PING frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- bool matched = true;
- bool frame_ack = frame->hd.flags & NGHTTP2_FLAG_ACK;
- if (is_ack_ != frame_ack) {
- *listener << "; expected is_ack=" << is_ack_ << ", saw " << frame_ack;
- matched = false;
- }
- uint64_t data;
- std::memcpy(&data, frame->ping.opaque_data, sizeof(data));
- data = quiche::QuicheEndian::HostToNet64(data);
- if (!id_.MatchAndExplain(data, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a PING frame, ";
- id_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a PING frame, ";
- id_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint64_t> id_;
- const bool is_ack_;
-};
-
-class GoAwayMatcher : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- GoAwayMatcher(const testing::Matcher<uint32_t> last_stream_id,
- const testing::Matcher<uint32_t> error_code,
- const testing::Matcher<absl::string_view> opaque_data)
- : last_stream_id_(last_stream_id),
- error_code_(error_code),
- opaque_data_(opaque_data) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_GOAWAY) {
- *listener << "; expected GOAWAY frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- bool matched = true;
- if (!last_stream_id_.MatchAndExplain(frame->goaway.last_stream_id,
- listener)) {
- matched = false;
- }
- if (!error_code_.MatchAndExplain(frame->goaway.error_code, listener)) {
- matched = false;
- }
- auto opaque_data =
- ToStringView(frame->goaway.opaque_data, frame->goaway.opaque_data_len);
- if (!opaque_data_.MatchAndExplain(opaque_data, listener)) {
- matched = false;
- }
- return matched;
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a GOAWAY frame, ";
- last_stream_id_.DescribeTo(os);
- error_code_.DescribeTo(os);
- opaque_data_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a GOAWAY frame, ";
- last_stream_id_.DescribeNegationTo(os);
- error_code_.DescribeNegationTo(os);
- opaque_data_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint32_t> last_stream_id_;
- const testing::Matcher<uint32_t> error_code_;
- const testing::Matcher<absl::string_view> opaque_data_;
-};
-
-class WindowUpdateMatcher
- : public testing::MatcherInterface<const nghttp2_frame*> {
- public:
- WindowUpdateMatcher(const testing::Matcher<uint32_t> delta) : delta_(delta) {}
-
- bool MatchAndExplain(const nghttp2_frame* frame,
- testing::MatchResultListener* listener) const override {
- if (frame->hd.type != NGHTTP2_WINDOW_UPDATE) {
- *listener << "; expected WINDOW_UPDATE frame, saw frame of type "
- << static_cast<int>(frame->hd.type);
- return false;
- }
- return delta_.MatchAndExplain(frame->window_update.window_size_increment,
- listener);
- }
-
- void DescribeTo(std::ostream* os) const override {
- *os << "contains a WINDOW_UPDATE frame, ";
- delta_.DescribeTo(os);
- }
-
- void DescribeNegationTo(std::ostream* os) const override {
- *os << "does not contain a WINDOW_UPDATE frame, ";
- delta_.DescribeNegationTo(os);
- }
-
- private:
- const testing::Matcher<uint32_t> delta_;
-};
-
} // namespace
testing::Matcher<absl::string_view> EqualsFrames(
@@ -467,61 +214,6 @@ testing::Matcher<absl::string_view> EqualsFrames(
return MakeMatcher(new SpdyControlFrameMatcher(std::move(types_and_lengths)));
}
-testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
- uint32_t streamid,
- uint8_t type,
- const testing::Matcher<int> flags) {
- return MakeMatcher(new FrameHeaderMatcher(streamid, type, flags));
-}
-
-testing::Matcher<const nghttp2_frame*> IsData(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<size_t> length,
- const testing::Matcher<int> flags) {
- return MakeMatcher(new DataMatcher(stream_id, length, flags));
-}
-
-testing::Matcher<const nghttp2_frame*> IsHeaders(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<int> flags,
- const testing::Matcher<int> category) {
- return MakeMatcher(new HeadersMatcher(stream_id, flags, category));
-}
-
-testing::Matcher<const nghttp2_frame*> IsRstStream(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<uint32_t> error_code) {
- return MakeMatcher(new RstStreamMatcher(stream_id, error_code));
-}
-
-testing::Matcher<const nghttp2_frame*> IsSettings(
- const testing::Matcher<std::vector<Http2Setting>> values) {
- return MakeMatcher(new SettingsMatcher(values));
-}
-
-testing::Matcher<const nghttp2_frame*> IsPing(
- const testing::Matcher<uint64_t> id) {
- return MakeMatcher(new PingMatcher(id, false));
-}
-
-testing::Matcher<const nghttp2_frame*> IsPingAck(
- const testing::Matcher<uint64_t> id) {
- return MakeMatcher(new PingMatcher(id, true));
-}
-
-testing::Matcher<const nghttp2_frame*> IsGoAway(
- const testing::Matcher<uint32_t> last_stream_id,
- const testing::Matcher<uint32_t> error_code,
- const testing::Matcher<absl::string_view> opaque_data) {
- return MakeMatcher(
- new GoAwayMatcher(last_stream_id, error_code, opaque_data));
-}
-
-testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
- const testing::Matcher<uint32_t> delta) {
- return MakeMatcher(new WindowUpdateMatcher(delta));
-}
-
} // namespace test
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
index ef1ae29a650..d92617fa3c9 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/test_utils.h
@@ -4,26 +4,99 @@
#include <string>
#include <vector>
+#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
+#include "http2/adapter/data_source.h"
#include "http2/adapter/http2_protocol.h"
#include "http2/adapter/mock_http2_visitor.h"
-#include "third_party/nghttp2/src/lib/includes/nghttp2/nghttp2.h"
+#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_test.h"
+#include "spdy/core/spdy_header_block.h"
#include "spdy/core/spdy_protocol.h"
namespace http2 {
namespace adapter {
namespace test {
-class DataSavingVisitor : public testing::StrictMock<MockHttp2Visitor> {
+class QUICHE_NO_EXPORT DataSavingVisitor
+ : public testing::StrictMock<MockHttp2Visitor> {
public:
- void Save(absl::string_view data) { absl::StrAppend(&data_, data); }
+ ssize_t OnReadyToSend(absl::string_view data) override {
+ if (is_write_blocked_) {
+ return kSendBlocked;
+ }
+ const size_t to_accept = std::min(send_limit_, data.size());
+ if (to_accept == 0) {
+ return kSendBlocked;
+ }
+ absl::StrAppend(&data_, data.substr(0, to_accept));
+ return to_accept;
+ }
+
+ void OnMetadataForStream(Http2StreamId stream_id,
+ absl::string_view metadata) override {
+ testing::StrictMock<MockHttp2Visitor>::OnMetadataForStream(stream_id,
+ metadata);
+ auto result =
+ metadata_map_.try_emplace(stream_id, std::vector<std::string>());
+ result.first->second.push_back(std::string(metadata));
+ }
+
+ const std::vector<std::string> GetMetadata(Http2StreamId stream_id) {
+ auto it = metadata_map_.find(stream_id);
+ if (it == metadata_map_.end()) {
+ return {};
+ } else {
+ return it->second;
+ }
+ }
const std::string& data() { return data_; }
void Clear() { data_.clear(); }
+ void set_send_limit(size_t limit) { send_limit_ = limit; }
+
+ bool is_write_blocked() const { return is_write_blocked_; }
+ void set_is_write_blocked(bool value) { is_write_blocked_ = value; }
+
private:
std::string data_;
+ absl::flat_hash_map<Http2StreamId, std::vector<std::string>> metadata_map_;
+ size_t send_limit_ = std::numeric_limits<size_t>::max();
+ bool is_write_blocked_ = false;
+};
+
+// A test DataFrameSource. Starts out in the empty, blocked state.
+class QUICHE_NO_EXPORT TestDataFrameSource : public DataFrameSource {
+ public:
+ TestDataFrameSource(Http2VisitorInterface& visitor, bool has_fin);
+
+ void AppendPayload(absl::string_view payload);
+ void EndData();
+
+ std::pair<ssize_t, bool> SelectPayloadLength(size_t max_length) override;
+ bool Send(absl::string_view frame_header, size_t payload_length) override;
+ bool send_fin() const override { return has_fin_; }
+
+ private:
+ Http2VisitorInterface& visitor_;
+ std::vector<std::string> payload_fragments_;
+ absl::string_view current_fragment_;
+ // Whether the stream should end with the final frame of data.
+ const bool has_fin_;
+ // Whether |payload_fragments_| contains the final segment of data.
+ bool end_data_ = false;
+};
+
+class QUICHE_NO_EXPORT TestMetadataSource : public MetadataSource {
+ public:
+ explicit TestMetadataSource(const spdy::SpdyHeaderBlock& entries);
+
+ std::pair<ssize_t, bool> Pack(uint8_t* dest, size_t dest_len) override;
+
+ private:
+ const std::string encoded_entries_;
+ absl::string_view remaining_;
};
// These matchers check whether a string consists entirely of HTTP/2 frames of
@@ -41,42 +114,6 @@ testing::Matcher<absl::string_view> EqualsFrames(
testing::Matcher<absl::string_view> EqualsFrames(
std::vector<spdy::SpdyFrameType> types);
-testing::Matcher<const nghttp2_frame_hd*> HasFrameHeader(
- uint32_t streamid,
- uint8_t type,
- const testing::Matcher<int> flags);
-
-testing::Matcher<const nghttp2_frame*> IsData(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<size_t> length,
- const testing::Matcher<int> flags);
-
-testing::Matcher<const nghttp2_frame*> IsHeaders(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<int> flags,
- const testing::Matcher<int> category);
-
-testing::Matcher<const nghttp2_frame*> IsRstStream(
- const testing::Matcher<uint32_t> stream_id,
- const testing::Matcher<uint32_t> error_code);
-
-testing::Matcher<const nghttp2_frame*> IsSettings(
- const testing::Matcher<std::vector<Http2Setting>> values);
-
-testing::Matcher<const nghttp2_frame*> IsPing(
- const testing::Matcher<uint64_t> id);
-
-testing::Matcher<const nghttp2_frame*> IsPingAck(
- const testing::Matcher<uint64_t> id);
-
-testing::Matcher<const nghttp2_frame*> IsGoAway(
- const testing::Matcher<uint32_t> last_stream_id,
- const testing::Matcher<uint32_t> error_code,
- const testing::Matcher<absl::string_view> opaque_data);
-
-testing::Matcher<const nghttp2_frame*> IsWindowUpdate(
- const testing::Matcher<uint32_t> delta);
-
} // namespace test
} // namespace adapter
} // namespace http2
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h
index 277c24f960e..f15982d466a 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager.h
@@ -3,6 +3,8 @@
#include <functional>
+#include "common/platform/api/quiche_export.h"
+
namespace http2 {
namespace adapter {
@@ -12,7 +14,7 @@ class WindowManagerPeer;
// This class keeps track of a HTTP/2 flow control window, notifying a listener
// when a window update needs to be sent. This class is not thread-safe.
-class WindowManager {
+class QUICHE_EXPORT_PRIVATE WindowManager {
public:
// A WindowUpdateListener is invoked when it is time to send a window update.
typedef std::function<void(size_t)> WindowUpdateListener;
diff --git a/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc b/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
index 5e0645365ec..e706156db69 100644
--- a/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/adapter/window_manager_test.cc
@@ -90,21 +90,21 @@ TEST_F(WindowManagerTest, AvoidWindowUnderflow) {
EXPECT_EQ(wm_.CurrentWindowSize(), wm_.WindowSizeLimit());
// Don't buffer more than the total window!
wm_.MarkDataBuffered(wm_.WindowSizeLimit() + 1);
- EXPECT_EQ(wm_.CurrentWindowSize(), 0);
+ EXPECT_EQ(wm_.CurrentWindowSize(), 0u);
}
// Window manager should GFE_BUG and avoid buffered underflow.
TEST_F(WindowManagerTest, AvoidBufferedUnderflow) {
- EXPECT_EQ(peer_.buffered(), 0);
+ EXPECT_EQ(peer_.buffered(), 0u);
// Don't flush more than has been buffered!
EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(1), "buffered underflow");
- EXPECT_EQ(peer_.buffered(), 0);
+ EXPECT_EQ(peer_.buffered(), 0u);
wm_.MarkDataBuffered(42);
- EXPECT_EQ(peer_.buffered(), 42);
+ EXPECT_EQ(peer_.buffered(), 42u);
// Don't flush more than has been buffered!
EXPECT_QUICHE_BUG(wm_.MarkDataFlushed(43), "buffered underflow");
- EXPECT_EQ(peer_.buffered(), 0);
+ EXPECT_EQ(peer_.buffered(), 0u);
}
// This test verifies that WindowManager notifies its listener when window is
diff --git a/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h
index b7046e7023a..4d64d75a961 100644
--- a/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h
+++ b/chromium/net/third_party/quiche/src/http2/core/http2_priority_write_scheduler.h
@@ -24,7 +24,6 @@
#include "common/platform/api/quiche_logging.h"
#include "spdy/core/spdy_intrusive_list.h"
#include "spdy/core/spdy_protocol.h"
-#include "spdy/platform/api/spdy_string_utils.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
index 0f1336ed29e..37933f19630 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.cc
@@ -5,7 +5,6 @@
#include "http2/hpack/decoder/hpack_decoder.h"
#include "http2/decoder/decode_status.h"
-#include "http2/platform/api/http2_estimate_memory_usage.h"
#include "http2/platform/api/http2_flag_utils.h"
#include "http2/platform/api/http2_flags.h"
#include "http2/platform/api/http2_logging.h"
@@ -110,10 +109,6 @@ bool HpackDecoder::DetectError() {
return error_ != HpackDecodingError::kOk;
}
-size_t HpackDecoder::EstimateMemoryUsage() const {
- return Http2EstimateMemoryUsage(entry_buffer_);
-}
-
void HpackDecoder::ReportError(HpackDecodingError error,
std::string detailed_error) {
HTTP2_DVLOG(3) << "HpackDecoder::ReportError is new="
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
index 01d32a38ac1..92177070acc 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder.h
@@ -92,12 +92,13 @@ class QUICHE_EXPORT_PRIVATE HpackDecoder {
// detected.
bool DetectError();
+ size_t GetDynamicTableSize() const {
+ return decoder_state_.GetDynamicTableSize();
+ }
+
// Error code if an error has occurred, HpackDecodingError::kOk otherwise.
HpackDecodingError error() const { return error_; }
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
std::string detailed_error() const { return detailed_error_; }
private:
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
index 14b4184bd5a..5dcdc40bf99 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_state.h
@@ -83,6 +83,10 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderState : public HpackWholeEntryListener {
// No further callbacks will be made to the listener.
HpackDecodingError error() const { return error_; }
+ size_t GetDynamicTableSize() const {
+ return decoder_tables_.current_header_table_size();
+ }
+
const HpackDecoderTables& decoder_tables_for_test() const {
return decoder_tables_;
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
index 8f2243d7f6b..d03590377e3 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "http2/platform/api/http2_bug_tracker.h"
-#include "http2/platform/api/http2_estimate_memory_usage.h"
#include "http2/platform/api/http2_logging.h"
namespace http2 {
@@ -232,10 +231,6 @@ void HpackDecoderStringBuffer::OutputDebugStringTo(std::ostream& out) const {
out << "}";
}
-size_t HpackDecoderStringBuffer::EstimateMemoryUsage() const {
- return Http2EstimateMemoryUsage(buffer_);
-}
-
std::ostream& operator<<(std::ostream& out, const HpackDecoderStringBuffer& v) {
v.OutputDebugStringTo(out);
return out;
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h
index 9397330fd96..83f59eda593 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer.h
@@ -67,9 +67,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderStringBuffer {
Backing backing_for_testing() const { return backing_; }
void OutputDebugStringTo(std::ostream& out) const;
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
private:
// Storage for the string being buffered, if buffering is necessary
// (e.g. if Huffman encoded, buffer_ is storage for the decoded string).
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
index b7a8b39d051..82244efe4eb 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_decoder_string_buffer_test.cc
@@ -10,7 +10,6 @@
#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "common/platform/api/quiche_test.h"
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc
index 76d1f31354e..5f3e63e2315 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.cc
@@ -5,12 +5,11 @@
#include "http2/hpack/decoder/hpack_whole_entry_buffer.h"
#include "absl/strings/str_cat.h"
-#include "http2/platform/api/http2_estimate_memory_usage.h"
#include "http2/platform/api/http2_flag_utils.h"
#include "http2/platform/api/http2_flags.h"
#include "http2/platform/api/http2_logging.h"
#include "http2/platform/api/http2_macros.h"
-#include "http2/platform/api/http2_string_utils.h"
+#include "common/quiche_text_utils.h"
namespace http2 {
@@ -35,10 +34,6 @@ void HpackWholeEntryBuffer::BufferStringsIfUnbuffered() {
value_.BufferStringIfUnbuffered();
}
-size_t HpackWholeEntryBuffer::EstimateMemoryUsage() const {
- return Http2EstimateMemoryUsage(name_) + Http2EstimateMemoryUsage(value_);
-}
-
void HpackWholeEntryBuffer::OnIndexedHeader(size_t index) {
HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnIndexedHeader: index=" << index;
listener_->OnIndexedHeader(index);
@@ -71,7 +66,8 @@ void HpackWholeEntryBuffer::OnNameStart(bool huffman_encoded, size_t len) {
void HpackWholeEntryBuffer::OnNameData(const char* data, size_t len) {
HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnNameData: len=" << len
<< " data:\n"
- << Http2HexDump(absl::string_view(data, len));
+ << quiche::QuicheTextUtils::HexDump(
+ absl::string_view(data, len));
QUICHE_DCHECK_EQ(maybe_name_index_, 0u);
if (!error_detected_ && !name_.OnData(data, len)) {
ReportError(HpackDecodingError::kNameHuffmanError, "");
@@ -108,7 +104,8 @@ void HpackWholeEntryBuffer::OnValueStart(bool huffman_encoded, size_t len) {
void HpackWholeEntryBuffer::OnValueData(const char* data, size_t len) {
HTTP2_DVLOG(2) << "HpackWholeEntryBuffer::OnValueData: len=" << len
<< " data:\n"
- << Http2HexDump(absl::string_view(data, len));
+ << quiche::QuicheTextUtils::HexDump(
+ absl::string_view(data, len));
if (!error_detected_ && !value_.OnData(data, len)) {
ReportError(HpackDecodingError::kValueHuffmanError, "");
HTTP2_CODE_COUNT_N(decompress_failure_3, 22, 23);
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h
index eb4edbe53f6..0cce0bafd72 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h
+++ b/chromium/net/third_party/quiche/src/http2/hpack/decoder/hpack_whole_entry_buffer.h
@@ -63,9 +63,6 @@ class QUICHE_EXPORT_PRIVATE HpackWholeEntryBuffer
// no further callbacks will be made to the listener.
bool error_detected() const { return error_detected_; }
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
// Implement the HpackEntryDecoderListener methods.
void OnIndexedHeader(size_t index) override;
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
index e7a346e7719..395706f219c 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_decoder_test.cc
@@ -12,7 +12,6 @@
#include "absl/strings/escaping.h"
#include "http2/decoder/decode_buffer.h"
#include "http2/decoder/decode_status.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/platform/api/http2_test_helpers.h"
#include "http2/tools/random_decoder_test.h"
#include "common/platform/api/quiche_test.h"
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
index 0d321876149..84439c16973 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_encoder_test.cc
@@ -6,7 +6,6 @@
#include "absl/base/macros.h"
#include "absl/strings/escaping.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
index bca12c50ebb..3b0047d49d4 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/huffman/hpack_huffman_transcoder_test.cc
@@ -11,9 +11,9 @@
#include "http2/decoder/decode_status.h"
#include "http2/hpack/huffman/hpack_huffman_decoder.h"
#include "http2/hpack/huffman/hpack_huffman_encoder.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/tools/random_decoder_test.h"
#include "common/platform/api/quiche_test.h"
+#include "common/quiche_text_utils.h"
using ::testing::AssertionResult;
using ::testing::AssertionSuccess;
@@ -114,8 +114,8 @@ TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomAsciiNonControlString) {
const std::string s = RandomAsciiNonControlString(length);
ASSERT_TRUE(TranscodeAndValidateSeveralWays(s))
<< "Unable to decode:\n\n"
- << Http2HexDump(s) << "\n\noutput_buffer_:\n"
- << Http2HexDump(output_buffer_);
+ << quiche::QuicheTextUtils::HexDump(s) << "\n\noutput_buffer_:\n"
+ << quiche::QuicheTextUtils::HexDump(output_buffer_);
}
}
@@ -124,8 +124,8 @@ TEST_F(HpackHuffmanTranscoderTest, RoundTripRandomBytes) {
const std::string s = RandomBytes(length);
ASSERT_TRUE(TranscodeAndValidateSeveralWays(s))
<< "Unable to decode:\n\n"
- << Http2HexDump(s) << "\n\noutput_buffer_:\n"
- << Http2HexDump(output_buffer_);
+ << quiche::QuicheTextUtils::HexDump(s) << "\n\noutput_buffer_:\n"
+ << quiche::QuicheTextUtils::HexDump(output_buffer_);
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
index 3821127bd08..b292c4b3767 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_block_builder_test.cc
@@ -5,7 +5,6 @@
#include "http2/hpack/tools/hpack_block_builder.h"
#include "absl/strings/escaping.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
index b2783e3b277..64255b1ef2d 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/tools/hpack_example.cc
@@ -10,7 +10,6 @@
#include "absl/strings/str_cat.h"
#include "http2/platform/api/http2_bug_tracker.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
index a67cca6c729..aff6af3730e 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_decoder_test.cc
@@ -12,7 +12,6 @@
#include "absl/strings/escaping.h"
#include "absl/strings/string_view.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/tools/random_decoder_test.h"
#include "common/platform/api/quiche_test.h"
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
index 7f049e8eabf..5daf88b99d7 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_encoder_test.cc
@@ -6,7 +6,6 @@
#include "absl/base/macros.h"
#include "absl/strings/escaping.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "common/platform/api/quiche_test.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
index d8152593547..0c832d9e83a 100644
--- a/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/hpack/varint/hpack_varint_round_trip_test.cc
@@ -18,9 +18,9 @@
#include "absl/strings/string_view.h"
#include "http2/hpack/tools/hpack_block_builder.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "http2/tools/random_decoder_test.h"
#include "common/platform/api/quiche_test.h"
+#include "common/quiche_text_utils.h"
using ::testing::AssertionFailure;
using ::testing::AssertionSuccess;
@@ -166,7 +166,7 @@ class HpackVarintRoundTripTest : public RandomDecoderTest {
std::string msg = absl::StrCat("value=", value, " (0x", absl::Hex(value),
"), prefix_length=", prefix_length,
", expected_bytes=", expected_bytes, "\n",
- Http2HexDump(buffer_));
+ quiche::QuicheTextUtils::HexDump(buffer_));
if (value == minimum) {
HTTP2_LOG(INFO) << "Checking minimum; " << msg;
@@ -221,7 +221,8 @@ class HpackVarintRoundTripTest : public RandomDecoderTest {
if (expected_bytes < 11) {
// Confirm the claim that beyond requires more bytes.
Encode(beyond, prefix_length);
- EXPECT_EQ(expected_bytes + 1, buffer_.size()) << Http2HexDump(buffer_);
+ EXPECT_EQ(expected_bytes + 1, buffer_.size())
+ << quiche::QuicheTextUtils::HexDump(buffer_);
}
std::set<uint64_t> values;
@@ -285,9 +286,9 @@ TEST_F(HpackVarintRoundTripTest, Encode) {
for (uint64_t value : values) {
EncodeNoRandom(value, prefix_length);
- std::string dump = Http2HexDump(buffer_);
+ std::string dump = quiche::QuicheTextUtils::HexDump(buffer_);
HTTP2_LOG(INFO) << absl::StrFormat("%10llu %0#18x ", value, value)
- << Http2HexDump(buffer_).substr(7);
+ << quiche::QuicheTextUtils::HexDump(buffer_).substr(7);
}
}
}
diff --git a/chromium/net/third_party/quiche/src/http2/http2_constants.cc b/chromium/net/third_party/quiche/src/http2/http2_constants.cc
index bebe8803652..43d89bcc221 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_constants.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_constants.cc
@@ -8,7 +8,6 @@
#include "absl/strings/str_format.h"
#include "absl/strings/string_view.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/http2_structures.cc b/chromium/net/third_party/quiche/src/http2/http2_structures.cc
index a96edccdd71..f8a8fadadbf 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_structures.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_structures.cc
@@ -9,7 +9,6 @@
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
-#include "http2/platform/api/http2_string_utils.h"
namespace http2 {
diff --git a/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc b/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
index 44712bc13b9..d74b74cc6f3 100644
--- a/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
+++ b/chromium/net/third_party/quiche/src/http2/http2_structures_test.cc
@@ -9,7 +9,7 @@
// Note that EXPECT.*DEATH tests are slow (a fork is probably involved).
// And in case you're wondering, yes, these are ridiculously thorough tests,
-// but believe it or not, I've found stupid bugs this way.
+// but believe it or not, I've found silly bugs this way.
#include <memory>
#include <ostream>
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_containers.h b/chromium/net/third_party/quiche/src/http2/platform/api/http2_containers.h
deleted file mode 100644
index 7bd3f8eb4a3..00000000000
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_containers.h
+++ /dev/null
@@ -1,17 +0,0 @@
-#ifndef QUICHE_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_
-#define QUICHE_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_
-
-#include "quiche_platform_impl/quiche_containers_impl.h"
-
-namespace http2 {
-
-// Represents a double-ended queue which may be backed by a list or a flat
-// circular buffer.
-//
-// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename T>
-using Http2Deque = quiche::QuicheDequeImpl<T>;
-
-} // namespace http2
-
-#endif // QUICHE_HTTP2_PLATFORM_API_HTTP2_CONTAINERS_H_
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_estimate_memory_usage.h b/chromium/net/third_party/quiche/src/http2/platform/api/http2_estimate_memory_usage.h
deleted file mode 100644
index 39b3af59528..00000000000
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_estimate_memory_usage.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_
-#define QUICHE_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_
-
-#include <cstddef>
-
-#include "quiche_platform_impl/quiche_estimate_memory_usage_impl.h"
-
-namespace http2 {
-
-template <class T>
-size_t Http2EstimateMemoryUsage(const T& object) {
- return quiche::QuicheEstimateMemoryUsageImpl(object);
-}
-
-} // namespace http2
-
-#endif // QUICHE_HTTP2_PLATFORM_API_HTTP2_ESTIMATE_MEMORY_USAGE_H_
diff --git a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h b/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h
deleted file mode 100644
index cf39515ad4c..00000000000
--- a/chromium/net/third_party/quiche/src/http2/platform/api/http2_string_utils.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_
-#define QUICHE_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_
-
-#include <string>
-#include <type_traits>
-#include <utility>
-
-#include "absl/strings/string_view.h"
-#include "net/http2/platform/impl/http2_string_utils_impl.h"
-
-namespace http2 {
-
-inline std::string Http2HexDump(absl::string_view data) {
- return Http2HexDumpImpl(data);
-}
-
-} // namespace http2
-
-#endif // QUICHE_HTTP2_PLATFORM_API_HTTP2_STRING_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc b/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
index a053beb10df..47135233ffd 100644
--- a/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
+++ b/chromium/net/third_party/quiche/src/http2/test_tools/frame_parts.cc
@@ -126,7 +126,7 @@ void FrameParts::SetAltSvcExpected(absl::string_view origin,
opt_altsvc_value_length_ = value.size();
}
-bool FrameParts::OnFrameHeader(const Http2FrameHeader& header) {
+bool FrameParts::OnFrameHeader(const Http2FrameHeader& /*header*/) {
ADD_FAILURE() << "OnFrameHeader: " << *this;
return true;
}
diff --git a/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc b/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
index 8f9014efd17..71c08b78faf 100644
--- a/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
+++ b/chromium/net/third_party/quiche/src/http2/test_tools/http2_random.cc
@@ -2,7 +2,6 @@
#include "absl/strings/escaping.h"
#include "http2/platform/api/http2_logging.h"
-#include "http2/platform/api/http2_string_utils.h"
#include "third_party/boringssl/src/include/openssl/chacha.h"
#include "third_party/boringssl/src/include/openssl/rand.h"
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
index 173c8d30488..9cdff7e2b6c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_base.cc
@@ -24,20 +24,10 @@ WriteResult QuicBatchWriterBase::WritePacket(
const WriteResult result =
InternalWritePacket(buffer, buf_len, self_address, peer_address, options);
- if (GetQuicReloadableFlag(quic_batch_writer_fix_write_blocked)) {
- if (IsWriteBlockedStatus(result.status)) {
- if (result.status == WRITE_STATUS_BLOCKED_DATA_BUFFERED) {
- QUIC_CODE_COUNT(quic_batch_writer_fix_write_blocked_data_buffered);
- } else {
- QUIC_CODE_COUNT(quic_batch_writer_fix_write_blocked_data_not_buffered);
- }
- write_blocked_ = true;
- }
- } else {
- if (result.status == WRITE_STATUS_BLOCKED) {
- write_blocked_ = true;
- }
+ if (IsWriteBlockedStatus(result.status)) {
+ write_blocked_ = true;
}
+
return result;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_test.h b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_test.h
index 820100adabd..e14040fb39c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_test.h
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_batch_writer_test.h
@@ -12,6 +12,7 @@
#include <iostream>
#include <utility>
+#include "absl/base/optimization.h"
#include "quic/core/batch_writer/quic_batch_writer_base.h"
#include "quic/core/quic_udp_socket.h"
#include "quic/platform/api/quic_test.h"
@@ -259,8 +260,9 @@ class QUIC_EXPORT_PRIVATE QuicUdpBatchWriterIOTest
QuicSocketAddress self_address_;
QuicSocketAddress peer_address_;
- char packet_buffer_[1500];
- char control_buffer_[kDefaultUdpPacketControlBufferSize];
+ ABSL_CACHELINE_ALIGNED char packet_buffer_[1500];
+ ABSL_CACHELINE_ALIGNED char
+ control_buffer_[kDefaultUdpPacketControlBufferSize];
int address_family_;
const size_t data_size_;
const size_t packet_size_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
index 8a1b93fc723..4aab1982f55 100644
--- a/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/batch_writer/quic_gso_batch_writer_test.cc
@@ -322,11 +322,9 @@ TEST_F(QuicGsoBatchWriterTest, WriteBlockDataBuffered) {
}));
ASSERT_EQ(WriteResult(WRITE_STATUS_BLOCKED_DATA_BUFFERED, EWOULDBLOCK),
WritePacket(&writer, 50));
- if (GetQuicReloadableFlag(quic_batch_writer_fix_write_blocked)) {
- EXPECT_TRUE(writer.IsWriteBlocked());
- } else {
- EXPECT_FALSE(writer.IsWriteBlocked());
- }
+
+ EXPECT_TRUE(writer.IsWriteBlocked());
+
ASSERT_EQ(250u, writer.batch_buffer().SizeInUse());
ASSERT_EQ(3u, writer.buffered_writes().size());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
index 6738f49ab05..2d5924b06e1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bandwidth_sampler.h
@@ -47,6 +47,7 @@ struct QUIC_EXPORT_PRIVATE SendTimeState {
bytes_in_flight(bytes_in_flight) {}
SendTimeState(const SendTimeState& other) = default;
+ SendTimeState& operator=(const SendTimeState& other) = default;
friend QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
const SendTimeState& s);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
index 8d4a49350b5..6eb9b2ec940 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.cc
@@ -264,9 +264,7 @@ void Bbr2NetworkModel::AdaptLowerBounds(
// sample_max_bandwidth will be Zero() if the loss is triggered by a timer
// expiring. Ideally we'd use the most recent bandwidth sample,
// but bandwidth_latest is safer than Zero().
- if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode2) &&
- !congestion_event.sample_max_bandwidth.IsZero()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode2, 1, 2);
+ if (!congestion_event.sample_max_bandwidth.IsZero()) {
// bandwidth_latest_ is the max bandwidth for the round, but to allow
// fast, conservation style response to loss, use the last sample.
last_bandwidth = congestion_event.sample_max_bandwidth;
@@ -286,9 +284,7 @@ void Bbr2NetworkModel::AdaptLowerBounds(
}
// If it's the end of the round, ensure bandwidth_lo doesn't decrease more
// than beta.
- if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode) &&
- congestion_event.end_of_round_trip) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode, 2, 2);
+ if (congestion_event.end_of_round_trip) {
bandwidth_lo_ =
std::max(bandwidth_lo_, prior_bandwidth_lo_ * (1.0 - Params().beta));
prior_bandwidth_lo_ = QuicBandwidth::Zero();
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
index b7007f55705..d28036df543 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_misc.h
@@ -176,10 +176,6 @@ struct QUIC_EXPORT_PRIVATE Bbr2Params {
// Can be disabled by connection option 'B2RP'.
bool avoid_unnecessary_probe_rtt = true;
- // Can be disabled by connection option 'B2CL'.
- bool avoid_too_low_probe_bw_cwnd =
- GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd);
-
// Can be enabled by connection option 'B2LO'.
bool ignore_inflight_lo = false;
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
index af0f00fee80..ce9443f7d1d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_probe_bw.cc
@@ -80,36 +80,12 @@ Bbr2Mode Bbr2ProbeBwMode::OnCongestionEvent(
}
Limits<QuicByteCount> Bbr2ProbeBwMode::GetCwndLimits() const {
- if (!GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd)) {
- if (cycle_.phase == CyclePhase::PROBE_CRUISE) {
- return NoGreaterThan(
- std::min(model_->inflight_lo(), model_->inflight_hi_with_headroom()));
- }
-
+ if (cycle_.phase == CyclePhase::PROBE_CRUISE) {
return NoGreaterThan(
- std::min(model_->inflight_lo(), model_->inflight_hi()));
- }
-
- QUIC_RELOADABLE_FLAG_COUNT(quic_bbr2_avoid_too_low_probe_bw_cwnd);
-
- QuicByteCount upper_limit =
- std::min(model_->inflight_lo(), cycle_.phase == CyclePhase::PROBE_CRUISE
- ? model_->inflight_hi_with_headroom()
- : model_->inflight_hi());
-
- if (Params().avoid_too_low_probe_bw_cwnd) {
- // Ensure upper_limit is at least BDP + AckHeight.
- QuicByteCount bdp_with_ack_height =
- model_->BDP(model_->MaxBandwidth()) + model_->MaxAckHeight();
- if (upper_limit < bdp_with_ack_height) {
- QUIC_DVLOG(3) << sender_ << " Rasing upper_limit from " << upper_limit
- << " to " << bdp_with_ack_height;
- QUIC_CODE_COUNT(quic_bbr2_avoid_too_low_probe_bw_cwnd_in_effect);
- upper_limit = bdp_with_ack_height;
- }
+ std::min(model_->inflight_lo(), model_->inflight_hi_with_headroom()));
}
- return NoGreaterThan(upper_limit);
+ return NoGreaterThan(std::min(model_->inflight_lo(), model_->inflight_hi()));
}
bool Bbr2ProbeBwMode::IsProbingForBandwidth() const {
@@ -500,9 +476,7 @@ void Bbr2ProbeBwMode::EnterProbeDown(bool probed_too_high,
cycle_.rounds_in_phase = 0;
cycle_.phase_start_time = now;
++sender_->connection_stats_->bbr_num_cycles;
- if (GetQuicReloadableFlag(quic_bbr2_fix_bw_lo_mode2) &&
- Params().bw_lo_mode_ != Bbr2Params::QuicBandwidthLoMode::DEFAULT) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_bbr2_fix_bw_lo_mode2, 2, 2);
+ if (Params().bw_lo_mode_ != Bbr2Params::QuicBandwidthLoMode::DEFAULT) {
// Clear bandwidth lo if it was set in PROBE_UP, because losses in PROBE_UP
// should not permanently change bandwidth_lo.
// It's possible for bandwidth_lo to be set during REFILL, but if that was
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
index b69a7952afa..09b920e5759 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_sender.cc
@@ -16,6 +16,7 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
+#include "common/print_elements.h"
namespace quic {
@@ -101,10 +102,6 @@ void Bbr2Sender::SetFromConfig(const QuicConfig& config,
if (config.HasClientRequestedIndependentOption(kB2RP, perspective)) {
params_.avoid_unnecessary_probe_rtt = false;
}
- if (GetQuicReloadableFlag(quic_bbr2_avoid_too_low_probe_bw_cwnd) &&
- config.HasClientRequestedIndependentOption(kB2CL, perspective)) {
- params_.avoid_too_low_probe_bw_cwnd = false;
- }
if (config.HasClientRequestedIndependentOption(k1RTT, perspective)) {
params_.startup_full_bw_rounds = 1;
}
@@ -287,7 +284,8 @@ void Bbr2Sender::OnCongestionEvent(bool /*rtt_updated*/,
}
QUIC_DVLOG(3)
- << this << " END CongestionEvent(acked:" << acked_packets
+ << this
+ << " END CongestionEvent(acked:" << quiche::PrintElements(acked_packets)
<< ", lost:" << lost_packets.size() << ") "
<< ", Mode:" << mode_ << ", RttCount:" << model_.RoundTripCount()
<< ", BytesInFlight:" << congestion_event.bytes_in_flight
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
index 99acf2c3e21..ae0c8842c8e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/bbr2_simulator_test.cc
@@ -477,7 +477,11 @@ TEST_F(Bbr2DefaultTopologyTest, SimpleTransfer2RTTAggregationBytes) {
EXPECT_APPROX_EQ(params.BottleneckBandwidth(),
sender_->ExportDebugState().bandwidth_hi, 0.01f);
- EXPECT_LE(sender_loss_rate_in_packets(), 0.05);
+ if (GetQuicReloadableFlag(quic_fix_pacing_sender_bursts)) {
+ EXPECT_EQ(sender_loss_rate_in_packets(), 0);
+ } else {
+ EXPECT_LE(sender_loss_rate_in_packets(), 0.05);
+ }
// The margin here is high, because both link level aggregation and ack
// decimation can greatly increase smoothed rtt.
EXPECT_GE(params.RTT() * 5, rtt_stats()->smoothed_rtt());
@@ -558,6 +562,9 @@ TEST_F(Bbr2DefaultTopologyTest, QUIC_SLOW_TEST(BandwidthIncrease)) {
[this]() { return sender_endpoint_.bytes_to_transfer() == 0; },
QuicTime::Delta::FromSeconds(50));
EXPECT_TRUE(simulator_result);
+ // Ensure the full bandwidth is discovered.
+ EXPECT_APPROX_EQ(params.test_link.bandwidth,
+ sender_->ExportDebugState().bandwidth_hi, 0.02f);
}
// Test the number of losses incurred by the startup phase in a situation when
@@ -1075,7 +1082,6 @@ TEST_F(Bbr2DefaultTopologyTest, ProbeBwAfterQuiescencePostponeMinRttTimestamp) {
min_rtt_timestamp_after_idle);
}
-// Regression test for http://go/switchtobbr2midconnection.
TEST_F(Bbr2DefaultTopologyTest, SwitchToBbr2MidConnection) {
QuicTime now = QuicTime::Zero();
BbrSender old_sender(sender_connection()->clock()->Now(),
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
index a43601eae0d..265a422817d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender.cc
@@ -102,6 +102,12 @@ void PacingSender::OnPacketSent(
// is about 10ms of queueing.
lumpy_tokens_ = 1u;
}
+ if (GetQuicReloadableFlag(quic_fix_pacing_sender_bursts) &&
+ (bytes_in_flight + bytes) >= sender_->GetCongestionWindow()) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_fix_pacing_sender_bursts);
+ // Don't add lumpy_tokens if the congestion controller is CWND limited.
+ lumpy_tokens_ = 1u;
+ }
}
--lumpy_tokens_;
if (pacing_limited_) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
index b7513576cca..ec3119d2407 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/pacing_sender_test.cc
@@ -7,6 +7,7 @@
#include <memory>
#include <utility>
+#include "quic/core/quic_constants.h"
#include "quic/core/quic_packets.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
@@ -75,42 +76,41 @@ class PacingSenderTest : public QuicTest {
}
void CheckPacketIsSentImmediately(HasRetransmittableData retransmittable_data,
- QuicByteCount bytes_in_flight,
+ QuicByteCount prior_in_flight,
bool in_recovery,
- bool cwnd_limited,
QuicPacketCount cwnd) {
// In order for the packet to be sendable, the underlying sender must
// permit it to be sent immediately.
for (int i = 0; i < 2; ++i) {
- EXPECT_CALL(*mock_sender_, CanSend(bytes_in_flight))
+ EXPECT_CALL(*mock_sender_, CanSend(prior_in_flight))
.WillOnce(Return(true));
// Verify that the packet can be sent immediately.
EXPECT_EQ(zero_time_,
- pacing_sender_->TimeUntilSend(clock_.Now(), bytes_in_flight));
+ pacing_sender_->TimeUntilSend(clock_.Now(), prior_in_flight));
}
// Actually send the packet.
- if (bytes_in_flight == 0) {
+ if (prior_in_flight == 0) {
EXPECT_CALL(*mock_sender_, InRecovery()).WillOnce(Return(in_recovery));
}
EXPECT_CALL(*mock_sender_,
- OnPacketSent(clock_.Now(), bytes_in_flight, packet_number_,
+ OnPacketSent(clock_.Now(), prior_in_flight, packet_number_,
kMaxOutgoingPacketSize, retransmittable_data));
EXPECT_CALL(*mock_sender_, GetCongestionWindow())
- .Times(AtMost(1))
.WillRepeatedly(Return(cwnd * kDefaultTCPMSS));
EXPECT_CALL(*mock_sender_,
- CanSend(bytes_in_flight + kMaxOutgoingPacketSize))
+ CanSend(prior_in_flight + kMaxOutgoingPacketSize))
.Times(AtMost(1))
- .WillRepeatedly(Return(!cwnd_limited));
- pacing_sender_->OnPacketSent(clock_.Now(), bytes_in_flight,
+ .WillRepeatedly(Return((prior_in_flight + kMaxOutgoingPacketSize) <
+ (cwnd * kDefaultTCPMSS)));
+ pacing_sender_->OnPacketSent(clock_.Now(), prior_in_flight,
packet_number_++, kMaxOutgoingPacketSize,
retransmittable_data);
}
void CheckPacketIsSentImmediately() {
CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight,
- false, false, 10);
+ false, 10);
}
void CheckPacketIsDelayed(QuicTime::Delta delay) {
@@ -242,7 +242,7 @@ TEST_F(PacingSenderTest, InitialBurst) {
// Next time TimeUntilSend is called with no bytes in flight, pacing should
// allow a packet to be sent, and when it's sent, the tokens are refilled.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, 10);
for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
CheckPacketIsSentImmediately();
}
@@ -276,7 +276,7 @@ TEST_F(PacingSenderTest, InitialBurstNoRttMeasurement) {
// Next time TimeUntilSend is called with no bytes in flight, the tokens
// should be refilled and there should be no delay.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, 10);
// Send 10 packets, and verify that they are not paced.
for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
CheckPacketIsSentImmediately();
@@ -314,7 +314,7 @@ TEST_F(PacingSenderTest, FastSending) {
// Next time TimeUntilSend is called with no bytes in flight, the tokens
// should be refilled and there should be no delay.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, false, 10);
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, false, 10);
for (int i = 0; i < kInitialBurstPackets - 1; ++i) {
CheckPacketIsSentImmediately();
}
@@ -348,10 +348,12 @@ TEST_F(PacingSenderTest, NoBurstEnteringRecovery) {
// One packet is sent immediately, because of 1ms pacing granularity.
CheckPacketIsSentImmediately();
// Ensure packets are immediately paced.
- EXPECT_CALL(*mock_sender_, CanSend(kDefaultTCPMSS)).WillOnce(Return(true));
+ EXPECT_CALL(*mock_sender_, CanSend(kMaxOutgoingPacketSize))
+ .WillOnce(Return(true));
// Verify the next packet is paced and delayed 2ms due to granularity.
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(2),
- pacing_sender_->TimeUntilSend(clock_.Now(), kDefaultTCPMSS));
+ EXPECT_EQ(
+ QuicTime::Delta::FromMilliseconds(2),
+ pacing_sender_->TimeUntilSend(clock_.Now(), kMaxOutgoingPacketSize));
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
@@ -364,7 +366,7 @@ TEST_F(PacingSenderTest, NoBurstInRecovery) {
UpdateRtt();
// Ensure only one packet is sent immediately and the rest are paced.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, true, false, 10);
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, 0, true, 10);
CheckPacketIsSentImmediately();
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
@@ -385,8 +387,11 @@ TEST_F(PacingSenderTest, CwndLimited) {
// Wake up on time.
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(2));
// After sending packet 3, cwnd is limited.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
- true, 10);
+ // This test is slightly odd because bytes_in_flight is calculated using
+ // kMaxOutgoingPacketSize and CWND is calculated using kDefaultTCPMSS,
+ // which is 8 bytes larger, so 3 packets can be sent for a CWND of 2.
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA,
+ 2 * kMaxOutgoingPacketSize, false, 2);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
// Verify pacing sender stops making up for lost time after sending packet 3.
@@ -438,20 +443,23 @@ TEST_F(PacingSenderTest, LumpyPacingWithInitialBurstToken) {
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(3));
CheckPacketIsSentImmediately();
// After sending packet 21, cwnd is limited.
- CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
- true, 10);
+ // This test is slightly odd because bytes_in_flight is calculated using
+ // kMaxOutgoingPacketSize and CWND is calculated using kDefaultTCPMSS,
+ // which is 8 bytes larger, so 21 packets can be sent for a CWND of 20.
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA,
+ 20 * kMaxOutgoingPacketSize, false, 20);
clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
// Suppose cwnd size is 5, so that lumpy size becomes 2.
CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA, kBytesInFlight, false,
- false, 5);
+ 5);
CheckPacketIsSentImmediately();
// Packet 24 will be delayed 2ms.
CheckPacketIsDelayed(QuicTime::Delta::FromMilliseconds(2));
}
TEST_F(PacingSenderTest, NoLumpyPacingForLowBandwidthFlows) {
- // Set lumpy size to be 3, and cwnd faction to 0.5
+ // Set lumpy size to be 3, and cwnd fraction to 0.5
SetQuicFlag(FLAGS_quic_lumpy_pacing_size, 3);
SetQuicFlag(FLAGS_quic_lumpy_pacing_cwnd_fraction, 0.5f);
@@ -476,6 +484,43 @@ TEST_F(PacingSenderTest, NoLumpyPacingForLowBandwidthFlows) {
}
}
+// Regression test for b/184471302 to ensure that ACKs received back-to-back
+// don't cause bursts in sending.
+TEST_F(PacingSenderTest, NoBurstsForLumpyPacingWithAckAggregation) {
+ // Configure pacing rate of 1 packet per millisecond.
+ QuicTime::Delta inter_packet_delay = QuicTime::Delta::FromMilliseconds(1);
+ InitPacingRate(kInitialBurstPackets,
+ QuicBandwidth::FromBytesAndTimeDelta(kMaxOutgoingPacketSize,
+ inter_packet_delay));
+ UpdateRtt();
+
+ // Send kInitialBurstPackets packets, and verify that they are not paced.
+ for (int i = 0; i < kInitialBurstPackets; ++i) {
+ CheckPacketIsSentImmediately();
+ }
+ // The last packet of the burst causes the sender to be CWND limited.
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA,
+ 10 * kMaxOutgoingPacketSize, false, 10);
+
+ if (GetQuicReloadableFlag(quic_fix_pacing_sender_bursts)) {
+ // The last sent packet made the connection CWND limited, so no lumpy tokens
+ // should be available.
+ EXPECT_EQ(0u, pacing_sender_->lumpy_tokens());
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA,
+ 10 * kMaxOutgoingPacketSize, false, 10);
+ EXPECT_EQ(0u, pacing_sender_->lumpy_tokens());
+ CheckPacketIsDelayed(2 * inter_packet_delay);
+ } else {
+ EXPECT_EQ(1u, pacing_sender_->lumpy_tokens());
+ // Repeatedly send single packets to make the sender CWND limited and
+ // observe that there's no pacing without the fix.
+ for (int i = 0; i < 10; ++i) {
+ CheckPacketIsSentImmediately(HAS_RETRANSMITTABLE_DATA,
+ 10 * kMaxOutgoingPacketSize, false, 10);
+ }
+ }
+}
+
TEST_F(PacingSenderTest, IdealNextPacketSendTimeWithLumpyPacing) {
// Set lumpy size to be 3, and cwnd faction to 0.5
SetQuicFlag(FLAGS_quic_lumpy_pacing_size, 3);
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
index 2be6fa44b2a..e167dec9cf1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.cc
@@ -29,8 +29,7 @@ RttStats::RttStats()
mean_deviation_(QuicTime::Delta::Zero()),
calculate_standard_deviation_(false),
initial_rtt_(QuicTime::Delta::FromMilliseconds(kInitialRttMs)),
- last_update_time_(QuicTime::Zero()),
- ignore_max_ack_delay_(false) {}
+ last_update_time_(QuicTime::Zero()) {}
void RttStats::ExpireSmoothedMetrics() {
mean_deviation_ = std::max(
@@ -63,17 +62,19 @@ void RttStats::UpdateRtt(QuicTime::Delta send_delta,
QuicTime::Delta rtt_sample(send_delta);
previous_srtt_ = smoothed_rtt_;
-
- if (ignore_max_ack_delay_) {
- ack_delay = QuicTime::Delta::Zero();
- }
// Correct for ack_delay if information received from the peer results in a
// an RTT sample at least as large as min_rtt. Otherwise, only use the
// send_delta.
+ // TODO(fayang): consider to ignore rtt_sample if rtt_sample < ack_delay and
+ // ack_delay is relatively large.
if (rtt_sample > ack_delay) {
if (rtt_sample - min_rtt_ >= ack_delay) {
rtt_sample = rtt_sample - ack_delay;
+ } else {
+ QUIC_CODE_COUNT(quic_ack_delay_makes_rtt_sample_smaller_than_min_rtt);
}
+ } else {
+ QUIC_CODE_COUNT(quic_ack_delay_greater_than_rtt_sample);
}
latest_rtt_ = rtt_sample;
if (calculate_standard_deviation_) {
@@ -138,7 +139,6 @@ void RttStats::CloneFrom(const RttStats& stats) {
calculate_standard_deviation_ = stats.calculate_standard_deviation_;
initial_rtt_ = stats.initial_rtt_;
last_update_time_ = stats.last_update_time_;
- ignore_max_ack_delay_ = stats.ignore_max_ack_delay_;
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
index 0047b0f0448..cb591dbf2e1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats.h
@@ -101,12 +101,6 @@ class QUIC_EXPORT_PRIVATE RttStats {
QuicTime last_update_time() const { return last_update_time_; }
- bool ignore_max_ack_delay() const { return ignore_max_ack_delay_; }
-
- void set_ignore_max_ack_delay(bool ignore_max_ack_delay) {
- ignore_max_ack_delay_ = ignore_max_ack_delay;
- }
-
void EnableStandardDeviationCalculation() {
calculate_standard_deviation_ = true;
}
@@ -130,8 +124,6 @@ class QUIC_EXPORT_PRIVATE RttStats {
bool calculate_standard_deviation_;
QuicTime::Delta initial_rtt_;
QuicTime last_update_time_;
- // Whether to ignore the peer's max ack delay.
- bool ignore_max_ack_delay_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
index bdf54c611fc..1df509f0f7c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/congestion_control/rtt_stats_test.cc
@@ -56,34 +56,6 @@ TEST_F(RttStatsTest, SmoothedRtt) {
rtt_stats_.smoothed_rtt());
}
-TEST_F(RttStatsTest, SmoothedRttIgnoreAckDelay) {
- rtt_stats_.set_ignore_max_ack_delay(true);
- // Verify that ack_delay is ignored in the first measurement.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- // Verify that a plausible ack delay increases the max ack delay.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Delta::FromMilliseconds(100),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- // Verify that Smoothed RTT includes max ack delay if it's reasonable.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Delta::FromMilliseconds(50), QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300), rtt_stats_.smoothed_rtt());
- // Verify that large erroneous ack_delay does not change Smoothed RTT.
- rtt_stats_.UpdateRtt(QuicTime::Delta::FromMilliseconds(200),
- QuicTime::Delta::FromMilliseconds(300),
- QuicTime::Zero());
- EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200), rtt_stats_.latest_rtt());
- EXPECT_EQ(QuicTime::Delta::FromMicroseconds(287500),
- rtt_stats_.smoothed_rtt());
-}
-
// Ensure that the potential rounding artifacts in EWMA calculation do not cause
// the SRTT to drift too far from the exact value.
TEST_F(RttStatsTest, SmoothedRttStability) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
index 6dcb989b9e8..b591becf4f9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_handshake_message.cc
@@ -16,7 +16,6 @@
#include "quic/core/crypto/crypto_utils.h"
#include "quic/core/quic_socket_address_coder.h"
#include "quic/core/quic_utils.h"
-#include "quic/platform/api/quic_map_util.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -171,7 +170,7 @@ bool CryptoHandshakeMessage::GetStringPiece(QuicTag tag,
}
bool CryptoHandshakeMessage::HasStringPiece(QuicTag tag) const {
- return QuicContainsKey(tag_value_map_, tag);
+ return tag_value_map_.find(tag) != tag_value_map_.end();
}
QuicErrorCode CryptoHandshakeMessage::GetNthValue24(
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
index af62865b653..d594f487549 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_protocol.h
@@ -28,7 +28,7 @@ using ServerConfigID = std::string;
// The following tags have been deprecated and should not be reused:
// "1CON", "BBQ4", "NCON", "RCID", "SREJ", "TBKP", "TB10", "SCLS", "SMHL",
-// "QNZR", "B2HI", "H2PR", "FIFO", "LIFO", "RRWS", "QNSP"
+// "QNZR", "B2HI", "H2PR", "FIFO", "LIFO", "RRWS", "QNSP", "B2CL"
// clang-format off
const QuicTag kCHLO = TAG('C', 'H', 'L', 'O'); // Client hello
@@ -133,9 +133,6 @@ const QuicTag kB2NE = TAG('B', '2', 'N', 'E'); // For BBRv2, always exit
// threshold.
const QuicTag kB2RP = TAG('B', '2', 'R', 'P'); // For BBRv2, run PROBE_RTT on
// the regular schedule
-const QuicTag kB2CL = TAG('B', '2', 'C', 'L'); // For BBRv2, allow PROBE_BW
- // cwnd to be below BDP + ack
- // height.
const QuicTag kB2LO = TAG('B', '2', 'L', 'O'); // Ignore inflight_lo in BBR2
const QuicTag kB2HR = TAG('B', '2', 'H', 'R'); // 15% inflight_hi headroom.
const QuicTag kB2SL = TAG('B', '2', 'S', 'L'); // When exiting STARTUP due to
@@ -344,6 +341,8 @@ const QuicTag kMTUL = TAG('M', 'T', 'U', 'L'); // Low-target MTU discovery.
const QuicTag kNSLC = TAG('N', 'S', 'L', 'C'); // Always send connection close
// for idle timeout.
const QuicTag kCHSP = TAG('C', 'H', 'S', 'P'); // Chaos protection.
+const QuicTag kBPTE = TAG('B', 'P', 'T', 'E'); // BoringSSL Permutes
+ // TLS Extensions.
// Proof types (i.e. certificate types)
// NOTE: although it would be silly to do so, specifying both kX509 and kX59R
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
index 7fadbbdcef7..753bd603f07 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_server_test.cc
@@ -59,21 +59,19 @@ const char kOldConfigId[] = "old-config-id";
struct TestParams {
friend std::ostream& operator<<(std::ostream& os, const TestParams& p) {
os << " versions: "
- << ParsedQuicVersionVectorToString(p.supported_versions)
- << " } allow_sni_without_dots: " << p.allow_sni_without_dots;
+ << ParsedQuicVersionVectorToString(p.supported_versions) << " }";
return os;
}
// Versions supported by client and server.
ParsedQuicVersionVector supported_versions;
- bool allow_sni_without_dots;
};
// Used by ::testing::PrintToStringParamName().
std::string PrintToString(const TestParams& p) {
std::string rv = ParsedQuicVersionVectorToString(p.supported_versions);
std::replace(rv.begin(), rv.end(), ',', '_');
- return absl::StrCat(rv, "_allow_sni_without_dots_", p.allow_sni_without_dots);
+ return rv;
}
// Constructs various test permutations.
@@ -83,9 +81,7 @@ std::vector<TestParams> GetTestParams() {
// Start with all versions, remove highest on each iteration.
ParsedQuicVersionVector supported_versions = AllSupportedVersions();
while (!supported_versions.empty()) {
- for (bool allow_sni_without_dots : {false, true}) {
- params.push_back({supported_versions, allow_sni_without_dots});
- }
+ params.push_back({supported_versions});
supported_versions.erase(supported_versions.begin());
}
@@ -109,8 +105,6 @@ class CryptoServerTest : public QuicTestWithParam<TestParams> {
signed_config_(new QuicSignedServerConfig),
chlo_packet_size_(kDefaultMaxPacketSize) {
supported_versions_ = GetParam().supported_versions;
- SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots,
- GetParam().allow_sni_without_dots);
config_.set_enable_serving_sct(true);
client_version_ = supported_versions_.front();
@@ -387,9 +381,6 @@ TEST_P(CryptoServerTest, BadSNI) {
"127.0.0.1",
"ffee::1",
};
- if (!GetParam().allow_sni_without_dots) {
- badSNIs.push_back("foo");
- }
// clang-format on
for (const std::string& bad_sni : badSNIs) {
@@ -402,12 +393,11 @@ TEST_P(CryptoServerTest, BadSNI) {
CheckRejectReasons(kRejectReasons, ABSL_ARRAYSIZE(kRejectReasons));
}
- if (GetParam().allow_sni_without_dots) {
- CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
- {{"PDMD", "X509"}, {"SNI", "foo"}, {"VER\0", client_version_string_}},
- kClientHelloMinimumSize);
- ShouldSucceed(msg);
- }
+ // Check that SNIs without dots are allowed
+ CryptoHandshakeMessage msg = crypto_test_utils::CreateCHLO(
+ {{"PDMD", "X509"}, {"SNI", "foo"}, {"VER\0", client_version_string_}},
+ kClientHelloMinimumSize);
+ ShouldSucceed(msg);
}
TEST_P(CryptoServerTest, DefaultCert) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
index 67527d45826..9c12d8cf309 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/crypto_utils.cc
@@ -713,35 +713,15 @@ const char* CryptoUtils::HandshakeFailureReasonToString(
return "INVALID_HANDSHAKE_FAILURE_REASON";
}
+#undef RETURN_STRING_LITERAL // undef for jumbo builds
+
// static
std::string CryptoUtils::EarlyDataReasonToString(
ssl_early_data_reason_t reason) {
-#if BORINGSSL_API_VERSION >= 12
const char* reason_string = SSL_early_data_reason_string(reason);
if (reason_string != nullptr) {
return std::string("ssl_early_data_") + reason_string;
}
-#else
- // TODO(davidben): Remove this logic once
- // https://boringssl-review.googlesource.com/c/boringssl/+/43724 has landed in
- // downstream repositories.
- switch (reason) {
- RETURN_STRING_LITERAL(ssl_early_data_unknown);
- RETURN_STRING_LITERAL(ssl_early_data_disabled);
- RETURN_STRING_LITERAL(ssl_early_data_accepted);
- RETURN_STRING_LITERAL(ssl_early_data_protocol_version);
- RETURN_STRING_LITERAL(ssl_early_data_peer_declined);
- RETURN_STRING_LITERAL(ssl_early_data_no_session_offered);
- RETURN_STRING_LITERAL(ssl_early_data_session_not_resumed);
- RETURN_STRING_LITERAL(ssl_early_data_unsupported_for_session);
- RETURN_STRING_LITERAL(ssl_early_data_hello_retry_request);
- RETURN_STRING_LITERAL(ssl_early_data_alpn_mismatch);
- RETURN_STRING_LITERAL(ssl_early_data_channel_id);
- RETURN_STRING_LITERAL(ssl_early_data_token_binding);
- RETURN_STRING_LITERAL(ssl_early_data_ticket_age_skew);
- RETURN_STRING_LITERAL(ssl_early_data_quic_parameter_mismatch);
- }
-#endif
QUIC_BUG_IF(quic_bug_12871_3,
reason < 0 || reason > ssl_early_data_reason_max_value)
<< "Unknown ssl_early_data_reason_t " << reason;
@@ -761,8 +741,6 @@ std::string CryptoUtils::HashHandshakeMessage(
return output;
}
-#undef RETURN_STRING_LITERAL // undef for jumbo builds
-
// static
bool CryptoUtils::GetSSLCapabilities(const SSL* ssl,
bssl::UniquePtr<uint8_t>* capabilities,
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
index c4e66c80e73..c97d5ddb512 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/key_exchange.cc
@@ -31,10 +31,8 @@ std::unique_ptr<SynchronousKeyExchange> CreateLocalSynchronousKeyExchange(
switch (type) {
case kC255:
return Curve25519KeyExchange::New(rand);
- break;
case kP256:
return P256KeyExchange::New();
- break;
default:
QUIC_BUG(quic_bug_10712_2)
<< "Unknown key exchange method: " << QuicTagToString(type);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
index 31cbfd66114..b0a24468a23 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source.h
@@ -166,6 +166,15 @@ class QUIC_EXPORT_PRIVATE ProofSource {
absl::string_view in,
std::unique_ptr<SignatureCallback> callback) = 0;
+ // Return the list of TLS signature algorithms that is acceptable by the
+ // ComputeTlsSignature method. If the entire BoringSSL's default list of
+ // supported signature algorithms are acceptable, return an empty list.
+ //
+ // If returns a non-empty list, ComputeTlsSignature will only be called with a
+ // algorithm in the list.
+ virtual absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const = 0;
+
class QUIC_EXPORT_PRIVATE DecryptCallback {
public:
DecryptCallback() = default;
@@ -197,7 +206,12 @@ class QUIC_EXPORT_PRIVATE ProofSource {
// returns the encrypted ticket. The resulting value must not be larger than
// MaxOverhead bytes larger than |in|. If encryption fails, this method
// returns an empty vector.
- virtual std::vector<uint8_t> Encrypt(absl::string_view in) = 0;
+ //
+ // If |encryption_key| is nonempty, this method should use it for minting
+ // TLS resumption tickets. If it is empty, this method may use an
+ // internally cached encryption key, if available.
+ virtual std::vector<uint8_t> Encrypt(absl::string_view in,
+ absl::string_view encryption_key) = 0;
// Decrypt takes an encrypted ticket |in|, decrypts it, and calls
// |callback->Run| with the decrypted ticket, which must not be larger than
@@ -231,13 +245,15 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandleCallback {
// |chain| the certificate chain in leaf-first order.
// |handshake_hints| (optional) handshake hints that can be used by
// SSL_set_handshake_hints.
+ // |ticket_encryption_key| (optional) encryption key to be used for minting
+ // TLS resumption tickets.
//
// When called asynchronously(is_sync=false), this method will be responsible
// to continue the handshake from where it left off.
- virtual void OnSelectCertificateDone(bool ok,
- bool is_sync,
- const ProofSource::Chain* chain,
- absl::string_view handshake_hints) = 0;
+ virtual void OnSelectCertificateDone(
+ bool ok, bool is_sync, const ProofSource::Chain* chain,
+ absl::string_view handshake_hints,
+ absl::string_view ticket_encryption_key) = 0;
// Called when a ProofSourceHandle::ComputeSignature operation completes.
virtual void OnComputeSignatureDone(
@@ -245,6 +261,10 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandleCallback {
bool is_sync,
std::string signature,
std::unique_ptr<ProofSource::Details> details) = 0;
+
+ // Return true iff ProofSourceHandle::ComputeSignature won't be called later.
+ // The handle can use this function to release resources promptly.
+ virtual bool WillNotCallComputeSignature() const = 0;
};
// ProofSourceHandle is an interface by which a TlsServerHandshaker can obtain
@@ -264,13 +284,17 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandle {
public:
virtual ~ProofSourceHandle() = default;
- // Cancel the pending operation, if any.
- // Once called, any completion method on |callback()| won't be invoked.
- virtual void CancelPendingOperation() = 0;
+ // Close the handle. Cancel the pending operation, if any.
+ // Once called, any completion method on |callback()| won't be invoked, and
+ // future SelectCertificate and ComputeSignature calls should return failure.
+ virtual void CloseHandle() = 0;
// Starts a select certificate operation. If the operation is not cancelled
// when it completes, callback()->OnSelectCertificateDone will be invoked.
//
+ // server_address and client_address should be normalized by the caller before
+ // sending down to this function.
+ //
// If the operation is handled synchronously:
// - QUIC_SUCCESS or QUIC_FAILURE will be returned.
// - callback()->OnSelectCertificateDone should be invoked before the function
@@ -289,7 +313,8 @@ class QUIC_EXPORT_PRIVATE ProofSourceHandle {
const std::string& alpn,
absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
- const absl::optional<std::vector<uint8_t>>& early_data_context) = 0;
+ const absl::optional<std::vector<uint8_t>>& early_data_context,
+ const QuicSSLConfig& ssl_config) = 0;
// Starts a compute signature operation. If the operation is not cancelled
// when it completes, callback()->OnComputeSignatureDone will be invoked.
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
index d61df716c3a..c7acd0056bc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.cc
@@ -80,6 +80,13 @@ void ProofSourceX509::ComputeTlsSignature(
callback->Run(/*ok=*/!signature.empty(), signature, nullptr);
}
+absl::InlinedVector<uint16_t, 8>
+ProofSourceX509::SupportedTlsSignatureAlgorithms() const {
+ // Let ComputeTlsSignature() report an error if a bad signature algorithm is
+ // requested.
+ return {};
+}
+
ProofSource::TicketCrypter* ProofSourceX509::GetTicketCrypter() {
return nullptr;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h
index 83de1de204e..9ac676939a3 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/proof_source_x509.h
@@ -41,11 +41,11 @@ class QUIC_EXPORT_PRIVATE ProofSourceX509 : public ProofSource {
const std::string& hostname) override;
void ComputeTlsSignature(
const QuicSocketAddress& server_address,
- const QuicSocketAddress& client_address,
- const std::string& hostname,
- uint16_t signature_algorithm,
- absl::string_view in,
+ const QuicSocketAddress& client_address, const std::string& hostname,
+ uint16_t signature_algorithm, absl::string_view in,
std::unique_ptr<SignatureCallback> callback) override;
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override;
TicketCrypter* GetTicketCrypter() override;
// Adds a certificate chain to the verifier. Returns false if the chain is
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
index 3f94e7cda60..99f92793c0e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.cc
@@ -33,7 +33,6 @@
#include "quic/platform/api/quic_client_stats.h"
#include "quic/platform/api/quic_hostname_utils.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -848,22 +847,23 @@ bool QuicCryptoClientConfig::PopulateFromCanonicalConfig(
QuicServerId suffix_server_id(canonical_suffixes_[i], server_id.port(),
server_id.privacy_mode_enabled());
- if (!QuicContainsKey(canonical_server_map_, suffix_server_id)) {
+ auto it = canonical_server_map_.lower_bound(suffix_server_id);
+ if (it == canonical_server_map_.end() || it->first != suffix_server_id) {
// This is the first host we've seen which matches the suffix, so make it
- // canonical.
- canonical_server_map_[suffix_server_id] = server_id;
+ // canonical. Use |it| as position hint for faster insertion.
+ canonical_server_map_.insert(
+ it, std::make_pair(std::move(suffix_server_id), std::move(server_id)));
return false;
}
- const QuicServerId& canonical_server_id =
- canonical_server_map_[suffix_server_id];
+ const QuicServerId& canonical_server_id = it->second;
CachedState* canonical_state = cached_states_[canonical_server_id].get();
if (!canonical_state->proof_valid()) {
return false;
}
// Update canonical version to point at the "most recent" entry.
- canonical_server_map_[suffix_server_id] = server_id;
+ it->second = server_id;
server_state->InitializeFrom(*canonical_state);
return true;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
index bb0626094db..847fc96ebe6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config.h
@@ -362,6 +362,14 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// handshake message.
const std::string& user_agent_id() const { return user_agent_id_; }
+ void set_tls_signature_algorithms(std::string signature_algorithms) {
+ tls_signature_algorithms_ = std::move(signature_algorithms);
+ }
+
+ const absl::optional<std::string>& tls_signature_algorithms() const {
+ return tls_signature_algorithms_;
+ }
+
// Saves the |alpn| that will be passed in QUIC's CHLO message.
void set_alpn(const std::string& alpn) { alpn_ = alpn; }
@@ -435,6 +443,10 @@ class QUIC_EXPORT_PRIVATE QuicCryptoClientConfig : public QuicCryptoConfig {
// incorporating |pre_shared_key_| into the key schedule.
std::string pre_shared_key_;
+ // If set, configure the client to use the specified signature algorithms, via
+ // SSL_set1_sigalgs_list. TLS only.
+ absl::optional<std::string> tls_signature_algorithms_;
+
// In QUIC, technically, client hello should be fully padded.
// However, fully padding on slow network connection (e.g. 50kbps) can add
// 150ms latency to one roundtrip. Therefore, you can disable padding of
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
index 6dd09677fb9..5bcf01cd074 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_client_config_test.cc
@@ -179,6 +179,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCIDNoEXPY) {
QuicWallTime expiry = QuicWallTime::FromUNIXSeconds(2);
state.SetServerConfig(scfg.GetSerialized().AsStringPiece(), now, expiry,
&details);
+ EXPECT_FALSE(state.IsEmpty());
QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
@@ -205,6 +206,7 @@ TEST_F(QuicCryptoClientConfigTest, InchoateChloSecureWithSCID) {
state.SetServerConfig(scfg.GetSerialized().AsStringPiece(),
QuicWallTime::FromUNIXSeconds(1),
QuicWallTime::FromUNIXSeconds(0), &details);
+ EXPECT_FALSE(state.IsEmpty());
QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
QuicReferenceCountedPointer<QuicCryptoNegotiatedParameters> params(
@@ -503,5 +505,46 @@ TEST_F(QuicCryptoClientConfigTest, ServerNonceinSHLO) {
EXPECT_EQ("server hello missing server nonce", error_details);
}
+// Test that PopulateFromCanonicalConfig() handles the case of multiple entries
+// in |canonical_server_map_|.
+TEST_F(QuicCryptoClientConfigTest, MultipleCanonicalEntries) {
+ QuicCryptoClientConfig config(crypto_test_utils::ProofVerifierForTesting());
+ config.AddCanonicalSuffix(".google.com");
+ QuicServerId canonical_server_id1("www.google.com", 443, false);
+ QuicCryptoClientConfig::CachedState* state1 =
+ config.LookupOrCreate(canonical_server_id1);
+
+ CryptoHandshakeMessage scfg;
+ scfg.set_tag(kSCFG);
+ scfg.SetStringPiece(kSCID, "12345678");
+ std::string details;
+ QuicWallTime now = QuicWallTime::FromUNIXSeconds(1);
+ QuicWallTime expiry = QuicWallTime::FromUNIXSeconds(2);
+ state1->SetServerConfig(scfg.GetSerialized().AsStringPiece(), now, expiry,
+ &details);
+ state1->set_source_address_token("TOKEN");
+ state1->SetProofValid();
+ EXPECT_FALSE(state1->IsEmpty());
+
+ // This will have the same |suffix_server_id| as |canonical_server_id1|,
+ // therefore |*state2| will be initialized from |*state1|.
+ QuicServerId canonical_server_id2("mail.google.com", 443, false);
+ QuicCryptoClientConfig::CachedState* state2 =
+ config.LookupOrCreate(canonical_server_id2);
+ EXPECT_FALSE(state2->IsEmpty());
+ const CryptoHandshakeMessage* const scfg2 = state2->GetServerConfig();
+ ASSERT_TRUE(scfg2);
+ EXPECT_EQ(kSCFG, scfg2->tag());
+
+ // With a different |suffix_server_id|, this will return an empty CachedState.
+ config.AddCanonicalSuffix(".example.com");
+ QuicServerId canonical_server_id3("www.example.com", 443, false);
+ QuicCryptoClientConfig::CachedState* state3 =
+ config.LookupOrCreate(canonical_server_id3);
+ EXPECT_TRUE(state3->IsEmpty());
+ const CryptoHandshakeMessage* const scfg3 = state3->GetServerConfig();
+ EXPECT_FALSE(scfg3);
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
index 4f3ad0819e4..15ce0f276d7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_crypto_server_config.h
@@ -507,9 +507,6 @@ class QUIC_EXPORT_PRIVATE QuicCryptoServerConfig {
// one-to-one, with the tags in |kexs| from the parent class.
std::vector<std::unique_ptr<AsynchronousKeyExchange>> key_exchanges;
- // tag_value_map contains the raw key/value pairs for the config.
- QuicTagValueMap tag_value_map;
-
// channel_id_enabled is true if the config in |serialized| specifies that
// ChannelIDs are supported.
bool channel_id_enabled;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_random.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_random.cc
index 56657b507f9..d3190c626e7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/quic_random.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/quic_random.cc
@@ -19,17 +19,22 @@ namespace {
// xoshiro256++ 1.0 based on code in the public domain from
// <http://prng.di.unimi.it/xoshiro256plusplus.c>.
+inline uint64_t Xoshiro256InitializeRngStateMember() {
+ uint64_t result;
+ RAND_bytes(reinterpret_cast<uint8_t*>(&result), sizeof(result));
+ return result;
+}
+
inline uint64_t Xoshiro256PlusPlusRotLeft(uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
uint64_t Xoshiro256PlusPlus() {
- static thread_local uint64_t rng_state[4];
- static thread_local bool rng_state_initialized = false;
- if (QUIC_PREDICT_FALSE(!rng_state_initialized)) {
- RAND_bytes(reinterpret_cast<uint8_t*>(&rng_state), sizeof(rng_state));
- rng_state_initialized = true;
- }
+ static thread_local uint64_t rng_state[4] = {
+ Xoshiro256InitializeRngStateMember(),
+ Xoshiro256InitializeRngStateMember(),
+ Xoshiro256InitializeRngStateMember(),
+ Xoshiro256InitializeRngStateMember()};
const uint64_t result =
Xoshiro256PlusPlusRotLeft(rng_state[0] + rng_state[3], 23) + rng_state[0];
const uint64_t t = rng_state[1] << 17;
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
index c6a45c4b834..dd53ee7037c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.cc
@@ -6,8 +6,12 @@
namespace quic {
-TlsClientConnection::TlsClientConnection(SSL_CTX* ssl_ctx, Delegate* delegate)
- : TlsConnection(ssl_ctx, delegate->ConnectionDelegate()),
+TlsClientConnection::TlsClientConnection(SSL_CTX* ssl_ctx,
+ Delegate* delegate,
+ QuicSSLConfig ssl_config)
+ : TlsConnection(ssl_ctx,
+ delegate->ConnectionDelegate(),
+ std::move(ssl_config)),
delegate_(delegate) {}
// static
@@ -24,6 +28,8 @@ bssl::UniquePtr<SSL_CTX> TlsClientConnection::CreateSslCtx(
ssl_ctx.get(), SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL);
SSL_CTX_sess_set_new_cb(ssl_ctx.get(), NewSessionCallback);
+ // TODO(wub): Always enable early data on the SSL_CTX, but allow it to be
+ // overridden on the SSL object, via QuicSSLConfig.
SSL_CTX_set_early_data_enabled(ssl_ctx.get(), enable_early_data);
return ssl_ctx;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
index c9471536b67..ce4b94804a6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_client_connection.h
@@ -30,7 +30,9 @@ class QUIC_EXPORT_PRIVATE TlsClientConnection : public TlsConnection {
friend class TlsClientConnection;
};
- TlsClientConnection(SSL_CTX* ssl_ctx, Delegate* delegate);
+ TlsClientConnection(SSL_CTX* ssl_ctx,
+ Delegate* delegate,
+ QuicSSLConfig ssl_config);
// Creates and configures an SSL_CTX that is appropriate for clients to use.
static bssl::UniquePtr<SSL_CTX> CreateSslCtx(bool enable_early_data);
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
index 381de7eeafb..7a66e2f8f8d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.cc
@@ -5,6 +5,7 @@
#include "quic/core/crypto/tls_connection.h"
#include "absl/strings/string_view.h"
+#include "third_party/boringssl/src/include/openssl/ssl.h"
#include "quic/platform/api/quic_bug_tracker.h"
namespace quic {
@@ -88,12 +89,32 @@ enum ssl_encryption_level_t TlsConnection::BoringEncryptionLevel(
}
TlsConnection::TlsConnection(SSL_CTX* ssl_ctx,
- TlsConnection::Delegate* delegate)
- : delegate_(delegate), ssl_(SSL_new(ssl_ctx)) {
+ TlsConnection::Delegate* delegate,
+ QuicSSLConfig ssl_config)
+ : delegate_(delegate),
+ ssl_(SSL_new(ssl_ctx)),
+ ssl_config_(std::move(ssl_config)) {
SSL_set_ex_data(
ssl(), SslIndexSingleton::GetInstance()->ssl_ex_data_index_connection(),
this);
+ if (ssl_config_.early_data_enabled.has_value()) {
+ const int early_data_enabled = *ssl_config_.early_data_enabled ? 1 : 0;
+ SSL_set_early_data_enabled(ssl(), early_data_enabled);
+ }
+ if (ssl_config_.signing_algorithm_prefs.has_value()) {
+ SSL_set_signing_algorithm_prefs(
+ ssl(), ssl_config_.signing_algorithm_prefs->data(),
+ ssl_config_.signing_algorithm_prefs->size());
+ }
}
+
+void TlsConnection::EnableInfoCallback() {
+ SSL_set_info_callback(
+ ssl(), +[](const SSL* ssl, int type, int value) {
+ ConnectionFromSsl(ssl)->delegate_->InfoCallback(type, value);
+ });
+}
+
// static
bssl::UniquePtr<SSL_CTX> TlsConnection::CreateSslCtx(int cert_verify_mode) {
CRYPTO_library_init();
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
index 28b5684ad4a..f59eaa13150 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_connection.h
@@ -75,12 +75,21 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
// level |level|.
virtual void SendAlert(EncryptionLevel level, uint8_t desc) = 0;
+ // Informational callback from BoringSSL. This callback is disabled by
+ // default, but can be enabled by TlsConnection::EnableInfoCallback.
+ //
+ // See |SSL_CTX_set_info_callback| for the meaning of |type| and |value|.
+ virtual void InfoCallback(int type, int value) = 0;
+
friend class TlsConnection;
};
TlsConnection(const TlsConnection&) = delete;
TlsConnection& operator=(const TlsConnection&) = delete;
+ // Configure the SSL such that delegate_->InfoCallback will be called.
+ void EnableInfoCallback();
+
// Functions to convert between BoringSSL's enum ssl_encryption_level_t and
// QUIC's EncryptionLevel.
static EncryptionLevel QuicEncryptionLevel(enum ssl_encryption_level_t level);
@@ -89,10 +98,12 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
SSL* ssl() const { return ssl_.get(); }
+ const QuicSSLConfig& ssl_config() const { return ssl_config_; }
+
protected:
- // TlsConnection does not take ownership of any of its arguments; they must
+ // TlsConnection does not take ownership of |ssl_ctx| or |delegate|; they must
// outlive the TlsConnection object.
- TlsConnection(SSL_CTX* ssl_ctx, Delegate* delegate);
+ TlsConnection(SSL_CTX* ssl_ctx, Delegate* delegate, QuicSSLConfig ssl_config);
// Creates an SSL_CTX and configures it with the options that are appropriate
// for both client and server. The caller is responsible for ownership of the
@@ -141,6 +152,7 @@ class QUIC_EXPORT_PRIVATE TlsConnection {
Delegate* delegate_;
bssl::UniquePtr<SSL> ssl_;
+ const QuicSSLConfig ssl_config_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
index 6e9901b995e..2042c15aaf2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.cc
@@ -12,8 +12,12 @@
namespace quic {
-TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate)
- : TlsConnection(ssl_ctx, delegate->ConnectionDelegate()),
+TlsServerConnection::TlsServerConnection(SSL_CTX* ssl_ctx,
+ Delegate* delegate,
+ QuicSSLConfig ssl_config)
+ : TlsConnection(ssl_ctx,
+ delegate->ConnectionDelegate(),
+ std::move(ssl_config)),
delegate_(delegate) {}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
index 774bb440f64..6c775b86cd7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/crypto/tls_server_connection.h
@@ -120,7 +120,9 @@ class QUIC_EXPORT_PRIVATE TlsServerConnection : public TlsConnection {
friend class TlsServerConnection;
};
- TlsServerConnection(SSL_CTX* ssl_ctx, Delegate* delegate);
+ TlsServerConnection(SSL_CTX* ssl_ctx,
+ Delegate* delegate,
+ QuicSSLConfig ssl_config);
// Creates and configures an SSL_CTX that is appropriate for servers to use.
static bssl::UniquePtr<SSL_CTX> CreateSslCtx(ProofSource* proof_source);
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
index ad10d601c31..c31b45e322e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.cc
@@ -391,11 +391,9 @@ QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator,
copy.message_frame->data = frame.message_frame->data;
copy.message_frame->message_length = frame.message_frame->message_length;
for (const auto& slice : frame.message_frame->message_data) {
- QuicUniqueBufferPtr buffer =
- MakeUniqueBuffer(allocator, slice.length());
- memcpy(buffer.get(), slice.data(), slice.length());
+ QuicBuffer buffer = QuicBuffer::Copy(allocator, slice.AsStringView());
copy.message_frame->message_data.push_back(
- QuicMemSlice(std::move(buffer), slice.length()));
+ QuicMemSlice(std::move(buffer)));
}
break;
case NEW_TOKEN_FRAME:
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
index 1efe1e662d7..9ee45689117 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frame.h
@@ -9,6 +9,7 @@
#include <type_traits>
#include <vector>
+#include "absl/container/inlined_vector.h"
#include "quic/core/frames/quic_ack_frame.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#include "quic/core/frames/quic_blocked_frame.h"
@@ -133,7 +134,7 @@ static_assert(offsetof(QuicStreamFrame, type) == offsetof(QuicFrame, type),
// A inline size of 1 is chosen to optimize the typical use case of
// 1-stream-frame in QuicTransmissionInfo.retransmittable_frames.
-using QuicFrames = QuicInlinedVector<QuicFrame, 1>;
+using QuicFrames = absl::InlinedVector<QuicFrame, 1>;
// Deletes all the sub-frames contained in |frames|.
QUIC_EXPORT_PRIVATE void DeleteFrames(QuicFrames* frames);
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
index c11be9eb016..038924e2165 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_frames_test.cc
@@ -543,10 +543,8 @@ TEST_F(QuicFramesTest, RemoveSmallestInterval) {
TEST_F(QuicFramesTest, CopyQuicFrames) {
QuicFrames frames;
- SimpleBufferAllocator allocator;
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
QuicMessageFrame* message_frame =
- new QuicMessageFrame(1, MakeSpan(&allocator, "message", &storage));
+ new QuicMessageFrame(1, MemSliceFromString("message"));
// Construct a frame list.
for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) {
switch (i) {
@@ -626,7 +624,7 @@ TEST_F(QuicFramesTest, CopyQuicFrames) {
}
}
- QuicFrames copy = CopyQuicFrames(&allocator, frames);
+ QuicFrames copy = CopyQuicFrames(SimpleBufferAllocator::Get(), frames);
ASSERT_EQ(NUM_FRAME_TYPES, copy.size());
for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) {
EXPECT_EQ(i, copy[i].type);
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.cc b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.cc
index 054303ac1ee..1ac0de67035 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.cc
@@ -14,13 +14,18 @@ QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id)
: message_id(message_id), data(nullptr), message_length(0) {}
QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan span)
+ absl::Span<QuicMemSlice> span)
: message_id(message_id), data(nullptr), message_length(0) {
- span.ConsumeAll([&](QuicMemSlice slice) {
+ for (QuicMemSlice& slice : span) {
+ if (slice.empty()) {
+ continue;
+ }
message_length += slice.length();
message_data.push_back(std::move(slice));
- });
+ }
}
+QuicMessageFrame::QuicMessageFrame(QuicMessageId message_id, QuicMemSlice slice)
+ : QuicMessageFrame(message_id, absl::MakeSpan(&slice, 1)) {}
QuicMessageFrame::QuicMessageFrame(const char* data, QuicPacketLength length)
: message_id(0), data(data), message_length(length) {}
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
index ef1e070deb5..1d090c902e1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_message_frame.h
@@ -5,20 +5,22 @@
#ifndef QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
#define QUICHE_QUIC_CORE_FRAMES_QUIC_MESSAGE_FRAME_H_
+#include "absl/container/inlined_vector.h"
+#include "absl/types/span.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_mem_slice.h"
-#include "quic/platform/api/quic_mem_slice_span.h"
namespace quic {
-using QuicMessageData = QuicInlinedVector<QuicMemSlice, 1>;
+using QuicMessageData = absl::InlinedVector<QuicMemSlice, 1>;
struct QUIC_EXPORT_PRIVATE QuicMessageFrame {
QuicMessageFrame() = default;
explicit QuicMessageFrame(QuicMessageId message_id);
- QuicMessageFrame(QuicMessageId message_id, QuicMemSliceSpan span);
+ QuicMessageFrame(QuicMessageId message_id, absl::Span<QuicMemSlice> span);
+ QuicMessageFrame(QuicMessageId message_id, QuicMemSlice slice);
QuicMessageFrame(const char* data, QuicPacketLength length);
QuicMessageFrame(const QuicMessageFrame& other) = delete;
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
index 9c3d2053d34..235d2af792b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_new_connection_id_frame.h
@@ -32,7 +32,7 @@ struct QUIC_EXPORT_PRIVATE QuicNewConnectionIdFrame {
QuicConnectionId connection_id = EmptyQuicConnectionId();
QuicConnectionIdSequenceNumber sequence_number = 0;
StatelessResetToken stateless_reset_token;
- uint64_t retire_prior_to;
+ uint64_t retire_prior_to = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h
index 7c27a4258b3..6966775a30d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_challenge_frame.h
@@ -27,7 +27,7 @@ struct QUIC_EXPORT_PRIVATE QuicPathChallengeFrame {
// and non-zero when sent.
QuicControlFrameId control_frame_id = kInvalidControlFrameId;
- QuicPathFrameBuffer data_buffer;
+ QuicPathFrameBuffer data_buffer{};
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h
index 6b43bda16ae..a4a75be208b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_path_response_frame.h
@@ -27,7 +27,7 @@ struct QUIC_EXPORT_PRIVATE QuicPathResponseFrame {
// and non-zero when sent.
QuicControlFrameId control_frame_id = kInvalidControlFrameId;
- QuicPathFrameBuffer data_buffer;
+ QuicPathFrameBuffer data_buffer{};
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h
index 94676fb00da..2d738901776 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_streams_blocked_frame.h
@@ -35,7 +35,7 @@ struct QUIC_EXPORT_PRIVATE QuicStreamsBlockedFrame
QuicControlFrameId control_frame_id = kInvalidControlFrameId;
// The number of streams that the sender wishes to exceed
- QuicStreamCount stream_count;
+ QuicStreamCount stream_count = 0;
// Whether uni- or bi-directional streams
bool unidirectional = false;
diff --git a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
index e4f2a86eac7..372a4ea598e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
+++ b/chromium/net/third_party/quiche/src/quic/core/frames/quic_window_update_frame.h
@@ -31,11 +31,11 @@ struct QUIC_EXPORT_PRIVATE QuicWindowUpdateFrame {
// The stream this frame applies to. 0 is a special case meaning the overall
// connection rather than a specific stream.
- QuicStreamId stream_id;
+ QuicStreamId stream_id = 0;
// Maximum data allowed in the stream or connection. The receiver of this
// frame must not send data which would exceedes this restriction.
- QuicByteCount max_data;
+ QuicByteCount max_data = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
index 8efba8869bf..e64d8e62581 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/end_to_end_test.cc
@@ -363,7 +363,6 @@ class EndToEndTest : public QuicTestWithParam<TestParams> {
bool Initialize() {
if (enable_web_transport_) {
- SetQuicReloadableFlag(quic_h3_datagram, true);
memory_cache_backend_.set_enable_webtransport(true);
}
@@ -1883,11 +1882,6 @@ TEST_P(EndToEndTest, RetransmissionAfterZeroRTTRejectBeforeOneRtt) {
ON_CALL(visitor, OnZeroRttRejected(_)).WillByDefault(Invoke([this]() {
EXPECT_FALSE(GetClientSession()->IsEncryptionEstablished());
- if (!GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
- // Trigger an OnCanWrite() to make sure no unencrypted data will be
- // written.
- GetClientSession()->OnCanWrite();
- }
}));
// The 0-RTT handshake should fail.
@@ -3882,7 +3876,7 @@ TEST_P(EndToEndTest, BadPacketHeaderFlags) {
SendSynchronousFooRequestAndCheckResponse();
// Packet with invalid public flags.
- char packet[] = {
+ uint8_t packet[] = {
// invalid public flags
0xFF,
// connection_id
@@ -3905,7 +3899,7 @@ TEST_P(EndToEndTest, BadPacketHeaderFlags) {
0x00,
};
client_writer_->WritePacket(
- &packet[0], sizeof(packet),
+ reinterpret_cast<const char*>(packet), sizeof(packet),
client_->client()->network_helper()->GetLatestClientAddress().host(),
server_address_, nullptr);
@@ -4739,20 +4733,15 @@ TEST_P(EndToEndTest, SendMessages) {
ASSERT_LT(0, client_session->GetCurrentLargestMessagePayload());
std::string message_string(kMaxOutgoingPacketSize, 'a');
- absl::string_view message_buffer(message_string);
QuicRandom* random =
QuicConnectionPeer::GetHelper(client_connection)->GetRandomGenerator();
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
{
QuicConnection::ScopedPacketFlusher flusher(client_session->connection());
// Verify the largest message gets successfully sent.
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
- client_session->SendMessage(MakeSpan(
- client_connection->helper()->GetStreamSendBufferAllocator(),
- absl::string_view(
- message_buffer.data(),
- client_session->GetCurrentLargestMessagePayload()),
- &storage)));
+ client_session->SendMessage(MemSliceFromString(absl::string_view(
+ message_string.data(),
+ client_session->GetCurrentLargestMessagePayload()))));
// Send more messages with size (0, largest_payload] until connection is
// write blocked.
const int kTestMaxNumberOfMessages = 100;
@@ -4761,9 +4750,8 @@ TEST_P(EndToEndTest, SendMessages) {
random->RandUint64() %
client_session->GetGuaranteedLargestMessagePayload() +
1;
- MessageResult result = client_session->SendMessage(MakeSpan(
- client_connection->helper()->GetStreamSendBufferAllocator(),
- absl::string_view(message_buffer.data(), message_length), &storage));
+ MessageResult result = client_session->SendMessage(MemSliceFromString(
+ absl::string_view(message_string.data(), message_length)));
if (result.status == MESSAGE_STATUS_BLOCKED) {
// Connection is write blocked.
break;
@@ -4775,12 +4763,9 @@ TEST_P(EndToEndTest, SendMessages) {
client_->WaitForDelayedAcks();
EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
client_session
- ->SendMessage(MakeSpan(
- client_connection->helper()->GetStreamSendBufferAllocator(),
- absl::string_view(
- message_buffer.data(),
- client_session->GetCurrentLargestMessagePayload() + 1),
- &storage))
+ ->SendMessage(MemSliceFromString(absl::string_view(
+ message_string.data(),
+ client_session->GetCurrentLargestMessagePayload() + 1)))
.status);
EXPECT_THAT(client_->connection_error(), IsQuicNoError());
}
@@ -5698,6 +5683,18 @@ TEST_P(EndToEndTest, ChaosProtectionWithMultiPacketChlo) {
SendSynchronousFooRequestAndCheckResponse();
}
+TEST_P(EndToEndTest, PermuteTlsExtensions) {
+ if (!version_.UsesTls()) {
+ ASSERT_TRUE(Initialize());
+ return;
+ }
+ // Enable TLS extension permutation and perform an HTTP request.
+ client_config_.SetClientConnectionOptions(QuicTagVector{kBPTE});
+ ASSERT_TRUE(Initialize());
+ EXPECT_TRUE(GetClientSession()->permutes_tls_extensions());
+ SendSynchronousFooRequestAndCheckResponse();
+}
+
TEST_P(EndToEndTest, KeyUpdateInitiatedByClient) {
if (!version_.UsesTls()) {
// Key Update is only supported in TLS handshake.
@@ -6043,6 +6040,7 @@ TEST_P(EndToEndTest, WebTransportSessionSetup) {
WebTransportHttp3* web_transport =
CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+ ASSERT_NE(web_transport, nullptr);
server_thread_->Pause();
QuicSpdySession* server_session = GetServerSession();
@@ -6064,6 +6062,7 @@ TEST_P(EndToEndTest, WebTransportSessionWithLoss) {
WebTransportHttp3* web_transport =
CreateWebTransportSession("/echo", /*wait_for_server_response=*/true);
+ ASSERT_NE(web_transport, nullptr);
server_thread_->Pause();
QuicSpdySession* server_session = GetServerSession();
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
index 6d9290a12c1..de86955739b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.cc
@@ -33,20 +33,9 @@ HttpDecoder::HttpDecoder(Visitor* visitor, Options options)
remaining_frame_length_(0),
current_type_field_length_(0),
remaining_type_field_length_(0),
- current_push_id_length_(0),
- remaining_push_id_length_(0),
error_(QUIC_NO_ERROR),
- error_detail_(""),
- ignore_old_priority_update_(
- GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)),
- error_on_http3_push_(GetQuicReloadableFlag(quic_error_on_http3_push)) {
+ error_detail_("") {
QUICHE_DCHECK(visitor_);
- if (ignore_old_priority_update_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_ignore_old_priority_update_frame);
- }
- if (error_on_http3_push_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_error_on_http3_push);
- }
}
HttpDecoder::~HttpDecoder() {}
@@ -182,17 +171,15 @@ bool HttpDecoder::ReadFrameType(QuicDataReader* reader) {
return false;
}
- if (error_on_http3_push_) {
- if (current_frame_type_ ==
- static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "CANCEL_PUSH frame received.");
- return false;
- }
- if (current_frame_type_ ==
- static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "PUSH_PROMISE frame received.");
- return false;
- }
+ if (current_frame_type_ ==
+ static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "CANCEL_PUSH frame received.");
+ return false;
+ }
+ if (current_frame_type_ ==
+ static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) {
+ RaiseError(QUIC_HTTP_FRAME_ERROR, "PUSH_PROMISE frame received.");
+ return false;
}
state_ = STATE_READING_FRAME_LENGTH;
@@ -241,6 +228,10 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
}
if (current_frame_length_ > MaxFrameLength(current_frame_type_)) {
+ // MaxFrameLength() returns numeric_limits::max()
+ // if IsFrameBuffered() is false.
+ QUICHE_DCHECK(IsFrameBuffered());
+
RaiseError(QUIC_HTTP_FRAME_TOO_LARGE, "Frame is too large.");
return false;
}
@@ -261,41 +252,18 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
visitor_->OnHeadersFrameStart(header_length, current_frame_length_);
break;
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- break;
- }
+ QUICHE_NOTREACHED();
break;
case static_cast<uint64_t>(HttpFrameType::SETTINGS):
continue_processing = visitor_->OnSettingsFrameStart(header_length);
break;
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE):
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- break;
- }
- // This edge case needs to be handled here, because ReadFramePayload()
- // does not get called if |current_frame_length_| is zero.
- if (current_frame_length_ == 0) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "PUSH_PROMISE frame with empty payload.");
- return false;
- }
- continue_processing = visitor_->OnPushPromiseFrameStart(header_length);
+ QUICHE_NOTREACHED();
break;
case static_cast<uint64_t>(HttpFrameType::GOAWAY):
break;
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
break;
- case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
- if (ignore_old_priority_update_) {
- continue_processing = visitor_->OnUnknownFrameStart(
- current_frame_type_, header_length, current_frame_length_);
- } else {
- continue_processing =
- visitor_->OnPriorityUpdateFrameStart(header_length);
- }
- break;
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM):
continue_processing = visitor_->OnPriorityUpdateFrameStart(header_length);
break;
@@ -314,6 +282,24 @@ bool HttpDecoder::ReadFrameLength(QuicDataReader* reader) {
return continue_processing;
}
+bool HttpDecoder::IsFrameBuffered() {
+ switch (current_frame_type_) {
+ case static_cast<uint64_t>(HttpFrameType::SETTINGS):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::GOAWAY):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM):
+ return true;
+ case static_cast<uint64_t>(HttpFrameType::ACCEPT_CH):
+ return true;
+ }
+
+ // Other defined frame types as well as unknown frames are not buffered.
+ return false;
+}
+
bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
QUICHE_DCHECK_NE(0u, reader->BytesRemaining());
QUICHE_DCHECK_NE(0u, remaining_frame_length_);
@@ -344,11 +330,7 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- } else {
- continue_processing = BufferOrParsePayload(reader);
- }
+ QUICHE_NOTREACHED();
break;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
@@ -356,72 +338,7 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- break;
- }
- PushId push_id;
- if (current_frame_length_ == remaining_frame_length_) {
- // A new Push Promise frame just arrived.
- QUICHE_DCHECK_EQ(0u, current_push_id_length_);
- current_push_id_length_ = reader->PeekVarInt62Length();
- if (current_push_id_length_ > remaining_frame_length_) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Unable to read PUSH_PROMISE push_id.");
- return false;
- }
- if (current_push_id_length_ > reader->BytesRemaining()) {
- // Not all bytes of push id is present yet, buffer push id.
- QUICHE_DCHECK_EQ(0u, remaining_push_id_length_);
- remaining_push_id_length_ = current_push_id_length_;
- BufferPushId(reader);
- break;
- }
- bool success = reader->ReadVarInt62(&push_id);
- QUICHE_DCHECK(success);
- remaining_frame_length_ -= current_push_id_length_;
- if (!visitor_->OnPushPromiseFramePushId(
- push_id, current_push_id_length_,
- current_frame_length_ - current_push_id_length_)) {
- continue_processing = false;
- current_push_id_length_ = 0;
- break;
- }
- current_push_id_length_ = 0;
- } else if (remaining_push_id_length_ > 0) {
- // Waiting for more bytes on push id.
- BufferPushId(reader);
- if (remaining_push_id_length_ != 0) {
- break;
- }
- QuicDataReader push_id_reader(push_id_buffer_.data(),
- current_push_id_length_);
-
- bool success = push_id_reader.ReadVarInt62(&push_id);
- QUICHE_DCHECK(success);
- if (!visitor_->OnPushPromiseFramePushId(
- push_id, current_push_id_length_,
- current_frame_length_ - current_push_id_length_)) {
- continue_processing = false;
- current_push_id_length_ = 0;
- break;
- }
- current_push_id_length_ = 0;
- }
-
- // Read Push Promise headers.
- QUICHE_DCHECK_LT(remaining_frame_length_, current_frame_length_);
- QuicByteCount bytes_to_read = std::min<QuicByteCount>(
- remaining_frame_length_, reader->BytesRemaining());
- if (bytes_to_read == 0) {
- break;
- }
- absl::string_view payload;
- bool success = reader->ReadStringPiece(&payload, bytes_to_read);
- QUICHE_DCHECK(success);
- QUICHE_DCHECK(!payload.empty());
- continue_processing = visitor_->OnPushPromiseFramePayload(payload);
- remaining_frame_length_ -= payload.length();
+ QUICHE_NOTREACHED();
break;
}
case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
@@ -432,14 +349,6 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
continue_processing = BufferOrParsePayload(reader);
break;
}
- case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- if (ignore_old_priority_update_) {
- continue_processing = HandleUnknownFramePayload(reader);
- } else {
- continue_processing = BufferOrParsePayload(reader);
- }
- break;
- }
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
continue_processing = BufferOrParsePayload(reader);
break;
@@ -454,6 +363,17 @@ bool HttpDecoder::ReadFramePayload(QuicDataReader* reader) {
}
}
+ if (IsFrameBuffered()) {
+ if (state_ != STATE_READING_FRAME_PAYLOAD) {
+ // BufferOrParsePayload() has advanced |state_|.
+ // TODO(bnc): Simplify state transitions.
+ QUICHE_DCHECK_EQ(STATE_READING_FRAME_TYPE, state_);
+ QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
+ }
+ } else {
+ QUICHE_DCHECK(state_ == STATE_READING_FRAME_PAYLOAD);
+ }
+
// BufferOrParsePayload() may have advanced |state_|.
if (state_ == STATE_READING_FRAME_PAYLOAD && remaining_frame_length_ == 0) {
state_ = STATE_FINISH_PARSING;
@@ -477,13 +397,7 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- } else {
- // If frame payload is not empty, FinishParsing() is skipped.
- QUICHE_DCHECK_EQ(0u, current_frame_length_);
- continue_processing = BufferOrParsePayload(reader);
- }
+ QUICHE_NOTREACHED();
break;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
@@ -493,11 +407,7 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
break;
}
case static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE): {
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- } else {
- continue_processing = visitor_->OnPushPromiseFrameEnd();
- }
+ QUICHE_NOTREACHED();
break;
}
case static_cast<uint64_t>(HttpFrameType::GOAWAY): {
@@ -512,16 +422,6 @@ bool HttpDecoder::FinishParsing(QuicDataReader* reader) {
continue_processing = BufferOrParsePayload(reader);
break;
}
- case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- if (ignore_old_priority_update_) {
- continue_processing = visitor_->OnUnknownFrameEnd();
- } else {
- // If frame payload is not empty, FinishParsing() is skipped.
- QUICHE_DCHECK_EQ(0u, current_frame_length_);
- continue_processing = BufferOrParsePayload(reader);
- }
- break;
- }
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
// If frame payload is not empty, FinishParsing() is skipped.
QUICHE_DCHECK_EQ(0u, current_frame_length_);
@@ -555,21 +455,8 @@ bool HttpDecoder::HandleUnknownFramePayload(QuicDataReader* reader) {
return visitor_->OnUnknownFramePayload(payload);
}
-void HttpDecoder::DiscardFramePayload(QuicDataReader* reader) {
- QuicByteCount bytes_to_read = std::min<QuicByteCount>(
- remaining_frame_length_, reader->BytesRemaining());
- absl::string_view payload;
- bool success = reader->ReadStringPiece(&payload, bytes_to_read);
- QUICHE_DCHECK(success);
- remaining_frame_length_ -= payload.length();
- if (remaining_frame_length_ == 0) {
- state_ = STATE_READING_FRAME_TYPE;
- current_length_field_length_ = 0;
- current_type_field_length_ = 0;
- }
-}
-
bool HttpDecoder::BufferOrParsePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK(IsFrameBuffered());
QUICHE_DCHECK_EQ(current_frame_length_,
buffer_.size() + remaining_frame_length_);
@@ -615,27 +502,14 @@ bool HttpDecoder::BufferOrParsePayload(QuicDataReader* reader) {
}
bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
+ QUICHE_DCHECK(IsFrameBuffered());
QUICHE_DCHECK_EQ(current_frame_length_, reader->BytesRemaining());
QUICHE_DCHECK_EQ(0u, remaining_frame_length_);
switch (current_frame_type_) {
case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH): {
- if (error_on_http3_push_) {
- QUICHE_NOTREACHED();
- return false;
- }
- CancelPushFrame frame;
- if (!reader->ReadVarInt62(&frame.push_id)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Unable to read CANCEL_PUSH push_id.");
- return false;
- }
- if (!reader->IsDoneReading()) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Superfluous data in CANCEL_PUSH frame.");
- return false;
- }
- return visitor_->OnCancelPushFrame(frame);
+ QUICHE_NOTREACHED();
+ return false;
}
case static_cast<uint64_t>(HttpFrameType::SETTINGS): {
SettingsFrame frame;
@@ -670,21 +544,9 @@ bool HttpDecoder::ParseEntirePayload(QuicDataReader* reader) {
}
return visitor_->OnMaxPushIdFrame(frame);
}
- case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE): {
- if (ignore_old_priority_update_) {
- QUICHE_NOTREACHED();
- return false;
- } else {
- PriorityUpdateFrame frame;
- if (!ParsePriorityUpdateFrame(reader, &frame)) {
- return false;
- }
- return visitor_->OnPriorityUpdateFrame(frame);
- }
- }
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM): {
PriorityUpdateFrame frame;
- if (!ParseNewPriorityUpdateFrame(reader, &frame)) {
+ if (!ParsePriorityUpdateFrame(reader, &frame)) {
return false;
}
return visitor_->OnPriorityUpdateFrame(frame);
@@ -725,19 +587,6 @@ void HttpDecoder::BufferFrameType(QuicDataReader* reader) {
remaining_type_field_length_ -= bytes_to_read;
}
-void HttpDecoder::BufferPushId(QuicDataReader* reader) {
- QUICHE_DCHECK_LE(remaining_push_id_length_, current_frame_length_);
- QuicByteCount bytes_to_read = std::min<QuicByteCount>(
- reader->BytesRemaining(), remaining_push_id_length_);
- bool success =
- reader->ReadBytes(push_id_buffer_.data() + current_push_id_length_ -
- remaining_push_id_length_,
- bytes_to_read);
- QUICHE_DCHECK(success);
- remaining_push_id_length_ -= bytes_to_read;
- remaining_frame_length_ -= bytes_to_read;
-}
-
void HttpDecoder::RaiseError(QuicErrorCode error, std::string error_detail) {
state_ = STATE_ERROR;
error_ = error;
@@ -769,36 +618,6 @@ bool HttpDecoder::ParseSettingsFrame(QuicDataReader* reader,
}
bool HttpDecoder::ParsePriorityUpdateFrame(QuicDataReader* reader,
- PriorityUpdateFrame* frame) {
- uint8_t prioritized_element_type;
- if (!reader->ReadUInt8(&prioritized_element_type)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR,
- "Unable to read prioritized element type.");
- return false;
- }
-
- if (prioritized_element_type != REQUEST_STREAM &&
- prioritized_element_type != PUSH_STREAM) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "Invalid prioritized element type.");
- return false;
- }
-
- frame->prioritized_element_type =
- static_cast<PrioritizedElementType>(prioritized_element_type);
-
- if (!reader->ReadVarInt62(&frame->prioritized_element_id)) {
- RaiseError(QUIC_HTTP_FRAME_ERROR, "Unable to read prioritized element id.");
- return false;
- }
-
- absl::string_view priority_field_value = reader->ReadRemainingPayload();
- frame->priority_field_value =
- std::string(priority_field_value.data(), priority_field_value.size());
-
- return true;
-}
-
-bool HttpDecoder::ParseNewPriorityUpdateFrame(QuicDataReader* reader,
PriorityUpdateFrame* frame) {
frame->prioritized_element_type = REQUEST_STREAM;
@@ -836,20 +655,13 @@ bool HttpDecoder::ParseAcceptChFrame(QuicDataReader* reader,
QuicByteCount HttpDecoder::MaxFrameLength(uint64_t frame_type) {
switch (frame_type) {
- case static_cast<uint64_t>(HttpFrameType::CANCEL_PUSH):
- // TODO(b/171463363): Remove.
- return sizeof(PushId);
case static_cast<uint64_t>(HttpFrameType::SETTINGS):
// This limit is arbitrary.
return 1024 * 1024;
case static_cast<uint64_t>(HttpFrameType::GOAWAY):
return VARIABLE_LENGTH_INTEGER_LENGTH_8;
case static_cast<uint64_t>(HttpFrameType::MAX_PUSH_ID):
- // TODO(b/171463363): Remove.
- return sizeof(PushId);
- case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE):
- // This limit is arbitrary.
- return 1024 * 1024;
+ return VARIABLE_LENGTH_INTEGER_LENGTH_8;
case static_cast<uint64_t>(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM):
// This limit is arbitrary.
return 1024 * 1024;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
index 3a970fb63b1..002ff68f008 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder.h
@@ -44,10 +44,6 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// On*FrameStart() methods are called after the frame header is completely
// processed. At that point it is safe to consume |header_length| bytes.
- // Called when a CANCEL_PUSH frame has been successfully parsed.
- // TODO(b/171463363): Remove.
- virtual bool OnCancelPushFrame(const CancelPushFrame& frame) = 0;
-
// Called when a MAX_PUSH_ID frame has been successfully parsed.
virtual bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) = 0;
@@ -84,24 +80,6 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Called when a HEADERS frame has been completely processed.
virtual bool OnHeadersFrameEnd() = 0;
- // TODO(b/171463363): Remove all.
- // Called when a PUSH_PROMISE frame has been received.
- virtual bool OnPushPromiseFrameStart(QuicByteCount header_length) = 0;
- // Called when the Push ID field of a PUSH_PROMISE frame has been parsed.
- // Called exactly once for a valid PUSH_PROMISE frame.
- // |push_id_length| is the length of the push ID field.
- // |header_block_length| is the length of the compressed header block.
- virtual bool OnPushPromiseFramePushId(
- PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length) = 0;
- // Called when part of the header block of a PUSH_PROMISE frame has been
- // read. May be called multiple times for a single frame. |payload| is
- // guaranteed to be non-empty.
- virtual bool OnPushPromiseFramePayload(absl::string_view payload) = 0;
- // Called when a PUSH_PROMISE frame has been completely processed.
- virtual bool OnPushPromiseFrameEnd() = 0;
-
// Called when a PRIORITY_UPDATE frame has been received.
// |header_length| contains PRIORITY_UPDATE frame length and payload length.
virtual bool OnPriorityUpdateFrameStart(QuicByteCount header_length) = 0;
@@ -193,16 +171,23 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// if there are any errors. Returns whether processing should continue.
bool ReadFrameLength(QuicDataReader* reader);
- // Depending on the frame type, reads and processes the payload of the current
- // frame from |reader| and calls visitor methods, or calls
- // BufferOrParsePayload(). Returns whether processing should continue.
+ // Returns whether the current frame is of a buffered type.
+ // The payload of buffered frames is buffered by HttpDecoder, and parsed by
+ // HttpDecoder after the entire frame has been received. (Copying to the
+ // buffer is skipped if the ProcessInput() call covers the entire payload.)
+ // Frames that are not buffered have every payload fragment synchronously
+ // passed to the Visitor without buffering.
+ bool IsFrameBuffered();
+
+ // For buffered frame types, calls BufferOrParsePayload(). For other frame
+ // types, reads the payload of the current frame from |reader| and calls
+ // visitor methods. Returns whether processing should continue.
bool ReadFramePayload(QuicDataReader* reader);
- // For frame types parsed by BufferOrParsePayload(), this method is only
- // called if frame payload is empty, at it calls BufferOrParsePayload(). For
- // other frame types, this method directly calls visitor methods to signal
- // that frame had been parsed completely. Returns whether processing should
- // continue.
+ // For buffered frame types, this method is only called if frame payload is
+ // empty, and it calls BufferOrParsePayload(). For other frame types, this
+ // method directly calls visitor methods to signal that frame had been
+ // received completely. Returns whether processing should continue.
bool FinishParsing(QuicDataReader* reader);
// Read payload of unknown frame from |reader| and call
@@ -210,18 +195,17 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// false if it should be paused.
bool HandleUnknownFramePayload(QuicDataReader* reader);
- // Discards any remaining frame payload from |reader|.
- void DiscardFramePayload(QuicDataReader* reader);
-
// Buffers any remaining frame payload from |*reader| into |buffer_| if
// necessary. Parses the frame payload if complete. Parses out of |*reader|
- // without unnecessary copy if |*reader| has entire payload.
+ // without unnecessary copy if |*reader| contains entire payload.
// Returns whether processing should continue.
+ // Must only be called when current frame type is buffered.
bool BufferOrParsePayload(QuicDataReader* reader);
// Parses the entire payload of certain kinds of frames that are parsed in a
// single pass. |reader| must have at least |current_frame_length_| bytes.
// Returns whether processing should continue.
+ // Must only be called when current frame type is buffered.
bool ParseEntirePayload(QuicDataReader* reader);
// Buffers any remaining frame length field from |reader| into
@@ -231,28 +215,17 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
// Buffers any remaining frame type field from |reader| into |type_buffer_|.
void BufferFrameType(QuicDataReader* reader);
- // Buffers at most |remaining_push_id_length_| from |reader| to
- // |push_id_buffer_|. TODO(b/171463363): Remove.
- void BufferPushId(QuicDataReader* reader);
-
// Sets |error_| and |error_detail_| accordingly.
void RaiseError(QuicErrorCode error, std::string error_detail);
// Parses the payload of a SETTINGS frame from |reader| into |frame|.
bool ParseSettingsFrame(QuicDataReader* reader, SettingsFrame* frame);
- // Parses the payload of a PRIORITY_UPDATE frame (draft-01, type 0x0f)
+ // Parses the payload of a PRIORITY_UPDATE frame (draft-02, type 0xf0700)
// from |reader| into |frame|.
- // TODO(b/147306124): Remove.
bool ParsePriorityUpdateFrame(QuicDataReader* reader,
PriorityUpdateFrame* frame);
- // Parses the payload of a PRIORITY_UPDATE frame (draft-02, type 0xf0700)
- // from |reader| into |frame|.
- // TODO(b/147306124): Rename to ParsePriorityUpdateFrame().
- bool ParseNewPriorityUpdateFrame(QuicDataReader* reader,
- PriorityUpdateFrame* frame);
-
// Parses the payload of an ACCEPT_CH frame from |reader| into |frame|.
bool ParseAcceptChFrame(QuicDataReader* reader, AcceptChFrame* frame);
@@ -279,12 +252,6 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
QuicByteCount current_type_field_length_;
// Remaining length that's needed for the frame's type field.
QuicByteCount remaining_type_field_length_;
- // Length of PUSH_PROMISE frame's push id.
- // TODO(b/171463363): Remove.
- QuicByteCount current_push_id_length_;
- // Remaining length that's needed for PUSH_PROMISE frame's push id field.
- // TODO(b/171463363): Remove.
- QuicByteCount remaining_push_id_length_;
// Last error.
QuicErrorCode error_;
// The issue which caused |error_|
@@ -295,17 +262,6 @@ class QUIC_EXPORT_PRIVATE HttpDecoder {
std::array<char, sizeof(uint64_t)> length_buffer_;
// Remaining unparsed type field data.
std::array<char, sizeof(uint64_t)> type_buffer_;
- // Remaining unparsed push id data.
- // TODO(b/171463363): Remove.
- std::array<char, sizeof(uint64_t)> push_id_buffer_;
-
- // Latched value of
- // gfe2_reloadable_flag_quic_ignore_old_priority_update_frame.
- const bool ignore_old_priority_update_;
-
- // Latched value of
- // gfe2_reloadable_flag_quic_error_on_http3_push.
- const bool error_on_http3_push_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
index 05d580e20e1..0266632aae7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_decoder_test.cc
@@ -45,10 +45,6 @@ class MockVisitor : public HttpDecoder::Visitor {
MOCK_METHOD(void, OnError, (HttpDecoder*), (override));
MOCK_METHOD(bool,
- OnCancelPushFrame,
- (const CancelPushFrame& frame),
- (override));
- MOCK_METHOD(bool,
OnMaxPushIdFrame,
(const MaxPushIdFrame& frame),
(override));
@@ -80,22 +76,6 @@ class MockVisitor : public HttpDecoder::Visitor {
MOCK_METHOD(bool, OnHeadersFrameEnd, (), (override));
MOCK_METHOD(bool,
- OnPushPromiseFrameStart,
- (QuicByteCount header_length),
- (override));
- MOCK_METHOD(bool,
- OnPushPromiseFramePushId,
- (PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length),
- (override));
- MOCK_METHOD(bool,
- OnPushPromiseFramePayload,
- (absl::string_view payload),
- (override));
- MOCK_METHOD(bool, OnPushPromiseFrameEnd, (), (override));
-
- MOCK_METHOD(bool,
OnPriorityUpdateFrameStart,
(QuicByteCount header_length),
(override));
@@ -130,7 +110,6 @@ class MockVisitor : public HttpDecoder::Visitor {
class HttpDecoderTest : public QuicTest {
public:
HttpDecoderTest() : decoder_(&visitor_) {
- ON_CALL(visitor_, OnCancelPushFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnMaxPushIdFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnGoAwayFrame(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnSettingsFrameStart(_)).WillByDefault(Return(true));
@@ -141,11 +120,6 @@ class HttpDecoderTest : public QuicTest {
ON_CALL(visitor_, OnHeadersFrameStart(_, _)).WillByDefault(Return(true));
ON_CALL(visitor_, OnHeadersFramePayload(_)).WillByDefault(Return(true));
ON_CALL(visitor_, OnHeadersFrameEnd()).WillByDefault(Return(true));
- ON_CALL(visitor_, OnPushPromiseFrameStart(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnPushPromiseFramePushId(_, _, _))
- .WillByDefault(Return(true));
- ON_CALL(visitor_, OnPushPromiseFramePayload(_)).WillByDefault(Return(true));
- ON_CALL(visitor_, OnPushPromiseFrameEnd()).WillByDefault(Return(true));
ON_CALL(visitor_, OnPriorityUpdateFrameStart(_))
.WillByDefault(Return(true));
ON_CALL(visitor_, OnPriorityUpdateFrame(_)).WillByDefault(Return(true));
@@ -248,144 +222,24 @@ TEST_F(HttpDecoderTest, CancelPush) {
"01" // length
"01"); // Push Id
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(1u, ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("CANCEL_PUSH frame received.", decoder_.error_detail());
- return;
- }
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})))
- .WillOnce(Return(false));
- EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnCancelPushFrame(CancelPushFrame({1})));
- ProcessInputCharByChar(input);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
+ EXPECT_CALL(visitor_, OnError(&decoder_));
+ EXPECT_EQ(1u, ProcessInput(input));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("CANCEL_PUSH frame received.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, PushPromiseFrame) {
InSequence s;
std::string input =
- absl::StrCat(absl::HexStringToBytes("05" // type (PUSH PROMISE)
- "0f" // length
- "C000000000000101"), // push id 257
- "Headers"); // headers
-
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(1u, ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("PUSH_PROMISE frame received.", decoder_.error_detail());
- return;
- }
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2)).WillOnce(Return(false));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7))
- .WillOnce(Return(false));
- absl::string_view remaining_input(input);
- QuicByteCount processed_bytes =
- ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(2u, processed_bytes);
- remaining_input = remaining_input.substr(processed_bytes);
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(8u, processed_bytes);
- remaining_input = remaining_input.substr(processed_bytes);
-
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("Headers")))
- .WillOnce(Return(false));
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(remaining_input.size(), processed_bytes);
-
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()).WillOnce(Return(false));
- EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
- EXPECT_CALL(visitor_,
- OnPushPromiseFramePayload(absl::string_view("Headers")));
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("H")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("e")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("a")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("d")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("e")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("r")));
- EXPECT_CALL(visitor_, OnPushPromiseFramePayload(absl::string_view("s")));
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
- ProcessInputCharByChar(input);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process push id incrementally and append headers with last byte of push id.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(257, 8, 7));
- EXPECT_CALL(visitor_,
- OnPushPromiseFramePayload(absl::string_view("Headers")));
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
- ProcessInputCharByChar(input.substr(0, 9));
- EXPECT_EQ(8u, ProcessInput(input.substr(9)));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-}
-
-TEST_F(HttpDecoderTest, CorruptPushPromiseFrame) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
-
- InSequence s;
-
- std::string input = absl::HexStringToBytes(
- "05" // type (PUSH_PROMISE)
- "01" // length
- "40"); // first byte of two-byte varint push id
-
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- decoder.ProcessInput(input.data(), input.size());
-
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("Unable to read PUSH_PROMISE push_id.", decoder.error_detail());
- }
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- for (auto c : input) {
- decoder.ProcessInput(&c, 1);
- }
+ absl::StrCat(absl::HexStringToBytes("05" // type (PUSH PROMISE)
+ "08" // length
+ "1f"), // push id 31
+ "Headers"); // headers
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("Unable to read PUSH_PROMISE push_id.", decoder.error_detail());
- }
+ EXPECT_CALL(visitor_, OnError(&decoder_));
+ EXPECT_EQ(1u, ProcessInput(input));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ("PUSH_PROMISE frame received.", decoder_.error_detail());
}
TEST_F(HttpDecoderTest, MaxPushId) {
@@ -564,10 +418,8 @@ TEST_F(HttpDecoderTest, FrameHeaderPartialDelivery) {
InSequence s;
// A large input that will occupy more than 1 byte in the length field.
std::string input(2048, 'x');
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(input.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ input.length(), SimpleBufferAllocator::Get());
// Partially send only 1 byte of the header to process.
EXPECT_EQ(1u, decoder_.ProcessInput(header.data(), 1));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
@@ -575,8 +427,8 @@ TEST_F(HttpDecoderTest, FrameHeaderPartialDelivery) {
// Send the rest of the header.
EXPECT_CALL(visitor_, OnDataFrameStart(3, input.length()));
- EXPECT_EQ(header_length - 1,
- decoder_.ProcessInput(header.data() + 1, header_length - 1));
+ EXPECT_EQ(header.size() - 1,
+ decoder_.ProcessInput(header.data() + 1, header.size() - 1));
EXPECT_THAT(decoder_.error(), IsQuicNoError());
EXPECT_EQ("", decoder_.error_detail());
@@ -751,55 +603,23 @@ TEST_F(HttpDecoderTest, EmptyHeadersFrame) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, PushPromiseFrameNoHeaders) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
-
- InSequence s;
+TEST_F(HttpDecoderTest, GoawayWithOverlyLargePayload) {
std::string input = absl::HexStringToBytes(
- "05" // type (PUSH_PROMISE)
- "01" // length
- "01"); // Push Id
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0))
- .WillOnce(Return(false));
- EXPECT_EQ(input.size(), ProcessInputWithGarbageAppended(input));
-
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd()).WillOnce(Return(false));
- EXPECT_EQ(0u, ProcessInputWithGarbageAppended(""));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0));
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnPushPromiseFrameStart(2));
- EXPECT_CALL(visitor_, OnPushPromiseFramePushId(1, 1, 0));
- EXPECT_CALL(visitor_, OnPushPromiseFrameEnd());
- ProcessInputCharByChar(input);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
+ "07" // type (GOAWAY)
+ "10"); // length exceeding the maximum possible length for GOAWAY frame
+ // Process all data at once.
+ EXPECT_CALL(visitor_, OnError(&decoder_));
+ EXPECT_EQ(2u, ProcessInput(input));
+ EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_TOO_LARGE));
+ EXPECT_EQ("Frame is too large.", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, MalformedFrameWithOverlyLargePayload) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
-
+TEST_F(HttpDecoderTest, MaxPushIdWithOverlyLargePayload) {
std::string input = absl::HexStringToBytes(
- "03" // type (CANCEL_PUSH)
- "10" // length
- "15"); // malformed payload
- // Process the full frame.
+ "0d" // type (MAX_PUSH_ID)
+ "10"); // length exceeding the maximum possible length for MAX_PUSH_ID
+ // frame
+ // Process all data at once.
EXPECT_CALL(visitor_, OnError(&decoder_));
EXPECT_EQ(2u, ProcessInput(input));
EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_TOO_LARGE));
@@ -868,193 +688,87 @@ TEST_F(HttpDecoderTest, HeadersPausedThenData) {
}
TEST_F(HttpDecoderTest, CorruptFrame) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- InSequence s;
-
- struct {
- const char* const input;
- const char* const error_message;
- } kTestData[] = {{"\x0D" // type (MAX_PUSH_ID)
- "\x01" // length
- "\x40", // first byte of two-byte varint push id
- "Unable to read MAX_PUSH_ID push_id."},
- {"\x0D" // type (MAX_PUSH_ID)
- "\x04" // length
- "\x05" // valid push id
- "foo", // superfluous data
- "Superfluous data in MAX_PUSH_ID frame."},
- {"\x07" // type (GOAWAY)
- "\x01" // length
- "\x40", // first byte of two-byte varint stream id
- "Unable to read GOAWAY ID."},
- {"\x07" // type (GOAWAY)
- "\x04" // length
- "\x05" // valid stream id
- "foo", // superfluous data
- "Superfluous data in GOAWAY frame."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x40", // first byte of two-byte varint origin length
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x05", // valid origin length but no origin string
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x05" // valid origin length
- "foo", // payload ends before origin ends
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x03" // valid origin length
- "foo", // payload ends at end of origin: no value
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x05" // length
- "\x03" // valid origin length
- "foo" // payload ends at end of origin: no value
- "\x40", // first byte of two-byte varint value length
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x08" // length
- "\x03" // valid origin length
- "foo" // origin
- "\x05" // valid value length
- "bar", // payload ends before value ends
- "Unable to read ACCEPT_CH value."}};
-
- for (const auto& test_data : kTestData) {
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- decoder.ProcessInput(input.data(), input.size());
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
- }
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- for (auto c : input) {
- decoder.ProcessInput(&c, 1);
- }
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
- }
+ InSequence s;
+
+ struct {
+ const char* const input;
+ const char* const error_message;
+ } kTestData[] = {{"\x0D" // type (MAX_PUSH_ID)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint push id
+ "Unable to read MAX_PUSH_ID push_id."},
+ {"\x0D" // type (MAX_PUSH_ID)
+ "\x04" // length
+ "\x05" // valid push id
+ "foo", // superfluous data
+ "Superfluous data in MAX_PUSH_ID frame."},
+ {"\x07" // type (GOAWAY)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint stream id
+ "Unable to read GOAWAY ID."},
+ {"\x07" // type (GOAWAY)
+ "\x04" // length
+ "\x05" // valid stream id
+ "foo", // superfluous data
+ "Superfluous data in GOAWAY frame."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x40", // first byte of two-byte varint origin length
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x01" // length
+ "\x05", // valid origin length but no origin string
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x05" // valid origin length
+ "foo", // payload ends before origin ends
+ "Unable to read ACCEPT_CH origin."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x04" // length
+ "\x03" // valid origin length
+ "foo", // payload ends at end of origin: no value
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x05" // length
+ "\x03" // valid origin length
+ "foo" // payload ends at end of origin: no value
+ "\x40", // first byte of two-byte varint value length
+ "Unable to read ACCEPT_CH value."},
+ {"\x40\x89" // type (ACCEPT_CH)
+ "\x08" // length
+ "\x03" // valid origin length
+ "foo" // origin
+ "\x05" // valid value length
+ "bar", // payload ends before value ends
+ "Unable to read ACCEPT_CH value."}};
+
+ for (const auto& test_data : kTestData) {
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ decoder.ProcessInput(input.data(), input.size());
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
- } else {
- InSequence s;
-
- struct {
- const char* const input;
- const char* const error_message;
- } kTestData[] = {{"\x03" // type (CANCEL_PUSH)
- "\x01" // length
- "\x40", // first byte of two-byte varint push id
- "Unable to read CANCEL_PUSH push_id."},
- {"\x03" // type (CANCEL_PUSH)
- "\x04" // length
- "\x05" // valid push id
- "foo", // superfluous data
- "Superfluous data in CANCEL_PUSH frame."},
- {"\x0D" // type (MAX_PUSH_ID)
- "\x01" // length
- "\x40", // first byte of two-byte varint push id
- "Unable to read MAX_PUSH_ID push_id."},
- {"\x0D" // type (MAX_PUSH_ID)
- "\x04" // length
- "\x05" // valid push id
- "foo", // superfluous data
- "Superfluous data in MAX_PUSH_ID frame."},
- {"\x07" // type (GOAWAY)
- "\x01" // length
- "\x40", // first byte of two-byte varint stream id
- "Unable to read GOAWAY ID."},
- {"\x07" // type (GOAWAY)
- "\x04" // length
- "\x05" // valid stream id
- "foo", // superfluous data
- "Superfluous data in GOAWAY frame."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x40", // first byte of two-byte varint origin length
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x01" // length
- "\x05", // valid origin length but no origin string
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x05" // valid origin length
- "foo", // payload ends before origin ends
- "Unable to read ACCEPT_CH origin."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x04" // length
- "\x03" // valid origin length
- "foo", // payload ends at end of origin: no value
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x05" // length
- "\x03" // valid origin length
- "foo" // payload ends at end of origin: no value
- "\x40", // first byte of two-byte varint value length
- "Unable to read ACCEPT_CH value."},
- {"\x40\x89" // type (ACCEPT_CH)
- "\x08" // length
- "\x03" // valid origin length
- "foo" // origin
- "\x05" // valid value length
- "bar", // payload ends before value ends
- "Unable to read ACCEPT_CH value."}};
-
- for (const auto& test_data : kTestData) {
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- decoder.ProcessInput(input.data(), input.size());
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
- }
- {
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- absl::string_view input(test_data.input);
- for (auto c : input) {
- decoder.ProcessInput(&c, 1);
- }
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
+ {
+ HttpDecoder decoder(&visitor_);
+ EXPECT_CALL(visitor_, OnAcceptChFrameStart(_)).Times(AnyNumber());
+ EXPECT_CALL(visitor_, OnError(&decoder));
+
+ absl::string_view input(test_data.input);
+ for (auto c : input) {
+ decoder.ProcessInput(&c, 1);
}
+ EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
+ EXPECT_EQ(test_data.error_message, decoder.error_detail());
}
}
}
-TEST_F(HttpDecoderTest, EmptyCancelPushFrame) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
-
- std::string input = absl::HexStringToBytes(
- "03" // type (CANCEL_PUSH)
- "00"); // frame length
-
- EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("Unable to read CANCEL_PUSH push_id.", decoder_.error_detail());
-}
-
TEST_F(HttpDecoderTest, EmptySettingsFrame) {
std::string input = absl::HexStringToBytes(
"04" // type (SETTINGS)
@@ -1070,22 +784,6 @@ TEST_F(HttpDecoderTest, EmptySettingsFrame) {
EXPECT_EQ("", decoder_.error_detail());
}
-// Regression test for https://crbug.com/1001823.
-TEST_F(HttpDecoderTest, EmptyPushPromiseFrame) {
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
-
- std::string input = absl::HexStringToBytes(
- "05" // type (PUSH_PROMISE)
- "00"); // frame length
-
- EXPECT_CALL(visitor_, OnError(&decoder_));
- EXPECT_EQ(input.size(), ProcessInput(input));
- EXPECT_THAT(decoder_.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ("PUSH_PROMISE frame with empty payload.", decoder_.error_detail());
-}
-
TEST_F(HttpDecoderTest, EmptyGoAwayFrame) {
std::string input = absl::HexStringToBytes(
"07" // type (GOAWAY)
@@ -1120,97 +818,8 @@ TEST_F(HttpDecoderTest, LargeStreamIdInGoAway) {
EXPECT_EQ("", decoder_.error_detail());
}
-TEST_F(HttpDecoderTest, OldPriorityUpdateFrame) {
- if (GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
- return;
- }
-
- InSequence s;
- std::string input1 = absl::HexStringToBytes(
- "0f" // type (PRIORITY_UPDATE)
- "02" // length
- "00" // prioritized element type: REQUEST_STREAM
- "03"); // prioritized element id
-
- PriorityUpdateFrame priority_update1;
- priority_update1.prioritized_element_type = REQUEST_STREAM;
- priority_update1.prioritized_element_id = 0x03;
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2)).WillOnce(Return(false));
- absl::string_view remaining_input(input1);
- QuicByteCount processed_bytes =
- ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(2u, processed_bytes);
- remaining_input = remaining_input.substr(processed_bytes);
-
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1))
- .WillOnce(Return(false));
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1));
- EXPECT_EQ(input1.size(), ProcessInput(input1));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update1));
- ProcessInputCharByChar(input1);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- std::string input2 = absl::HexStringToBytes(
- "0f" // type (PRIORITY_UPDATE)
- "05" // length
- "80" // prioritized element type: PUSH_STREAM
- "05" // prioritized element id
- "666f6f"); // priority field value: "foo"
-
- PriorityUpdateFrame priority_update2;
- priority_update2.prioritized_element_type = PUSH_STREAM;
- priority_update2.prioritized_element_id = 0x05;
- priority_update2.priority_field_value = "foo";
-
- // Visitor pauses processing.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2)).WillOnce(Return(false));
- remaining_input = input2;
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(2u, processed_bytes);
- remaining_input = remaining_input.substr(processed_bytes);
-
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2))
- .WillOnce(Return(false));
- processed_bytes = ProcessInputWithGarbageAppended(remaining_input);
- EXPECT_EQ(remaining_input.size(), processed_bytes);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the full frame.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2));
- EXPECT_EQ(input2.size(), ProcessInput(input2));
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-
- // Process the frame incrementally.
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(2));
- EXPECT_CALL(visitor_, OnPriorityUpdateFrame(priority_update2));
- ProcessInputCharByChar(input2);
- EXPECT_THAT(decoder_.error(), IsQuicNoError());
- EXPECT_EQ("", decoder_.error_detail());
-}
-
+// Old PRIORITY_UPDATE frame is parsed as unknown frame.
TEST_F(HttpDecoderTest, ObsoletePriorityUpdateFrame) {
- if (!GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
- return;
- }
-
const QuicByteCount header_length = 2;
const QuicByteCount payload_length = 3;
InSequence s;
@@ -1324,46 +933,6 @@ TEST_F(HttpDecoderTest, PriorityUpdateFrame) {
}
TEST_F(HttpDecoderTest, CorruptPriorityUpdateFrame) {
- if (GetQuicReloadableFlag(quic_ignore_old_priority_update_frame)) {
- return;
- }
-
- std::string payload1 = absl::HexStringToBytes(
- "80" // prioritized element type: PUSH_STREAM
- "4005"); // prioritized element id
- std::string payload2 =
- absl::HexStringToBytes("42"); // invalid prioritized element type
- struct {
- const char* const payload;
- size_t payload_length;
- const char* const error_message;
- } kTestData[] = {
- {payload1.data(), 0, "Unable to read prioritized element type."},
- {payload1.data(), 1, "Unable to read prioritized element id."},
- {payload1.data(), 2, "Unable to read prioritized element id."},
- {payload2.data(), 1, "Invalid prioritized element type."},
- };
-
- for (const auto& test_data : kTestData) {
- std::string input;
- input.push_back(15u); // type PRIORITY_UPDATE
- input.push_back(test_data.payload_length);
- size_t header_length = input.size();
- input.append(test_data.payload, test_data.payload_length);
-
- HttpDecoder decoder(&visitor_);
- EXPECT_CALL(visitor_, OnPriorityUpdateFrameStart(header_length));
- EXPECT_CALL(visitor_, OnError(&decoder));
-
- QuicByteCount processed_bytes =
- decoder.ProcessInput(input.data(), input.size());
- EXPECT_EQ(input.size(), processed_bytes);
- EXPECT_THAT(decoder.error(), IsError(QUIC_HTTP_FRAME_ERROR));
- EXPECT_EQ(test_data.error_message, decoder.error_detail());
- }
-}
-
-TEST_F(HttpDecoderTest, CorruptNewPriorityUpdateFrame) {
std::string payload =
absl::HexStringToBytes("4005"); // prioritized element id
struct {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
index 2fbc2380cf7..25f6200e59b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.cc
@@ -34,23 +34,30 @@ QuicByteCount GetTotalLength(QuicByteCount payload_length, HttpFrameType type) {
} // namespace
// static
-QuicByteCount HttpEncoder::SerializeDataFrameHeader(
+QuicByteCount HttpEncoder::GetDataFrameHeaderLength(
+ QuicByteCount payload_length) {
+ QUICHE_DCHECK_NE(0u, payload_length);
+ return QuicDataWriter::GetVarInt62Len(payload_length) +
+ QuicDataWriter::GetVarInt62Len(
+ static_cast<uint64_t>(HttpFrameType::DATA));
+}
+
+// static
+QuicBuffer HttpEncoder::SerializeDataFrameHeader(
QuicByteCount payload_length,
- std::unique_ptr<char[]>* output) {
+ QuicBufferAllocator* allocator) {
QUICHE_DCHECK_NE(0u, payload_length);
- QuicByteCount header_length = QuicDataWriter::GetVarInt62Len(payload_length) +
- QuicDataWriter::GetVarInt62Len(
- static_cast<uint64_t>(HttpFrameType::DATA));
+ QuicByteCount header_length = GetDataFrameHeaderLength(payload_length);
- output->reset(new char[header_length]);
- QuicDataWriter writer(header_length, output->get());
+ QuicBuffer header(allocator, header_length);
+ QuicDataWriter writer(header.size(), header.data());
if (WriteFrameHeader(payload_length, HttpFrameType::DATA, &writer)) {
- return header_length;
+ return header;
}
QUIC_DLOG(ERROR)
<< "Http encoder failed when attempting to serialize data frame header.";
- return 0;
+ return QuicBuffer();
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
index 0a8aa84e0b7..585e739ef53 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder.h
@@ -7,6 +7,7 @@
#include <memory>
#include "quic/core/http/http_frames.h"
+#include "quic/core/quic_buffer_allocator.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_types.h"
#include "quic/platform/api/quic_export.h"
@@ -21,11 +22,13 @@ class QUIC_EXPORT_PRIVATE HttpEncoder {
public:
HttpEncoder() = delete;
- // Serializes a DATA frame header into a new buffer stored in |output|.
- // Returns the length of the buffer on success, or 0 otherwise.
- static QuicByteCount SerializeDataFrameHeader(
- QuicByteCount payload_length,
- std::unique_ptr<char[]>* output);
+ // Returns the length of the header for a DATA frame.
+ static QuicByteCount GetDataFrameHeaderLength(QuicByteCount payload_length);
+
+ // Serializes a DATA frame header into a QuicBuffer; returns said QuicBuffer
+ // on success, empty buffer otherwise.
+ static QuicBuffer SerializeDataFrameHeader(QuicByteCount payload_length,
+ QuicBufferAllocator* allocator);
// Serializes a HEADERS frame header into a new buffer stored in |output|.
// Returns the length of the buffer on success, or 0 otherwise.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
index 66e988facca..c2b0f36946e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_encoder_test.cc
@@ -5,6 +5,7 @@
#include "quic/core/http/http_encoder.h"
#include "absl/base/macros.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -14,16 +15,15 @@ namespace quic {
namespace test {
TEST(HttpEncoderTest, SerializeDataFrameHeader) {
- std::unique_ptr<char[]> buffer;
- uint64_t length =
- HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 5, &buffer);
+ QuicBuffer buffer = HttpEncoder::SerializeDataFrameHeader(
+ /* payload_length = */ 5, SimpleBufferAllocator::Get());
char output[] = {// type (DATA)
0x00,
// length
0x05};
- EXPECT_EQ(ABSL_ARRAYSIZE(output), length);
- quiche::test::CompareCharArraysWithHexError("DATA", buffer.get(), length,
- output, ABSL_ARRAYSIZE(output));
+ EXPECT_EQ(ABSL_ARRAYSIZE(output), buffer.size());
+ quiche::test::CompareCharArraysWithHexError(
+ "DATA", buffer.data(), buffer.size(), output, ABSL_ARRAYSIZE(output));
}
TEST(HttpEncoderTest, SerializeHeadersFrameHeader) {
@@ -87,40 +87,42 @@ TEST(HttpEncoderTest, SerializePriorityUpdateFrame) {
PriorityUpdateFrame priority_update1;
priority_update1.prioritized_element_type = REQUEST_STREAM;
priority_update1.prioritized_element_id = 0x03;
- char output1[] = {0x80, 0x0f, 0x07, 0x00, // type (PRIORITY_UPDATE)
- 0x01, // length
- 0x03}; // prioritized element id
+ uint8_t output1[] = {0x80, 0x0f, 0x07, 0x00, // type (PRIORITY_UPDATE)
+ 0x01, // length
+ 0x03}; // prioritized element id
std::unique_ptr<char[]> buffer;
uint64_t length =
HttpEncoder::SerializePriorityUpdateFrame(priority_update1, &buffer);
EXPECT_EQ(ABSL_ARRAYSIZE(output1), length);
- quiche::test::CompareCharArraysWithHexError("PRIORITY_UPDATE", buffer.get(),
- length, output1,
- ABSL_ARRAYSIZE(output1));
+ quiche::test::CompareCharArraysWithHexError(
+ "PRIORITY_UPDATE", buffer.get(), length, reinterpret_cast<char*>(output1),
+ ABSL_ARRAYSIZE(output1));
}
TEST(HttpEncoderTest, SerializeAcceptChFrame) {
AcceptChFrame accept_ch;
- char output1[] = {0x40, 0x89, // type (ACCEPT_CH)
- 0x00}; // length
+ uint8_t output1[] = {0x40, 0x89, // type (ACCEPT_CH)
+ 0x00}; // length
std::unique_ptr<char[]> buffer;
uint64_t length = HttpEncoder::SerializeAcceptChFrame(accept_ch, &buffer);
EXPECT_EQ(ABSL_ARRAYSIZE(output1), length);
quiche::test::CompareCharArraysWithHexError("ACCEPT_CH", buffer.get(), length,
- output1, ABSL_ARRAYSIZE(output1));
+ reinterpret_cast<char*>(output1),
+ ABSL_ARRAYSIZE(output1));
accept_ch.entries.push_back({"foo", "bar"});
- char output2[] = {0x40, 0x89, // type (ACCEPT_CH)
- 0x08, // payload length
- 0x03, 0x66, 0x6f, 0x6f, // length of "foo"; "foo"
- 0x03, 0x62, 0x61, 0x72}; // length of "bar"; "bar"
+ uint8_t output2[] = {0x40, 0x89, // type (ACCEPT_CH)
+ 0x08, // payload length
+ 0x03, 0x66, 0x6f, 0x6f, // length of "foo"; "foo"
+ 0x03, 0x62, 0x61, 0x72}; // length of "bar"; "bar"
length = HttpEncoder::SerializeAcceptChFrame(accept_ch, &buffer);
EXPECT_EQ(ABSL_ARRAYSIZE(output2), length);
quiche::test::CompareCharArraysWithHexError("ACCEPT_CH", buffer.get(), length,
- output2, ABSL_ARRAYSIZE(output2));
+ reinterpret_cast<char*>(output2),
+ ABSL_ARRAYSIZE(output2));
}
TEST(HttpEncoderTest, SerializeWebTransportStreamFrameHeader) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h b/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
index b14ebe5a91b..6a00ad7bb53 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_frames.h
@@ -20,6 +20,9 @@
namespace quic {
+// TODO(b/171463363): Remove.
+using PushId = uint64_t;
+
enum class HttpFrameType {
DATA = 0x0,
HEADERS = 0x1,
@@ -28,12 +31,9 @@ enum class HttpFrameType {
PUSH_PROMISE = 0x5,
GOAWAY = 0x7,
MAX_PUSH_ID = 0xD,
- // https://tools.ietf.org/html/draft-ietf-httpbis-priority-01
- // TODO(b/147306124): Remove.
- PRIORITY_UPDATE = 0XF,
// https://tools.ietf.org/html/draft-davidben-http-client-hint-reliability-02
ACCEPT_CH = 0x89,
- // https://tools.ietf.org/html/draft-ietf-httpbis-priority-02
+ // https://tools.ietf.org/html/draft-ietf-httpbis-priority-03
PRIORITY_UPDATE_REQUEST_STREAM = 0xF0700,
// https://www.ietf.org/archive/id/draft-ietf-webtrans-http3-00.html
WEBTRANSPORT_STREAM = 0x41,
@@ -55,20 +55,6 @@ struct QUIC_EXPORT_PRIVATE HeadersFrame {
absl::string_view headers;
};
-// 7.2.3. CANCEL_PUSH
-//
-// The CANCEL_PUSH frame (type=0x3) is used to request cancellation of
-// server push prior to the push stream being created.
-using PushId = uint64_t;
-
-struct QUIC_EXPORT_PRIVATE CancelPushFrame {
- PushId push_id;
-
- bool operator==(const CancelPushFrame& rhs) const {
- return push_id == rhs.push_id;
- }
-};
-
// 7.2.4. SETTINGS
//
// The SETTINGS frame (type=0x4) conveys configuration parameters that
@@ -102,20 +88,6 @@ struct QUIC_EXPORT_PRIVATE SettingsFrame {
}
};
-// 7.2.5. PUSH_PROMISE
-//
-// The PUSH_PROMISE frame (type=0x05) is used to carry a request header
-// set from server to client, as in HTTP/2.
-// TODO(b/171463363): Remove.
-struct QUIC_EXPORT_PRIVATE PushPromiseFrame {
- PushId push_id;
- absl::string_view headers;
-
- bool operator==(const PushPromiseFrame& rhs) const {
- return push_id == rhs.push_id && headers == rhs.headers;
- }
-};
-
// 7.2.6. GOAWAY
//
// The GOAWAY frame (type=0x7) is used to initiate shutdown of a connection by
@@ -144,10 +116,9 @@ struct QUIC_EXPORT_PRIVATE MaxPushIdFrame {
// https://httpwg.org/http-extensions/draft-ietf-httpbis-priority.html
//
// The PRIORITY_UPDATE frame specifies the sender-advised priority of a stream.
-// https://tools.ietf.org/html/draft-ietf-httpbis-priority-01 uses frame type
-// 0x0f, both for request streams and push streams.
-// https://tools.ietf.org/html/draft-ietf-httpbis-priority-02 uses frame types
-// 0xf0700 for request streams and 0xf0701 for push streams (not implemented).
+// Frame type 0xf0700 (called PRIORITY_UPDATE_REQUEST_STREAM in the
+// implementation) is used for for request streams.
+// Frame type 0xf0701 is used for push streams and is not implemented.
// Length of a priority frame's first byte.
const QuicByteCount kPriorityFirstByteLength = 1;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/http_frames_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/http_frames_test.cc
index c9a285dc8d9..24fd5780af8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/http_frames_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/http_frames_test.cc
@@ -12,17 +12,6 @@
namespace quic {
namespace test {
-TEST(HttpFramesTest, CancelPushFrame) {
- CancelPushFrame a{1};
- EXPECT_TRUE(a == a);
-
- CancelPushFrame b{1};
- EXPECT_TRUE(a == b);
-
- b.push_id = 2;
- EXPECT_FALSE(a == b);
-}
-
TEST(HttpFramesTest, SettingsFrame) {
SettingsFrame a;
EXPECT_TRUE(a == a);
@@ -44,21 +33,6 @@ TEST(HttpFramesTest, SettingsFrame) {
EXPECT_EQ("SETTINGS_QPACK_MAX_TABLE_CAPACITY = 1; ", s.str());
}
-TEST(HttpFramesTest, PushPromiseFrame) {
- PushPromiseFrame a{1, ""};
- EXPECT_TRUE(a == a);
-
- PushPromiseFrame b{2, ""};
- EXPECT_FALSE(a == b);
-
- b.push_id = 1;
- EXPECT_TRUE(a == b);
-
- b.headers = "foo";
- EXPECT_FALSE(a == b);
- EXPECT_TRUE(b == b);
-}
-
TEST(HttpFramesTest, GoAwayFrame) {
GoAwayFrame a{1};
EXPECT_TRUE(a == a);
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
index 36011804056..1c951ba108b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_client_promised_info.cc
@@ -24,7 +24,11 @@ QuicClientPromisedInfo::QuicClientPromisedInfo(
url_(std::move(url)),
client_request_delegate_(nullptr) {}
-QuicClientPromisedInfo::~QuicClientPromisedInfo() {}
+QuicClientPromisedInfo::~QuicClientPromisedInfo() {
+ if (cleanup_alarm_ != nullptr) {
+ cleanup_alarm_->PermanentCancel();
+ }
+}
void QuicClientPromisedInfo::CleanupAlarm::OnAlarm() {
QUIC_DVLOG(1) << "self GC alarm for stream " << promised_->id_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
index 39d8b42a5a2..9c164d0e448 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.cc
@@ -65,14 +65,6 @@ void QuicReceiveControlStream::OnError(HttpDecoder* decoder) {
stream_delegate()->OnStreamError(decoder->error(), decoder->error_detail());
}
-bool QuicReceiveControlStream::OnCancelPushFrame(const CancelPushFrame& frame) {
- if (spdy_session()->debug_visitor()) {
- spdy_session()->debug_visitor()->OnCancelPushFrameReceived(frame);
- }
-
- return ValidateFrameType(HttpFrameType::CANCEL_PUSH);
-}
-
bool QuicReceiveControlStream::OnMaxPushIdFrame(const MaxPushIdFrame& frame) {
if (spdy_session()->debug_visitor()) {
spdy_session()->debug_visitor()->OnMaxPushIdFrameReceived(frame);
@@ -144,33 +136,9 @@ bool QuicReceiveControlStream::OnHeadersFrameEnd() {
return false;
}
-bool QuicReceiveControlStream::OnPushPromiseFrameStart(
- QuicByteCount /*header_length*/) {
- return ValidateFrameType(HttpFrameType::PUSH_PROMISE);
-}
-
-bool QuicReceiveControlStream::OnPushPromiseFramePushId(
- PushId /*push_id*/,
- QuicByteCount /*push_id_length*/,
- QuicByteCount /*header_block_length*/) {
- QUICHE_NOTREACHED();
- return false;
-}
-
-bool QuicReceiveControlStream::OnPushPromiseFramePayload(
- absl::string_view /*payload*/) {
- QUICHE_NOTREACHED();
- return false;
-}
-
-bool QuicReceiveControlStream::OnPushPromiseFrameEnd() {
- QUICHE_NOTREACHED();
- return false;
-}
-
bool QuicReceiveControlStream::OnPriorityUpdateFrameStart(
QuicByteCount /*header_length*/) {
- return ValidateFrameType(HttpFrameType::PRIORITY_UPDATE);
+ return ValidateFrameType(HttpFrameType::PRIORITY_UPDATE_REQUEST_STREAM);
}
bool QuicReceiveControlStream::OnPriorityUpdateFrame(
@@ -264,9 +232,8 @@ bool QuicReceiveControlStream::OnUnknownFrameEnd() {
bool QuicReceiveControlStream::ValidateFrameType(HttpFrameType frame_type) {
// Certain frame types are forbidden.
- if ((frame_type == HttpFrameType::DATA ||
- frame_type == HttpFrameType::HEADERS ||
- frame_type == HttpFrameType::PUSH_PROMISE) ||
+ if (frame_type == HttpFrameType::DATA ||
+ frame_type == HttpFrameType::HEADERS ||
(spdy_session()->perspective() == Perspective::IS_CLIENT &&
frame_type == HttpFrameType::MAX_PUSH_ID) ||
(spdy_session()->perspective() == Perspective::IS_SERVER &&
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
index 4ed01043662..3c61d3cb621 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream.h
@@ -33,9 +33,8 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream
// Implementation of QuicStream.
void OnDataAvailable() override;
- // HttpDecoderVisitor implementation.
+ // HttpDecoder::Visitor implementation.
void OnError(HttpDecoder* decoder) override;
- bool OnCancelPushFrame(const CancelPushFrame& frame) override;
bool OnMaxPushIdFrame(const MaxPushIdFrame& frame) override;
bool OnGoAwayFrame(const GoAwayFrame& frame) override;
bool OnSettingsFrameStart(QuicByteCount header_length) override;
@@ -48,12 +47,6 @@ class QUIC_EXPORT_PRIVATE QuicReceiveControlStream
QuicByteCount payload_length) override;
bool OnHeadersFramePayload(absl::string_view payload) override;
bool OnHeadersFrameEnd() override;
- bool OnPushPromiseFrameStart(QuicByteCount header_length) override;
- bool OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length) override;
- bool OnPushPromiseFramePayload(absl::string_view payload) override;
- bool OnPushPromiseFrameEnd() override;
bool OnPriorityUpdateFrameStart(QuicByteCount header_length) override;
bool OnPriorityUpdateFrame(const PriorityUpdateFrame& frame) override;
bool OnAcceptChFrameStart(QuicByteCount header_length) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
index 03f21d8a70f..ae7a0d818cc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_receive_control_stream_test.cc
@@ -9,6 +9,7 @@
#include "absl/strings/string_view.h"
#include "quic/core/http/http_constants.h"
#include "quic/core/qpack/qpack_header_table.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
@@ -239,12 +240,11 @@ TEST_P(QuicReceiveControlStreamTest, ReceiveSettingsFragments) {
TEST_P(QuicReceiveControlStreamTest, ReceiveWrongFrame) {
// DATA frame header without payload.
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(/* payload_length = */ 2, &buffer);
- std::string data = std::string(buffer.get(), header_length);
+ QuicBuffer data = HttpEncoder::SerializeDataFrameHeader(
+ /* payload_length = */ 2, SimpleBufferAllocator::Get());
- QuicStreamFrame frame(receive_control_stream_->id(), false, 1, data);
+ QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
+ data.AsStringView());
EXPECT_CALL(
*connection_,
CloseConnection(QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM, _, _));
@@ -260,7 +260,7 @@ TEST_P(QuicReceiveControlStreamTest,
EXPECT_CALL(*connection_,
CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
"First frame received on control stream is type "
- "15, but it must be SETTINGS.",
+ "984832, but it must be SETTINGS.",
_))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
@@ -308,12 +308,7 @@ TEST_P(QuicReceiveControlStreamTest, PushPromiseOnControlStreamShouldClose) {
"00"); // push ID
QuicStreamFrame frame(receive_control_stream_->id(), false, 1,
push_promise_frame);
- EXPECT_CALL(
- *connection_,
- CloseConnection(GetQuicReloadableFlag(quic_error_on_http3_push)
- ? QUIC_HTTP_FRAME_ERROR
- : QUIC_HTTP_FRAME_UNEXPECTED_ON_CONTROL_STREAM,
- _, _))
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR, _, _))
.WillOnce(
Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
@@ -384,21 +379,10 @@ TEST_P(QuicReceiveControlStreamTest, CancelPushFrameBeforeSettings) {
"01" // payload length
"01"); // push ID
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
- "CANCEL_PUSH frame received.", _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- } else {
- EXPECT_CALL(
- *connection_,
- CloseConnection(QUIC_HTTP_MISSING_SETTINGS_FRAME,
- "First frame received on control stream is type "
- "3, but it must be SETTINGS.",
- _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- }
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
EXPECT_CALL(*connection_, SendConnectionClosePacket(_, _, _));
EXPECT_CALL(session_, OnConnectionClosed(_, _));
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
index c5af1dc4a90..3066cb38871 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_send_control_stream_test.cc
@@ -133,7 +133,7 @@ TEST_P(QuicSendControlStreamTest, WriteSettings) {
"4040" // 0x40 as the reserved frame type
"01" // 1 byte frame length
"61"); // payload "a"
- if (GetQuicReloadableFlag(quic_h3_datagram)) {
+ if (QuicSpdySessionPeer::ShouldNegotiateHttp3Datagram(&session_)) {
expected_write_data = absl::HexStringToBytes(
"00" // stream type: control stream
"04" // frame type: SETTINGS frame
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
index c78df58e18a..69d6cb47a9d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.cc
@@ -282,4 +282,23 @@ void QuicServerSessionBase::SendSettingsToCryptoStream() {
std::move(serialized_settings));
}
+QuicSSLConfig QuicServerSessionBase::GetSSLConfig() const {
+ QUICHE_DCHECK(crypto_config_ && crypto_config_->proof_source());
+
+ QuicSSLConfig ssl_config = QuicSpdySession::GetSSLConfig();
+ if (!GetQuicReloadableFlag(quic_tls_set_signature_algorithm_prefs) ||
+ !crypto_config_ || !crypto_config_->proof_source()) {
+ return ssl_config;
+ }
+
+ absl::InlinedVector<uint16_t, 8> signature_algorithms =
+ crypto_config_->proof_source()->SupportedTlsSignatureAlgorithms();
+ if (!signature_algorithms.empty()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_set_signature_algorithm_prefs, 1, 2);
+ ssl_config.signing_algorithm_prefs = std::move(signature_algorithms);
+ }
+
+ return ssl_config;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
index 9bdaa30adf9..bd9f5e71f42 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_server_session_base.h
@@ -68,6 +68,8 @@ class QUIC_EXPORT_PRIVATE QuicServerSessionBase : public QuicSpdySession {
serving_region_ = serving_region;
}
+ QuicSSLConfig GetSSLConfig() const override;
+
protected:
// QuicSession methods(override them with return type of QuicSpdyStream*):
QuicCryptoServerStreamBase* GetMutableCryptoStream() override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
index b71cba9958f..45bdd1d31b1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.cc
@@ -126,6 +126,10 @@ int QuicSpdyClientSession::GetNumSentClientHellos() const {
return crypto_stream_->num_sent_client_hellos();
}
+bool QuicSpdyClientSession::IsResumption() const {
+ return crypto_stream_->IsResumption();
+}
+
bool QuicSpdyClientSession::EarlyDataAccepted() const {
return crypto_stream_->EarlyDataAccepted();
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
index 88df049e06d..a1c0883b8ad 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_session.h
@@ -61,6 +61,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdyClientSession
// than the number of round-trips needed for the handshake.
int GetNumSentClientHellos() const;
+ // Return true if the handshake performed is a TLS resumption.
+ // Always return false for QUIC Crypto.
+ bool IsResumption() const;
+
// Returns true if early data (0-RTT data) was sent and the server accepted
// it.
bool EarlyDataAccepted() const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
index fa4943dcda7..9043d0b0e71 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_client_stream_test.cc
@@ -12,6 +12,7 @@
#include "quic/core/crypto/null_encrypter.h"
#include "quic/core/http/quic_spdy_client_session.h"
#include "quic/core/http/spdy_utils.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_socket_address.h"
@@ -131,12 +132,10 @@ TEST_P(QuicSpdyClientStreamTest, TestFraming) {
auto headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
std::string data = VersionUsesHttp3(connection_->transport_version())
- ? header + body_
+ ? absl::StrCat(header.AsStringView(), body_)
: body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
@@ -160,12 +159,11 @@ TEST_P(QuicSpdyClientStreamTest, Test100ContinueBeforeSuccessful) {
headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data =
- connection_->version().UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data = VersionUsesHttp3(connection_->transport_version())
+ ? absl::StrCat(header.AsStringView(), body_)
+ : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
// Make sure the 200 response got parsed correctly.
@@ -190,12 +188,11 @@ TEST_P(QuicSpdyClientStreamTest, TestUnknownInformationalBeforeSuccessful) {
headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data =
- connection_->version().UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data = VersionUsesHttp3(connection_->transport_version())
+ ? absl::StrCat(header.AsStringView(), body_)
+ : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
// Make sure the 200 response got parsed correctly.
@@ -222,12 +219,10 @@ TEST_P(QuicSpdyClientStreamTest, TestFramingOnePacket) {
auto headers = AsHeaderList(headers_);
stream_->OnStreamHeaderList(false, headers.uncompressed_header_bytes(),
headers);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
std::string data = VersionUsesHttp3(connection_->transport_version())
- ? header + body_
+ ? absl::StrCat(header.AsStringView(), body_)
: body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
@@ -247,12 +242,10 @@ TEST_P(QuicSpdyClientStreamTest,
EXPECT_THAT(stream_->stream_error(), IsQuicStreamNoError());
EXPECT_EQ("200", stream_->response_headers().find(":status")->second);
EXPECT_EQ(200, stream_->response_code());
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ large_body.length(), SimpleBufferAllocator::Get());
std::string data = VersionUsesHttp3(connection_->transport_version())
- ? header + large_body
+ ? absl::StrCat(header.AsStringView(), large_body)
: large_body;
EXPECT_CALL(session_, WriteControlFrame(_, _));
EXPECT_CALL(*connection_,
@@ -290,12 +283,10 @@ TEST_P(QuicSpdyClientStreamTest, ReceivingTrailers) {
// Now send the body, which should close the stream as the FIN has been
// received, as well as all data.
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
std::string data = VersionUsesHttp3(connection_->transport_version())
- ? header + body_
+ ? absl::StrCat(header.AsStringView(), body_)
: body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
index 276a7aff6b6..56b0db3ff48 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.cc
@@ -72,10 +72,6 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor {
// HttpDecoder::Visitor implementation.
void OnError(HttpDecoder* /*decoder*/) override {}
- bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
- error_detail_ = "CANCEL_PUSH frame forbidden";
- return false;
- }
bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override {
error_detail_ = "MAX_PUSH_ID frame forbidden";
return false;
@@ -124,26 +120,6 @@ class AlpsFrameDecoder : public HttpDecoder::Visitor {
QUICHE_NOTREACHED();
return false;
}
- bool OnPushPromiseFrameStart(QuicByteCount /*header_length*/) override {
- error_detail_ = "PUSH_PROMISE frame forbidden";
- return false;
- }
- bool OnPushPromiseFramePushId(
- PushId /*push_id*/,
- QuicByteCount
- /*push_id_length*/,
- QuicByteCount /*header_block_length*/) override {
- QUICHE_NOTREACHED();
- return false;
- }
- bool OnPushPromiseFramePayload(absl::string_view /*payload*/) override {
- QUICHE_NOTREACHED();
- return false;
- }
- bool OnPushPromiseFrameEnd() override {
- QUICHE_NOTREACHED();
- return false;
- }
bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
error_detail_ = "PRIORITY_UPDATE frame forbidden";
return false;
@@ -461,14 +437,9 @@ Http3DebugVisitor::~Http3DebugVisitor() {}
// Expected unidirectional static streams Requirement can be found at
// https://tools.ietf.org/html/draft-ietf-quic-http-22#section-6.2.
QuicSpdySession::QuicSpdySession(
- QuicConnection* connection,
- QuicSession::Visitor* visitor,
- const QuicConfig& config,
- const ParsedQuicVersionVector& supported_versions)
- : QuicSession(connection,
- visitor,
- config,
- supported_versions,
+ QuicConnection* connection, QuicSession::Visitor* visitor,
+ const QuicConfig& config, const ParsedQuicVersionVector& supported_versions)
+ : QuicSession(connection, visitor, config, supported_versions,
/*num_expected_unidirectional_static_streams = */
VersionUsesHttp3(connection->transport_version())
? static_cast<QuicStreamCount>(
@@ -495,13 +466,13 @@ QuicSpdySession::QuicSpdySession(
spdy_framer_(SpdyFramer::ENABLE_COMPRESSION),
spdy_framer_visitor_(new SpdyFramerVisitor(this)),
debug_visitor_(nullptr),
- destruction_indicator_(123456789),
- next_available_datagram_flow_id_(perspective() == Perspective::IS_SERVER
- ? kFirstDatagramFlowIdServer
- : kFirstDatagramFlowIdClient) {
+ destruction_indicator_(123456789) {
h2_deframer_.set_visitor(spdy_framer_visitor_.get());
h2_deframer_.set_debug_visitor(spdy_framer_visitor_.get());
spdy_framer_.set_debug_visitor(spdy_framer_visitor_.get());
+ if (decline_server_push_stream_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_decline_server_push_stream);
+ }
}
QuicSpdySession::~QuicSpdySession() {
@@ -553,7 +524,6 @@ void QuicSpdySession::FillSettingsFrame() {
settings_.values[SETTINGS_MAX_FIELD_SECTION_SIZE] =
max_inbound_header_list_size_;
if (ShouldNegotiateHttp3Datagram() && version().UsesHttp3()) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_h3_datagram);
settings_.values[SETTINGS_H3_DATAGRAM] = 1;
}
if (WillNegotiateWebTransport()) {
@@ -1391,6 +1361,11 @@ QuicStream* QuicSpdySession::ProcessPendingStream(PendingStream* pending) {
return receive_control_stream_;
}
case kServerPushStream: { // Push Stream.
+ if (decline_server_push_stream_) {
+ CloseConnectionWithDetails(QUIC_HTTP_RECEIVE_SERVER_PUSH,
+ "Received server push stream");
+ return nullptr;
+ }
QuicSpdyStream* stream = CreateIncomingStream(pending);
return stream;
}
@@ -1645,53 +1620,55 @@ void QuicSpdySession::LogHeaderCompressionRatioHistogram(
}
}
-QuicDatagramFlowId QuicSpdySession::GetNextDatagramFlowId() {
- QuicDatagramFlowId result = next_available_datagram_flow_id_;
- next_available_datagram_flow_id_ += kDatagramFlowIdIncrement;
- return result;
-}
-
-MessageStatus QuicSpdySession::SendHttp3Datagram(QuicDatagramFlowId flow_id,
- absl::string_view payload) {
+MessageStatus QuicSpdySession::SendHttp3Datagram(
+ QuicDatagramStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload) {
size_t slice_length =
- QuicDataWriter::GetVarInt62Len(flow_id) + payload.length();
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
- connection()->helper()->GetStreamSendBufferAllocator(), slice_length);
- QuicDataWriter writer(slice_length, buffer.get());
- if (!writer.WriteVarInt62(flow_id)) {
- QUIC_BUG(quic_bug_10360_10) << "Failed to write HTTP/3 datagram flow ID";
+ QuicDataWriter::GetVarInt62Len(stream_id) + payload.length();
+ if (context_id.has_value()) {
+ slice_length += QuicDataWriter::GetVarInt62Len(context_id.value());
+ }
+ QuicBuffer buffer(connection()->helper()->GetStreamSendBufferAllocator(),
+ slice_length);
+ QuicDataWriter writer(slice_length, buffer.data());
+ if (!writer.WriteVarInt62(stream_id)) {
+ QUIC_BUG(h3 datagram stream ID write fail)
+ << "Failed to write HTTP/3 datagram stream ID";
return MESSAGE_STATUS_INTERNAL_ERROR;
}
+ if (context_id.has_value()) {
+ if (!writer.WriteVarInt62(context_id.value())) {
+ QUIC_BUG(h3 datagram context ID write fail)
+ << "Failed to write HTTP/3 datagram context ID";
+ return MESSAGE_STATUS_INTERNAL_ERROR;
+ }
+ }
if (!writer.WriteBytes(payload.data(), payload.length())) {
- QUIC_BUG(quic_bug_10360_11) << "Failed to write HTTP/3 datagram payload";
+ QUIC_BUG(h3 datagram payload write fail)
+ << "Failed to write HTTP/3 datagram payload";
return MESSAGE_STATUS_INTERNAL_ERROR;
}
- QuicMemSlice slice(std::move(buffer), slice_length);
+ QuicMemSlice slice(std::move(buffer));
return datagram_queue()->SendOrQueueDatagram(std::move(slice));
}
-void QuicSpdySession::RegisterHttp3FlowId(
- QuicDatagramFlowId flow_id,
- QuicSpdySession::Http3DatagramVisitor* visitor) {
- QUICHE_DCHECK_NE(visitor, nullptr);
- auto insertion_result = h3_datagram_registrations_.insert({flow_id, visitor});
- QUIC_BUG_IF(quic_bug_12477_7, !insertion_result.second)
- << "Attempted to doubly register HTTP/3 flow ID " << flow_id;
+void QuicSpdySession::SetMaxDatagramTimeInQueueForStreamId(
+ QuicStreamId /*stream_id*/, QuicTime::Delta max_time_in_queue) {
+ // TODO(b/184598230): implement this in a way that works for multiple sessions
+ // on a same connection.
+ datagram_queue()->SetMaxTimeInQueue(max_time_in_queue);
}
-void QuicSpdySession::UnregisterHttp3FlowId(QuicDatagramFlowId flow_id) {
- size_t num_erased = h3_datagram_registrations_.erase(flow_id);
- QUIC_BUG_IF(quic_bug_12477_8, num_erased != 1)
- << "Attempted to unregister unknown HTTP/3 flow ID " << flow_id;
+void QuicSpdySession::RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id,
+ QuicStreamId stream_id) {
+ h3_datagram_flow_id_to_stream_id_map_[flow_id] = stream_id;
}
-void QuicSpdySession::SetMaxTimeInQueueForFlowId(
- QuicDatagramFlowId /*flow_id*/,
- QuicTime::Delta max_time_in_queue) {
- // TODO(b/184598230): implement this in a way that works for multiple sessions
- // on a same connection.
- datagram_queue()->SetMaxTimeInQueue(max_time_in_queue);
+void QuicSpdySession::UnregisterHttp3DatagramFlowId(
+ QuicDatagramStreamId flow_id) {
+ h3_datagram_flow_id_to_stream_id_map_.erase(flow_id);
}
void QuicSpdySession::OnMessageReceived(absl::string_view message) {
@@ -1701,20 +1678,38 @@ void QuicSpdySession::OnMessageReceived(absl::string_view message) {
return;
}
QuicDataReader reader(message);
- QuicDatagramFlowId flow_id;
- if (!reader.ReadVarInt62(&flow_id)) {
- QUIC_DLOG(ERROR) << "Failed to parse flow ID in received HTTP/3 datagram";
+ uint64_t stream_id64;
+ if (!reader.ReadVarInt62(&stream_id64)) {
+ QUIC_DLOG(ERROR) << "Failed to parse stream ID in received HTTP/3 datagram";
return;
}
- auto it = h3_datagram_registrations_.find(flow_id);
- if (it == h3_datagram_registrations_.end()) {
- // TODO(dschinazi) buffer unknown HTTP/3 datagram flow IDs for a short
+ if (perspective() == Perspective::IS_SERVER) {
+ auto it = h3_datagram_flow_id_to_stream_id_map_.find(stream_id64);
+ if (it == h3_datagram_flow_id_to_stream_id_map_.end()) {
+ QUIC_DLOG(INFO) << "Received unknown HTTP/3 datagram flow ID "
+ << stream_id64;
+ return;
+ }
+ stream_id64 = it->second;
+ }
+ if (stream_id64 > std::numeric_limits<QuicStreamId>::max()) {
+ // TODO(b/181256914) make this a connection close once we deprecate
+ // draft-ietf-masque-h3-datagram-00 in favor of later drafts.
+ QUIC_DLOG(ERROR) << "Received unexpectedly high HTTP/3 datagram stream ID "
+ << stream_id64;
+ return;
+ }
+ QuicStreamId stream_id = static_cast<QuicStreamId>(stream_id64);
+ QuicSpdyStream* stream =
+ static_cast<QuicSpdyStream*>(GetActiveStream(stream_id));
+ if (stream == nullptr) {
+ QUIC_DLOG(INFO) << "Received HTTP/3 datagram for unknown stream ID "
+ << stream_id;
+ // TODO(b/181256914) buffer unknown HTTP/3 datagram flow IDs for a short
// period of time in case they were reordered.
- QUIC_DLOG(ERROR) << "Received unknown HTTP/3 datagram flow ID " << flow_id;
return;
}
- absl::string_view payload = reader.ReadRemainingPayload();
- it->second->OnHttp3Datagram(flow_id, payload);
+ stream->OnDatagramReceived(&reader);
}
bool QuicSpdySession::SupportsWebTransport() {
@@ -1850,7 +1845,7 @@ void QuicSpdySession::DatagramObserver::OnDatagramProcessed(
}
bool QuicSpdySession::ShouldNegotiateHttp3Datagram() {
- return GetQuicReloadableFlag(quic_h3_datagram);
+ return false;
}
#undef ENDPOINT // undef for jumbo builds
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
index 214d1da13e2..78c132a6ad6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session.h
@@ -78,8 +78,6 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/) {}
// Incoming HTTP/3 frames on the control stream.
- // TODO(b/171463363): Remove.
- virtual void OnCancelPushFrameReceived(const CancelPushFrame& /*frame*/) {}
virtual void OnSettingsFrameReceived(const SettingsFrame& /*frame*/) = 0;
virtual void OnGoAwayFrameReceived(const GoAwayFrame& /*frame*/) {}
// TODO(b/171463363): Remove.
@@ -96,15 +94,6 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
QuicByteCount /*compressed_headers_length*/) {}
virtual void OnHeadersDecoded(QuicStreamId /*stream_id*/,
QuicHeaderList /*headers*/) {}
- // TODO(b/171463363): Remove.
- virtual void OnPushPromiseFrameReceived(QuicStreamId /*stream_id*/,
- QuicStreamId /*push_id*/,
- QuicByteCount
- /*compressed_headers_length*/) {}
- // TODO(b/171463363): Remove.
- virtual void OnPushPromiseDecoded(QuicStreamId /*stream_id*/,
- QuicStreamId /*push_id*/,
- QuicHeaderList /*headers*/) {}
// Incoming HTTP/3 frames of unknown type on any stream.
virtual void OnUnknownFrameReceived(QuicStreamId /*stream_id*/,
@@ -125,12 +114,6 @@ class QUIC_EXPORT_PRIVATE Http3DebugVisitor {
virtual void OnHeadersFrameSent(
QuicStreamId /*stream_id*/,
const spdy::SpdyHeaderBlock& /*header_block*/) {}
- // TODO(b/171463363): Remove.
- virtual void OnPushPromiseFrameSent(
- QuicStreamId /*stream_id*/,
- QuicStreamId
- /*push_id*/,
- const spdy::SpdyHeaderBlock& /*header_block*/) {}
// 0-RTT related events.
virtual void OnSettingsFrameResumed(const SettingsFrame& /*frame*/) {}
@@ -391,41 +374,24 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// extension.
virtual void OnAcceptChFrameReceivedViaAlps(const AcceptChFrame& /*frame*/);
- // Generates a new HTTP/3 datagram flow ID.
- QuicDatagramFlowId GetNextDatagramFlowId();
-
// Whether HTTP/3 datagrams are supported on this session, based on received
// SETTINGS.
bool h3_datagram_supported() const { return h3_datagram_supported_; }
- // Sends an HTTP/3 datagram. The flow ID is not part of |payload|.
- MessageStatus SendHttp3Datagram(QuicDatagramFlowId flow_id,
- absl::string_view payload);
-
- class QUIC_EXPORT_PRIVATE Http3DatagramVisitor {
- public:
- virtual ~Http3DatagramVisitor() {}
-
- // Called when an HTTP/3 datagram is received. |payload| does not contain
- // the flow ID.
- virtual void OnHttp3Datagram(QuicDatagramFlowId flow_id,
- absl::string_view payload) = 0;
- };
-
- // Registers |visitor| to receive HTTP/3 datagrams for flow ID |flow_id|. This
- // must not be called on a previously register flow ID without first calling
- // UnregisterHttp3FlowId. |visitor| must be valid until a corresponding call
- // to UnregisterHttp3FlowId. The flow ID must be unregistered before the
- // QuicSpdySession is destroyed.
- void RegisterHttp3FlowId(QuicDatagramFlowId flow_id,
- Http3DatagramVisitor* visitor);
-
- // Unregister a given HTTP/3 datagram flow ID.
- void UnregisterHttp3FlowId(QuicDatagramFlowId flow_id);
-
- // Sets max time in queue for a specified datagram flow ID.
- void SetMaxTimeInQueueForFlowId(QuicDatagramFlowId flow_id,
- QuicTime::Delta max_time_in_queue);
+ // This must not be used except by QuicSpdyStream::SendHttp3Datagram.
+ MessageStatus SendHttp3Datagram(
+ QuicDatagramStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload);
+ // This must not be used except by QuicSpdyStream::SetMaxDatagramTimeInQueue.
+ void SetMaxDatagramTimeInQueueForStreamId(QuicStreamId stream_id,
+ QuicTime::Delta max_time_in_queue);
+ // This must not be used except by
+ // QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders.
+ void RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id,
+ QuicStreamId stream_id);
+ // This must not be used except by QuicSpdyStream::OnClose.
+ void UnregisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id);
// Override from QuicSession to support HTTP/3 datagrams.
void OnMessageReceived(absl::string_view message) override;
@@ -433,6 +399,9 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Indicates whether the HTTP/3 session supports WebTransport.
bool SupportsWebTransport();
+ // Indicates whether both the peer and us support HTTP/3 Datagrams.
+ bool SupportsH3Datagram() { return h3_datagram_supported_; }
+
// Indicates whether the HTTP/3 session will indicate WebTransport support to
// the peer.
bool WillNegotiateWebTransport();
@@ -445,7 +414,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// until the SETTINGS are received. Only works for HTTP/3.
bool ShouldBufferRequestsUntilSettings() {
return version().UsesHttp3() && perspective() == Perspective::IS_SERVER &&
- WillNegotiateWebTransport();
+ ShouldNegotiateHttp3Datagram();
}
// Returns if the incoming bidirectional streams should process data. This is
@@ -685,18 +654,17 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// frame has been sent yet.
absl::optional<uint64_t> last_sent_http3_goaway_id_;
- // Value of the smallest unused HTTP/3 datagram flow ID that this endpoint's
- // datagram flow ID allocation service will use next.
- QuicDatagramFlowId next_available_datagram_flow_id_;
-
// Whether both this endpoint and our peer support HTTP/3 datagrams.
bool h3_datagram_supported_ = false;
// Whether the peer has indicated WebTransport support.
bool peer_supports_webtransport_ = false;
- absl::flat_hash_map<QuicDatagramFlowId, Http3DatagramVisitor*>
- h3_datagram_registrations_;
+ // This maps from draft-ietf-masque-h3-datagram-00 flow IDs to stream IDs.
+ // TODO(b/181256914) remove this when we deprecate support for that draft in
+ // favor of more recent ones.
+ absl::flat_hash_map<uint64_t, QuicStreamId>
+ h3_datagram_flow_id_to_stream_id_map_;
// Whether any settings have been received, either from the peer or from a
// session ticket.
@@ -710,6 +678,10 @@ class QUIC_EXPORT_PRIVATE QuicSpdySession
// Limited to kMaxUnassociatedWebTransportStreams; when the list is full,
// oldest streams are evicated first.
std::list<BufferedWebTransportStream> buffered_streams_;
+
+ // Latched value of flag_quic_decline_server_push_stream.
+ const bool decline_server_push_stream_ =
+ GetQuicReloadableFlag(quic_decline_server_push_stream);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
index 29e1f6b7bcd..5a984323de4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_session_test.cc
@@ -35,7 +35,6 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_encoder_peer.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
@@ -309,12 +308,10 @@ class TestSession : public QuicSpdySession {
return QuicSpdySession::GetOrCreateStream(stream_id);
}
- QuicConsumedData WritevData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
+ QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset, StreamSendingState state,
TransmissionType type,
- absl::optional<EncryptionLevel> level) override {
+ EncryptionLevel level) override {
bool fin = state != NO_FIN;
QuicConsumedData consumed(write_length, fin);
if (!writev_consumes_all_data_) {
@@ -356,6 +353,13 @@ class TestSession : public QuicSpdySession {
bool ShouldNegotiateWebTransport() override { return supports_webtransport_; }
void set_supports_webtransport(bool value) { supports_webtransport_ = value; }
+ bool ShouldNegotiateHttp3Datagram() override {
+ return should_negotiate_h3_datagram_;
+ }
+ void set_should_negotiate_h3_datagram(bool value) {
+ should_negotiate_h3_datagram_ = value;
+ }
+
MOCK_METHOD(void, OnAcceptChFrame, (const AcceptChFrame&), (override));
using QuicSession::closed_streams;
@@ -368,6 +372,7 @@ class TestSession : public QuicSpdySession {
bool writev_consumes_all_data_;
bool supports_webtransport_ = false;
+ bool should_negotiate_h3_datagram_ = false;
};
class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
@@ -420,7 +425,7 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
first_stream_id = QuicUtils::GetCryptoStreamId(transport_version());
}
for (QuicStreamId i = first_stream_id; i < 100; i++) {
- if (!QuicContainsKey(closed_streams_, i)) {
+ if (closed_streams_.find(i) == closed_streams_.end()) {
EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
} else {
EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
@@ -566,8 +571,7 @@ class QuicSpdySessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
headers.OnHeaderBlockStart();
headers.OnHeader(":method", "CONNECT");
headers.OnHeader(":protocol", "webtransport");
- headers.OnHeader("datagram-flow-id",
- absl::StrCat(session_.GetNextDatagramFlowId()));
+ headers.OnHeader("datagram-flow-id", absl::StrCat(session_id));
stream->OnStreamHeaderList(/*fin=*/true, 0, headers);
WebTransportHttp3* web_transport =
session_.GetWebTransportSession(session_id);
@@ -1495,61 +1499,6 @@ TEST_P(QuicSpdySessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
}
-TEST_P(QuicSpdySessionTestServer,
- HandshakeUnblocksFlowControlBlockedCryptoStream) {
- if (QuicVersionUsesCryptoFrames(transport_version()) ||
- connection_->encrypted_control_frames()) {
- // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
- // test doesn't make sense for those versions. With
- // use_encryption_level_context, control frames can only be sent when
- // encryption gets established, do not send BLOCKED for crypto streams.
- return;
- }
- // Test that if the crypto stream is flow control blocked, then if the SHLO
- // contains a larger send window offset, the stream becomes unblocked.
- session_.set_writev_consumes_all_data(true);
- TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
- EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- QuicHeadersStream* headers_stream =
- QuicSpdySessionPeer::GetHeadersStream(&session_);
- EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
- for (QuicStreamId i = 0; !crypto_stream->IsFlowControlBlocked() && i < 1000u;
- i++) {
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- QuicStreamOffset offset = crypto_stream->stream_bytes_written();
- QuicConfig config;
- CryptoHandshakeMessage crypto_message;
- config.ToHandshakeMessage(&crypto_message, transport_version());
- crypto_stream->SendHandshakeMessage(crypto_message, ENCRYPTION_INITIAL);
- char buf[1000];
- QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
- crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
- }
- EXPECT_TRUE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(headers_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
- EXPECT_FALSE(session_.HasDataToWrite());
- EXPECT_TRUE(crypto_stream->HasBufferedData());
-
- // Now complete the crypto handshake, resulting in an increased flow control
- // send window.
- CompleteHandshake();
- EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
- &session_, QuicUtils::GetCryptoStreamId(transport_version())));
- // Stream is now unblocked and will no longer have buffered data.
- EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
-}
-
#if !defined(OS_IOS)
// This test is failing flakily for iOS bots.
// http://crbug.com/425050
@@ -2058,25 +2007,33 @@ TEST_P(QuicSpdySessionTestClient, Http3ServerPush) {
std::string frame_type1 = absl::HexStringToBytes("01");
QuicStreamId stream_id1 =
GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 0);
- session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
- /* offset = */ 0, frame_type1));
+ if (!GetQuicReloadableFlag(quic_decline_server_push_stream)) {
+ session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
+ /* offset = */ 0, frame_type1));
- EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
- QuicStream* stream = session_.GetOrCreateStream(stream_id1);
- EXPECT_EQ(1u, QuicStreamPeer::bytes_consumed(stream));
- EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
-
- // The same stream type can be encoded differently.
- std::string frame_type2 = absl::HexStringToBytes("80000001");
- QuicStreamId stream_id2 =
- GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
- session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false,
- /* offset = */ 0, frame_type2));
-
- EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
- stream = session_.GetOrCreateStream(stream_id2);
- EXPECT_EQ(4u, QuicStreamPeer::bytes_consumed(stream));
- EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed());
+ EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
+ QuicStream* stream = session_.GetOrCreateStream(stream_id1);
+ EXPECT_EQ(1u, QuicStreamPeer::bytes_consumed(stream));
+ EXPECT_EQ(1u, session_.flow_controller()->bytes_consumed());
+
+ // The same stream type can be encoded differently.
+ std::string frame_type2 = absl::HexStringToBytes("80000001");
+ QuicStreamId stream_id2 =
+ GetNthServerInitiatedUnidirectionalStreamId(transport_version(), 1);
+ session_.OnStreamFrame(QuicStreamFrame(stream_id2, /* fin = */ false,
+ /* offset = */ 0, frame_type2));
+
+ EXPECT_EQ(2u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
+ stream = session_.GetOrCreateStream(stream_id2);
+ EXPECT_EQ(4u, QuicStreamPeer::bytes_consumed(stream));
+ EXPECT_EQ(5u, session_.flow_controller()->bytes_consumed());
+ } else {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_RECEIVE_SERVER_PUSH, _, _))
+ .Times(1);
+ session_.OnStreamFrame(QuicStreamFrame(stream_id1, /* fin = */ false,
+ /* offset = */ 0, frame_type1));
+ }
}
TEST_P(QuicSpdySessionTestClient, Http3ServerPushOutofOrderFrame) {
@@ -2104,10 +2061,17 @@ TEST_P(QuicSpdySessionTestClient, Http3ServerPushOutofOrderFrame) {
session_.OnStreamFrame(data2);
EXPECT_EQ(0u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
- session_.OnStreamFrame(data1);
- EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
- QuicStream* stream = session_.GetOrCreateStream(stream_id);
- EXPECT_EQ(3u, stream->highest_received_byte_offset());
+ if (!GetQuicReloadableFlag(quic_decline_server_push_stream)) {
+ session_.OnStreamFrame(data1);
+ EXPECT_EQ(1u, QuicSessionPeer::GetNumOpenDynamicStreams(&session_));
+ QuicStream* stream = session_.GetOrCreateStream(stream_id);
+ EXPECT_EQ(3u, stream->highest_received_byte_offset());
+ } else {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_HTTP_RECEIVE_SERVER_PUSH, _, _))
+ .Times(1);
+ session_.OnStreamFrame(data1);
+ }
}
TEST_P(QuicSpdySessionTestServer, OnStreamFrameLost) {
@@ -2921,18 +2885,13 @@ TEST_P(QuicSpdySessionTestClient, CloseConnectionOnCancelPush) {
"00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
cancel_push_frame);
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
- "CANCEL_PUSH frame received.", _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- EXPECT_CALL(*connection_,
- SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
- "CANCEL_PUSH frame received."));
- } else {
- // CANCEL_PUSH is ignored.
- EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
- }
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_,
+ SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
+ "CANCEL_PUSH frame received."));
session_.OnStreamFrame(data3);
}
@@ -3128,18 +3087,13 @@ TEST_P(QuicSpdySessionTestServer, CloseConnectionOnCancelPush) {
"00"); // push ID
QuicStreamFrame data3(receive_control_stream_id, /* fin = */ false, offset,
cancel_push_frame);
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
- "CANCEL_PUSH frame received.", _))
- .WillOnce(
- Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
- EXPECT_CALL(*connection_,
- SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
- "CANCEL_PUSH frame received."));
- } else {
- // CANCEL_PUSH is ignored.
- EXPECT_CALL(debug_visitor, OnCancelPushFrameReceived(_));
- }
+ EXPECT_CALL(*connection_, CloseConnection(QUIC_HTTP_FRAME_ERROR,
+ "CANCEL_PUSH frame received.", _))
+ .WillOnce(
+ Invoke(connection_, &MockQuicConnection::ReallyCloseConnection));
+ EXPECT_CALL(*connection_,
+ SendConnectionClosePacket(QUIC_HTTP_FRAME_ERROR, _,
+ "CANCEL_PUSH frame received."));
session_.OnStreamFrame(data3);
}
@@ -3463,31 +3417,11 @@ TEST_P(QuicSpdySessionTestClient, AlpsTwoSettingsFrame) {
EXPECT_EQ("multiple SETTINGS frames", error.value());
}
-TEST_P(QuicSpdySessionTestClient, GetNextDatagramFlowId) {
- if (!version().UsesHttp3()) {
- return;
- }
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 0u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 2u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 4u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 6u);
-}
-
-TEST_P(QuicSpdySessionTestServer, GetNextDatagramFlowId) {
- if (!version().UsesHttp3()) {
- return;
- }
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 1u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 3u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 5u);
- EXPECT_EQ(session_.GetNextDatagramFlowId(), 7u);
-}
-
TEST_P(QuicSpdySessionTestClient, H3DatagramSetting) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
// HTTP/3 datagrams aren't supported before SETTINGS are received.
EXPECT_FALSE(session_.h3_datagram_supported());
// Receive SETTINGS.
@@ -3506,52 +3440,11 @@ TEST_P(QuicSpdySessionTestClient, H3DatagramSetting) {
EXPECT_TRUE(session_.h3_datagram_supported());
}
-TEST_P(QuicSpdySessionTestClient, H3DatagramRegistration) {
- if (!version().UsesHttp3()) {
- return;
- }
- CompleteHandshake();
- SetQuicReloadableFlag(quic_h3_datagram, true);
- QuicSpdySessionPeer::SetH3DatagramSupported(&session_, true);
- SavingHttp3DatagramVisitor h3_datagram_visitor;
- QuicDatagramFlowId flow_id = session_.GetNextDatagramFlowId();
- ASSERT_EQ(QuicDataWriter::GetVarInt62Len(flow_id), 1);
- uint8_t datagram[256];
- datagram[0] = flow_id;
- for (size_t i = 1; i < ABSL_ARRAYSIZE(datagram); i++) {
- datagram[i] = i;
- }
- session_.RegisterHttp3FlowId(flow_id, &h3_datagram_visitor);
- session_.OnMessageReceived(absl::string_view(
- reinterpret_cast<const char*>(datagram), sizeof(datagram)));
- EXPECT_THAT(
- h3_datagram_visitor.received_h3_datagrams(),
- ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
- flow_id, std::string(reinterpret_cast<const char*>(datagram + 1),
- sizeof(datagram) - 1)}));
- session_.UnregisterHttp3FlowId(flow_id);
-}
-
-TEST_P(QuicSpdySessionTestClient, SendHttp3Datagram) {
- if (!version().UsesHttp3()) {
- return;
- }
- CompleteHandshake();
- SetQuicReloadableFlag(quic_h3_datagram, true);
- QuicSpdySessionPeer::SetH3DatagramSupported(&session_, true);
- QuicDatagramFlowId flow_id = session_.GetNextDatagramFlowId();
- std::string h3_datagram_payload = {1, 2, 3, 4, 5, 6};
- EXPECT_CALL(*connection_, SendMessage(1, _, false))
- .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
- EXPECT_EQ(session_.SendHttp3Datagram(flow_id, h3_datagram_payload),
- MESSAGE_STATUS_SUCCESS);
-}
-
TEST_P(QuicSpdySessionTestClient, WebTransportSetting) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
EXPECT_FALSE(session_.SupportsWebTransport());
@@ -3581,7 +3474,7 @@ TEST_P(QuicSpdySessionTestClient, WebTransportSettingSetToZero) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
EXPECT_FALSE(session_.SupportsWebTransport());
@@ -3611,7 +3504,7 @@ TEST_P(QuicSpdySessionTestServer, WebTransportSetting) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
EXPECT_FALSE(session_.SupportsWebTransport());
@@ -3628,7 +3521,7 @@ TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreams) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
CompleteHandshake();
@@ -3661,7 +3554,7 @@ TEST_P(QuicSpdySessionTestServer, BufferingIncomingStreamsLimit) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
CompleteHandshake();
@@ -3702,7 +3595,7 @@ TEST_P(QuicSpdySessionTestServer, ResetOutgoingWebTransportStreams) {
if (!version().UsesHttp3()) {
return;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
+ session_.set_should_negotiate_h3_datagram(true);
session_.set_supports_webtransport(true);
CompleteHandshake();
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
index 6ec48ca5896..bc23474e72a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.cc
@@ -50,11 +50,6 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
stream_->OnUnrecoverableError(decoder->error(), decoder->error_detail());
}
- bool OnCancelPushFrame(const CancelPushFrame& /*frame*/) override {
- CloseConnectionOnWrongFrame("Cancel Push");
- return false;
- }
-
bool OnMaxPushIdFrame(const MaxPushIdFrame& /*frame*/) override {
CloseConnectionOnWrongFrame("Max Push Id");
return false;
@@ -113,42 +108,6 @@ class QuicSpdyStream::HttpDecoderVisitor : public HttpDecoder::Visitor {
return stream_->OnHeadersFrameEnd();
}
- bool OnPushPromiseFrameStart(QuicByteCount header_length) override {
- if (!VersionUsesHttp3(stream_->transport_version())) {
- CloseConnectionOnWrongFrame("Push Promise");
- return false;
- }
- return stream_->OnPushPromiseFrameStart(header_length);
- }
-
- bool OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length) override {
- if (!VersionUsesHttp3(stream_->transport_version())) {
- CloseConnectionOnWrongFrame("Push Promise");
- return false;
- }
- return stream_->OnPushPromiseFramePushId(push_id, push_id_length,
- header_block_length);
- }
-
- bool OnPushPromiseFramePayload(absl::string_view payload) override {
- QUICHE_DCHECK(!payload.empty());
- if (!VersionUsesHttp3(stream_->transport_version())) {
- CloseConnectionOnWrongFrame("Push Promise");
- return false;
- }
- return stream_->OnPushPromiseFramePayload(payload);
- }
-
- bool OnPushPromiseFrameEnd() override {
- if (!VersionUsesHttp3(stream_->transport_version())) {
- CloseConnectionOnWrongFrame("Push Promise");
- return false;
- }
- return stream_->OnPushPromiseFrameEnd();
- }
-
bool OnPriorityUpdateFrameStart(QuicByteCount /*header_length*/) override {
CloseConnectionOnWrongFrame("Priority update");
return false;
@@ -213,8 +172,7 @@ HttpDecoder::Options HttpDecoderOptionsForBidiStream(
}
} // namespace
-QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
- QuicSpdySession* spdy_session,
+QuicSpdyStream::QuicSpdyStream(QuicStreamId id, QuicSpdySession* spdy_session,
StreamType type)
: QuicStream(id, spdy_session, /*is_static=*/false, type),
spdy_session_(spdy_session),
@@ -232,7 +190,11 @@ QuicSpdyStream::QuicSpdyStream(QuicStreamId id,
sequencer_offset_(0),
is_decoder_processing_input_(false),
ack_listener_(nullptr),
- last_sent_urgency_(kDefaultUrgency) {
+ last_sent_urgency_(kDefaultUrgency),
+ datagram_next_available_context_id_(spdy_session->perspective() ==
+ Perspective::IS_SERVER
+ ? kFirstDatagramContextIdServer
+ : kFirstDatagramContextIdClient) {
QUICHE_DCHECK_EQ(session()->connection(), spdy_session->connection());
QUICHE_DCHECK_EQ(transport_version(), spdy_session->transport_version());
QUICHE_DCHECK(!QuicUtils::IsCryptoStreamId(transport_version(), id));
@@ -342,18 +304,9 @@ void QuicSpdyStream::WriteOrBufferBody(absl::string_view data, bool fin) {
spdy_session_->debug_visitor()->OnDataFrameSent(id(), data.length());
}
- // Write frame header.
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(data.length(), &buffer);
- unacked_frame_headers_offsets_.Add(
- send_buffer().stream_offset(),
- send_buffer().stream_offset() + header_length);
- QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
- << " is writing DATA frame header of length "
- << header_length;
- WriteOrBufferData(absl::string_view(buffer.get(), header_length), false,
- nullptr);
+ const bool success =
+ WriteDataFrameHeader(data.length(), /*force_write=*/true);
+ QUICHE_DCHECK(success);
// Write body.
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
@@ -413,49 +366,71 @@ QuicConsumedData QuicSpdyStream::WritevBody(const struct iovec* iov,
return WriteBodySlices(storage.ToSpan(), fin);
}
+bool QuicSpdyStream::WriteDataFrameHeader(QuicByteCount data_length,
+ bool force_write) {
+ QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
+ QUICHE_DCHECK_GT(data_length, 0u);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ data_length,
+ spdy_session_->connection()->helper()->GetStreamSendBufferAllocator());
+ const bool can_write = CanWriteNewDataAfterData(header.size());
+ if (!can_write && !force_write) {
+ return false;
+ }
+
+ if (spdy_session_->debug_visitor()) {
+ spdy_session_->debug_visitor()->OnDataFrameSent(id(), data_length);
+ }
+
+ unacked_frame_headers_offsets_.Add(
+ send_buffer().stream_offset(),
+ send_buffer().stream_offset() + header.size());
+ QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
+ << " is writing DATA frame header of length "
+ << header.size();
+ if (can_write) {
+ // Save one copy and allocation if send buffer can accomodate the header.
+ QuicMemSlice header_slice(std::move(header));
+ WriteMemSlices(QuicMemSliceSpan(&header_slice), false);
+ } else {
+ QUICHE_DCHECK(force_write);
+ WriteOrBufferData(header.AsStringView(), false, nullptr);
+ }
+ return true;
+}
+
QuicConsumedData QuicSpdyStream::WriteBodySlices(QuicMemSliceSpan slices,
bool fin) {
if (!VersionUsesHttp3(transport_version()) || slices.empty()) {
return WriteMemSlices(slices, fin);
}
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(slices.total_length(), &buffer);
- if (!CanWriteNewDataAfterData(header_length)) {
+ QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
+ if (!WriteDataFrameHeader(slices.total_length(), /*force_write=*/false)) {
return {0, false};
}
- if (spdy_session_->debug_visitor()) {
- spdy_session_->debug_visitor()->OnDataFrameSent(id(),
- slices.total_length());
+ QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
+ << " is writing DATA frame payload of length "
+ << slices.total_length();
+ return WriteMemSlices(slices, fin);
+}
+
+QuicConsumedData QuicSpdyStream::WriteBodySlices(
+ absl::Span<QuicMemSlice> slices,
+ bool fin) {
+ if (!VersionUsesHttp3(transport_version()) || slices.empty()) {
+ return WriteMemSlices(slices, fin);
}
QuicConnection::ScopedPacketFlusher flusher(spdy_session_->connection());
+ const QuicByteCount data_size = MemSliceSpanTotalSize(slices);
+ if (!WriteDataFrameHeader(data_size, /*force_write=*/false)) {
+ return {0, false};
+ }
- // Write frame header.
-#if !defined(__ANDROID__)
- struct iovec header_iov = {static_cast<void*>(buffer.get()), header_length};
-#else
- struct iovec header_iov = {static_cast<void*>(buffer.get()),
- static_cast<__kernel_size_t>(header_length)};
-#endif
- QuicMemSliceStorage storage(
- &header_iov, 1,
- spdy_session_->connection()->helper()->GetStreamSendBufferAllocator(),
- GetQuicFlag(FLAGS_quic_send_buffer_max_data_slice_size));
- unacked_frame_headers_offsets_.Add(
- send_buffer().stream_offset(),
- send_buffer().stream_offset() + header_length);
- QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
- << " is writing DATA frame header of length "
- << header_length;
- WriteMemSlices(storage.ToSpan(), false);
-
- // Write body.
QUIC_DLOG(INFO) << ENDPOINT << "Stream " << id()
- << " is writing DATA frame payload of length "
- << slices.total_length();
+ << " is writing DATA frame payload of length " << data_size;
return WriteMemSlices(slices, fin);
}
@@ -598,10 +573,6 @@ void QuicSpdyStream::OnHeadersDecoded(QuicHeaderList headers,
OnStreamHeaderList(/* fin = */ false, headers_payload_length_, headers);
} else {
- if (debug_visitor) {
- debug_visitor->OnPushPromiseDecoded(id(), promised_stream_id, headers);
- }
-
spdy_session_->OnHeaderList(headers);
}
@@ -873,6 +844,10 @@ void QuicSpdyStream::OnClose() {
visitor->OnClose(this);
}
+ if (datagram_flow_id_.has_value()) {
+ spdy_session_->UnregisterHttp3DatagramFlowId(datagram_flow_id_.value());
+ }
+
if (web_transport_ != nullptr) {
web_transport_->CloseAllAssociatedStreams();
}
@@ -1085,50 +1060,6 @@ bool QuicSpdyStream::OnHeadersFrameEnd() {
return !sequencer()->IsClosed() && !reading_stopped();
}
-bool QuicSpdyStream::OnPushPromiseFrameStart(QuicByteCount header_length) {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QUICHE_DCHECK(!qpack_decoded_headers_accumulator_);
-
- sequencer()->MarkConsumed(body_manager_.OnNonBody(header_length));
-
- return true;
-}
-
-bool QuicSpdyStream::OnPushPromiseFramePushId(
- PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length) {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
- QUICHE_DCHECK(!qpack_decoded_headers_accumulator_);
-
- if (spdy_session_->debug_visitor()) {
- spdy_session_->debug_visitor()->OnPushPromiseFrameReceived(
- id(), push_id, header_block_length);
- }
-
- // TODO(b/151749109): Check max push id and handle errors.
- spdy_session_->OnPushPromise(id(), push_id);
- sequencer()->MarkConsumed(body_manager_.OnNonBody(push_id_length));
-
- qpack_decoded_headers_accumulator_ =
- std::make_unique<QpackDecodedHeadersAccumulator>(
- id(), spdy_session_->qpack_decoder(), this,
- spdy_session_->max_inbound_header_list_size());
-
- return true;
-}
-
-bool QuicSpdyStream::OnPushPromiseFramePayload(absl::string_view payload) {
- spdy_session_->OnCompressedFrameSize(payload.length());
- return OnHeadersFramePayload(payload);
-}
-
-bool QuicSpdyStream::OnPushPromiseFrameEnd() {
- QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
-
- return OnHeadersFrameEnd();
-}
-
void QuicSpdyStream::OnWebTransportStreamFrameType(
QuicByteCount header_length,
WebTransportSessionId session_id) {
@@ -1237,6 +1168,16 @@ size_t QuicSpdyStream::WriteHeadersImpl(
return encoded_headers.size();
}
+bool QuicSpdyStream::CanWriteNewBodyData(QuicByteCount write_size) const {
+ QUICHE_DCHECK_NE(0u, write_size);
+ if (!VersionUsesHttp3(transport_version())) {
+ return CanWriteNewData();
+ }
+
+ return CanWriteNewDataAfterData(
+ HttpEncoder::GetDataFrameHeaderLength(write_size));
+}
+
void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
if (!spdy_session_->SupportsWebTransport()) {
return;
@@ -1248,7 +1189,7 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
std::string method;
std::string protocol;
- absl::optional<QuicDatagramFlowId> flow_id;
+ absl::optional<QuicDatagramStreamId> flow_id;
for (const auto& header : header_list_) {
const std::string& header_name = header.first;
const std::string& header_value = header.second;
@@ -1268,7 +1209,7 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
if (flow_id.has_value() || header_value.empty()) {
return;
}
- QuicDatagramFlowId flow_id_out;
+ QuicDatagramStreamId flow_id_out;
if (!absl::SimpleAtoi(header_value, &flow_id_out)) {
return;
}
@@ -1281,8 +1222,18 @@ void QuicSpdyStream::MaybeProcessReceivedWebTransportHeaders() {
return;
}
+ RegisterHttp3DatagramFlowId(*flow_id);
+
web_transport_ =
- std::make_unique<WebTransportHttp3>(spdy_session_, this, id(), *flow_id);
+ std::make_unique<WebTransportHttp3>(spdy_session_, this, id());
+
+ // If we're in draft-ietf-masque-h3-datagram-00 mode, pretend we also received
+ // a REGISTER_DATAGRAM_NO_CONTEXT capsule with no extensions.
+ // TODO(b/181256914) remove this when we remove support for
+ // draft-ietf-masque-h3-datagram-00 in favor of later drafts.
+ RegisterHttp3DatagramContextId(/*context_id=*/absl::nullopt,
+ Http3DatagramContextExtensions(),
+ web_transport_.get());
}
void QuicSpdyStream::MaybeProcessSentWebTransportHeaders(
@@ -1304,11 +1255,14 @@ void QuicSpdyStream::MaybeProcessSentWebTransportHeaders(
return;
}
- QuicDatagramFlowId flow_id = spdy_session_->GetNextDatagramFlowId();
- headers["datagram-flow-id"] = absl::StrCat(flow_id);
+ QuicDatagramStreamId stream_id = id();
+ headers["datagram-flow-id"] = absl::StrCat(stream_id);
web_transport_ =
- std::make_unique<WebTransportHttp3>(spdy_session_, this, id(), flow_id);
+ std::make_unique<WebTransportHttp3>(spdy_session_, this, id());
+ RegisterHttp3DatagramContextId(web_transport_->context_id(),
+ Http3DatagramContextExtensions(),
+ web_transport_.get());
}
void QuicSpdyStream::OnCanWriteNewData() {
@@ -1369,5 +1323,206 @@ QuicSpdyStream::WebTransportDataStream::WebTransportDataStream(
: session_id(session_id),
adapter(stream->spdy_session_, stream, stream->sequencer()) {}
+MessageStatus QuicSpdyStream::SendHttp3Datagram(
+ absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload) {
+ QuicDatagramStreamId stream_id =
+ datagram_flow_id_.has_value() ? datagram_flow_id_.value() : id();
+ return spdy_session_->SendHttp3Datagram(stream_id, context_id, payload);
+}
+
+void QuicSpdyStream::RegisterHttp3DatagramRegistrationVisitor(
+ Http3DatagramRegistrationVisitor* visitor) {
+ if (visitor == nullptr) {
+ QUIC_BUG(null datagram registration visitor)
+ << ENDPOINT << "Null datagram registration visitor for" << id();
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Registering datagram stream ID " << id();
+ datagram_registration_visitor_ = visitor;
+}
+
+void QuicSpdyStream::UnregisterHttp3DatagramRegistrationVisitor() {
+ QUIC_BUG_IF(h3 datagram unregister unknown stream ID,
+ datagram_registration_visitor_ == nullptr)
+ << ENDPOINT
+ << "Attempted to unregister unknown HTTP/3 datagram stream ID " << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Unregistering datagram stream ID " << id();
+ datagram_registration_visitor_ = nullptr;
+}
+
+void QuicSpdyStream::MoveHttp3DatagramRegistration(
+ Http3DatagramRegistrationVisitor* visitor) {
+ QUIC_BUG_IF(h3 datagram move unknown stream ID,
+ datagram_registration_visitor_ == nullptr)
+ << ENDPOINT << "Attempted to move unknown HTTP/3 datagram stream ID "
+ << id();
+ QUIC_DLOG(INFO) << ENDPOINT << "Moving datagram stream ID " << id();
+ datagram_registration_visitor_ = visitor;
+}
+
+void QuicSpdyStream::RegisterHttp3DatagramContextId(
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/,
+ Http3DatagramVisitor* visitor) {
+ if (visitor == nullptr) {
+ QUIC_BUG(null datagram visitor)
+ << ENDPOINT << "Null datagram visitor for stream ID " << id()
+ << " context ID " << (context_id.has_value() ? context_id.value() : 0);
+ return;
+ }
+ if (datagram_registration_visitor_ == nullptr) {
+ QUIC_BUG(context registration without registration visitor)
+ << ENDPOINT << "Cannot register context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " without registration visitor for stream ID " << id();
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Registering datagram context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " with stream ID " << id();
+ if (context_id.has_value()) {
+ if (datagram_no_context_visitor_ != nullptr) {
+ QUIC_BUG(h3 datagram context ID mix1)
+ << ENDPOINT
+ << "Attempted to mix registrations without and with context IDs "
+ "for stream ID "
+ << id();
+ return;
+ }
+ auto insertion_result =
+ datagram_context_visitors_.insert({context_id.value(), visitor});
+ QUIC_BUG_IF(h3 datagram double context registration,
+ !insertion_result.second)
+ << ENDPOINT << "Attempted to doubly register HTTP/3 stream ID " << id()
+ << " context ID " << context_id.value();
+ return;
+ }
+ // Registration without a context ID.
+ if (!datagram_context_visitors_.empty()) {
+ QUIC_BUG(h3 datagram context ID mix2)
+ << ENDPOINT
+ << "Attempted to mix registrations with and without context IDs "
+ "for stream ID "
+ << id();
+ return;
+ }
+ if (datagram_no_context_visitor_ != nullptr) {
+ QUIC_BUG(h3 datagram double no context registration)
+ << ENDPOINT << "Attempted to doubly register HTTP/3 stream ID " << id()
+ << " with no context ID";
+ return;
+ }
+ datagram_no_context_visitor_ = visitor;
+}
+
+void QuicSpdyStream::UnregisterHttp3DatagramContextId(
+ absl::optional<QuicDatagramContextId> context_id) {
+ if (datagram_registration_visitor_ == nullptr) {
+ QUIC_BUG(context unregistration without registration visitor)
+ << ENDPOINT << "Cannot unregister context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " without registration visitor for stream ID " << id();
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Unregistering datagram context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " with stream ID " << id();
+ if (context_id.has_value()) {
+ size_t num_erased = datagram_context_visitors_.erase(context_id.value());
+ QUIC_BUG_IF(h3 datagram unregister unknown context, num_erased != 1)
+ << "Attempted to unregister unknown HTTP/3 context ID "
+ << context_id.value() << " on stream ID " << id();
+ return;
+ }
+ // Unregistration without a context ID.
+ QUIC_BUG_IF(h3 datagram unknown context unregistration,
+ datagram_no_context_visitor_ == nullptr)
+ << "Attempted to unregister unknown no context on HTTP/3 stream ID "
+ << id();
+ datagram_no_context_visitor_ = nullptr;
+}
+
+void QuicSpdyStream::MoveHttp3DatagramContextIdRegistration(
+ absl::optional<QuicDatagramContextId> context_id,
+ Http3DatagramVisitor* visitor) {
+ if (datagram_registration_visitor_ == nullptr) {
+ QUIC_BUG(context move without registration visitor)
+ << ENDPOINT << "Cannot move context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " without registration visitor for stream ID " << id();
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Moving datagram context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " with stream ID " << id();
+ if (context_id.has_value()) {
+ QUIC_BUG_IF(h3 datagram move unknown context,
+ !datagram_context_visitors_.contains(context_id.value()))
+ << ENDPOINT << "Attempted to move unknown context ID "
+ << context_id.value() << " on stream ID " << id();
+ datagram_context_visitors_[context_id.value()] = visitor;
+ return;
+ }
+ // Move without a context ID.
+ QUIC_BUG_IF(h3 datagram unknown context move,
+ datagram_no_context_visitor_ == nullptr)
+ << "Attempted to move unknown no context on HTTP/3 stream ID " << id();
+ datagram_no_context_visitor_ = visitor;
+}
+
+void QuicSpdyStream::SetMaxDatagramTimeInQueue(
+ QuicTime::Delta max_time_in_queue) {
+ spdy_session_->SetMaxDatagramTimeInQueueForStreamId(id(), max_time_in_queue);
+}
+
+QuicDatagramContextId QuicSpdyStream::GetNextDatagramContextId() {
+ QuicDatagramContextId result = datagram_next_available_context_id_;
+ datagram_next_available_context_id_ += kDatagramContextIdIncrement;
+ return result;
+}
+
+void QuicSpdyStream::OnDatagramReceived(QuicDataReader* reader) {
+ absl::optional<QuicDatagramContextId> context_id;
+ const bool context_id_present = !datagram_context_visitors_.empty();
+ Http3DatagramVisitor* visitor;
+ if (context_id_present) {
+ QuicDatagramContextId parsed_context_id;
+ if (!reader->ReadVarInt62(&parsed_context_id)) {
+ QUIC_DLOG(ERROR) << "Failed to parse context ID in received HTTP/3 "
+ "datagram on stream ID "
+ << id();
+ return;
+ }
+ context_id = parsed_context_id;
+ auto it = datagram_context_visitors_.find(parsed_context_id);
+ if (it == datagram_context_visitors_.end()) {
+ // TODO(b/181256914) buffer unknown HTTP/3 datagrams for a short
+ // period of time in case they were reordered.
+ QUIC_DLOG(ERROR) << "Received unknown HTTP/3 datagram context ID "
+ << parsed_context_id << " on stream ID " << id();
+ return;
+ }
+ visitor = it->second;
+ } else {
+ if (datagram_no_context_visitor_ == nullptr) {
+ // TODO(b/181256914) buffer unknown HTTP/3 datagrams for a short
+ // period of time in case they were reordered.
+ QUIC_DLOG(ERROR)
+ << "Received HTTP/3 datagram without any registrations on stream ID "
+ << id();
+ return;
+ }
+ visitor = datagram_no_context_visitor_;
+ }
+ absl::string_view payload = reader->ReadRemainingPayload();
+ visitor->OnHttp3Datagram(id(), context_id, payload);
+}
+
+void QuicSpdyStream::RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id) {
+ datagram_flow_id_ = flow_id;
+ spdy_session_->RegisterHttp3DatagramFlowId(datagram_flow_id_.value(), id());
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
index 5f96d8395cf..4df1196abeb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream.h
@@ -16,7 +16,9 @@
#include <memory>
#include <string>
+#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
#include "quic/core/http/http_decoder.h"
#include "quic/core/http/http_encoder.h"
#include "quic/core/http/quic_header_list.h"
@@ -44,6 +46,8 @@ class QuicStreamPeer;
class QuicSpdySession;
class WebTransportHttp3;
+class QUIC_EXPORT_PRIVATE Http3DatagramContextExtensions {};
+
// A QUIC stream that can send and receive HTTP2 (SPDY) headers.
class QUIC_EXPORT_PRIVATE QuicSpdyStream
: public QuicStream,
@@ -158,6 +162,7 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// Does the same thing as WriteOrBufferBody except this method takes
// memslicespan as the data input. Right now it only calls WriteMemSlices.
QuicConsumedData WriteBodySlices(QuicMemSliceSpan slices, bool fin);
+ QuicConsumedData WriteBodySlices(absl::Span<QuicMemSlice> slices, bool fin);
// Marks the trailers as consumed. This applies to the case where this object
// receives headers and trailers as QuicHeaderLists via calls to
@@ -244,6 +249,98 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// error, and returns false.
bool AssertNotWebTransportDataStream(absl::string_view operation);
+ // Indicates whether a call to WriteBodySlices will be successful and not
+ // rejected due to buffer being full. |write_size| must be non-zero.
+ bool CanWriteNewBodyData(QuicByteCount write_size) const;
+
+ // Sends an HTTP/3 datagram. The stream and context IDs are not part of
+ // |payload|.
+ MessageStatus SendHttp3Datagram(
+ absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload);
+
+ class QUIC_EXPORT_PRIVATE Http3DatagramVisitor {
+ public:
+ virtual ~Http3DatagramVisitor() {}
+
+ // Called when an HTTP/3 datagram is received. |payload| does not contain
+ // the stream or context IDs. Note that this contains the stream ID even if
+ // flow IDs from draft-ietf-masque-h3-datagram-00 are in use.
+ virtual void OnHttp3Datagram(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload) = 0;
+ };
+
+ class QUIC_EXPORT_PRIVATE Http3DatagramRegistrationVisitor {
+ public:
+ virtual ~Http3DatagramRegistrationVisitor() {}
+
+ // Called when a REGISTER_DATAGRAM_CONTEXT or REGISTER_DATAGRAM_NO_CONTEXT
+ // capsule is received. Note that this contains the stream ID even if flow
+ // IDs from draft-ietf-masque-h3-datagram-00 are in use.
+ virtual void OnContextReceived(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) = 0;
+
+ // Called when a CLOSE_DATAGRAM_CONTEXT capsule is received. Note that this
+ // contains the stream ID even if flow IDs from
+ // draft-ietf-masque-h3-datagram-00 are in use.
+ virtual void OnContextClosed(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) = 0;
+ };
+
+ // Registers |visitor| to receive HTTP/3 datagram context registrations. This
+ // must not be called without first calling
+ // UnregisterHttp3DatagramRegistrationVisitor. |visitor| must be valid until a
+ // corresponding call to UnregisterHttp3DatagramRegistrationVisitor.
+ void RegisterHttp3DatagramRegistrationVisitor(
+ Http3DatagramRegistrationVisitor* visitor);
+
+ // Unregisters for HTTP/3 datagram context registrations. Must not be called
+ // unless previously registered.
+ void UnregisterHttp3DatagramRegistrationVisitor();
+
+ // Moves an HTTP/3 datagram registration to a different visitor. Mainly meant
+ // to be used by the visitors' move operators.
+ void MoveHttp3DatagramRegistration(Http3DatagramRegistrationVisitor* visitor);
+
+ // Registers |visitor| to receive HTTP/3 datagrams for optional context ID
+ // |context_id|. This must not be called on a previously registered context ID
+ // without first calling UnregisterHttp3DatagramContextId. |visitor| must be
+ // valid until a corresponding call to UnregisterHttp3DatagramContextId. If
+ // this method is called multiple times, the context ID MUST either be always
+ // present, or always absent.
+ void RegisterHttp3DatagramContextId(
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions,
+ Http3DatagramVisitor* visitor);
+
+ // Unregisters an HTTP/3 datagram context ID. Must be called on a previously
+ // registered context.
+ void UnregisterHttp3DatagramContextId(
+ absl::optional<QuicDatagramContextId> context_id);
+
+ // Moves an HTTP/3 datagram context ID to a different visitor. Mainly meant
+ // to be used by the visitors' move operators.
+ void MoveHttp3DatagramContextIdRegistration(
+ absl::optional<QuicDatagramContextId> context_id,
+ Http3DatagramVisitor* visitor);
+
+ // Sets max datagram time in queue.
+ void SetMaxDatagramTimeInQueue(QuicTime::Delta max_time_in_queue);
+
+ // Generates a new HTTP/3 datagram context ID for this stream. A datagram
+ // registration visitor must be currently registered on this stream.
+ QuicDatagramContextId GetNextDatagramContextId();
+
+ void OnDatagramReceived(QuicDataReader* reader);
+
+ void RegisterHttp3DatagramFlowId(QuicDatagramStreamId flow_id);
+
protected:
// Called when the received headers are too large. By default this will
// reset the stream.
@@ -292,12 +389,6 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
QuicByteCount payload_length);
bool OnHeadersFramePayload(absl::string_view payload);
bool OnHeadersFrameEnd();
- bool OnPushPromiseFrameStart(QuicByteCount header_length);
- bool OnPushPromiseFramePushId(PushId push_id,
- QuicByteCount push_id_length,
- QuicByteCount header_block_length);
- bool OnPushPromiseFramePayload(absl::string_view payload);
- bool OnPushPromiseFrameEnd();
void OnWebTransportStreamFrameType(QuicByteCount header_length,
WebTransportSessionId session_id);
bool OnUnknownFrameStart(uint64_t frame_type,
@@ -314,6 +405,11 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
void MaybeProcessSentWebTransportHeaders(spdy::SpdyHeaderBlock& headers);
void MaybeProcessReceivedWebTransportHeaders();
+ // Writes HTTP/3 DATA frame header. If |force_write| is true, use
+ // WriteOrBufferData if send buffer cannot accomodate the header + data.
+ ABSL_MUST_USE_RESULT bool WriteDataFrameHeader(QuicByteCount data_length,
+ bool force_write);
+
QuicSpdySession* spdy_session_;
bool on_body_available_called_because_sequencer_is_closed_;
@@ -382,6 +478,14 @@ class QUIC_EXPORT_PRIVATE QuicSpdyStream
// If this stream is a WebTransport data stream, |web_transport_data_|
// contains all of the associated metadata.
std::unique_ptr<WebTransportDataStream> web_transport_data_;
+
+ // HTTP/3 Datagram support.
+ Http3DatagramRegistrationVisitor* datagram_registration_visitor_ = nullptr;
+ Http3DatagramVisitor* datagram_no_context_visitor_ = nullptr;
+ absl::optional<QuicDatagramStreamId> datagram_flow_id_;
+ QuicDatagramContextId datagram_next_available_context_id_;
+ absl::flat_hash_map<QuicDatagramContextId, Http3DatagramVisitor*>
+ datagram_context_visitors_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
index 8b814b8400b..c19dc3c8431 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/quic_spdy_stream_test.cc
@@ -19,12 +19,12 @@
#include "quic/core/http/spdy_utils.h"
#include "quic/core/http/web_transport_http3.h"
#include "quic/core/quic_connection.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/quic_stream_sequencer_buffer.h"
#include "quic/core/quic_utils.h"
#include "quic/core/quic_versions.h"
#include "quic/core/quic_write_blocked_list.h"
#include "quic/platform/api/quic_expect_bug.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
#include "quic/test_tools/quic_config_peer.h"
@@ -259,8 +259,16 @@ class TestSession : public MockQuicSpdySession {
bool ShouldNegotiateWebTransport() override { return enable_webtransport_; }
void EnableWebTransport() { enable_webtransport_ = true; }
+ bool ShouldNegotiateHttp3Datagram() override {
+ return should_negotiate_h3_datagram_;
+ }
+ void set_should_negotiate_h3_datagram(bool value) {
+ should_negotiate_h3_datagram_ = value;
+ }
+
private:
bool enable_webtransport_ = false;
+ bool should_negotiate_h3_datagram_ = false;
StrictMock<TestCryptoStream> crypto_stream_;
};
@@ -447,40 +455,10 @@ class QuicSpdyStreamTest : public QuicTestWithParam<ParsedQuicVersion> {
return absl::StrCat(headers_frame_header, payload);
}
- // Construct PUSH_PROMISE frame with given payload.
- // TODO(b/171463363): Remove.
- std::string SerializePushPromiseFrame(PushId push_id,
- absl::string_view headers) {
- const QuicByteCount payload_length =
- QuicDataWriter::GetVarInt62Len(push_id) + headers.length();
-
- const QuicByteCount length_without_headers =
- QuicDataWriter::GetVarInt62Len(
- static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)) +
- QuicDataWriter::GetVarInt62Len(payload_length) +
- QuicDataWriter::GetVarInt62Len(push_id);
-
- std::string push_promise_frame(length_without_headers, '\0');
- QuicDataWriter writer(length_without_headers, &*push_promise_frame.begin());
-
- QUICHE_CHECK(writer.WriteVarInt62(
- static_cast<uint64_t>(HttpFrameType::PUSH_PROMISE)));
- QUICHE_CHECK(writer.WriteVarInt62(payload_length));
- QUICHE_CHECK(writer.WriteVarInt62(push_id));
- QUICHE_CHECK_EQ(0u, writer.remaining());
-
- absl::StrAppend(&push_promise_frame, headers);
-
- return push_promise_frame;
- }
-
std::string DataFrame(absl::string_view payload) {
- std::unique_ptr<char[]> data_buffer;
- QuicByteCount data_frame_header_length =
- HttpEncoder::SerializeDataFrameHeader(payload.length(), &data_buffer);
- absl::string_view data_frame_header(data_buffer.get(),
- data_frame_header_length);
- return absl::StrCat(data_frame_header, payload);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ payload.length(), SimpleBufferAllocator::Get());
+ return absl::StrCat(header.AsStringView(), payload);
}
std::string UnknownFrame(uint64_t frame_type, absl::string_view payload) {
@@ -1005,11 +983,10 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlNoWindowUpdateIfNotConsumed) {
std::string data;
if (UsesHttp3()) {
- std::unique_ptr<char[]> buffer;
- header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- data = header + body;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
+ data = absl::StrCat(header.AsStringView(), body);
+ header_length = header.size();
} else {
data = body;
}
@@ -1049,11 +1026,10 @@ TEST_P(QuicSpdyStreamTest, StreamFlowControlWindowUpdate) {
std::string data;
if (UsesHttp3()) {
- std::unique_ptr<char[]> buffer;
- header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- data = header + body;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
+ data = absl::StrCat(header.AsStringView(), body);
+ header_length = header.size();
} else {
data = body;
}
@@ -1115,16 +1091,13 @@ TEST_P(QuicSpdyStreamTest, ConnectionFlowControlWindowUpdate) {
if (UsesHttp3()) {
body = std::string(kWindow / 4 - 2, 'a');
- std::unique_ptr<char[]> buffer;
- header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- data = header + body;
- std::unique_ptr<char[]> buffer2;
- QuicByteCount header_length2 =
- HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer2);
- std::string header2 = std::string(buffer2.get(), header_length2);
- data2 = header2 + body2;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
+ data = absl::StrCat(header.AsStringView(), body);
+ header_length = header.size();
+ QuicBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
+ data2 = absl::StrCat(header2.AsStringView(), body2);
} else {
body = std::string(kWindow / 4, 'a');
data = body;
@@ -1595,8 +1568,9 @@ TEST_P(QuicSpdyStreamTest, WritingTrailersFinalOffset) {
std::string body(1024, 'x'); // 1 kB
QuicByteCount header_length = 0;
if (UsesHttp3()) {
- std::unique_ptr<char[]> buf;
- header_length = HttpEncoder::SerializeDataFrameHeader(body.length(), &buf);
+ header_length = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get())
+ .size();
}
stream_->WriteOrBufferBody(body, false);
@@ -1939,30 +1913,26 @@ TEST_P(QuicSpdyStreamTest, HeadersAckNotReportedWriteOrBufferBody) {
stream_->WriteOrBufferBody(body, false);
stream_->WriteOrBufferBody(body2, true);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
-
- header_length =
- HttpEncoder::SerializeDataFrameHeader(body2.length(), &buffer);
- std::string header2 = std::string(buffer.get(), header_length);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
+ QuicBuffer header2 = HttpEncoder::SerializeDataFrameHeader(
+ body2.length(), SimpleBufferAllocator::Get());
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body.length(), _));
- QuicStreamFrame frame(stream_->id(), false, 0, header + body);
+ QuicStreamFrame frame(stream_->id(), false, 0,
+ absl::StrCat(header.AsStringView(), body));
EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame), QuicTime::Delta::Zero(),
QuicTime::Zero()));
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(0, _));
- QuicStreamFrame frame2(stream_->id(), false, header.length() + body.length(),
- header2);
+ QuicStreamFrame frame2(stream_->id(), false, header.size() + body.length(),
+ header2.AsStringView());
EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame2), QuicTime::Delta::Zero(),
QuicTime::Zero()));
EXPECT_CALL(*mock_ack_listener, OnPacketAcked(body2.length(), _));
QuicStreamFrame frame3(stream_->id(), true,
- header.length() + body.length() + header2.length(),
- body2);
+ header.size() + body.length() + header2.size(), body2);
EXPECT_TRUE(session_->OnFrameAcked(QuicFrame(frame3), QuicTime::Delta::Zero(),
QuicTime::Zero()));
@@ -2769,71 +2739,6 @@ TEST_P(QuicSpdyStreamIncrementalConsumptionTest, UnknownFramesInterleaved) {
EXPECT_EQ(unknown_frame4.size(), NewlyConsumedBytes());
}
-// TODO(b/171463363): Remove.
-TEST_P(QuicSpdyStreamTest, PushPromiseOnDataStream) {
- Initialize(kShouldProcessData);
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
- if (!UsesHttp3()) {
- return;
- }
-
- StrictMock<MockHttp3DebugVisitor> debug_visitor;
- session_->set_debug_visitor(&debug_visitor);
-
- SpdyHeaderBlock pushed_headers;
- pushed_headers["foo"] = "bar";
- std::string headers = EncodeQpackHeaders(pushed_headers);
-
- const QuicStreamId push_id = 1;
- std::string data = SerializePushPromiseFrame(push_id, headers);
- QuicStreamFrame frame(stream_->id(), false, 0, data);
-
- EXPECT_CALL(debug_visitor, OnPushPromiseFrameReceived(stream_->id(), push_id,
- headers.length()));
- EXPECT_CALL(debug_visitor,
- OnPushPromiseDecoded(stream_->id(), push_id,
- AsHeaderList(pushed_headers)));
- EXPECT_CALL(*session_,
- OnPromiseHeaderList(stream_->id(), push_id, headers.length(), _));
- stream_->OnStreamFrame(frame);
-}
-
-// Regression test for b/152518220.
-// TODO(b/171463363): Remove.
-TEST_P(QuicSpdyStreamTest,
- OnStreamHeaderBlockArgumentDoesNotIncludePushedHeaderBlock) {
- Initialize(kShouldProcessData);
- if (GetQuicReloadableFlag(quic_error_on_http3_push)) {
- return;
- }
- if (!UsesHttp3()) {
- return;
- }
-
- std::string pushed_headers = EncodeQpackHeaders({{"foo", "bar"}});
- const QuicStreamId push_id = 1;
- std::string push_promise_frame =
- SerializePushPromiseFrame(push_id, pushed_headers);
- QuicStreamOffset offset = 0;
- QuicStreamFrame frame1(stream_->id(), /* fin = */ false, offset,
- push_promise_frame);
- offset += push_promise_frame.length();
-
- EXPECT_CALL(*session_, OnPromiseHeaderList(stream_->id(), push_id,
- pushed_headers.length(), _));
- stream_->OnStreamFrame(frame1);
-
- std::string headers =
- EncodeQpackHeaders({{":method", "GET"}, {":path", "/"}});
- std::string headers_frame = HeadersFrame(headers);
- QuicStreamFrame frame2(stream_->id(), /* fin = */ false, offset,
- headers_frame);
- stream_->OnStreamFrame(frame2);
- EXPECT_EQ(headers.length(), stream_->headers_payload_length());
-}
-
// Close connection if a DATA frame is received before a HEADERS frame.
TEST_P(QuicSpdyStreamTest, DataBeforeHeaders) {
if (!UsesHttp3()) {
@@ -3118,6 +3023,7 @@ TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeaders) {
}
InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+ session_->set_should_negotiate_h3_datagram(true);
session_->EnableWebTransport();
QuicSpdySessionPeer::EnableWebTransport(*session_);
@@ -3128,7 +3034,7 @@ TEST_P(QuicSpdyStreamTest, ProcessOutgoingWebTransportHeaders) {
spdy::SpdyHeaderBlock headers;
headers[":method"] = "CONNECT";
headers[":protocol"] = "webtransport";
- headers["datagram-flow-id"] = absl::StrCat(session_->GetNextDatagramFlowId());
+ headers["datagram-flow-id"] = absl::StrCat(stream_->id());
stream_->WriteHeaders(std::move(headers), /*fin=*/false, nullptr);
ASSERT_TRUE(stream_->web_transport() != nullptr);
EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
@@ -3140,13 +3046,13 @@ TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeaders) {
}
Initialize(kShouldProcessData);
+ session_->set_should_negotiate_h3_datagram(true);
session_->EnableWebTransport();
QuicSpdySessionPeer::EnableWebTransport(*session_);
headers_[":method"] = "CONNECT";
headers_[":protocol"] = "webtransport";
- headers_["datagram-flow-id"] =
- absl::StrCat(session_->GetNextDatagramFlowId());
+ headers_["datagram-flow-id"] = absl::StrCat(stream_->id());
stream_->OnStreamHeadersPriority(
spdy::SpdyStreamPrecedence(kV3HighestPriority));
@@ -3158,6 +3064,155 @@ TEST_P(QuicSpdyStreamTest, ProcessIncomingWebTransportHeaders) {
EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
}
+TEST_P(QuicSpdyStreamTest,
+ ProcessIncomingWebTransportHeadersWithMismatchedFlowId) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ // TODO(b/181256914) Remove this test when we deprecate
+ // draft-ietf-masque-h3-datagram-00 in favor of later drafts.
+
+ Initialize(kShouldProcessData);
+ session_->set_should_negotiate_h3_datagram(true);
+ session_->EnableWebTransport();
+ QuicSpdySessionPeer::EnableWebTransport(*session_);
+
+ headers_[":method"] = "CONNECT";
+ headers_[":protocol"] = "webtransport";
+ headers_["datagram-flow-id"] = "2";
+
+ stream_->OnStreamHeadersPriority(
+ spdy::SpdyStreamPrecedence(kV3HighestPriority));
+ ProcessHeaders(false, headers_);
+ EXPECT_EQ("", stream_->data());
+ EXPECT_FALSE(stream_->header_list().empty());
+ EXPECT_FALSE(stream_->IsDoneReading());
+ ASSERT_TRUE(stream_->web_transport() != nullptr);
+ EXPECT_EQ(stream_->id(), stream_->web_transport()->id());
+}
+
+TEST_P(QuicSpdyStreamTest, GetNextDatagramContextIdClient) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_CLIENT);
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> visitor;
+ stream_->RegisterHttp3DatagramRegistrationVisitor(&visitor);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 0u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 2u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 4u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 6u);
+ stream_->UnregisterHttp3DatagramRegistrationVisitor();
+}
+
+TEST_P(QuicSpdyStreamTest, GetNextDatagramContextIdServer) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ InitializeWithPerspective(kShouldProcessData, Perspective::IS_SERVER);
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor> visitor;
+ stream_->RegisterHttp3DatagramRegistrationVisitor(&visitor);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 1u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 3u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 5u);
+ EXPECT_EQ(stream_->GetNextDatagramContextId(), 7u);
+ stream_->UnregisterHttp3DatagramRegistrationVisitor();
+}
+
+TEST_P(QuicSpdyStreamTest, H3DatagramRegistrationWithoutContext) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ Initialize(kShouldProcessData);
+ session_->set_should_negotiate_h3_datagram(true);
+ QuicSpdySessionPeer::SetH3DatagramSupported(session_.get(), true);
+ session_->RegisterHttp3DatagramFlowId(stream_->id(), stream_->id());
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor>
+ h3_datagram_registration_visitor;
+ SavingHttp3DatagramVisitor h3_datagram_visitor;
+ absl::optional<QuicDatagramContextId> context_id;
+ Http3DatagramContextExtensions extensions;
+ ASSERT_EQ(QuicDataWriter::GetVarInt62Len(stream_->id()), 1);
+ std::array<char, 256> datagram;
+ datagram[0] = stream_->id();
+ for (size_t i = 1; i < datagram.size(); i++) {
+ datagram[i] = i;
+ }
+ stream_->RegisterHttp3DatagramRegistrationVisitor(
+ &h3_datagram_registration_visitor);
+ stream_->RegisterHttp3DatagramContextId(context_id, extensions,
+ &h3_datagram_visitor);
+ session_->OnMessageReceived(
+ absl::string_view(datagram.data(), datagram.size()));
+ EXPECT_THAT(h3_datagram_visitor.received_h3_datagrams(),
+ ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
+ stream_->id(), context_id,
+ std::string(&datagram[1], datagram.size() - 1)}));
+ // Test move.
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor>
+ h3_datagram_registration_visitor2;
+ stream_->MoveHttp3DatagramRegistration(&h3_datagram_registration_visitor2);
+ SavingHttp3DatagramVisitor h3_datagram_visitor2;
+ stream_->MoveHttp3DatagramContextIdRegistration(context_id,
+ &h3_datagram_visitor2);
+ EXPECT_TRUE(h3_datagram_visitor2.received_h3_datagrams().empty());
+ session_->OnMessageReceived(
+ absl::string_view(datagram.data(), datagram.size()));
+ EXPECT_THAT(h3_datagram_visitor2.received_h3_datagrams(),
+ ElementsAre(SavingHttp3DatagramVisitor::SavedHttp3Datagram{
+ stream_->id(), context_id,
+ std::string(&datagram[1], datagram.size() - 1)}));
+ // Cleanup.
+ stream_->UnregisterHttp3DatagramContextId(context_id);
+ stream_->UnregisterHttp3DatagramRegistrationVisitor();
+ session_->UnregisterHttp3DatagramFlowId(stream_->id());
+}
+
+TEST_P(QuicSpdyStreamTest, H3DatagramRegistrationWithContext) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ Initialize(kShouldProcessData);
+ session_->set_should_negotiate_h3_datagram(true);
+ QuicSpdySessionPeer::SetH3DatagramSupported(session_.get(), true);
+ session_->RegisterHttp3DatagramFlowId(stream_->id(), stream_->id());
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor>
+ h3_datagram_registration_visitor;
+ SavingHttp3DatagramVisitor h3_datagram_visitor;
+ absl::optional<QuicDatagramContextId> context_id = 42;
+ Http3DatagramContextExtensions extensions;
+ stream_->RegisterHttp3DatagramRegistrationVisitor(
+ &h3_datagram_registration_visitor);
+ stream_->RegisterHttp3DatagramContextId(context_id, extensions,
+ &h3_datagram_visitor);
+ // Test move.
+ ::testing::NiceMock<MockHttp3DatagramRegistrationVisitor>
+ h3_datagram_registration_visitor2;
+ stream_->MoveHttp3DatagramRegistration(&h3_datagram_registration_visitor2);
+ SavingHttp3DatagramVisitor h3_datagram_visitor2;
+ stream_->MoveHttp3DatagramContextIdRegistration(context_id,
+ &h3_datagram_visitor2);
+ // Cleanup.
+ stream_->UnregisterHttp3DatagramContextId(context_id);
+ stream_->UnregisterHttp3DatagramRegistrationVisitor();
+ session_->UnregisterHttp3DatagramFlowId(stream_->id());
+}
+
+TEST_P(QuicSpdyStreamTest, SendHttp3Datagram) {
+ if (!UsesHttp3()) {
+ return;
+ }
+ Initialize(kShouldProcessData);
+ session_->set_should_negotiate_h3_datagram(true);
+ QuicSpdySessionPeer::SetH3DatagramSupported(session_.get(), true);
+ absl::optional<QuicDatagramContextId> context_id;
+ std::string h3_datagram_payload = {1, 2, 3, 4, 5, 6};
+ EXPECT_CALL(*connection_, SendMessage(1, _, false))
+ .WillOnce(Return(MESSAGE_STATUS_SUCCESS));
+ EXPECT_EQ(stream_->SendHttp3Datagram(context_id, h3_datagram_payload),
+ MESSAGE_STATUS_SUCCESS);
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
index 28b463afebe..27f5314b05f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.cc
@@ -16,7 +16,6 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "common/quiche_text_utils.h"
#include "spdy/core/spdy_protocol.h"
@@ -78,7 +77,7 @@ bool SpdyUtils::CopyAndValidateHeaders(const QuicHeaderList& header_list,
headers->AppendValueOrAddHeader(name, p.second);
}
- if (QuicContainsKey(*headers, "content-length") &&
+ if (headers->contains("content-length") &&
!ExtractContentLengthFromHeaders(content_length, headers)) {
return false;
}
@@ -155,7 +154,7 @@ bool SpdyUtils::PopulateHeaderBlockFromUrl(const std::string url,
}
// static
-absl::optional<QuicDatagramFlowId> SpdyUtils::ParseDatagramFlowIdHeader(
+absl::optional<QuicDatagramStreamId> SpdyUtils::ParseDatagramFlowIdHeader(
const spdy::SpdyHeaderBlock& headers) {
auto flow_id_pair = headers.find("datagram-flow-id");
if (flow_id_pair == headers.end()) {
@@ -163,7 +162,7 @@ absl::optional<QuicDatagramFlowId> SpdyUtils::ParseDatagramFlowIdHeader(
}
std::vector<absl::string_view> flow_id_strings =
absl::StrSplit(flow_id_pair->second, ',');
- absl::optional<QuicDatagramFlowId> first_named_flow_id;
+ absl::optional<QuicDatagramStreamId> first_named_flow_id;
for (absl::string_view flow_id_string : flow_id_strings) {
std::vector<absl::string_view> flow_id_components =
absl::StrSplit(flow_id_string, ';');
@@ -173,7 +172,7 @@ absl::optional<QuicDatagramFlowId> SpdyUtils::ParseDatagramFlowIdHeader(
absl::string_view flow_id_value_string = flow_id_components[0];
quiche::QuicheTextUtils::RemoveLeadingAndTrailingWhitespace(
&flow_id_value_string);
- QuicDatagramFlowId flow_id;
+ QuicDatagramStreamId flow_id;
if (!absl::SimpleAtoi(flow_id_value_string, &flow_id)) {
continue;
}
@@ -191,7 +190,7 @@ absl::optional<QuicDatagramFlowId> SpdyUtils::ParseDatagramFlowIdHeader(
// static
void SpdyUtils::AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers,
- QuicDatagramFlowId flow_id) {
+ QuicDatagramStreamId flow_id) {
(*headers)["datagram-flow-id"] = absl::StrCat(flow_id);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
index e3a8a97de48..01fae4f17a7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils.h
@@ -55,12 +55,12 @@ class QUIC_EXPORT_PRIVATE SpdyUtils {
// Parses the "datagram-flow-id" header, returns the flow ID on success, or
// returns absl::nullopt if the header was not present or failed to parse.
- static absl::optional<QuicDatagramFlowId> ParseDatagramFlowIdHeader(
+ static absl::optional<QuicDatagramStreamId> ParseDatagramFlowIdHeader(
const spdy::SpdyHeaderBlock& headers);
// Adds the "datagram-flow-id" header.
static void AddDatagramFlowIdHeader(spdy::SpdyHeaderBlock* headers,
- QuicDatagramFlowId flow_id);
+ QuicDatagramStreamId flow_id);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
index 7307665da3d..918739d6f90 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/spdy_utils_test.cc
@@ -34,7 +34,7 @@ static std::unique_ptr<QuicHeaderList> FromList(
static void ValidateDatagramFlowId(
const std::string& header_value,
- absl::optional<QuicDatagramFlowId> expected_flow_id) {
+ absl::optional<QuicDatagramStreamId> expected_flow_id) {
SpdyHeaderBlock headers;
headers["datagram-flow-id"] = header_value;
ASSERT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), expected_flow_id);
@@ -391,7 +391,7 @@ TEST_F(DatagramFlowIdTest, DatagramFlowId) {
SpdyHeaderBlock headers;
EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), absl::nullopt);
// Add header and verify it parses.
- QuicDatagramFlowId flow_id = 123;
+ QuicDatagramStreamId flow_id = 123;
SpdyUtils::AddDatagramFlowIdHeader(&headers, flow_id);
EXPECT_EQ(SpdyUtils::ParseDatagramFlowIdHeader(headers), flow_id);
// Test empty header.
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc
index 2a105c2e5bf..820950b31bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.cc
@@ -36,17 +36,19 @@ class QUIC_NO_EXPORT NoopWebTransportVisitor : public WebTransportVisitor {
WebTransportHttp3::WebTransportHttp3(QuicSpdySession* session,
QuicSpdyStream* connect_stream,
- WebTransportSessionId id,
- QuicDatagramFlowId flow_id)
+ WebTransportSessionId id)
: session_(session),
connect_stream_(connect_stream),
id_(id),
- flow_id_(flow_id),
visitor_(std::make_unique<NoopWebTransportVisitor>()) {
QUICHE_DCHECK(session_->SupportsWebTransport());
QUICHE_DCHECK(IsValidWebTransportSessionId(id, session_->version()));
QUICHE_DCHECK_EQ(connect_stream_->id(), id);
- session_->RegisterHttp3FlowId(flow_id, this);
+ connect_stream_->RegisterHttp3DatagramRegistrationVisitor(this);
+ if (session_->perspective() == Perspective::IS_CLIENT) {
+ context_is_known_ = true;
+ context_currently_registered_ = true;
+ }
}
void WebTransportHttp3::AssociateStream(QuicStreamId stream_id) {
@@ -74,7 +76,11 @@ void WebTransportHttp3::CloseAllAssociatedStreams() {
for (QuicStreamId id : streams) {
session_->ResetStream(id, QUIC_STREAM_WEBTRANSPORT_SESSION_GONE);
}
- session_->UnregisterHttp3FlowId(flow_id_);
+ if (context_currently_registered_) {
+ context_currently_registered_ = false;
+ connect_stream_->UnregisterHttp3DatagramContextId(context_id_);
+ }
+ connect_stream_->UnregisterHttp3DatagramRegistrationVisitor();
}
void WebTransportHttp3::HeadersReceived(const spdy::SpdyHeaderBlock& headers) {
@@ -153,21 +159,81 @@ WebTransportStream* WebTransportHttp3::OpenOutgoingUnidirectionalStream() {
}
MessageStatus WebTransportHttp3::SendOrQueueDatagram(QuicMemSlice datagram) {
- return session_->SendHttp3Datagram(
- flow_id_, absl::string_view(datagram.data(), datagram.length()));
+ return connect_stream_->SendHttp3Datagram(
+ context_id_, absl::string_view(datagram.data(), datagram.length()));
}
void WebTransportHttp3::SetDatagramMaxTimeInQueue(
QuicTime::Delta max_time_in_queue) {
- session_->SetMaxTimeInQueueForFlowId(flow_id_, max_time_in_queue);
+ connect_stream_->SetMaxDatagramTimeInQueue(max_time_in_queue);
}
-void WebTransportHttp3::OnHttp3Datagram(QuicDatagramFlowId flow_id,
- absl::string_view payload) {
- QUICHE_DCHECK_EQ(flow_id, flow_id_);
+void WebTransportHttp3::OnHttp3Datagram(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ absl::string_view payload) {
+ QUICHE_DCHECK_EQ(stream_id, connect_stream_->id());
+ QUICHE_DCHECK(context_id == context_id_);
visitor_->OnDatagramReceived(payload);
}
+void WebTransportHttp3::OnContextReceived(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != connect_stream_->id()) {
+ QUIC_BUG(WT3 bad datagram context registration)
+ << ENDPOINT << "Registered stream ID " << stream_id << ", expected "
+ << connect_stream_->id();
+ return;
+ }
+ if (!context_is_known_) {
+ context_is_known_ = true;
+ context_id_ = context_id;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Ignoring unexpected context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << connect_stream_->id();
+ return;
+ }
+ if (session_->perspective() == Perspective::IS_SERVER) {
+ if (context_currently_registered_) {
+ QUIC_DLOG(ERROR) << ENDPOINT << "Received duplicate context ID "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << connect_stream_->id();
+ session_->ResetStream(connect_stream_->id(), QUIC_STREAM_CANCELLED);
+ return;
+ }
+ context_currently_registered_ = true;
+ Http3DatagramContextExtensions reply_extensions;
+ connect_stream_->RegisterHttp3DatagramContextId(context_id_,
+ reply_extensions, this);
+ }
+}
+
+void WebTransportHttp3::OnContextClosed(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != connect_stream_->id()) {
+ QUIC_BUG(WT3 bad datagram context registration)
+ << ENDPOINT << "Closed context on stream ID " << stream_id
+ << ", expected " << connect_stream_->id();
+ return;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << ENDPOINT << "Ignoring unexpected close of context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << connect_stream_->id();
+ return;
+ }
+ QUIC_DLOG(INFO) << ENDPOINT << "Received datagram context close on stream ID "
+ << connect_stream_->id() << ", resetting stream";
+ session_->ResetStream(connect_stream_->id(), QUIC_STREAM_CANCELLED);
+}
+
WebTransportHttp3UnidirectionalStream::WebTransportHttp3UnidirectionalStream(
PendingStream* pending,
QuicSpdySession* session)
diff --git a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
index 667256ea515..df5c4f61bf7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
+++ b/chromium/net/third_party/quiche/src/quic/core/http/web_transport_http3.h
@@ -28,12 +28,11 @@ class QuicSpdyStream;
// <https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3>
class QUIC_EXPORT_PRIVATE WebTransportHttp3
: public WebTransportSession,
- public QuicSpdySession::Http3DatagramVisitor {
+ public QuicSpdyStream::Http3DatagramRegistrationVisitor,
+ public QuicSpdyStream::Http3DatagramVisitor {
public:
- WebTransportHttp3(QuicSpdySession* session,
- QuicSpdyStream* connect_stream,
- WebTransportSessionId id,
- QuicDatagramFlowId flow_id);
+ WebTransportHttp3(QuicSpdySession* session, QuicSpdyStream* connect_stream,
+ WebTransportSessionId id);
void HeadersReceived(const spdy::SpdyHeaderBlock& headers);
void SetVisitor(std::unique_ptr<WebTransportVisitor> visitor) {
@@ -42,6 +41,9 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3
WebTransportSessionId id() { return id_; }
bool ready() { return ready_; }
+ absl::optional<QuicDatagramContextId> context_id() const {
+ return context_id_;
+ }
void AssociateStream(QuicStreamId stream_id);
void OnStreamClosed(QuicStreamId stream_id) { streams_.erase(stream_id); }
@@ -63,16 +65,32 @@ class QUIC_EXPORT_PRIVATE WebTransportHttp3
MessageStatus SendOrQueueDatagram(QuicMemSlice datagram) override;
void SetDatagramMaxTimeInQueue(QuicTime::Delta max_time_in_queue) override;
- void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ // From QuicSpdyStream::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) override;
+ // From QuicSpdyStream::Http3DatagramRegistrationVisitor.
+ void OnContextReceived(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+ void OnContextClosed(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+
private:
QuicSpdySession* const session_; // Unowned.
QuicSpdyStream* const connect_stream_; // Unowned.
const WebTransportSessionId id_;
- const QuicDatagramFlowId flow_id_;
+ absl::optional<QuicDatagramContextId> context_id_;
// |ready_| is set to true when the peer has seen both sets of headers.
bool ready_ = false;
+ // Whether we know which |context_id_| to use. On the client this is always
+ // true, and on the server it becomes true when we receive a context
+ // registeration capsule.
+ bool context_is_known_ = false;
+ // Whether |context_id_| is currently registered with |connect_stream_|.
+ bool context_currently_registered_ = false;
std::unique_ptr<WebTransportVisitor> visitor_;
absl::flat_hash_set<QuicStreamId> streams_;
quiche::QuicheCircularDeque<QuicStreamId> incoming_bidirectional_streams_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
index 2ddf4b2498a..19128abf2ca 100644
--- a/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/legacy_quic_stream_id_manager.cc
@@ -7,7 +7,6 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/core/quic_versions.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -125,7 +124,7 @@ bool LegacyQuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
return largest_peer_created_stream_id_ ==
QuicUtils::GetInvalidStreamId(transport_version_) ||
id > largest_peer_created_stream_id_ ||
- QuicContainsKey(available_streams_, id);
+ available_streams_.contains(id);
}
bool LegacyQuicStreamIdManager::IsIncomingStream(QuicStreamId id) const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
index 495a58ffdfd..acd52c2ce33 100644
--- a/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/qpack/qpack_instruction_decoder.cc
@@ -86,8 +86,6 @@ bool QpackInstructionDecoder::Decode(absl::string_view data) {
return true;
}
}
-
- return true;
}
bool QpackInstructionDecoder::AtInstructionBoundary() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_alarm.cc b/chromium/net/third_party/quiche/src/quic/core/quic_alarm.cc
index bfef316ff62..81640a4c68e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_alarm.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_alarm.cc
@@ -4,30 +4,74 @@
#include "quic/core/quic_alarm.h"
+#include "quic/platform/api/quic_bug_tracker.h"
+#include "quic/platform/api/quic_flag_utils.h"
+#include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_stack_trace.h"
+
namespace quic {
QuicAlarm::QuicAlarm(QuicArenaScopedPtr<Delegate> delegate)
: delegate_(std::move(delegate)), deadline_(QuicTime::Zero()) {}
-QuicAlarm::~QuicAlarm() {}
+QuicAlarm::~QuicAlarm() {
+ if (GetQuicRestartFlag(quic_alarm_add_permanent_cancel) && IsSet()) {
+ QUIC_CODE_COUNT(quic_alarm_not_cancelled_in_dtor);
+ static uint64_t hit_count = 0;
+ ++hit_count;
+ if ((hit_count & (hit_count - 1)) == 0) {
+ QUIC_LOG(ERROR) << "QuicAlarm not cancelled at destruction. "
+ << QuicStackTrace();
+ }
+ }
+}
void QuicAlarm::Set(QuicTime new_deadline) {
QUICHE_DCHECK(!IsSet());
QUICHE_DCHECK(new_deadline.IsInitialized());
+
+ if (IsPermanentlyCancelled()) {
+ QUIC_BUG(quic_alarm_illegal_set)
+ << "Set called after alarm is permanently cancelled. new_deadline:"
+ << new_deadline;
+ return;
+ }
+
deadline_ = new_deadline;
SetImpl();
}
-void QuicAlarm::Cancel() {
- if (!IsSet()) {
- // Don't try to cancel an alarm that hasn't been set.
+void QuicAlarm::CancelInternal(bool permanent) {
+ if (!GetQuicRestartFlag(quic_alarm_add_permanent_cancel)) {
+ if (!IsSet()) {
+ // Don't try to cancel an alarm that hasn't been set.
+ return;
+ }
+ deadline_ = QuicTime::Zero();
+ CancelImpl();
return;
}
- deadline_ = QuicTime::Zero();
- CancelImpl();
+
+ if (IsSet()) {
+ deadline_ = QuicTime::Zero();
+ CancelImpl();
+ }
+
+ if (permanent) {
+ delegate_.reset();
+ }
}
+bool QuicAlarm::IsPermanentlyCancelled() const { return delegate_ == nullptr; }
+
void QuicAlarm::Update(QuicTime new_deadline, QuicTime::Delta granularity) {
+ if (IsPermanentlyCancelled()) {
+ QUIC_BUG(quic_alarm_illegal_update)
+ << "Update called after alarm is permanently cancelled. new_deadline:"
+ << new_deadline << ", granularity:" << granularity;
+ return;
+ }
+
if (!new_deadline.IsInitialized()) {
Cancel();
return;
@@ -55,7 +99,9 @@ void QuicAlarm::Fire() {
}
deadline_ = QuicTime::Zero();
- delegate_->OnAlarm();
+ if (!IsPermanentlyCancelled()) {
+ delegate_->OnAlarm();
+ }
}
void QuicAlarm::UpdateImpl() {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_alarm.h b/chromium/net/third_party/quiche/src/quic/core/quic_alarm.h
index 527d2e3c662..5080fd4b263 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_alarm.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_alarm.h
@@ -36,11 +36,18 @@ class QUIC_EXPORT_PRIVATE QuicAlarm {
// then Set().
void Set(QuicTime new_deadline);
- // Cancels the alarm. May be called repeatedly. Does not
- // guarantee that the underlying scheduling system will remove
- // the alarm's associated task, but guarantees that the
- // delegates OnAlarm method will not be called.
- void Cancel();
+ // Both PermanentCancel() and Cancel() can cancel the alarm. If permanent,
+ // future calls to Set() and Update() will become no-op except emitting an
+ // error log.
+ //
+ // Both may be called repeatedly. Does not guarantee that the underlying
+ // scheduling system will remove the alarm's associated task, but guarantees
+ // that the delegates OnAlarm method will not be called.
+ void PermanentCancel() { CancelInternal(true); }
+ void Cancel() { CancelInternal(false); }
+
+ // Return true if PermanentCancel() has been called.
+ bool IsPermanentlyCancelled() const;
// Cancels and sets the alarm if the |deadline| is farther from the current
// deadline than |granularity|, and otherwise does nothing. If |deadline| is
@@ -77,6 +84,8 @@ class QUIC_EXPORT_PRIVATE QuicAlarm {
void Fire();
private:
+ void CancelInternal(bool permanent);
+
QuicArenaScopedPtr<Delegate> delegate_;
QuicTime deadline_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_alarm_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_alarm_test.cc
index 8f7296c8e10..ab070022eec 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_alarm_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_alarm_test.cc
@@ -4,6 +4,7 @@
#include "quic/core/quic_alarm.h"
+#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_test.h"
using testing::Invoke;
@@ -111,6 +112,48 @@ TEST_F(QuicAlarmTest, Cancel) {
EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
}
+TEST_F(QuicAlarmTest, PermanentCancel) {
+ QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
+ alarm_.Set(deadline);
+ alarm_.PermanentCancel();
+ EXPECT_FALSE(alarm_.IsSet());
+ EXPECT_FALSE(alarm_.scheduled());
+ EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+
+ if (!GetQuicRestartFlag(quic_alarm_add_permanent_cancel)) {
+ alarm_.Set(deadline);
+ // When flag is false, PermanentCancel should work like a normal Cancel.
+ EXPECT_TRUE(alarm_.IsSet());
+ EXPECT_TRUE(alarm_.scheduled());
+ EXPECT_EQ(deadline, alarm_.deadline());
+ EXPECT_FALSE(alarm_.IsPermanentlyCancelled());
+ alarm_.PermanentCancel();
+ } else {
+ EXPECT_QUIC_BUG(alarm_.Set(deadline),
+ "Set called after alarm is permanently cancelled");
+ EXPECT_TRUE(alarm_.IsPermanentlyCancelled());
+ }
+ EXPECT_FALSE(alarm_.IsSet());
+ EXPECT_FALSE(alarm_.scheduled());
+ EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+
+ if (!GetQuicRestartFlag(quic_alarm_add_permanent_cancel)) {
+ alarm_.Update(deadline, QuicTime::Delta::Zero());
+ EXPECT_TRUE(alarm_.IsSet());
+ EXPECT_TRUE(alarm_.scheduled());
+ EXPECT_EQ(deadline, alarm_.deadline());
+ EXPECT_FALSE(alarm_.IsPermanentlyCancelled());
+ alarm_.PermanentCancel();
+ } else {
+ EXPECT_QUIC_BUG(alarm_.Update(deadline, QuicTime::Delta::Zero()),
+ "Update called after alarm is permanently cancelled");
+ EXPECT_TRUE(alarm_.IsPermanentlyCancelled());
+ }
+ EXPECT_FALSE(alarm_.IsSet());
+ EXPECT_FALSE(alarm_.scheduled());
+ EXPECT_EQ(QuicTime::Zero(), alarm_.deadline());
+}
+
TEST_F(QuicAlarmTest, Update) {
QuicTime deadline = QuicTime::Zero() + QuicTime::Delta::FromSeconds(7);
alarm_.Set(deadline);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
index a661a7ee76b..d3905e70064 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffer_allocator.h
@@ -9,6 +9,7 @@
#include <memory>
+#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_export.h"
namespace quic {
@@ -56,6 +57,58 @@ inline QuicUniqueBufferPtr MakeUniqueBuffer(QuicBufferAllocator* allocator,
QuicBufferDeleter(allocator));
}
+// QuicUniqueBufferPtr with a length attached to it. Similar to QuicMemSlice,
+// except unlike QuicMemSlice, QuicBuffer is mutable and is not
+// platform-specific. Also unlike QuicMemSlice, QuicBuffer can be empty.
+class QUIC_EXPORT_PRIVATE QuicBuffer {
+ public:
+ QuicBuffer() : buffer_(nullptr, QuicBufferDeleter(nullptr)), size_(0) {}
+ QuicBuffer(QuicBufferAllocator* allocator, size_t size)
+ : buffer_(MakeUniqueBuffer(allocator, size)), size_(size) {}
+
+ // Make sure the move constructor zeroes out the size field.
+ QuicBuffer(QuicBuffer&& other)
+ : buffer_(std::move(other.buffer_)), size_(other.size_) {
+ other.buffer_ = nullptr;
+ other.size_ = 0;
+ }
+ QuicBuffer& operator=(QuicBuffer&& other) {
+ buffer_ = std::move(other.buffer_);
+ size_ = other.size_;
+
+ other.buffer_ = nullptr;
+ other.size_ = 0;
+ return *this;
+ }
+
+ // Convenience method to initialize a QuicBuffer by copying from an existing
+ // one.
+ static QuicBuffer Copy(QuicBufferAllocator* allocator,
+ absl::string_view data) {
+ QuicBuffer result(allocator, data.size());
+ memcpy(result.data(), data.data(), data.size());
+ return result;
+ }
+
+ const char* data() const { return buffer_.get(); }
+ char* data() { return buffer_.get(); }
+ size_t size() const { return size_; }
+ bool empty() const { return size_ == 0; }
+ absl::string_view AsStringView() const {
+ return absl::string_view(data(), size());
+ }
+
+ // Releases the ownership of the underlying buffer.
+ QuicUniqueBufferPtr Release() {
+ size_ = 0;
+ return std::move(buffer_);
+ }
+
+ private:
+ QuicUniqueBufferPtr buffer_;
+ size_t size_;
+};
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_BUFFER_ALLOCATOR_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
index e4d4c971338..9312ea5deae 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.cc
@@ -8,7 +8,6 @@
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -77,7 +76,12 @@ QuicBufferedPacketStore::QuicBufferedPacketStore(
expiration_alarm_(
alarm_factory->CreateAlarm(new ConnectionExpireAlarm(this))) {}
-QuicBufferedPacketStore::~QuicBufferedPacketStore() {}
+QuicBufferedPacketStore::~QuicBufferedPacketStore() {
+ if (GetQuicRestartFlag(quic_alarm_add_permanent_cancel) &&
+ expiration_alarm_ != nullptr) {
+ expiration_alarm_->PermanentCancel();
+ }
+}
EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
QuicConnectionId connection_id,
@@ -92,15 +96,14 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
QUIC_BUG_IF(quic_bug_12410_1, !GetQuicFlag(FLAGS_quic_allow_chlo_buffering))
<< "Shouldn't buffer packets if disabled via flag.";
QUIC_BUG_IF(quic_bug_12410_2,
- is_chlo && QuicContainsKey(connections_with_chlo_, connection_id))
+ is_chlo && connections_with_chlo_.contains(connection_id))
<< "Shouldn't buffer duplicated CHLO on connection " << connection_id;
QUIC_BUG_IF(quic_bug_12410_3, !is_chlo && !alpns.empty())
<< "Shouldn't have an ALPN defined for a non-CHLO packet.";
QUIC_BUG_IF(quic_bug_12410_4, is_chlo && !version.IsKnown())
<< "Should have version for CHLO packet.";
- const bool is_first_packet =
- !QuicContainsKey(undecryptable_packets_, connection_id);
+ const bool is_first_packet = !undecryptable_packets_.contains(connection_id);
if (is_first_packet) {
if (ShouldNotBufferPacket(is_chlo)) {
// Drop the packet if the upper limit of undecryptable packets has been
@@ -112,17 +115,16 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
undecryptable_packets_.back().second.ietf_quic = ietf_quic;
undecryptable_packets_.back().second.version = version;
}
- QUICHE_CHECK(QuicContainsKey(undecryptable_packets_, connection_id));
+ QUICHE_CHECK(undecryptable_packets_.contains(connection_id));
BufferedPacketList& queue =
undecryptable_packets_.find(connection_id)->second;
if (!is_chlo) {
// If current packet is not CHLO, it might not be buffered because store
// only buffers certain number of undecryptable packets per connection.
- size_t num_non_chlo_packets =
- QuicContainsKey(connections_with_chlo_, connection_id)
- ? (queue.buffered_packets.size() - 1)
- : queue.buffered_packets.size();
+ size_t num_non_chlo_packets = connections_with_chlo_.contains(connection_id)
+ ? (queue.buffered_packets.size() - 1)
+ : queue.buffered_packets.size();
if (num_non_chlo_packets >= kDefaultMaxUndecryptablePackets) {
// If there are kMaxBufferedPacketsPerConnection packets buffered up for
// this connection, drop the current packet.
@@ -169,7 +171,7 @@ EnqueuePacketResult QuicBufferedPacketStore::EnqueuePacket(
bool QuicBufferedPacketStore::HasBufferedPackets(
QuicConnectionId connection_id) const {
- return QuicContainsKey(undecryptable_packets_, connection_id);
+ return undecryptable_packets_.contains(connection_id);
}
bool QuicBufferedPacketStore::HasChlosBuffered() const {
@@ -254,7 +256,7 @@ BufferedPacketList QuicBufferedPacketStore::DeliverPacketsForNextConnection(
bool QuicBufferedPacketStore::HasChloForConnection(
QuicConnectionId connection_id) {
- return QuicContainsKey(connections_with_chlo_, connection_id);
+ return connections_with_chlo_.contains(connection_id);
}
bool QuicBufferedPacketStore::IngestPacketForTlsChloExtraction(
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
index 29be2c86a42..5ba0a25ed0b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_buffered_packet_store.h
@@ -14,9 +14,9 @@
#include "quic/core/quic_packets.h"
#include "quic/core/quic_time.h"
#include "quic/core/tls_chlo_extractor.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -78,9 +78,9 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore {
TlsChloExtractor tls_chlo_extractor;
};
- using BufferedPacketMap = QuicLinkedHashMap<QuicConnectionId,
- BufferedPacketList,
- QuicConnectionIdHash>;
+ using BufferedPacketMap = quiche::QuicheLinkedHashMap<QuicConnectionId,
+ BufferedPacketList,
+ QuicConnectionIdHash>;
class QUIC_NO_EXPORT VisitorInterface {
public:
@@ -186,7 +186,7 @@ class QUIC_NO_EXPORT QuicBufferedPacketStore {
// Keeps track of connection with CHLO buffered up already and the order they
// arrive.
- QuicLinkedHashMap<QuicConnectionId, bool, QuicConnectionIdHash>
+ quiche::QuicheLinkedHashMap<QuicConnectionId, bool, QuicConnectionIdHash>
connections_with_chlo_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
index 09806f5a8a8..12bf186d318 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.cc
@@ -45,7 +45,6 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_hostname_utils.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_socket_address.h"
#include "common/quiche_text_utils.h"
@@ -63,13 +62,23 @@ const QuicPacketCount kMaxConsecutiveNonRetransmittablePackets = 19;
// The minimum release time into future in ms.
const int kMinReleaseTimeIntoFutureMs = 1;
-// An alarm that is scheduled to send an ack if a timeout occurs.
-class AckAlarmDelegate : public QuicAlarm::Delegate {
+// Base class of all alarms owned by a QuicConnection.
+class QuicConnectionAlarmDelegate : public QuicAlarm::Delegate {
public:
- explicit AckAlarmDelegate(QuicConnection* connection)
+ explicit QuicConnectionAlarmDelegate(QuicConnection* connection)
: connection_(connection) {}
- AckAlarmDelegate(const AckAlarmDelegate&) = delete;
- AckAlarmDelegate& operator=(const AckAlarmDelegate&) = delete;
+ QuicConnectionAlarmDelegate(const QuicConnectionAlarmDelegate&) = delete;
+ QuicConnectionAlarmDelegate& operator=(const QuicConnectionAlarmDelegate&) =
+ delete;
+
+ protected:
+ QuicConnection* connection_;
+};
+
+// An alarm that is scheduled to send an ack if a timeout occurs.
+class AckAlarmDelegate : public QuicConnectionAlarmDelegate {
+ public:
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->ack_frame_updated());
@@ -81,136 +90,86 @@ class AckAlarmDelegate : public QuicAlarm::Delegate {
connection_->SendAck();
}
}
-
- private:
- QuicConnection* connection_;
};
// This alarm will be scheduled any time a data-bearing packet is sent out.
// When the alarm goes off, the connection checks to see if the oldest packets
// have been acked, and retransmit them if they have not.
-class RetransmissionAlarmDelegate : public QuicAlarm::Delegate {
+class RetransmissionAlarmDelegate : public QuicConnectionAlarmDelegate {
public:
- explicit RetransmissionAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- RetransmissionAlarmDelegate(const RetransmissionAlarmDelegate&) = delete;
- RetransmissionAlarmDelegate& operator=(const RetransmissionAlarmDelegate&) =
- delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
connection_->OnRetransmissionTimeout();
}
-
- private:
- QuicConnection* connection_;
};
// An alarm that is scheduled when the SentPacketManager requires a delay
// before sending packets and fires when the packet may be sent.
-class SendAlarmDelegate : public QuicAlarm::Delegate {
+class SendAlarmDelegate : public QuicConnectionAlarmDelegate {
public:
- explicit SendAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- SendAlarmDelegate(const SendAlarmDelegate&) = delete;
- SendAlarmDelegate& operator=(const SendAlarmDelegate&) = delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
connection_->WriteIfNotBlocked();
}
-
- private:
- QuicConnection* connection_;
};
-class PingAlarmDelegate : public QuicAlarm::Delegate {
+class PingAlarmDelegate : public QuicConnectionAlarmDelegate {
public:
- explicit PingAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- PingAlarmDelegate(const PingAlarmDelegate&) = delete;
- PingAlarmDelegate& operator=(const PingAlarmDelegate&) = delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
connection_->OnPingTimeout();
}
-
- private:
- QuicConnection* connection_;
};
-class MtuDiscoveryAlarmDelegate : public QuicAlarm::Delegate {
+class MtuDiscoveryAlarmDelegate : public QuicConnectionAlarmDelegate {
public:
- explicit MtuDiscoveryAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- MtuDiscoveryAlarmDelegate(const MtuDiscoveryAlarmDelegate&) = delete;
- MtuDiscoveryAlarmDelegate& operator=(const MtuDiscoveryAlarmDelegate&) =
- delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
connection_->DiscoverMtu();
}
-
- private:
- QuicConnection* connection_;
};
-class ProcessUndecryptablePacketsAlarmDelegate : public QuicAlarm::Delegate {
+class ProcessUndecryptablePacketsAlarmDelegate
+ : public QuicConnectionAlarmDelegate {
public:
- explicit ProcessUndecryptablePacketsAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- ProcessUndecryptablePacketsAlarmDelegate(
- const ProcessUndecryptablePacketsAlarmDelegate&) = delete;
- ProcessUndecryptablePacketsAlarmDelegate& operator=(
- const ProcessUndecryptablePacketsAlarmDelegate&) = delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
QuicConnection::ScopedPacketFlusher flusher(connection_);
connection_->MaybeProcessUndecryptablePackets();
}
-
- private:
- QuicConnection* connection_;
};
-class DiscardPreviousOneRttKeysAlarmDelegate : public QuicAlarm::Delegate {
+class DiscardPreviousOneRttKeysAlarmDelegate
+ : public QuicConnectionAlarmDelegate {
public:
- explicit DiscardPreviousOneRttKeysAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- DiscardPreviousOneRttKeysAlarmDelegate(
- const DiscardPreviousOneRttKeysAlarmDelegate&) = delete;
- DiscardPreviousOneRttKeysAlarmDelegate& operator=(
- const DiscardPreviousOneRttKeysAlarmDelegate&) = delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
connection_->DiscardPreviousOneRttKeys();
}
-
- private:
- QuicConnection* connection_;
};
-class DiscardZeroRttDecryptionKeysAlarmDelegate : public QuicAlarm::Delegate {
+class DiscardZeroRttDecryptionKeysAlarmDelegate
+ : public QuicConnectionAlarmDelegate {
public:
- explicit DiscardZeroRttDecryptionKeysAlarmDelegate(QuicConnection* connection)
- : connection_(connection) {}
- DiscardZeroRttDecryptionKeysAlarmDelegate(
- const DiscardZeroRttDecryptionKeysAlarmDelegate&) = delete;
- DiscardZeroRttDecryptionKeysAlarmDelegate& operator=(
- const DiscardZeroRttDecryptionKeysAlarmDelegate&) = delete;
+ using QuicConnectionAlarmDelegate::QuicConnectionAlarmDelegate;
void OnAlarm() override {
QUICHE_DCHECK(connection_->connected());
QUIC_DLOG(INFO) << "0-RTT discard alarm fired";
connection_->RemoveDecrypter(ENCRYPTION_ZERO_RTT);
}
-
- private:
- QuicConnection* connection_;
};
// When the clearer goes out of scope, the coalesced packet gets cleared.
@@ -278,8 +237,6 @@ QuicConnection::QuicConnection(
encryption_level_(ENCRYPTION_INITIAL),
clock_(helper->GetClock()),
random_generator_(helper->GetRandomGenerator()),
- server_connection_id_(server_connection_id),
- client_connection_id_(EmptyQuicConnectionId()),
client_connection_id_is_set_(false),
direct_peer_address_(initial_peer_address),
default_path_(initial_self_address,
@@ -335,7 +292,7 @@ QuicConnection::QuicConnection(
visitor_(nullptr),
debug_visitor_(nullptr),
packet_creator_(server_connection_id, &framer_, random_generator_, this),
- time_of_last_received_packet_(clock_->ApproximateNow()),
+ last_received_packet_info_(clock_->ApproximateNow()),
sent_packet_manager_(perspective,
clock_,
random_generator_,
@@ -357,8 +314,6 @@ QuicConnection::QuicConnection(
bundle_retransmittable_with_pto_ack_(false),
fill_up_link_during_probing_(false),
probing_retransmission_pending_(false),
- stateless_reset_token_received_(false),
- received_stateless_reset_token_({}),
last_control_frame_id_(kInvalidControlFrameId),
is_path_degrading_(false),
processing_ack_frame_(false),
@@ -369,18 +324,13 @@ QuicConnection::QuicConnection(
clock_->ApproximateNow(),
&arena_,
alarm_factory_),
- encrypted_control_frames_(
- GetQuicReloadableFlag(quic_encrypted_control_frames)),
- use_encryption_level_context_(
- encrypted_control_frames_ &&
- GetQuicReloadableFlag(quic_use_encryption_level_context)),
path_validator_(alarm_factory_, &arena_, this, random_generator_),
most_recent_frame_type_(NUM_FRAME_TYPES) {
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
default_path_.self_address.IsInitialized());
- if (use_encryption_level_context_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_use_encryption_level_context);
+ if (add_missing_update_ack_timeout_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_add_missing_update_ack_timeout);
}
support_multiple_connection_ids_ =
@@ -417,7 +367,7 @@ QuicConnection::QuicConnection(
MaybeEnableMultiplePacketNumberSpacesSupport();
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT ||
supported_versions.size() == 1);
- InstallInitialCrypters(ServerConnectionId());
+ InstallInitialCrypters(default_path_.server_connection_id);
// On the server side, version negotiation has been done by the dispatcher,
// and the server connection is created with the right version.
@@ -482,9 +432,9 @@ bool QuicConnection::ValidateConfigConnectionIds(const QuicConfig& config) {
// Validate initial_source_connection_id.
QuicConnectionId expected_initial_source_connection_id;
if (perspective_ == Perspective::IS_CLIENT) {
- expected_initial_source_connection_id = ServerConnectionId();
+ expected_initial_source_connection_id = default_path_.server_connection_id;
} else {
- expected_initial_source_connection_id = ClientConnectionId();
+ expected_initial_source_connection_id = default_path_.client_connection_id;
}
if (!config.HasReceivedInitialSourceConnectionId() ||
config.ReceivedInitialSourceConnectionId() !=
@@ -682,14 +632,8 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
no_stop_waiting_frames_ = true;
}
if (config.HasReceivedStatelessResetToken()) {
- if (use_connection_id_on_default_path_) {
- default_path_.stateless_reset_token_received = true;
- default_path_.stateless_reset_token =
- config.ReceivedStatelessResetToken();
- } else {
- stateless_reset_token_received_ = true;
- received_stateless_reset_token_ = config.ReceivedStatelessResetToken();
- }
+ default_path_.stateless_reset_token_received = true;
+ default_path_.stateless_reset_token = config.ReceivedStatelessResetToken();
}
if (config.HasReceivedAckDelayExponent()) {
framer_.set_peer_ack_delay_exponent(config.ReceivedAckDelayExponent());
@@ -720,7 +664,6 @@ void QuicConnection::SetFromConfig(const QuicConfig& config) {
// 2) Client side's rollout can be protected by the same connection option.
connection_migration_use_new_cid_ =
support_multiple_connection_ids_ && validate_client_addresses_ &&
- use_connection_id_on_default_path_ &&
group_path_response_and_challenge_sending_closer_ &&
GetQuicReloadableFlag(quic_drop_unsent_path_response) &&
GetQuicReloadableFlag(quic_connection_migration_use_new_cid_v2);
@@ -858,7 +801,8 @@ bool QuicConnection::SelectMutualVersion(
framer_.supported_versions();
for (size_t i = 0; i < supported_versions.size(); ++i) {
const ParsedQuicVersion& version = supported_versions[i];
- if (QuicContainsValue(available_versions, version)) {
+ if (std::find(available_versions.begin(), available_versions.end(),
+ version) != available_versions.end()) {
framer_.set_version(version);
return true;
}
@@ -885,7 +829,7 @@ void QuicConnection::OnPublicResetPacket(const QuicPublicResetPacket& packet) {
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- QUICHE_DCHECK_EQ(ServerConnectionId(), packet.connection_id);
+ QUICHE_DCHECK_EQ(default_path_.server_connection_id, packet.connection_id);
QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
QUICHE_DCHECK(!version().HasIetfInvariantHeader());
if (debug_visitor_ != nullptr) {
@@ -923,7 +867,7 @@ void QuicConnection::OnVersionNegotiationPacket(
// Check that any public reset packet with a different connection ID that was
// routed to this QuicConnection has been redirected before control reaches
// here. (Check for a bug regression.)
- QUICHE_DCHECK_EQ(ServerConnectionId(), packet.connection_id);
+ QUICHE_DCHECK_EQ(default_path_.server_connection_id, packet.connection_id);
if (perspective_ == Perspective::IS_SERVER) {
const std::string error_details =
"Server received version negotiation packet.";
@@ -942,7 +886,8 @@ void QuicConnection::OnVersionNegotiationPacket(
return;
}
- if (QuicContainsValue(packet.versions, version())) {
+ if (std::find(packet.versions.begin(), packet.versions.end(), version()) !=
+ packet.versions.end()) {
const std::string error_details = absl::StrCat(
"Server already supports client's version ",
ParsedQuicVersionToString(version()),
@@ -974,17 +919,17 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
absl::string_view retry_without_tag) {
QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
if (version().UsesTls()) {
- if (!CryptoUtils::ValidateRetryIntegrityTag(version(), ServerConnectionId(),
- retry_without_tag,
- retry_integrity_tag)) {
+ if (!CryptoUtils::ValidateRetryIntegrityTag(
+ version(), default_path_.server_connection_id, retry_without_tag,
+ retry_integrity_tag)) {
QUIC_DLOG(ERROR) << "Ignoring RETRY with invalid integrity tag";
return;
}
} else {
- if (original_connection_id != ServerConnectionId()) {
+ if (original_connection_id != default_path_.server_connection_id) {
QUIC_DLOG(ERROR) << "Ignoring RETRY with original connection ID "
<< original_connection_id << " not matching expected "
- << ServerConnectionId() << " token "
+ << default_path_.server_connection_id << " token "
<< absl::BytesToHexString(retry_token);
return;
}
@@ -992,10 +937,11 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
framer_.set_drop_incoming_retry_packets(true);
stats_.retry_packet_processed = true;
QUIC_DLOG(INFO) << "Received RETRY, replacing connection ID "
- << ServerConnectionId() << " with " << new_connection_id
- << ", received token " << absl::BytesToHexString(retry_token);
+ << default_path_.server_connection_id << " with "
+ << new_connection_id << ", received token "
+ << absl::BytesToHexString(retry_token);
if (!original_destination_connection_id_.has_value()) {
- original_destination_connection_id_ = ServerConnectionId();
+ original_destination_connection_id_ = default_path_.server_connection_id;
}
QUICHE_DCHECK(!retry_source_connection_id_.has_value())
<< retry_source_connection_id_.value();
@@ -1004,51 +950,32 @@ void QuicConnection::OnRetryPacket(QuicConnectionId original_connection_id,
packet_creator_.SetRetryToken(retry_token);
// Reinstall initial crypters because the connection ID changed.
- InstallInitialCrypters(ServerConnectionId());
+ InstallInitialCrypters(default_path_.server_connection_id);
sent_packet_manager_.MarkInitialPacketsForRetransmission();
}
-bool QuicConnection::HasIncomingConnectionId(
- QuicConnectionId connection_id) const {
- if (quic_deprecate_incoming_connection_ids_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_deprecate_incoming_connection_ids);
- // TODO(haoyuewang) Inline this after the flag is deprecated.
- return connection_id == original_destination_connection_id_;
- }
- for (QuicConnectionId const& incoming_connection_id :
- incoming_connection_ids_) {
- if (incoming_connection_id == connection_id) {
- return true;
- }
- }
- return false;
-}
-
void QuicConnection::SetOriginalDestinationConnectionId(
const QuicConnectionId& original_destination_connection_id) {
QUIC_DLOG(INFO) << "Setting original_destination_connection_id to "
<< original_destination_connection_id
<< " on connection with server_connection_id "
- << ServerConnectionId();
- QUICHE_DCHECK_NE(original_destination_connection_id, ServerConnectionId());
- if (!quic_deprecate_incoming_connection_ids_) {
- if (!HasIncomingConnectionId(original_destination_connection_id)) {
- incoming_connection_ids_.push_back(original_destination_connection_id);
- }
- }
+ << default_path_.server_connection_id;
+ QUICHE_DCHECK_NE(original_destination_connection_id,
+ default_path_.server_connection_id);
InstallInitialCrypters(original_destination_connection_id);
QUICHE_DCHECK(!original_destination_connection_id_.has_value())
<< original_destination_connection_id_.value();
original_destination_connection_id_ = original_destination_connection_id;
- original_destination_connection_id_replacement_ = ServerConnectionId();
+ original_destination_connection_id_replacement_ =
+ default_path_.server_connection_id;
}
QuicConnectionId QuicConnection::GetOriginalDestinationConnectionId() {
if (original_destination_connection_id_.has_value()) {
return original_destination_connection_id_.value();
}
- return ServerConnectionId();
+ return default_path_.server_connection_id;
}
bool QuicConnection::ValidateServerConnectionId(
@@ -1061,15 +988,15 @@ bool QuicConnection::ValidateServerConnectionId(
QuicConnectionId server_connection_id =
GetServerConnectionIdAsRecipient(header, perspective_);
- if (server_connection_id == ServerConnectionId() ||
- HasIncomingConnectionId(server_connection_id)) {
+ if (server_connection_id == default_path_.server_connection_id ||
+ server_connection_id == original_destination_connection_id_) {
return true;
}
if (PacketCanReplaceServerConnectionId(header, perspective_)) {
QUIC_DLOG(INFO) << ENDPOINT << "Accepting packet with new connection ID "
<< server_connection_id << " instead of "
- << ServerConnectionId();
+ << default_path_.server_connection_id;
return true;
}
@@ -1089,13 +1016,10 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
// If last packet destination connection ID is the original server
// connection ID chosen by client, replaces it with the connection ID chosen
// by server.
- if (use_connection_id_on_default_path_ &&
- perspective_ == Perspective::IS_SERVER &&
+ if (perspective_ == Perspective::IS_SERVER &&
original_destination_connection_id_.has_value() &&
last_packet_destination_connection_id_ ==
*original_destination_connection_id_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 3,
- 3);
last_packet_destination_connection_id_ =
original_destination_connection_id_replacement_;
}
@@ -1112,7 +1036,7 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
QUIC_DLOG(INFO) << ENDPOINT
<< "Ignoring packet from unexpected server connection ID "
<< server_connection_id << " instead of "
- << ServerConnectionId();
+ << default_path_.server_connection_id;
if (debug_visitor_ != nullptr) {
debug_visitor_->OnIncorrectConnectionId(server_connection_id);
}
@@ -1135,7 +1059,7 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
QuicConnectionId client_connection_id =
GetClientConnectionIdAsRecipient(header, perspective_);
- if (client_connection_id == ClientConnectionId()) {
+ if (client_connection_id == default_path_.client_connection_id) {
return true;
}
@@ -1158,7 +1082,7 @@ bool QuicConnection::OnUnauthenticatedPublicHeader(
QUIC_DLOG(INFO) << ENDPOINT
<< "Ignoring packet from unexpected client connection ID "
<< client_connection_id << " instead of "
- << ClientConnectionId();
+ << default_path_.client_connection_id;
return false;
}
@@ -1261,7 +1185,8 @@ void QuicConnection::OnDecryptedPacket(size_t /*length*/,
default_path_.validated = true;
stats_.address_validated_via_decrypting_packet = true;
}
- idle_network_detector_.OnPacketReceived(time_of_last_received_packet_);
+ idle_network_detector_.OnPacketReceived(
+ last_received_packet_info_.receipt_time);
visitor_->OnPacketDecrypted(level);
}
@@ -1270,7 +1195,7 @@ QuicSocketAddress QuicConnection::GetEffectivePeerAddressFromCurrentPacket()
const {
// By default, the connection is not proxied, and the effective peer address
// is the packet's source address, i.e. the direct peer address.
- return last_packet_source_address_;
+ return last_received_packet_info_.source_address;
}
bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
@@ -1300,7 +1225,7 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
// for client connections.
// TODO(fayang): only change peer addresses in application data packet
// number space.
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
default_path_.peer_address = GetEffectivePeerAddressFromCurrentPacket();
}
} else {
@@ -1338,19 +1263,20 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
// last_packet_destination_connection_id_ has the advantage that it is
// still present in the session map since the packet can be routed here
// regardless of packet reordering.
- if (IsDefaultPath(last_packet_destination_address_,
+ if (IsDefaultPath(last_received_packet_info_.destination_address,
effective_peer_address)) {
default_path_.server_connection_id =
last_packet_destination_connection_id_;
- } else if (IsAlternativePath(last_packet_destination_address_,
- effective_peer_address)) {
+ } else if (IsAlternativePath(
+ last_received_packet_info_.destination_address,
+ effective_peer_address)) {
alternative_path_.server_connection_id =
last_packet_destination_connection_id_;
}
}
- if (use_connection_id_on_default_path_ &&
- last_packet_destination_connection_id_ != ServerConnectionId() &&
+ if (last_packet_destination_connection_id_ !=
+ default_path_.server_connection_id &&
(!original_destination_connection_id_.has_value() ||
last_packet_destination_connection_id_ !=
*original_destination_connection_id_)) {
@@ -1374,9 +1300,15 @@ bool QuicConnection::OnPacketHeader(const QuicPacketHeader& header) {
// Record packet receipt to populate ack info before processing stream
// frames, since the processing may result in sending a bundled ack.
+ QuicTime receipt_time = idle_network_detector_.time_of_last_received_packet();
+ if (reset_per_packet_state_for_undecryptable_packets_ &&
+ SupportsMultiplePacketNumberSpaces()) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_reset_per_packet_state_for_undecryptable_packets, 2, 2);
+ receipt_time = last_received_packet_info_.receipt_time;
+ }
uber_received_packet_manager_.RecordPacketReceived(
- last_decrypted_packet_level_, last_header_,
- idle_network_detector_.time_of_last_received_packet());
+ last_decrypted_packet_level_, last_header_, receipt_time);
if (EnforceAntiAmplificationLimit() && !IsHandshakeConfirmed() &&
!header.retry_token.empty() &&
visitor_->ValidateToken(header.retry_token)) {
@@ -1422,6 +1354,9 @@ bool QuicConnection::OnStreamFrame(const QuicStreamFrame& frame) {
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
+ // TODO(fayang): Consider moving UpdatePacketContent and
+ // MaybeUpdateAckTimeout to a stand-alone function instead of calling them for
+ // all frames.
MaybeUpdateAckTimeout();
visitor_->OnStreamFrame(frame);
stats_.stream_bytes_received += frame.data_length;
@@ -1730,7 +1665,9 @@ bool QuicConnection::OnStopSendingFrame(const QuicStopSendingFrame& frame) {
QUIC_DLOG(INFO) << ENDPOINT << "STOP_SENDING frame received for stream: "
<< frame.stream_id
<< " with error: " << frame.ietf_error_code;
-
+ if (add_missing_update_ack_timeout_) {
+ MaybeUpdateAckTimeout();
+ }
visitor_->OnStopSendingFrame(frame);
return connected_;
}
@@ -1777,7 +1714,7 @@ bool QuicConnection::OnPathChallengeFrame(const QuicPathChallengeFrame& frame) {
group_path_response_and_challenge_sending_closer_
? nullptr
: std::make_unique<QuicPacketCreator::ScopedPeerAddressContext>(
- &packet_creator_, last_packet_source_address_,
+ &packet_creator_, last_received_packet_info_.source_address,
/*update_connection_id=*/false);
if (!OnPathChallengeFrameInternal(frame)) {
return false;
@@ -1802,12 +1739,12 @@ bool QuicConnection::OnPathChallengeFrameInternal(
GetEffectivePeerAddressFromCurrentPacket();
if (group_path_response_and_challenge_sending_closer_) {
QuicConnectionId client_cid, server_cid;
- FindOnPathConnectionIds(last_packet_destination_address_,
+ FindOnPathConnectionIds(last_received_packet_info_.destination_address,
current_effective_peer_address, &client_cid,
&server_cid);
context = std::make_unique<QuicPacketCreator::ScopedPeerAddressContext>(
- &packet_creator_, last_packet_source_address_, client_cid, server_cid,
- connection_migration_use_new_cid_);
+ &packet_creator_, last_received_packet_info_.source_address, client_cid,
+ server_cid, connection_migration_use_new_cid_);
}
if (should_proactively_validate_peer_address_on_path_challenge_) {
QUIC_RELOADABLE_FLAG_COUNT(
@@ -1821,7 +1758,8 @@ bool QuicConnection::OnPathChallengeFrameInternal(
<< current_effective_peer_address;
QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 2, 6);
ValidatePath(std::make_unique<ReversePathValidationContext>(
- default_path_.self_address, last_packet_source_address_,
+ default_path_.self_address,
+ last_received_packet_info_.source_address,
current_effective_peer_address, this),
std::make_unique<ReversePathValidationResultDelegate>(
this, peer_address()));
@@ -1840,9 +1778,9 @@ bool QuicConnection::OnPathChallengeFrameInternal(
// Queue or send PATH_RESPONSE. Send PATH_RESPONSE to the source address of
// the current incoming packet, even if it's not the default path or the
// alternative path.
- const bool success =
- SendPathResponse(frame.data_buffer, last_packet_source_address_,
- current_effective_peer_address);
+ const bool success = SendPathResponse(
+ frame.data_buffer, last_received_packet_info_.source_address,
+ current_effective_peer_address);
if (GetQuicReloadableFlag(quic_drop_unsent_path_response)) {
QUIC_RELOADABLE_FLAG_COUNT(quic_drop_unsent_path_response);
}
@@ -1851,7 +1789,7 @@ bool QuicConnection::OnPathChallengeFrameInternal(
if (!GetQuicReloadableFlag(quic_drop_unsent_path_response)) {
// Queue the payloads to re-try later.
pending_path_challenge_payloads_.push_back(
- {frame.data_buffer, last_packet_source_address_});
+ {frame.data_buffer, last_received_packet_info_.source_address});
}
}
// TODO(b/150095588): change the stats to
@@ -1876,8 +1814,8 @@ bool QuicConnection::OnPathResponseFrame(const QuicPathResponseFrame& frame) {
MaybeUpdateAckTimeout();
if (use_path_validator_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 1, 4);
- path_validator_.OnPathResponse(frame.data_buffer,
- last_packet_destination_address_);
+ path_validator_.OnPathResponse(
+ frame.data_buffer, last_received_packet_info_.destination_address);
} else {
if (!transmitted_connectivity_probe_payload_ ||
*transmitted_connectivity_probe_payload_ != frame.data_buffer) {
@@ -1953,6 +1891,9 @@ bool QuicConnection::OnMaxStreamsFrame(const QuicMaxStreamsFrame& frame) {
if (debug_visitor_ != nullptr) {
debug_visitor_->OnMaxStreamsFrame(frame);
}
+ if (add_missing_update_ack_timeout_) {
+ MaybeUpdateAckTimeout();
+ }
return visitor_->OnMaxStreamsFrame(frame) && connected_;
}
@@ -1969,6 +1910,9 @@ bool QuicConnection::OnStreamsBlockedFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnStreamsBlockedFrame(frame);
}
+ if (add_missing_update_ack_timeout_) {
+ MaybeUpdateAckTimeout();
+ }
return visitor_->OnStreamsBlockedFrame(frame) && connected_;
}
@@ -2018,12 +1962,14 @@ bool QuicConnection::OnWindowUpdateFrame(const QuicWindowUpdateFrame& frame) {
}
void QuicConnection::OnClientConnectionIdAvailable() {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 3, 5);
QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
if (!peer_issued_cid_manager_->HasUnusedConnectionId()) {
return;
}
if (default_path_.client_connection_id.IsEmpty()) {
+ // Count client connection ID patched onto the default path.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 3,
+ 6);
const QuicConnectionIdData* unused_cid_data =
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
@@ -2039,6 +1985,9 @@ void QuicConnection::OnClientConnectionIdAvailable() {
}
if (alternative_path_.peer_address.IsInitialized() &&
alternative_path_.client_connection_id.IsEmpty()) {
+ // Count client connection ID patched onto the alternative path.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 4,
+ 6);
const QuicConnectionIdData* unused_cid_data =
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
QUIC_DVLOG(1) << ENDPOINT << "Patch connection ID "
@@ -2050,6 +1999,28 @@ void QuicConnection::OnClientConnectionIdAvailable() {
}
}
+bool QuicConnection::ShouldSetRetransmissionAlarmOnPacketSent(
+ bool in_flight, EncryptionLevel level) const {
+ if (!retransmission_alarm_->IsSet()) {
+ return true;
+ }
+ if (!in_flight) {
+ return false;
+ }
+
+ if (!SupportsMultiplePacketNumberSpaces()) {
+ return true;
+ }
+ // Before handshake gets confirmed, do not re-arm PTO timer on application
+ // data. Think about this scenario: on the client side, the CHLO gets
+ // acknowledged and the SHLO is not received yet. The PTO alarm is set when
+ // the CHLO acknowledge is received (and there is no in flight INITIAL
+ // packet). Re-arming PTO alarm on 0-RTT packet would keep postponing the PTO
+ // alarm.
+ return IsHandshakeConfirmed() || level == ENCRYPTION_INITIAL ||
+ level == ENCRYPTION_HANDSHAKE;
+}
+
bool QuicConnection::OnNewConnectionIdFrameInner(
const QuicNewConnectionIdFrame& frame) {
QUICHE_DCHECK(support_multiple_connection_ids_);
@@ -2068,11 +2039,14 @@ bool QuicConnection::OnNewConnectionIdFrameInner(
ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET);
return false;
}
- if (use_connection_id_on_default_path_ &&
- perspective_ == Perspective::IS_SERVER) {
+ if (perspective_ == Perspective::IS_SERVER) {
OnClientConnectionIdAvailable();
}
QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 1, 2);
+ if (ack_cid_frames_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_ack_cid_frames, 1, 2);
+ MaybeUpdateAckTimeout();
+ }
return true;
}
@@ -2108,8 +2082,7 @@ bool QuicConnection::OnRetireConnectionIdFrame(
if (debug_visitor_ != nullptr) {
debug_visitor_->OnRetireConnectionIdFrame(frame);
}
- if (use_connection_id_on_default_path_ &&
- !connection_migration_use_new_cid_) {
+ if (!connection_migration_use_new_cid_) {
// Do not respond to RetireConnectionId frame.
return true;
}
@@ -2132,6 +2105,12 @@ bool QuicConnection::OnRetireConnectionIdFrame(
return false;
}
QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_support_multiple_cids_v4, 2, 2);
+ // Count successfully received RETIRE_CONNECTION_ID frames.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 6);
+ if (ack_cid_frames_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_ack_cid_frames, 2, 2);
+ MaybeUpdateAckTimeout();
+ }
return true;
}
@@ -2311,8 +2290,8 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
if (perspective_ == Perspective::IS_CLIENT) {
// This node is a client, notify that a speculative connectivity probing
// packet has been received anyway.
- visitor_->OnPacketReceived(last_packet_destination_address_,
- last_packet_source_address_,
+ visitor_->OnPacketReceived(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address,
/*is_connectivity_probe=*/false);
return;
}
@@ -2325,29 +2304,31 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
// If the packet contains PATH CHALLENGE, send appropriate RESPONSE.
// There was at least one PATH CHALLENGE in the received packet,
// Generate the required PATH RESPONSE.
- SendGenericPathProbePacket(nullptr, last_packet_source_address_,
+ SendGenericPathProbePacket(nullptr,
+ last_received_packet_info_.source_address,
/* is_response=*/true);
return;
}
} else {
if (IsCurrentPacketConnectivityProbing()) {
- visitor_->OnPacketReceived(last_packet_destination_address_,
- last_packet_source_address_,
+ visitor_->OnPacketReceived(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address,
/*is_connectivity_probe=*/true);
return;
}
if (perspective_ == Perspective::IS_CLIENT) {
// This node is a client, notify that a speculative connectivity probing
// packet has been received anyway.
- QUIC_DVLOG(1) << ENDPOINT
- << "Received a speculative connectivity probing packet for "
- << GetServerConnectionIdAsRecipient(last_header_,
- perspective_)
- << " from ip:port: "
- << last_packet_source_address_.ToString() << " to ip:port: "
- << last_packet_destination_address_.ToString();
- visitor_->OnPacketReceived(last_packet_destination_address_,
- last_packet_source_address_,
+ QUIC_DVLOG(1)
+ << ENDPOINT
+ << "Received a speculative connectivity probing packet for "
+ << GetServerConnectionIdAsRecipient(last_header_, perspective_)
+ << " from ip:port: "
+ << last_received_packet_info_.source_address.ToString()
+ << " to ip:port: "
+ << last_received_packet_info_.destination_address.ToString();
+ visitor_->OnPacketReceived(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address,
/*is_connectivity_probe=*/false);
return;
}
@@ -2356,12 +2337,10 @@ void QuicConnection::MaybeRespondToConnectivityProbingOrMigration() {
bool QuicConnection::IsValidStatelessResetToken(
const StatelessResetToken& token) const {
- if (use_connection_id_on_default_path_) {
+ QUICHE_DCHECK_EQ(perspective_, Perspective::IS_CLIENT);
return default_path_.stateless_reset_token_received &&
- token == default_path_.stateless_reset_token;
- }
- return stateless_reset_token_received_ &&
- token == received_stateless_reset_token_;
+ QuicUtils::AreStatelessResetTokensEqual(
+ token, default_path_.stateless_reset_token);
}
void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
@@ -2373,10 +2352,10 @@ void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
if (use_path_validator_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_pass_path_response_to_validator, 4, 4);
- if (!IsDefaultPath(last_packet_destination_address_,
- last_packet_source_address_)) {
+ if (!IsDefaultPath(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address)) {
// This packet is received on a probing path. Do not close connection.
- if (IsAlternativePath(last_packet_destination_address_,
+ if (IsAlternativePath(last_received_packet_info_.destination_address,
GetEffectivePeerAddressFromCurrentPacket())) {
QUIC_BUG_IF(quic_bug_12714_18, alternative_path_.validated)
<< "STATELESS_RESET received on alternate path after it's "
@@ -2388,8 +2367,9 @@ void QuicConnection::OnAuthenticatedIetfStatelessResetPacket(
}
return;
}
- } else if (!visitor_->ValidateStatelessReset(last_packet_destination_address_,
- last_packet_source_address_)) {
+ } else if (!visitor_->ValidateStatelessReset(
+ last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address)) {
// This packet is received on a probing path. Do not close connection.
return;
}
@@ -2570,15 +2550,12 @@ QuicConsumedData QuicConnection::SendStreamData(QuicStreamId id,
}
if (perspective_ == Perspective::IS_SERVER &&
version().CanSendCoalescedPackets() && !IsHandshakeConfirmed()) {
- if (GetQuicReloadableFlag(quic_donot_pto_half_rtt_data)) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_donot_pto_half_rtt_data);
- if (in_on_retransmission_time_out_ &&
- coalesced_packet_.NumberOfPackets() == 0u) {
- // PTO fires while handshake is not confirmed. Do not preempt handshake
- // data with stream data.
- QUIC_CODE_COUNT(quic_try_to_send_half_rtt_data_when_pto_fires);
- return QuicConsumedData(0, false);
- }
+ if (in_on_retransmission_time_out_ &&
+ coalesced_packet_.NumberOfPackets() == 0u) {
+ // PTO fires while handshake is not confirmed. Do not preempt handshake
+ // data with stream data.
+ QUIC_CODE_COUNT(quic_try_to_send_half_rtt_data_when_pto_fires);
+ return QuicConsumedData(0, false);
}
if (coalesced_packet_.ContainsPacketOfEncryptionLevel(ENCRYPTION_INITIAL) &&
coalesced_packet_.NumberOfPackets() == 1u) {
@@ -2739,25 +2716,38 @@ void QuicConnection::OnUndecryptablePacket(const QuicEncryptedPacket& packet,
}
bool QuicConnection::ShouldEnqueueUnDecryptablePacket(
- EncryptionLevel decryption_level,
- bool has_decryption_key) const {
- if (encryption_level_ == ENCRYPTION_FORWARD_SECURE) {
+ EncryptionLevel decryption_level, bool has_decryption_key) const {
+ if (!GetQuicReloadableFlag(quic_queue_until_handshake_complete) &&
+ encryption_level_ == ENCRYPTION_FORWARD_SECURE) {
// We do not expect to install any further keys.
return false;
}
- if (undecryptable_packets_.size() >= max_undecryptable_packets_) {
- // We do not queue more than max_undecryptable_packets_ packets.
- return false;
- }
if (has_decryption_key) {
// We already have the key for this decryption level, therefore no
// future keys will allow it be decrypted.
return false;
}
+ if (GetQuicReloadableFlag(quic_queue_until_handshake_complete) &&
+ IsHandshakeComplete()) {
+ QUICHE_RELOADABLE_FLAG_COUNT(quic_queue_until_handshake_complete);
+ // We do not expect to install any further keys.
+ return false;
+ }
+ if (undecryptable_packets_.size() >= max_undecryptable_packets_) {
+ // We do not queue more than max_undecryptable_packets_ packets.
+ return false;
+ }
if (version().KnowsWhichDecrypterToUse() &&
- decryption_level <= encryption_level_) {
- // On versions that know which decrypter to use, we install keys in order
- // so we will not get newer keys for lower encryption levels.
+ decryption_level == ENCRYPTION_INITIAL) {
+ // When the corresponding decryption key is not available, all
+ // non-Initial packets should be buffered until the handshake is complete.
+ return false;
+ }
+ if (perspective_ == Perspective::IS_CLIENT && version().UsesTls() &&
+ decryption_level == ENCRYPTION_ZERO_RTT) {
+ // Only clients send Zero RTT packets in IETF QUIC.
+ QUIC_PEER_BUG(quic_peer_bug_client_received_zero_rtt)
+ << "Client received a Zero RTT packet, not buffering.";
return false;
}
return true;
@@ -2812,18 +2802,17 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
if (debug_visitor_ != nullptr) {
debug_visitor_->OnPacketReceived(self_address, peer_address, packet);
}
- current_incoming_packet_received_bytes_counted_ = false;
+ last_received_packet_info_ =
+ ReceivedPacketInfo(self_address, peer_address, packet.receipt_time());
last_size_ = packet.length();
current_packet_data_ = packet.data();
- last_packet_destination_address_ = self_address;
- last_packet_source_address_ = peer_address;
if (!default_path_.self_address.IsInitialized()) {
- default_path_.self_address = last_packet_destination_address_;
+ default_path_.self_address = last_received_packet_info_.destination_address;
}
if (!direct_peer_address_.IsInitialized()) {
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
}
if (!default_path_.peer_address.IsInitialized()) {
@@ -2844,11 +2833,11 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
if (EnforceAntiAmplificationLimit()) {
default_path_.bytes_received_before_address_validation += last_size_;
}
- } else if (IsDefaultPath(last_packet_destination_address_,
- last_packet_source_address_) &&
+ } else if (IsDefaultPath(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address) &&
EnforceAntiAmplificationLimit()) {
QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 1, 5);
- current_incoming_packet_received_bytes_counted_ = true;
+ last_received_packet_info_.received_bytes_counted = true;
default_path_.bytes_received_before_address_validation += last_size_;
}
@@ -2860,10 +2849,9 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
<< " too far from current time:"
<< clock_->ApproximateNow().ToDebuggingValue();
}
- time_of_last_received_packet_ = packet.receipt_time();
QUIC_DVLOG(1) << ENDPOINT << "time of last received packet: "
<< packet.receipt_time().ToDebuggingValue() << " from peer "
- << last_packet_source_address_;
+ << last_received_packet_info_.source_address;
ScopedPacketFlusher flusher(this);
if (!framer_.ProcessPacket(packet)) {
@@ -2897,9 +2885,7 @@ void QuicConnection::ProcessUdpPacket(const QuicSocketAddress& self_address,
}
}
- const bool processed = MaybeProcessCoalescedPackets();
- if (!donot_write_mid_packet_processing_ || !processed) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 3, 3);
+ if (!MaybeProcessCoalescedPackets()) {
MaybeProcessUndecryptablePackets();
MaybeSendInResponseToPacket();
}
@@ -2980,7 +2966,7 @@ void QuicConnection::OnCanWrite() {
}
void QuicConnection::WriteIfNotBlocked() {
- if (donot_write_mid_packet_processing_ && framer().is_processing_packet()) {
+ if (framer().is_processing_packet()) {
QUIC_BUG(connection_write_mid_packet_processing)
<< ENDPOINT << "Tried to write in mid of packet processing";
return;
@@ -2990,14 +2976,14 @@ void QuicConnection::WriteIfNotBlocked() {
}
}
-void QuicConnection::SetServerConnectionId(
- const QuicConnectionId& server_connection_id) {
- if (use_connection_id_on_default_path_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 2,
- 3);
- default_path_.server_connection_id = server_connection_id;
- } else {
- server_connection_id_ = server_connection_id;
+void QuicConnection::MaybeClearQueuedPacketsOnPathChange() {
+ if (connection_migration_use_new_cid_ &&
+ peer_issued_cid_manager_ != nullptr && HasQueuedPackets()) {
+ // Discard packets serialized with the connection ID on the old code path.
+ // It is possible to clear queued packets only if connection ID changes.
+ // However, the case where connection ID is unchanged and queued packets are
+ // non-empty is quite rare.
+ ClearQueuedPackets();
}
}
@@ -3011,11 +2997,12 @@ void QuicConnection::ReplaceInitialServerConnectionId(
if (peer_issued_cid_manager_ != nullptr) {
QUIC_BUG_IF(quic_bug_12714_22,
!peer_issued_cid_manager_->IsConnectionIdActive(
- ServerConnectionId()))
+ default_path_.server_connection_id))
<< "Connection ID replaced header is no longer active. old id: "
- << ServerConnectionId() << " new_id: " << new_server_connection_id;
- peer_issued_cid_manager_->ReplaceConnectionId(ServerConnectionId(),
- new_server_connection_id);
+ << default_path_.server_connection_id
+ << " new_id: " << new_server_connection_id;
+ peer_issued_cid_manager_->ReplaceConnectionId(
+ default_path_.server_connection_id, new_server_connection_id);
} else {
peer_issued_cid_manager_ =
std::make_unique<QuicPeerIssuedConnectionIdManager>(
@@ -3024,8 +3011,8 @@ void QuicConnection::ReplaceInitialServerConnectionId(
}
}
}
- SetServerConnectionId(new_server_connection_id);
- packet_creator_.SetServerConnectionId(ServerConnectionId());
+ default_path_.server_connection_id = new_server_connection_id;
+ packet_creator_.SetServerConnectionId(default_path_.server_connection_id);
}
void QuicConnection::FindMatchingOrNewClientConnectionIdOrToken(
@@ -3035,9 +3022,6 @@ void QuicConnection::FindMatchingOrNewClientConnectionIdOrToken(
QuicConnectionId* client_connection_id,
bool* stateless_reset_token_received,
StatelessResetToken* stateless_reset_token) {
- if (!use_connection_id_on_default_path_) {
- return;
- }
QUICHE_DCHECK(perspective_ == Perspective::IS_SERVER);
if (peer_issued_cid_manager_ == nullptr ||
server_connection_id == default_path.server_connection_id) {
@@ -3097,9 +3081,10 @@ void QuicConnection::SetDefaultPathState(PathState new_path_state) {
bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
if (perspective_ == Perspective::IS_CLIENT && version().HasIetfQuicFrames() &&
direct_peer_address_.IsInitialized() &&
- last_packet_source_address_.IsInitialized() &&
- direct_peer_address_ != last_packet_source_address_ &&
- !visitor_->IsKnownServerAddress(last_packet_source_address_)) {
+ last_received_packet_info_.source_address.IsInitialized() &&
+ direct_peer_address_ != last_received_packet_info_.source_address &&
+ !visitor_->IsKnownServerAddress(
+ last_received_packet_info_.source_address)) {
// TODO(haoyuewang) Revisit this when preferred_address transport parameter
// is used on the client side.
// Discard packets received from unseen server addresses.
@@ -3108,13 +3093,15 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
if (perspective_ == Perspective::IS_SERVER &&
default_path_.self_address.IsInitialized() &&
- last_packet_destination_address_.IsInitialized() &&
- default_path_.self_address != last_packet_destination_address_) {
+ last_received_packet_info_.destination_address.IsInitialized() &&
+ default_path_.self_address !=
+ last_received_packet_info_.destination_address) {
// Allow change between pure IPv4 and equivalent mapped IPv4 address.
if (default_path_.self_address.port() !=
- last_packet_destination_address_.port() ||
+ last_received_packet_info_.destination_address.port() ||
default_path_.self_address.host().Normalized() !=
- last_packet_destination_address_.host().Normalized()) {
+ last_received_packet_info_.destination_address.host()
+ .Normalized()) {
if (!visitor_->AllowSelfAddressChange()) {
CloseConnection(
QUIC_ERROR_MIGRATING_ADDRESS,
@@ -3123,24 +3110,24 @@ bool QuicConnection::ProcessValidatedPacket(const QuicPacketHeader& header) {
return false;
}
}
- default_path_.self_address = last_packet_destination_address_;
+ default_path_.self_address = last_received_packet_info_.destination_address;
}
if (PacketCanReplaceServerConnectionId(header, perspective_) &&
- ServerConnectionId() != header.source_connection_id) {
+ default_path_.server_connection_id != header.source_connection_id) {
QUICHE_DCHECK_EQ(header.long_packet_type, INITIAL);
if (server_connection_id_replaced_by_initial_) {
QUIC_DLOG(ERROR) << ENDPOINT << "Refusing to replace connection ID "
- << ServerConnectionId() << " with "
+ << default_path_.server_connection_id << " with "
<< header.source_connection_id;
return false;
}
server_connection_id_replaced_by_initial_ = true;
QUIC_DLOG(INFO) << ENDPOINT << "Replacing connection ID "
- << ServerConnectionId() << " with "
+ << default_path_.server_connection_id << " with "
<< header.source_connection_id;
if (!original_destination_connection_id_.has_value()) {
- original_destination_connection_id_ = ServerConnectionId();
+ original_destination_connection_id_ = default_path_.server_connection_id;
}
ReplaceInitialServerConnectionId(header.source_connection_id);
}
@@ -3569,7 +3556,7 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
legacy_version_encapsulation_sni_,
absl::string_view(packet->encrypted_buffer,
packet->encrypted_length),
- ServerConnectionId(), framer_.creation_time(),
+ default_path_.server_connection_id, framer_.creation_time(),
GetLimitedMaxPacketSize(long_term_mtu_),
const_cast<char*>(packet->encrypted_buffer));
if (encapsulated_length != 0) {
@@ -3759,8 +3746,15 @@ bool QuicConnection::WritePacket(SerializedPacket* packet) {
return true;
}
}
-
- if (in_flight || !retransmission_alarm_->IsSet()) {
+ if (GetQuicReloadableFlag(
+ quic_donot_rearm_pto_on_application_data_during_handshake)) {
+ QUIC_RELOADABLE_FLAG_COUNT(
+ quic_donot_rearm_pto_on_application_data_during_handshake);
+ if (ShouldSetRetransmissionAlarmOnPacketSent(in_flight,
+ packet->encryption_level)) {
+ SetRetransmissionAlarm();
+ }
+ } else if (in_flight || !retransmission_alarm_->IsSet()) {
SetRetransmissionAlarm();
}
SetPingAlarm();
@@ -4078,13 +4072,14 @@ void QuicConnection::OnPathMtuIncreased(QuicPacketLength packet_size) {
std::unique_ptr<QuicSelfIssuedConnectionIdManager>
QuicConnection::MakeSelfIssuedConnectionIdManager() {
QUICHE_DCHECK((perspective_ == Perspective::IS_CLIENT &&
- !ClientConnectionId().IsEmpty()) ||
+ !default_path_.client_connection_id.IsEmpty()) ||
(perspective_ == Perspective::IS_SERVER &&
- !ServerConnectionId().IsEmpty()));
+ !default_path_.server_connection_id.IsEmpty()));
return std::make_unique<QuicSelfIssuedConnectionIdManager>(
kMinNumOfActiveConnectionIds,
- perspective_ == Perspective::IS_CLIENT ? ClientConnectionId()
- : ServerConnectionId(),
+ perspective_ == Perspective::IS_CLIENT
+ ? default_path_.client_connection_id
+ : default_path_.server_connection_id,
clock_, alarm_factory_, this);
}
@@ -4149,9 +4144,7 @@ void QuicConnection::OnPingTimeout() {
!visitor_->ShouldKeepConnectionAlive()) {
return;
}
- SendPingAtLevel(use_encryption_level_context_
- ? framer().GetEncryptionLevelToSendApplicationData()
- : encryption_level_);
+ SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData());
}
void QuicConnection::SendAck() {
@@ -4218,7 +4211,7 @@ void QuicConnection::OnRetransmissionTimeout() {
blackhole_detector_.IsDetectionInProgress()) {
// Stop detection in quiescence.
QUICHE_DCHECK_EQ(QuicSentPacketManager::LOSS_MODE, retransmission_mode);
- blackhole_detector_.StopDetection();
+ blackhole_detector_.StopDetection(/*permanent=*/false);
}
WriteIfNotBlocked();
@@ -4249,15 +4242,28 @@ void QuicConnection::OnRetransmissionTimeout() {
<< retransmission_mode << ", send PING";
QUICHE_DCHECK_LT(0u,
sent_packet_manager_.pending_timer_transmission_count());
- EncryptionLevel level = encryption_level_;
- PacketNumberSpace packet_number_space = NUM_PACKET_NUMBER_SPACES;
- if (SupportsMultiplePacketNumberSpaces() &&
- sent_packet_manager_
- .GetEarliestPacketSentTimeForPto(&packet_number_space)
- .IsInitialized()) {
- level = QuicUtils::GetEncryptionLevel(packet_number_space);
+ if (SupportsMultiplePacketNumberSpaces()) {
+ // Based on https://datatracker.ietf.org/doc/html/rfc9002#appendix-A.9
+ PacketNumberSpace packet_number_space;
+ if (sent_packet_manager_
+ .GetEarliestPacketSentTimeForPto(&packet_number_space)
+ .IsInitialized()) {
+ SendPingAtLevel(QuicUtils::GetEncryptionLevel(packet_number_space));
+ } else {
+ // The client must PTO when there is nothing in flight if the server
+ // could be blocked from sending by the amplification limit
+ QUICHE_DCHECK_EQ(Perspective::IS_CLIENT, perspective_);
+ if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_HANDSHAKE)) {
+ SendPingAtLevel(ENCRYPTION_HANDSHAKE);
+ } else if (framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_INITIAL)) {
+ SendPingAtLevel(ENCRYPTION_INITIAL);
+ } else {
+ QUIC_BUG(quic_bug_no_pto) << "PTO fired but nothing was sent.";
+ }
+ }
+ } else {
+ SendPingAtLevel(encryption_level_);
}
- SendPingAtLevel(level);
}
if (retransmission_mode == QuicSentPacketManager::PTO_MODE) {
sent_packet_manager_.AdjustPendingTimerTransmissions();
@@ -4417,9 +4423,14 @@ void QuicConnection::QueueUndecryptablePacket(
}
}
QUIC_DVLOG(1) << ENDPOINT << "Queueing undecryptable packet.";
- undecryptable_packets_.emplace_back(packet, decryption_level);
+ undecryptable_packets_.emplace_back(packet, decryption_level,
+ last_received_packet_info_);
if (perspective_ == Perspective::IS_CLIENT) {
- SetRetransmissionAlarm();
+ if (!retransmission_alarm_->IsSet() ||
+ GetRetransmissionDeadline() < retransmission_alarm_->deadline()) {
+ // Re-arm PTO only if we can make it sooner to speed up recovery.
+ SetRetransmissionAlarm();
+ }
}
}
@@ -4445,7 +4456,19 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
debug_visitor_->OnAttemptingToProcessUndecryptablePacket(
undecryptable_packet->encryption_level);
}
- if (framer_.ProcessPacket(*undecryptable_packet->packet)) {
+ bool processed = false;
+ if (reset_per_packet_state_for_undecryptable_packets_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_reset_per_packet_state_for_undecryptable_packets, 1, 2);
+ last_received_packet_info_ = undecryptable_packet->packet_info;
+ last_size_ = undecryptable_packet->packet->length();
+ current_packet_data_ = undecryptable_packet->packet->data();
+ processed = framer_.ProcessPacket(*undecryptable_packet->packet);
+ current_packet_data_ = nullptr;
+ } else {
+ processed = framer_.ProcessPacket(*undecryptable_packet->packet);
+ }
+ if (processed) {
QUIC_DVLOG(1) << ENDPOINT << "Processed undecryptable packet!";
iter = undecryptable_packets_.erase(iter);
++stats_.packets_processed;
@@ -4479,7 +4502,14 @@ void QuicConnection::MaybeProcessUndecryptablePackets() {
undecryptable_packets_.clear();
}
if (perspective_ == Perspective::IS_CLIENT) {
- SetRetransmissionAlarm();
+ if (!retransmission_alarm_->IsSet() || undecryptable_packets_.empty() ||
+ GetRetransmissionDeadline() < retransmission_alarm_->deadline()) {
+ // 1) If there is still undecryptable packet, only re-arm PTO to make it
+ // sooner to speed up recovery.
+ // 2) If all undecryptable packets get processed, re-arm (which may
+ // postpone) PTO since no immediate recovery is needed.
+ SetRetransmissionAlarm();
+ }
}
}
@@ -4514,11 +4544,7 @@ bool QuicConnection::MaybeProcessCoalescedPackets() {
}
if (processed) {
MaybeProcessUndecryptablePackets();
- if (donot_write_mid_packet_processing_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 2,
- 3);
- MaybeSendInResponseToPacket();
- }
+ MaybeSendInResponseToPacket();
}
return processed;
}
@@ -4571,12 +4597,8 @@ void QuicConnection::SendConnectionClosePacket(
default_path_.server_connection_id, connection_migration_use_new_cid_);
if (!SupportsMultiplePacketNumberSpaces()) {
QUIC_DLOG(INFO) << ENDPOINT << "Sending connection close packet.";
- if (!use_encryption_level_context_) {
- SetDefaultEncryptionLevel(GetConnectionCloseEncryptionLevel());
- }
- ScopedEncryptionLevelContext context(
- use_encryption_level_context_ ? this : nullptr,
- GetConnectionCloseEncryptionLevel());
+ ScopedEncryptionLevelContext context(this,
+ GetConnectionCloseEncryptionLevel());
if (version().CanSendCoalescedPackets()) {
coalesced_packet_.Clear();
}
@@ -4607,7 +4629,6 @@ void QuicConnection::SendConnectionClosePacket(
ClearQueuedPackets();
return;
}
- const EncryptionLevel current_encryption_level = encryption_level_;
ScopedPacketFlusher flusher(this);
// Now that the connection is being closed, discard any unsent packets
@@ -4625,11 +4646,7 @@ void QuicConnection::SendConnectionClosePacket(
}
QUIC_DLOG(INFO) << ENDPOINT
<< "Sending connection close packet at level: " << level;
- if (!use_encryption_level_context_) {
- SetDefaultEncryptionLevel(level);
- }
- ScopedEncryptionLevelContext context(
- use_encryption_level_context_ ? this : nullptr, level);
+ ScopedEncryptionLevelContext context(this, level);
// Bundle an ACK of the corresponding packet number space for debugging
// purpose.
bool send_ack = error != QUIC_PACKET_WRITE_ERROR &&
@@ -4662,9 +4679,6 @@ void QuicConnection::SendConnectionClosePacket(
// Since the connection is closing, if the connection close packets were not
// sent, then they should be discarded.
ClearQueuedPackets();
- if (!use_encryption_level_context_) {
- SetDefaultEncryptionLevel(current_encryption_level);
- }
}
void QuicConnection::TearDownLocalConnectionState(
@@ -4712,15 +4726,15 @@ void QuicConnection::TearDownLocalConnectionState(
void QuicConnection::CancelAllAlarms() {
QUIC_DVLOG(1) << "Cancelling all QuicConnection alarms.";
- ack_alarm_->Cancel();
- ping_alarm_->Cancel();
- retransmission_alarm_->Cancel();
- send_alarm_->Cancel();
- mtu_discovery_alarm_->Cancel();
- process_undecryptable_packets_alarm_->Cancel();
- discard_previous_one_rtt_keys_alarm_->Cancel();
- discard_zero_rtt_decryption_keys_alarm_->Cancel();
- blackhole_detector_.StopDetection();
+ ack_alarm_->PermanentCancel();
+ ping_alarm_->PermanentCancel();
+ retransmission_alarm_->PermanentCancel();
+ send_alarm_->PermanentCancel();
+ mtu_discovery_alarm_->PermanentCancel();
+ process_undecryptable_packets_alarm_->PermanentCancel();
+ discard_previous_one_rtt_keys_alarm_->PermanentCancel();
+ discard_zero_rtt_decryption_keys_alarm_->PermanentCancel();
+ blackhole_detector_.StopDetection(/*permanent=*/true);
idle_network_detector_.StopDetection();
}
@@ -4754,6 +4768,9 @@ void QuicConnection::SetNetworkTimeouts(QuicTime::Delta handshake_timeout,
}
void QuicConnection::SetPingAlarm() {
+ if (!connected_) {
+ return;
+ }
if (perspective_ == Perspective::IS_SERVER &&
initial_retransmittable_on_wire_timeout_.IsInfinite()) {
// The PING alarm exists to support two features:
@@ -5097,7 +5114,7 @@ bool QuicConnection::SendGenericPathProbePacket(
QUIC_DLOG(INFO) << ENDPOINT
<< "Sending path probe packet for connection_id = "
- << ServerConnectionId();
+ << default_path_.server_connection_id;
std::unique_ptr<SerializedPacket> probing_packet;
if (!version().HasIetfQuicFrames()) {
@@ -5142,7 +5159,7 @@ bool QuicConnection::WritePacketUsingWriter(
const QuicTime packet_send_time = clock_->Now();
QUIC_DVLOG(2) << ENDPOINT
<< "Sending path probe packet for server connection ID "
- << ServerConnectionId() << std::endl
+ << default_path_.server_connection_id << std::endl
<< quiche::QuicheTextUtils::HexDump(absl::string_view(
packet->encrypted_buffer, packet->encrypted_length));
WriteResult result = writer->WritePacket(
@@ -5277,11 +5294,20 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 3, 6);
if (type == NO_CHANGE) {
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
QUIC_BUG(quic_bug_10511_36)
<< "EffectivePeerMigration started without address change.";
return;
}
+ if (packet_creator_.HasPendingFrames()) {
+ QUIC_BUG(bug_731_2)
+ << "Starts effective peer migration with pending frame types: "
+ << packet_creator_.GetPendingFramesInfo() << ". Address change type is "
+ << AddressChangeTypeToString(type)
+ << ". Current frame type: " << framer_.current_received_frame_type()
+ << ". Previous frame type: "
+ << framer_.previously_received_frame_type();
+ }
// Action items:
// 1. Switch congestion controller;
@@ -5302,6 +5328,7 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
const QuicSocketAddress previous_direct_peer_address = direct_peer_address_;
PathState previous_default_path = std::move(default_path_);
active_effective_peer_migration_type_ = type;
+ MaybeClearQueuedPacketsOnPathChange();
OnConnectionMigration();
// Update congestion controller if the address change type is not PORT_CHANGE.
@@ -5338,9 +5365,18 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
}
// Update to the new peer address.
- UpdatePeerAddress(last_packet_source_address_);
+ if (packet_creator_.HasPendingFrames()) {
+ QUIC_BUG(bug_731_1)
+ << "Starts effective peer migration with pending frame types: "
+ << packet_creator_.GetPendingFramesInfo() << ". Address change type is "
+ << AddressChangeTypeToString(type)
+ << ". Current frame type: " << framer_.current_received_frame_type()
+ << ". Previous frame type: "
+ << framer_.previously_received_frame_type();
+ }
+ UpdatePeerAddress(last_received_packet_info_.source_address);
// Update the default path.
- if (IsAlternativePath(last_packet_destination_address_,
+ if (IsAlternativePath(last_received_packet_info_.destination_address,
current_effective_peer_address)) {
SetDefaultPathState(std::move(alternative_path_));
} else {
@@ -5351,10 +5387,11 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
previous_default_path, alternative_path_,
last_packet_destination_connection_id_, &client_connection_id,
&stateless_reset_token_received, &stateless_reset_token);
- SetDefaultPathState(PathState(
- last_packet_destination_address_, current_effective_peer_address,
- client_connection_id, last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token));
+ SetDefaultPathState(
+ PathState(last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_connection_id,
+ last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token));
// The path is considered validated if its peer IP address matches any
// validated path's peer IP address.
default_path_.validated =
@@ -5363,10 +5400,10 @@ void QuicConnection::StartEffectivePeerMigration(AddressChangeType type) {
alternative_path_.validated) ||
(previous_default_path.validated && type == PORT_CHANGE);
}
- if (!current_incoming_packet_received_bytes_counted_) {
+ if (!last_received_packet_info_.received_bytes_counted) {
// Increment bytes counting on the new default path.
default_path_.bytes_received_before_address_validation += last_size_;
- current_incoming_packet_received_bytes_counted_ = true;
+ last_received_packet_info_.received_bytes_counted = true;
}
if (!previous_default_path.validated) {
@@ -5547,19 +5584,19 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
QuicSocketAddress current_effective_peer_address =
GetEffectivePeerAddressFromCurrentPacket();
if (!count_bytes_on_alternative_path_separately_ ||
- IsDefaultPath(last_packet_destination_address_,
- last_packet_source_address_)) {
+ IsDefaultPath(last_received_packet_info_.destination_address,
+ last_received_packet_info_.source_address)) {
return connected_;
}
QUIC_CODE_COUNT_N(quic_count_bytes_on_alternative_path_seperately, 3, 5);
if (perspective_ == Perspective::IS_SERVER &&
type == PATH_CHALLENGE_FRAME &&
- !IsAlternativePath(last_packet_destination_address_,
+ !IsAlternativePath(last_received_packet_info_.destination_address,
current_effective_peer_address)) {
QUIC_DVLOG(1)
<< "The peer is probing a new path with effective peer address "
<< current_effective_peer_address << ", self address "
- << last_packet_destination_address_;
+ << last_received_packet_info_.destination_address;
if (!validate_client_addresses_) {
QuicConnectionId client_cid;
bool stateless_reset_token_received = false;
@@ -5568,10 +5605,11 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
default_path_, alternative_path_,
last_packet_destination_connection_id_, &client_cid,
&stateless_reset_token_received, &stateless_reset_token);
- alternative_path_ = PathState(
- last_packet_destination_address_, current_effective_peer_address,
- client_cid, last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token);
+ alternative_path_ =
+ PathState(last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_cid,
+ last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token);
} else if (!default_path_.validated) {
QUIC_CODE_COUNT_N(quic_server_reverse_validate_new_path3, 4, 6);
// Skip reverse path validation because either handshake hasn't
@@ -5598,10 +5636,11 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
// Only override alternative path state upon receiving a PATH_CHALLENGE
// from an unvalidated peer address, and the connection isn't validating
// a recent peer migration.
- alternative_path_ = PathState(
- last_packet_destination_address_, current_effective_peer_address,
- client_connection_id, last_packet_destination_connection_id_,
- stateless_reset_token_received, stateless_reset_token);
+ alternative_path_ =
+ PathState(last_received_packet_info_.destination_address,
+ current_effective_peer_address, client_connection_id,
+ last_packet_destination_connection_id_,
+ stateless_reset_token_received, stateless_reset_token);
if (group_path_response_and_challenge_sending_closer_) {
should_proactively_validate_peer_address_on_path_challenge_ = true;
} else {
@@ -5613,12 +5652,12 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
QUIC_DVLOG(1) << "Proactively validate the effective peer address "
<< current_effective_peer_address;
QUIC_CODE_COUNT_N(quic_kick_off_client_address_validation, 1, 6);
- ValidatePath(
- std::make_unique<ReversePathValidationContext>(
- default_path_.self_address, last_packet_source_address_,
- current_effective_peer_address, this),
- std::make_unique<ReversePathValidationResultDelegate>(
- this, peer_address()));
+ ValidatePath(std::make_unique<ReversePathValidationContext>(
+ default_path_.self_address,
+ last_received_packet_info_.source_address,
+ current_effective_peer_address, this),
+ std::make_unique<ReversePathValidationResultDelegate>(
+ this, peer_address()));
}
}
}
@@ -5659,15 +5698,17 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
<< current_effective_peer_migration_type_;
} else {
is_current_packet_connectivity_probing_ =
- (last_packet_source_address_ != peer_address()) ||
- (last_packet_destination_address_ != default_path_.self_address);
+ (last_received_packet_info_.source_address != peer_address()) ||
+ (last_received_packet_info_.destination_address !=
+ default_path_.self_address);
QUIC_DLOG_IF(INFO, is_current_packet_connectivity_probing_)
<< ENDPOINT
<< "Detected connectivity probing packet. "
- "last_packet_source_address_:"
- << last_packet_source_address_ << ", peer_address_:" << peer_address()
- << ", last_packet_destination_address_:"
- << last_packet_destination_address_
+ "last_packet_source_address:"
+ << last_received_packet_info_.source_address
+ << ", peer_address_:" << peer_address()
+ << ", last_packet_destination_address:"
+ << last_received_packet_info_.destination_address
<< ", default path self_address :" << default_path_.self_address;
}
return connected_;
@@ -5676,7 +5717,7 @@ bool QuicConnection::UpdatePacketContent(QuicFrameType type) {
current_packet_content_ = NOT_PADDED_PING;
if (GetLargestReceivedPacket().IsInitialized() &&
last_header_.packet_number == GetLargestReceivedPacket()) {
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
if (current_effective_peer_migration_type_ != NO_CHANGE) {
// Start effective peer migration immediately when the current packet is
// confirmed not a connectivity probing packet.
@@ -5715,11 +5756,11 @@ void QuicConnection::MaybeStartIetfPeerMigration() {
// TODO(fayang): When multiple packet number spaces is supported, only
// start peer migration for the application data.
if (!validate_client_addresses_) {
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
}
StartEffectivePeerMigration(current_effective_peer_migration_type_);
} else {
- UpdatePeerAddress(last_packet_source_address_);
+ UpdatePeerAddress(last_received_packet_info_.source_address);
}
}
current_effective_peer_migration_type_ = NO_CHANGE;
@@ -5746,7 +5787,7 @@ void QuicConnection::PostProcessAfterAckFrame(bool send_stop_waiting,
// In case no new packets get acknowledged, it is possible packets are
// detected lost because of time based loss detection. Cancel blackhole
// detection if there is no packets in flight.
- blackhole_detector_.StopDetection();
+ blackhole_detector_.StopDetection(/*permanent=*/false);
}
if (send_stop_waiting) {
@@ -5793,14 +5834,14 @@ void QuicConnection::ResetAckStates() {
}
MessageStatus QuicConnection::SendMessage(QuicMessageId message_id,
- QuicMemSliceSpan message,
+ absl::Span<QuicMemSlice> message,
bool flush) {
if (!VersionSupportsMessageFrames(transport_version())) {
QUIC_BUG(quic_bug_10511_38)
<< "MESSAGE frame is not supported for version " << transport_version();
return MESSAGE_STATUS_UNSUPPORTED;
}
- if (message.total_length() > GetCurrentLargestMessagePayload()) {
+ if (MemSliceSpanTotalSize(message) > GetCurrentLargestMessagePayload()) {
return MESSAGE_STATUS_TOO_LARGE;
}
if (!connected_ || (!flush && !CanWrite(HAS_RETRANSMITTABLE_DATA))) {
@@ -5899,8 +5940,6 @@ void QuicConnection::SendAllPendingAcks() {
if (!earliest_ack_timeout.IsInitialized()) {
return;
}
- // Latches current encryption level.
- const EncryptionLevel current_encryption_level = encryption_level_;
for (int8_t i = INITIAL_DATA; i <= APPLICATION_DATA; ++i) {
const QuicTime ack_timeout = uber_received_packet_manager_.GetAckTimeout(
static_cast<PacketNumberSpace>(i));
@@ -5920,14 +5959,8 @@ void QuicConnection::SendAllPendingAcks() {
QUIC_DVLOG(1) << ENDPOINT << "Sending ACK of packet number space "
<< PacketNumberSpaceToString(
static_cast<PacketNumberSpace>(i));
- // Switch to the appropriate encryption level.
- if (!use_encryption_level_context_) {
- SetDefaultEncryptionLevel(
- QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)));
- }
ScopedEncryptionLevelContext context(
- use_encryption_level_context_ ? this : nullptr,
- QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)));
+ this, QuicUtils::GetEncryptionLevel(static_cast<PacketNumberSpace>(i)));
QuicFrames frames;
frames.push_back(uber_received_packet_manager_.GetUpdatedAckFrame(
static_cast<PacketNumberSpace>(i), clock_->ApproximateNow()));
@@ -5943,10 +5976,6 @@ void QuicConnection::SendAllPendingAcks() {
}
ResetAckStates();
}
- if (!use_encryption_level_context_) {
- // Restores encryption level.
- SetDefaultEncryptionLevel(current_encryption_level);
- }
const QuicTime timeout =
uber_received_packet_manager_.GetEarliestAckTimeout();
@@ -6138,6 +6167,9 @@ void QuicConnection::SetLargestReceivedPacketWithAck(
}
void QuicConnection::OnForwardProgressMade() {
+ if (GetQuicRestartFlag(quic_alarm_add_permanent_cancel) && !connected_) {
+ return;
+ }
if (is_path_degrading_) {
visitor_->OnForwardProgressMadeAfterPathDegrading();
is_path_degrading_ = false;
@@ -6149,7 +6181,7 @@ void QuicConnection::OnForwardProgressMade() {
GetPathMtuReductionDeadline());
} else {
// Stop detections in quiecense.
- blackhole_detector_.StopDetection();
+ blackhole_detector_.StopDetection(/*permanent=*/false);
}
QUIC_BUG_IF(quic_bug_12714_35,
default_enable_5rto_blackhole_detection_ &&
@@ -6257,13 +6289,7 @@ void QuicConnection::set_client_connection_id(
<< client_connection_id << " with unsupported version " << version();
return;
}
- if (use_connection_id_on_default_path_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_use_connection_id_on_default_path_v2, 1,
- 3);
- default_path_.client_connection_id = client_connection_id;
- } else {
- client_connection_id_ = client_connection_id;
- }
+ default_path_.client_connection_id = client_connection_id;
client_connection_id_is_set_ = true;
if (support_multiple_connection_ids_ && !client_connection_id.IsEmpty()) {
@@ -6280,11 +6306,12 @@ void QuicConnection::set_client_connection_id(
}
}
QUIC_DLOG(INFO) << ENDPOINT << "setting client connection ID to "
- << ClientConnectionId()
+ << default_path_.client_connection_id
<< " for connection with server connection ID "
- << ServerConnectionId();
- packet_creator_.SetClientConnectionId(ClientConnectionId());
- framer_.SetExpectedClientConnectionIdLength(ClientConnectionId().length());
+ << default_path_.server_connection_id;
+ packet_creator_.SetClientConnectionId(default_path_.client_connection_id);
+ framer_.SetExpectedClientConnectionIdLength(
+ default_path_.client_connection_id.length());
}
void QuicConnection::OnPathDegradingDetected() {
@@ -6333,6 +6360,10 @@ void QuicConnection::OnIdleNetworkDetected() {
"No recent network activity after ", duration.ToDebuggingValue(),
". Timeout:",
idle_network_detector_.idle_network_timeout().ToDebuggingValue());
+ if (perspective() == Perspective::IS_CLIENT && version().UsesTls() &&
+ !IsHandshakeComplete()) {
+ absl::StrAppend(&error_details, UndecryptablePacketsInfo());
+ }
QUIC_DVLOG(1) << ENDPOINT << error_details;
const bool has_consecutive_pto =
sent_packet_manager_.GetConsecutiveTlpCount() > 0 ||
@@ -6362,9 +6393,10 @@ void QuicConnection::OnIdleNetworkDetected() {
void QuicConnection::OnPeerIssuedConnectionIdRetired() {
QUICHE_DCHECK(peer_issued_cid_manager_ != nullptr);
- QuicConnectionId* default_path_cid = perspective_ == Perspective::IS_CLIENT
- ? &ServerConnectionId()
- : &ClientConnectionId();
+ QuicConnectionId* default_path_cid =
+ perspective_ == Perspective::IS_CLIENT
+ ? &default_path_.server_connection_id
+ : &default_path_.client_connection_id;
QuicConnectionId* alternative_path_cid =
perspective_ == Perspective::IS_CLIENT
? &alternative_path_.server_connection_id
@@ -6376,8 +6408,7 @@ void QuicConnection::OnPeerIssuedConnectionIdRetired() {
*default_path_cid = QuicConnectionId();
}
// TODO(haoyuewang) Handle the change for default_path_ & alternatvie_path_
- // via the same helper function after use_connection_id_on_default_path_ is
- // default true.
+ // via the same helper function.
if (default_path_cid->IsEmpty()) {
// Try setting a new connection ID now such that subsequent
// RetireConnectionId frames can be sent on the default path.
@@ -6385,15 +6416,9 @@ void QuicConnection::OnPeerIssuedConnectionIdRetired() {
peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
if (unused_connection_id_data != nullptr) {
*default_path_cid = unused_connection_id_data->connection_id;
- if (use_connection_id_on_default_path_) {
- default_path_.stateless_reset_token =
- unused_connection_id_data->stateless_reset_token;
- default_path_.stateless_reset_token_received = true;
- } else {
- received_stateless_reset_token_ =
- unused_connection_id_data->stateless_reset_token;
- stateless_reset_token_received_ = true;
- }
+ default_path_.stateless_reset_token =
+ unused_connection_id_data->stateless_reset_token;
+ default_path_.stateless_reset_token_received = true;
if (perspective_ == Perspective::IS_CLIENT) {
packet_creator_.SetServerConnectionId(
unused_connection_id_data->connection_id);
@@ -6403,25 +6428,23 @@ void QuicConnection::OnPeerIssuedConnectionIdRetired() {
}
}
}
- if (use_connection_id_on_default_path_) {
- if (default_path_and_alternative_path_use_the_same_peer_connection_id) {
- *alternative_path_cid = *default_path_cid;
- alternative_path_.stateless_reset_token_received =
- default_path_.stateless_reset_token_received;
+ if (default_path_and_alternative_path_use_the_same_peer_connection_id) {
+ *alternative_path_cid = *default_path_cid;
+ alternative_path_.stateless_reset_token_received =
+ default_path_.stateless_reset_token_received;
+ alternative_path_.stateless_reset_token =
+ default_path_.stateless_reset_token;
+ } else if (!alternative_path_cid->IsEmpty() &&
+ !peer_issued_cid_manager_->IsConnectionIdActive(
+ *alternative_path_cid)) {
+ *alternative_path_cid = EmptyQuicConnectionId();
+ const QuicConnectionIdData* unused_connection_id_data =
+ peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
+ if (unused_connection_id_data != nullptr) {
+ *alternative_path_cid = unused_connection_id_data->connection_id;
alternative_path_.stateless_reset_token =
- default_path_.stateless_reset_token;
- } else if (!alternative_path_cid->IsEmpty() &&
- !peer_issued_cid_manager_->IsConnectionIdActive(
- *alternative_path_cid)) {
- *alternative_path_cid = EmptyQuicConnectionId();
- const QuicConnectionIdData* unused_connection_id_data =
- peer_issued_cid_manager_->ConsumeOneUnusedConnectionId();
- if (unused_connection_id_data != nullptr) {
- *alternative_path_cid = unused_connection_id_data->connection_id;
- alternative_path_.stateless_reset_token =
- unused_connection_id_data->stateless_reset_token;
- alternative_path_.stateless_reset_token_received = true;
- }
+ unused_connection_id_data->stateless_reset_token;
+ alternative_path_.stateless_reset_token_received = true;
}
}
@@ -6532,6 +6555,9 @@ bool QuicConnection::SendPathChallenge(
const QuicSocketAddress& peer_address,
const QuicSocketAddress& effective_peer_address,
QuicPacketWriter* writer) {
+ if (!framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_FORWARD_SECURE)) {
+ return connected_;
+ }
if (connection_migration_use_new_cid_) {
{
QuicConnectionId client_cid, server_cid;
@@ -6653,9 +6679,12 @@ bool QuicConnection::SendPathResponse(
const QuicPathFrameBuffer& data_buffer,
const QuicSocketAddress& peer_address_to_send,
const QuicSocketAddress& effective_peer_address) {
+ if (!framer_.HasEncrypterOfEncryptionLevel(ENCRYPTION_FORWARD_SECURE)) {
+ return false;
+ }
QuicConnectionId client_cid, server_cid;
if (connection_migration_use_new_cid_) {
- FindOnPathConnectionIds(last_packet_destination_address_,
+ FindOnPathConnectionIds(last_received_packet_info_.destination_address,
effective_peer_address, &client_cid, &server_cid);
}
// Send PATH_RESPONSE using the provided peer address. If the creator has been
@@ -6665,7 +6694,8 @@ bool QuicConnection::SendPathResponse(
&packet_creator_, peer_address_to_send, client_cid, server_cid,
connection_migration_use_new_cid_);
QUIC_DVLOG(1) << ENDPOINT << "Send PATH_RESPONSE to " << peer_address_to_send;
- if (default_path_.self_address == last_packet_destination_address_) {
+ if (default_path_.self_address ==
+ last_received_packet_info_.destination_address) {
// The PATH_CHALLENGE is received on the default socket. Respond on the same
// socket.
return packet_creator_.AddPathResponseFrame(data_buffer);
@@ -6676,8 +6706,9 @@ bool QuicConnection::SendPathResponse(
// used to send PATH_RESPONSE.
if (!path_validator_.HasPendingPathValidation() ||
path_validator_.GetContext()->self_address() !=
- last_packet_destination_address_) {
- // Ignore this PATH_CHALLENGE if it's received from an uninteresting socket.
+ last_received_packet_info_.destination_address) {
+ // Ignore this PATH_CHALLENGE if it's received from an uninteresting
+ // socket.
return true;
}
QuicPacketWriter* writer = path_validator_.GetContext()->WriterToUse();
@@ -6688,12 +6719,13 @@ bool QuicConnection::SendPathResponse(
QUICHE_DCHECK_EQ(IsRetransmittable(*probing_packet), NO_RETRANSMITTABLE_DATA);
QUIC_DVLOG(1) << ENDPOINT
<< "Send PATH_RESPONSE from alternative socket with address "
- << last_packet_destination_address_;
+ << last_received_packet_info_.destination_address;
// Ignore the return value to treat write error on the alternative writer as
// part of network error. If the writer becomes blocked, wait for the peer to
// send another PATH_CHALLENGE.
WritePacketUsingWriter(std::move(probing_packet), writer,
- last_packet_destination_address_, peer_address_to_send,
+ last_received_packet_info_.destination_address,
+ peer_address_to_send,
/*measure_rtt=*/false);
return true;
}
@@ -6766,7 +6798,6 @@ bool QuicConnection::UpdateConnectionIdsOnClientMigration(
}
void QuicConnection::RetirePeerIssuedConnectionIdsNoLongerOnPath() {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 4, 5);
if (!connection_migration_use_new_cid_ ||
peer_issued_cid_manager_ == nullptr) {
return;
@@ -6786,13 +6817,20 @@ bool QuicConnection::MigratePath(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
QuicPacketWriter* writer,
bool owns_writer) {
+ QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
if (!connected_) {
+ if (owns_writer) {
+ delete writer;
+ }
return false;
}
QUICHE_DCHECK(!version().UsesHttp3() || IsHandshakeConfirmed());
if (connection_migration_use_new_cid_) {
if (!UpdateConnectionIdsOnClientMigration(self_address, peer_address)) {
+ if (owns_writer) {
+ delete writer;
+ }
return false;
}
if (packet_creator_.GetServerConnectionId().length() !=
@@ -6816,6 +6854,7 @@ bool QuicConnection::MigratePath(const QuicSocketAddress& self_address,
SetSelfAddress(self_address);
UpdatePeerAddress(peer_address);
SetQuicPacketWriter(writer, owns_writer);
+ MaybeClearQueuedPacketsOnPathChange();
OnSuccessfulMigration(is_port_change);
return true;
}
@@ -6825,13 +6864,19 @@ void QuicConnection::OnPathValidationFailureAtClient() {
QUICHE_DCHECK(perspective_ == Perspective::IS_CLIENT);
alternative_path_.Clear();
}
+ // The alarm to retire connection IDs no longer on paths is scheduled at the
+ // end of writing and reading packet. On path validation failure, there could
+ // be no packet to write or read. Hence the retirement alarm for the
+ // connection ID associated with the failed path needs to be proactively
+ // scheduled here.
+ RetirePeerIssuedConnectionIdsNoLongerOnPath();
}
std::vector<QuicConnectionId> QuicConnection::GetActiveServerConnectionIds()
const {
if (!support_multiple_connection_ids_ ||
self_issued_cid_manager_ == nullptr) {
- return {ServerConnectionId()};
+ return {default_path_.server_connection_id};
}
return self_issued_cid_manager_->GetUnretiredConnectionIds();
}
@@ -6842,14 +6887,14 @@ void QuicConnection::CreateConnectionIdManager() {
}
if (perspective_ == Perspective::IS_CLIENT) {
- if (!ServerConnectionId().IsEmpty()) {
+ if (!default_path_.server_connection_id.IsEmpty()) {
peer_issued_cid_manager_ =
std::make_unique<QuicPeerIssuedConnectionIdManager>(
- kMinNumOfActiveConnectionIds, ServerConnectionId(), clock_,
- alarm_factory_, this);
+ kMinNumOfActiveConnectionIds, default_path_.server_connection_id,
+ clock_, alarm_factory_, this);
}
} else {
- if (!ServerConnectionId().IsEmpty()) {
+ if (!default_path_.server_connection_id.IsEmpty()) {
self_issued_cid_manager_ = MakeSelfIssuedConnectionIdManager();
}
}
@@ -6905,20 +6950,20 @@ void QuicConnection::MaybeUpdateBytesReceivedFromAlternativeAddress(
QuicByteCount received_packet_size) {
if (!version().SupportsAntiAmplificationLimit() ||
perspective_ != Perspective::IS_SERVER ||
- !IsAlternativePath(last_packet_destination_address_,
+ !IsAlternativePath(last_received_packet_info_.destination_address,
GetEffectivePeerAddressFromCurrentPacket()) ||
- current_incoming_packet_received_bytes_counted_) {
+ last_received_packet_info_.received_bytes_counted) {
return;
}
// Only update bytes received if this probing frame is received on the most
// recent alternative path.
- QUICHE_DCHECK(!IsDefaultPath(last_packet_destination_address_,
+ QUICHE_DCHECK(!IsDefaultPath(last_received_packet_info_.destination_address,
GetEffectivePeerAddressFromCurrentPacket()));
if (!alternative_path_.validated) {
alternative_path_.bytes_received_before_address_validation +=
received_packet_size;
}
- current_incoming_packet_received_bytes_counted_ = true;
+ last_received_packet_info_.received_bytes_counted = true;
}
bool QuicConnection::IsDefaultPath(
@@ -7061,6 +7106,7 @@ void QuicConnection::RestoreToLastValidatedPath(
ConnectionCloseBehavior::SILENT_CLOSE);
return;
}
+ MaybeClearQueuedPacketsOnPathChange();
// Revert congestion control context to old state.
OnPeerIpAddressChanged();
@@ -7097,7 +7143,7 @@ QuicConnection::OnPeerIpAddressChanged() {
// re-arm it.
SetRetransmissionAlarm();
// Stop detections in quiecense.
- blackhole_detector_.StopDetection();
+ blackhole_detector_.StopDetection(/*permanent=*/false);
return old_send_algorithm;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
index b9567250637..dea513a1768 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection.h
@@ -36,6 +36,7 @@
#include "quic/core/quic_alarm.h"
#include "quic/core/quic_alarm_factory.h"
#include "quic/core/quic_blocked_writer_interface.h"
+#include "quic/core/quic_connection_context.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_connection_id_manager.h"
#include "quic/core/quic_connection_stats.h"
@@ -777,9 +778,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicSocketAddress& effective_peer_address() const {
return default_path_.peer_address;
}
- const QuicConnectionId& connection_id() const { return ServerConnectionId(); }
+ const QuicConnectionId& connection_id() const {
+ return default_path_.server_connection_id;
+ }
const QuicConnectionId& client_connection_id() const {
- return ClientConnectionId();
+ return default_path_.client_connection_id;
}
void set_client_connection_id(QuicConnectionId client_connection_id);
const QuicClock* clock() const { return clock_; }
@@ -985,7 +988,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// If |flush| is false, this will return a MESSAGE_STATUS_BLOCKED
// when the connection is deemed unwritable.
virtual MessageStatus SendMessage(QuicMessageId message_id,
- QuicMemSliceSpan message,
+ absl::Span<QuicMemSlice> message,
bool flush);
// Returns the largest payload that will fit into a single MESSAGE frame.
@@ -1028,7 +1031,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
}
const QuicSocketAddress& last_packet_source_address() const {
- return last_packet_source_address_;
+ return last_received_packet_info_.source_address;
}
bool fill_up_link_during_probing() const {
@@ -1199,12 +1202,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool is_processing_packet() const { return framer_.is_processing_packet(); }
- bool encrypted_control_frames() const { return encrypted_control_frames_; }
-
- bool use_encryption_level_context() const {
- return use_encryption_level_context_;
- }
-
bool HasPendingPathValidation() const;
QuicPathValidationContext* GetPathValidationContext() const;
@@ -1225,9 +1222,7 @@ class QUIC_EXPORT_PRIVATE QuicConnection
void SetSourceAddressTokenToSend(absl::string_view token);
void SendPing() {
- SendPingAtLevel(use_encryption_level_context_
- ? framer().GetEncryptionLevelToSendApplicationData()
- : encryption_level_);
+ SendPingAtLevel(framer().GetEncryptionLevelToSendApplicationData());
}
virtual std::vector<QuicConnectionId> GetActiveServerConnectionIds() const;
@@ -1238,10 +1233,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
return support_multiple_connection_ids_;
}
- bool use_connection_id_on_default_path() const {
- return use_connection_id_on_default_path_;
- }
-
bool connection_migration_use_new_cid() const {
return connection_migration_use_new_cid_;
}
@@ -1253,8 +1244,11 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Instantiates connection ID manager.
void CreateConnectionIdManager();
- bool donot_write_mid_packet_processing() const {
- return donot_write_mid_packet_processing_;
+ QuicConnectionContext* context() { return &context_; }
+ const QuicConnectionContext* context() const { return &context_; }
+
+ void set_tracer(std::unique_ptr<QuicConnectionTracer> tracer) {
+ context_.tracer.swap(tracer);
}
protected:
@@ -1423,15 +1417,38 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicSocketAddress peer_address;
};
- // UndecrytablePacket comprises a undecryptable packet and the its encryption
- // level.
+ // ReceivedPacketInfo comprises the received packet information, which can be
+ // retrieved before the packet gets successfully decrypted.
+ struct QUIC_EXPORT_PRIVATE ReceivedPacketInfo {
+ explicit ReceivedPacketInfo(QuicTime receipt_time)
+ : received_bytes_counted(false), receipt_time(receipt_time) {}
+ ReceivedPacketInfo(const QuicSocketAddress& destination_address,
+ const QuicSocketAddress& source_address,
+ QuicTime receipt_time)
+ : received_bytes_counted(false),
+ destination_address(destination_address),
+ source_address(source_address),
+ receipt_time(receipt_time) {}
+
+ bool received_bytes_counted;
+ QuicSocketAddress destination_address;
+ QuicSocketAddress source_address;
+ QuicTime receipt_time;
+ };
+
+ // UndecrytablePacket comprises a undecryptable packet and related
+ // information.
struct QUIC_EXPORT_PRIVATE UndecryptablePacket {
UndecryptablePacket(const QuicEncryptedPacket& packet,
- EncryptionLevel encryption_level)
- : packet(packet.Clone()), encryption_level(encryption_level) {}
+ EncryptionLevel encryption_level,
+ const ReceivedPacketInfo& packet_info)
+ : packet(packet.Clone()),
+ encryption_level(encryption_level),
+ packet_info(packet_info) {}
std::unique_ptr<QuicEncryptedPacket> packet;
EncryptionLevel encryption_level;
+ ReceivedPacketInfo packet_info;
};
// Handles the reverse path validation result depending on connection state:
@@ -1468,27 +1485,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicConnection* connection_; // Not owned.
};
- QuicConnectionId& ClientConnectionId() {
- return use_connection_id_on_default_path_
- ? default_path_.client_connection_id
- : client_connection_id_;
- }
- const QuicConnectionId& ClientConnectionId() const {
- return use_connection_id_on_default_path_
- ? default_path_.client_connection_id
- : client_connection_id_;
- }
- QuicConnectionId& ServerConnectionId() {
- return use_connection_id_on_default_path_
- ? default_path_.server_connection_id
- : server_connection_id_;
- }
- const QuicConnectionId& ServerConnectionId() const {
- return use_connection_id_on_default_path_
- ? default_path_.server_connection_id
- : server_connection_id_;
- }
- void SetServerConnectionId(const QuicConnectionId& server_connection_id);
+ // If peer uses non-empty connection ID, discards any buffered packets on path
+ // change in IETF QUIC.
+ void MaybeClearQueuedPacketsOnPathChange();
// Notifies the visitor of the close and marks the connection as disconnected.
// Does not send a connection close frame to the peer. It should only be
@@ -1704,9 +1703,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// Returns the largest sent packet number that has been ACKed by peer.
QuicPacketNumber GetLargestAckedPacket() const;
- // Whether incoming_connection_ids_ contains connection_id.
- bool HasIncomingConnectionId(QuicConnectionId connection_id) const;
-
// Whether connection is limited by amplification factor.
bool LimitedByAmplificationFactor() const;
@@ -1846,6 +1842,13 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// when a new client connection ID is received.
void OnClientConnectionIdAvailable();
+ // Returns true if connection needs to set retransmission alarm after a packet
+ // gets sent.
+ bool ShouldSetRetransmissionAlarmOnPacketSent(bool in_flight,
+ EncryptionLevel level) const;
+
+ QuicConnectionContext context_;
+
QuicFramer framer_;
// Contents received in the current packet, especially used to identify
@@ -1873,8 +1876,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
const QuicClock* clock_;
QuicRandom* random_generator_;
- QuicConnectionId server_connection_id_;
- QuicConnectionId client_connection_id_;
// On the server, the connection ID is set when receiving the first packet.
// This variable ensures we only set it this way once.
bool client_connection_id_is_set_;
@@ -2022,10 +2023,9 @@ class QUIC_EXPORT_PRIVATE QuicConnection
QuicPacketCreator packet_creator_;
- // The time that a packet is received for this connection. Initialized to
- // connection creation time.
- // This does not indicate the packet was processed.
- QuicTime time_of_last_received_packet_;
+ // Information about the last received QUIC packet, which may not have been
+ // successfully decrypted and processed.
+ ReceivedPacketInfo last_received_packet_info_;
// Sent packet manager which tracks the status of packets sent by this
// connection and contains the send and receive algorithms to determine when
@@ -2043,12 +2043,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// close.
bool connected_;
- // Destination address of the last received packet.
- QuicSocketAddress last_packet_destination_address_;
-
- // Source address of the last received packet.
- QuicSocketAddress last_packet_source_address_;
-
// Destination connection ID of the last received packet. If this ID is the
// original server connection ID chosen by client and server replaces it with
// a different ID, last_packet_destination_connection_id_ is set to the
@@ -2118,12 +2112,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// retransmission code.
bool probing_retransmission_pending_;
- // Indicates whether a stateless reset token has been received from peer.
- bool stateless_reset_token_received_;
- // Stores received stateless reset token from peer. Used to verify whether a
- // packet is a stateless reset packet.
- StatelessResetToken received_stateless_reset_token_;
-
// Id of latest sent control frame. 0 if no control frame has been sent.
QuicControlFrameId last_control_frame_id_;
@@ -2164,11 +2152,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
quiche::QuicheCircularDeque<PendingPathChallenge>
pending_path_challenge_payloads_;
- // Set of connection IDs that should be accepted as destination on
- // received packets. This is conceptually a set but is implemented as a
- // vector to improve performance since it is expected to be very small.
- std::vector<QuicConnectionId> incoming_connection_ids_;
-
// When we receive a RETRY packet or some INITIAL packets, we replace
// |server_connection_id_| with the value from that packet and save off the
// original value of |server_connection_id_| into
@@ -2252,10 +2235,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// True if we are currently processing OnRetransmissionTimeout.
bool in_on_retransmission_time_out_ = false;
- const bool encrypted_control_frames_;
-
- const bool use_encryption_level_context_;
-
QuicPathValidator path_validator_;
// Stores information of a path which maybe used as default path in the
@@ -2273,8 +2252,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
// This field is used to debug b/177312785.
QuicFrameType most_recent_frame_type_;
- bool current_incoming_packet_received_bytes_counted_ = false;
-
bool count_bytes_on_alternative_path_separately_ =
GetQuicReloadableFlag(quic_count_bytes_on_alternative_path_seperately);
@@ -2283,12 +2260,6 @@ class QUIC_EXPORT_PRIVATE QuicConnection
bool support_multiple_connection_ids_ = false;
- const bool donot_write_mid_packet_processing_ =
- GetQuicReloadableFlag(quic_donot_write_mid_packet_processing);
-
- bool use_connection_id_on_default_path_ =
- GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2);
-
// Indicates whether we should proactively validate peer address on a
// PATH_CHALLENGE received.
bool should_proactively_validate_peer_address_on_path_challenge_ = false;
@@ -2300,8 +2271,14 @@ class QUIC_EXPORT_PRIVATE QuicConnection
GetQuicReloadableFlag(
quic_group_path_response_and_challenge_sending_closer);
- const bool quic_deprecate_incoming_connection_ids_ =
- GetQuicReloadableFlag(quic_deprecate_incoming_connection_ids);
+ const bool reset_per_packet_state_for_undecryptable_packets_ =
+ GetQuicReloadableFlag(
+ quic_reset_per_packet_state_for_undecryptable_packets);
+
+ const bool add_missing_update_ack_timeout_ =
+ GetQuicReloadableFlag(quic_add_missing_update_ack_timeout);
+
+ const bool ack_cid_frames_ = GetQuicReloadableFlag(quic_ack_cid_frames);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.cc
new file mode 100644
index 00000000000..e77fc431289
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.cc
@@ -0,0 +1,36 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quic/core/quic_connection_context.h"
+
+#include "common/platform/api/quiche_thread_local.h"
+
+namespace quic {
+namespace {
+DEFINE_QUICHE_THREAD_LOCAL_POINTER(CurrentContext, QuicConnectionContext);
+} // namespace
+
+// static
+QuicConnectionContext* QuicConnectionContext::Current() {
+ return GET_QUICHE_THREAD_LOCAL_POINTER(CurrentContext);
+}
+
+QuicConnectionContextSwitcher::QuicConnectionContextSwitcher(
+ QuicConnectionContext* new_context)
+ : old_context_(QuicConnectionContext::Current()) {
+ SET_QUICHE_THREAD_LOCAL_POINTER(CurrentContext, new_context);
+ if (new_context && new_context->tracer) {
+ new_context->tracer->Activate();
+ }
+}
+
+QuicConnectionContextSwitcher::~QuicConnectionContextSwitcher() {
+ QuicConnectionContext* current = QuicConnectionContext::Current();
+ if (current && current->tracer) {
+ current->tracer->Deactivate();
+ }
+ SET_QUICHE_THREAD_LOCAL_POINTER(CurrentContext, old_context_);
+}
+
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.h b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.h
new file mode 100644
index 00000000000..7cedee63353
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context.h
@@ -0,0 +1,118 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_
+#define QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "quic/platform/api/quic_export.h"
+#include "common/platform/api/quiche_logging.h"
+
+namespace quic {
+
+// QuicConnectionTracer is responsible for emit trace messages for a single
+// QuicConnection.
+// QuicConnectionTracer is part of the QuicConnectionContext.
+class QUIC_EXPORT_PRIVATE QuicConnectionTracer {
+ public:
+ virtual ~QuicConnectionTracer() = default;
+
+ // Emit a trace message from a string literal. The trace may simply remember
+ // the address of the literal in this function and read it at a later time.
+ virtual void PrintLiteral(const char* literal) = 0;
+
+ // Emit a trace message from a string_view. Unlike PrintLiteral, this function
+ // will not read |s| after it returns.
+ virtual void PrintString(absl::string_view s) = 0;
+
+ // Emit a trace message from printf-style arguments.
+ template <typename... Args>
+ void Printf(const absl::FormatSpec<Args...>& format, const Args&... args) {
+ std::string s = absl::StrFormat(format, args...);
+ PrintString(s);
+ }
+
+ private:
+ friend class QuicConnectionContextSwitcher;
+
+ // Called by QuicConnectionContextSwitcher, when |this| becomes the current
+ // thread's QUIC connection tracer.
+ //
+ // Activate/Deactivate are only called by QuicConnectionContextSwitcher's
+ // constructor/destructor, they always come in pairs.
+ virtual void Activate() {}
+
+ // Called by QuicConnectionContextSwitcher, when |this| stops from being the
+ // current thread's QUIC connection tracer.
+ //
+ // Activate/Deactivate are only called by QuicConnectionContextSwitcher's
+ // constructor/destructor, they always come in pairs.
+ virtual void Deactivate() {}
+};
+
+// QuicConnectionContext is a per-QuicConnection context that includes
+// facilities useable by any part of a QuicConnection. A QuicConnectionContext
+// is owned by a QuicConnection.
+//
+// The 'top-level' QuicConnection functions are responsible for maintaining the
+// thread-local QuicConnectionContext pointer, such that any function called by
+// them(directly or indirectly) can access the context.
+//
+// Like QuicConnection, all facilities in QuicConnectionContext are assumed to
+// be called from a single thread at a time, they are NOT thread-safe.
+struct QUIC_EXPORT_PRIVATE QuicConnectionContext final {
+ // Get the context on the current executing thread. nullptr if the current
+ // function is not called from a 'top-level' QuicConnection function.
+ static QuicConnectionContext* Current();
+
+ std::unique_ptr<QuicConnectionTracer> tracer;
+};
+
+// QuicConnectionContextSwitcher is a RAII object used for maintaining the
+// thread-local QuicConnectionContext pointer.
+class QUIC_EXPORT_PRIVATE QuicConnectionContextSwitcher final {
+ public:
+ // The constructor switches from QuicConnectionContext::Current() to
+ // |new_context|.
+ explicit QuicConnectionContextSwitcher(QuicConnectionContext* new_context);
+
+ // The destructor switches from QuicConnectionContext::Current() back to the
+ // old context.
+ ~QuicConnectionContextSwitcher();
+
+ private:
+ QuicConnectionContext* old_context_;
+};
+
+// Emit a trace message from a string literal to the current tracer(if any).
+inline void QUIC_TRACELITERAL(const char* literal) {
+ QuicConnectionContext* current = QuicConnectionContext::Current();
+ if (current && current->tracer) {
+ current->tracer->PrintLiteral(literal);
+ }
+}
+
+// Emit a trace message from a string_view to the current tracer(if any).
+inline void QUIC_TRACESTRING(absl::string_view s) {
+ QuicConnectionContext* current = QuicConnectionContext::Current();
+ if (current && current->tracer) {
+ current->tracer->PrintString(s);
+ }
+}
+
+// Emit a trace message from printf-style arguments to the current tracer(if
+// any).
+template <typename... Args>
+void QUIC_TRACEPRINTF(const absl::FormatSpec<Args...>& format,
+ const Args&... args) {
+ QuicConnectionContext* current = QuicConnectionContext::Current();
+ if (current && current->tracer) {
+ current->tracer->Printf(format, args...);
+ }
+}
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_CONNECTION_CONTEXT_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_context_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context_test.cc
new file mode 100644
index 00000000000..0f5b2c481b6
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_context_test.cc
@@ -0,0 +1,173 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "quic/core/quic_connection_context.h"
+
+#include "quic/platform/api/quic_test.h"
+#include "quic/platform/api/quic_thread.h"
+
+using testing::ElementsAre;
+
+namespace quic {
+namespace {
+
+class TraceCollector : public QuicConnectionTracer {
+ public:
+ ~TraceCollector() override = default;
+
+ void PrintLiteral(const char* literal) override { trace_.push_back(literal); }
+
+ void PrintString(absl::string_view s) override {
+ trace_.push_back(std::string(s));
+ }
+
+ const std::vector<std::string>& trace() const { return trace_; }
+
+ private:
+ std::vector<std::string> trace_;
+};
+
+struct FakeConnection {
+ FakeConnection() { context.tracer = std::make_unique<TraceCollector>(); }
+
+ const std::vector<std::string>& trace() const {
+ return static_cast<const TraceCollector*>(context.tracer.get())->trace();
+ }
+
+ QuicConnectionContext context;
+};
+
+void SimpleSwitch() {
+ FakeConnection connection;
+
+ // These should be ignored since current context is nullptr.
+ EXPECT_EQ(QuicConnectionContext::Current(), nullptr);
+ QUIC_TRACELITERAL("before switch: literal");
+ QUIC_TRACESTRING(std::string("before switch: string"));
+ QUIC_TRACEPRINTF("%s: %s", "before switch", "printf");
+
+ {
+ QuicConnectionContextSwitcher switcher(&connection.context);
+ QUIC_TRACELITERAL("literal");
+ QUIC_TRACESTRING(std::string("string"));
+ QUIC_TRACEPRINTF("%s", "printf");
+ }
+
+ EXPECT_EQ(QuicConnectionContext::Current(), nullptr);
+ QUIC_TRACELITERAL("after switch: literal");
+ QUIC_TRACESTRING(std::string("after switch: string"));
+ QUIC_TRACEPRINTF("%s: %s", "after switch", "printf");
+
+ EXPECT_THAT(connection.trace(), ElementsAre("literal", "string", "printf"));
+}
+
+void NestedSwitch() {
+ FakeConnection outer, inner;
+
+ {
+ QuicConnectionContextSwitcher switcher(&outer.context);
+ QUIC_TRACELITERAL("outer literal 0");
+ QUIC_TRACESTRING(std::string("outer string 0"));
+ QUIC_TRACEPRINTF("%s %s %d", "outer", "printf", 0);
+
+ {
+ QuicConnectionContextSwitcher switcher(&inner.context);
+ QUIC_TRACELITERAL("inner literal");
+ QUIC_TRACESTRING(std::string("inner string"));
+ QUIC_TRACEPRINTF("%s %s", "inner", "printf");
+ }
+
+ QUIC_TRACELITERAL("outer literal 1");
+ QUIC_TRACESTRING(std::string("outer string 1"));
+ QUIC_TRACEPRINTF("%s %s %d", "outer", "printf", 1);
+ }
+
+ EXPECT_THAT(outer.trace(), ElementsAre("outer literal 0", "outer string 0",
+ "outer printf 0", "outer literal 1",
+ "outer string 1", "outer printf 1"));
+
+ EXPECT_THAT(inner.trace(),
+ ElementsAre("inner literal", "inner string", "inner printf"));
+}
+
+void AlternatingSwitch() {
+ FakeConnection zero, one, two;
+ for (int i = 0; i < 15; ++i) {
+ FakeConnection* connection =
+ ((i % 3) == 0) ? &zero : (((i % 3) == 1) ? &one : &two);
+
+ QuicConnectionContextSwitcher switcher(&connection->context);
+ QUIC_TRACEPRINTF("%d", i);
+ }
+
+ EXPECT_THAT(zero.trace(), ElementsAre("0", "3", "6", "9", "12"));
+ EXPECT_THAT(one.trace(), ElementsAre("1", "4", "7", "10", "13"));
+ EXPECT_THAT(two.trace(), ElementsAre("2", "5", "8", "11", "14"));
+}
+
+typedef void (*ThreadFunction)();
+
+template <ThreadFunction func>
+class TestThread : public QuicThread {
+ public:
+ TestThread() : QuicThread("TestThread") {}
+ ~TestThread() override = default;
+
+ protected:
+ void Run() override { func(); }
+};
+
+template <ThreadFunction func>
+void RunInThreads(size_t n_threads) {
+ using ThreadType = TestThread<func>;
+ std::vector<ThreadType> threads(n_threads);
+
+ for (ThreadType& t : threads) {
+ t.Start();
+ }
+
+ for (ThreadType& t : threads) {
+ t.Join();
+ }
+}
+
+class QuicConnectionContextTest : public QuicTest {
+ protected:
+};
+
+TEST_F(QuicConnectionContextTest, NullTracerOK) {
+ FakeConnection connection;
+ std::unique_ptr<QuicConnectionTracer> tracer;
+
+ {
+ QuicConnectionContextSwitcher switcher(&connection.context);
+ QUIC_TRACELITERAL("msg 1 recorded");
+ }
+
+ connection.context.tracer.swap(tracer);
+
+ {
+ QuicConnectionContextSwitcher switcher(&connection.context);
+ // Should be a no-op since connection.context.tracer is nullptr.
+ QUIC_TRACELITERAL("msg 2 ignored");
+ }
+
+ EXPECT_THAT(static_cast<TraceCollector*>(tracer.get())->trace(),
+ ElementsAre("msg 1 recorded"));
+}
+
+TEST_F(QuicConnectionContextTest, TestSimpleSwitch) {
+ RunInThreads<SimpleSwitch>(10);
+}
+
+TEST_F(QuicConnectionContextTest, TestNestedSwitch) {
+ RunInThreads<NestedSwitch>(10);
+}
+
+TEST_F(QuicConnectionContextTest, TestAlternatingSwitch) {
+ RunInThreads<AlternatingSwitch>(10);
+}
+
+} // namespace
+} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
index fe2ff6cab6e..69666301c59 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_connection_test.cc
@@ -23,6 +23,7 @@
#include "quic/core/frames/quic_connection_close_frame.h"
#include "quic/core/frames/quic_new_connection_id_frame.h"
#include "quic/core/frames/quic_path_response_frame.h"
+#include "quic/core/frames/quic_rst_stream_frame.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_error_codes.h"
@@ -33,6 +34,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/core/quic_versions.h"
+#include "quic/platform/api/quic_error_code_wrappers.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_ip_address.h"
@@ -1102,12 +1104,9 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
MessageStatus SendMessage(absl::string_view message) {
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
- return connection_.SendMessage(
- 1,
- MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(), message,
- &storage),
- false);
+ QuicMemSlice slice(QuicBuffer::Copy(
+ connection_.helper()->GetStreamSendBufferAllocator(), message));
+ return connection_.SendMessage(1, absl::MakeSpan(&slice, 1), false);
}
void ProcessAckPacket(uint64_t packet_number, QuicAckFrame* frame) {
@@ -1179,7 +1178,12 @@ class QuicConnectionTest : public QuicTestWithParam<TestParams> {
}
if (peer_framer_.version().HasIetfInvariantHeader() &&
peer_framer_.perspective() == Perspective::IS_SERVER) {
- header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ if (!connection_.client_connection_id().IsEmpty()) {
+ header.destination_connection_id = connection_.client_connection_id();
+ header.destination_connection_id_included = CONNECTION_ID_PRESENT;
+ } else {
+ header.destination_connection_id_included = CONNECTION_ID_ABSENT;
+ }
if (header.version_flag) {
header.source_connection_id = connection_id_;
header.source_connection_id_included = CONNECTION_ID_PRESENT;
@@ -2171,6 +2175,10 @@ TEST_P(QuicConnectionTest, ReversePathValidationFailureAtServer) {
EXPECT_EQ(IPV6_TO_IPV4_CHANGE,
connection_.active_effective_peer_migration_type());
+ // Make sure anti-amplification limit is not reached.
+ ProcessFramesPacketWithAddresses(
+ {QuicFrame(QuicPingFrame()), QuicFrame(QuicPaddingFrame())}, kSelfAddress,
+ kNewPeerAddress, ENCRYPTION_FORWARD_SECURE);
SendStreamDataToPeer(1, "foo", 0, NO_FIN, nullptr);
EXPECT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
@@ -3754,11 +3762,9 @@ TEST_P(QuicConnectionTest, OnCanWrite) {
TEST_P(QuicConnectionTest, RetransmitOnNack) {
QuicPacketNumber last_packet;
- QuicByteCount second_packet_size;
- SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet); // Packet 1
- second_packet_size =
- SendStreamDataToPeer(3, "foos", 3, NO_FIN, &last_packet); // Packet 2
- SendStreamDataToPeer(3, "fooos", 7, NO_FIN, &last_packet); // Packet 3
+ SendStreamDataToPeer(3, "foo", 0, NO_FIN, &last_packet);
+ SendStreamDataToPeer(3, "foos", 3, NO_FIN, &last_packet);
+ SendStreamDataToPeer(3, "fooos", 7, NO_FIN, &last_packet);
EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
@@ -8775,8 +8781,7 @@ TEST_P(QuicConnectionTest, SendMessage) {
connection_.SetFromConfig(config);
}
std::string message(connection_.GetCurrentLargestMessagePayload() * 2, 'a');
- absl::string_view message_data(message);
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
+ QuicMemSlice slice;
{
QuicConnection::ScopedPacketFlusher flusher(&connection_);
connection_.SendStreamData3();
@@ -8784,36 +8789,23 @@ TEST_P(QuicConnectionTest, SendMessage) {
// get sent, one contains stream frame, and the other only contains the
// message frame.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ slice = MemSliceFromString(absl::string_view(
+ message.data(), connection_.GetCurrentLargestMessagePayload()));
EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
- connection_.SendMessage(
- 1,
- MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- absl::string_view(
- message_data.data(),
- connection_.GetCurrentLargestMessagePayload()),
- &storage),
- false));
+ connection_.SendMessage(1, absl::MakeSpan(&slice, 1), false));
}
// Fail to send a message if connection is congestion control blocked.
EXPECT_CALL(*send_algorithm_, CanSend(_)).WillOnce(Return(false));
+ slice = MemSliceFromString("message");
EXPECT_EQ(MESSAGE_STATUS_BLOCKED,
- connection_.SendMessage(
- 2,
- MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- "message", &storage),
- false));
+ connection_.SendMessage(2, absl::MakeSpan(&slice, 1), false));
// Always fail to send a message which cannot fit into one packet.
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(0);
+ slice = MemSliceFromString(absl::string_view(
+ message.data(), connection_.GetCurrentLargestMessagePayload() + 1));
EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
- connection_.SendMessage(
- 3,
- MakeSpan(connection_.helper()->GetStreamSendBufferAllocator(),
- absl::string_view(
- message_data.data(),
- connection_.GetCurrentLargestMessagePayload() + 1),
- &storage),
- false));
+ connection_.SendMessage(3, absl::MakeSpan(&slice, 1), false));
}
TEST_P(QuicConnectionTest, GetCurrentLargestMessagePayload) {
@@ -10545,16 +10537,16 @@ void QuicConnectionTest::TestClientRetryHandling(
}
// These values come from draft-ietf-quic-tls Appendix A.4.
- char retry_packet_rfcv1[] = {
+ uint8_t retry_packet_rfcv1[] = {
0xff, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a,
0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x04, 0xa2, 0x65, 0xba,
0x2e, 0xff, 0x4d, 0x82, 0x90, 0x58, 0xfb, 0x3f, 0x0f, 0x24, 0x96, 0xba};
- char retry_packet29[] = {
+ uint8_t retry_packet29[] = {
0xff, 0xff, 0x00, 0x00, 0x1d, 0x00, 0x08, 0xf0, 0x67, 0xa5, 0x50, 0x2a,
0x42, 0x62, 0xb5, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0xd1, 0x69, 0x26, 0xd8,
0x1f, 0x6f, 0x9c, 0xa2, 0x95, 0x3a, 0x8a, 0xa4, 0x57, 0x5e, 0x1e, 0x49};
- char* retry_packet;
+ uint8_t* retry_packet;
size_t retry_packet_length;
if (version() == ParsedQuicVersion::RFCv1()) {
retry_packet = retry_packet_rfcv1;
@@ -10568,19 +10560,21 @@ void QuicConnectionTest::TestClientRetryHandling(
return;
}
- char original_connection_id_bytes[] = {0x83, 0x94, 0xc8, 0xf0,
- 0x3e, 0x51, 0x57, 0x08};
- char new_connection_id_bytes[] = {0xf0, 0x67, 0xa5, 0x50,
- 0x2a, 0x42, 0x62, 0xb5};
- char retry_token_bytes[] = {0x74, 0x6f, 0x6b, 0x65, 0x6e};
+ uint8_t original_connection_id_bytes[] = {0x83, 0x94, 0xc8, 0xf0,
+ 0x3e, 0x51, 0x57, 0x08};
+ uint8_t new_connection_id_bytes[] = {0xf0, 0x67, 0xa5, 0x50,
+ 0x2a, 0x42, 0x62, 0xb5};
+ uint8_t retry_token_bytes[] = {0x74, 0x6f, 0x6b, 0x65, 0x6e};
QuicConnectionId original_connection_id(
- original_connection_id_bytes,
+ reinterpret_cast<char*>(original_connection_id_bytes),
ABSL_ARRAYSIZE(original_connection_id_bytes));
- QuicConnectionId new_connection_id(new_connection_id_bytes,
- ABSL_ARRAYSIZE(new_connection_id_bytes));
+ QuicConnectionId new_connection_id(
+ reinterpret_cast<char*>(new_connection_id_bytes),
+ ABSL_ARRAYSIZE(new_connection_id_bytes));
- std::string retry_token(retry_token_bytes, ABSL_ARRAYSIZE(retry_token_bytes));
+ std::string retry_token(reinterpret_cast<char*>(retry_token_bytes),
+ ABSL_ARRAYSIZE(retry_token_bytes));
if (invalid_retry_tag) {
// Flip the last bit of the retry packet to prevent the integrity tag
@@ -10611,7 +10605,8 @@ void QuicConnectionTest::TestClientRetryHandling(
// Process the RETRY packet.
connection_.ProcessUdpPacket(
kSelfAddress, kPeerAddress,
- QuicReceivedPacket(retry_packet, retry_packet_length, clock_.Now()));
+ QuicReceivedPacket(reinterpret_cast<char*>(retry_packet),
+ retry_packet_length, clock_.Now()));
if (invalid_retry_tag) {
// Make sure we refuse to process a RETRY with invalid tag.
@@ -11572,6 +11567,67 @@ TEST_P(QuicConnectionTest, CoalscingPacketCausesInfiniteLoop) {
connection_.GetRetransmissionAlarm()->Fire();
}
+TEST_P(QuicConnectionTest, ClientAckDelayForAsyncPacketProcessing) {
+ if (!version().HasIetfQuicFrames()) {
+ return;
+ }
+ // SetFromConfig is always called after construction from InitializeSession.
+ EXPECT_CALL(visitor_, OnSuccessfulVersionNegotiation(_));
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(visitor_, OnHandshakePacketSent()).Times(AnyNumber());
+ QuicConfig config;
+ connection_.SetFromConfig(config);
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ peer_framer_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x01));
+ EXPECT_EQ(0u, QuicConnectionPeer::NumUndecryptablePackets(&connection_));
+
+ // Received undecryptable HANDSHAKE 2.
+ ProcessDataPacketAtLevel(2, !kHasStopWaiting, ENCRYPTION_HANDSHAKE);
+ ASSERT_EQ(1u, QuicConnectionPeer::NumUndecryptablePackets(&connection_));
+ // Received INITIAL 4 (which is retransmission of INITIAL 1) after 100ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(100));
+ ProcessDataPacketAtLevel(4, !kHasStopWaiting, ENCRYPTION_INITIAL);
+ // Generate HANDSHAKE key.
+ SetDecrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<StrictTaggingDecrypter>(0x01));
+ EXPECT_TRUE(connection_.GetProcessUndecryptablePacketsAlarm()->IsSet());
+ connection_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_HANDSHAKE);
+ // Verify HANDSHAKE packet gets processed.
+ connection_.GetProcessUndecryptablePacketsAlarm()->Fire();
+ ASSERT_TRUE(connection_.HasPendingAcks());
+ // Send ACKs.
+ clock_.AdvanceTime(connection_.GetAckAlarm()->deadline() - clock_.Now());
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(2);
+ connection_.GetAckAlarm()->Fire();
+ ASSERT_FALSE(writer_->ack_frames().empty());
+ // Verify the ack_delay_time in the INITIAL ACK frame is 1ms.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1),
+ writer_->ack_frames()[0].ack_delay_time);
+ // Process the coalesced HANDSHAKE packet.
+ ASSERT_TRUE(writer_->coalesced_packet() != nullptr);
+ auto packet = writer_->coalesced_packet()->Clone();
+ writer_->framer()->ProcessPacket(*packet);
+ ASSERT_FALSE(writer_->ack_frames().empty());
+ if (GetQuicReloadableFlag(
+ quic_reset_per_packet_state_for_undecryptable_packets)) {
+ // Verify the ack_delay_time in the HANDSHAKE ACK frame includes the
+ // buffering time.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(101),
+ writer_->ack_frames()[0].ack_delay_time);
+ } else {
+ // This ack_delay_time is wrong.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(1),
+ writer_->ack_frames()[0].ack_delay_time);
+ }
+ ASSERT_TRUE(writer_->coalesced_packet() == nullptr);
+}
+
TEST_P(QuicConnectionTest, TestingLiveness) {
const size_t kMinRttMs = 40;
RttStats* rtt_stats = const_cast<RttStats*>(manager_->GetRttStats());
@@ -12017,7 +12073,7 @@ TEST_P(QuicConnectionTest, PathValidationReceivesStatelessReset) {
// writer.
TEST_P(QuicConnectionTest, SendPathChallengeUsingBlockedNewSocket) {
if (!VersionHasIetfQuicFrames(connection_.version().transport_version) ||
- !connection_.use_path_validator()) {
+ !connection_.connection_migration_use_new_cid()) {
return;
}
PathProbeTestInit(Perspective::IS_CLIENT);
@@ -12027,6 +12083,7 @@ TEST_P(QuicConnectionTest, SendPathChallengeUsingBlockedNewSocket) {
new_writer.BlockOnNextWrite();
EXPECT_CALL(visitor_, OnWriteBlocked()).Times(0);
EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _))
+ .Times(AtLeast(1))
.WillOnce(Invoke([&]() {
// Even though the socket is blocked, the PATH_CHALLENGE should still be
// treated as sent.
@@ -12047,7 +12104,13 @@ TEST_P(QuicConnectionTest, SendPathChallengeUsingBlockedNewSocket) {
new_writer.SetWritable();
// Write event on the default socket shouldn't make any difference.
connection_.OnCanWrite();
- EXPECT_EQ(0u, writer_->packets_write_attempts());
+ if (GetQuicReloadableFlag(quic_ack_cid_frames)) {
+ // A NEW_CONNECTION_ID frame is received in PathProbeTestInit and OnCanWrite
+ // will write a acking packet.
+ EXPECT_EQ(1u, writer_->packets_write_attempts());
+ } else {
+ EXPECT_EQ(0u, writer_->packets_write_attempts());
+ }
EXPECT_EQ(1u, new_writer.packets_write_attempts());
}
@@ -12232,9 +12295,12 @@ TEST_P(QuicConnectionTest,
return;
}
PathProbeTestInit(Perspective::IS_CLIENT);
+ // Make sure there is no outstanding ACK_FRAME to write.
+ connection_.OnCanWrite();
+ uint32_t num_packets_write_attempts = writer_->packets_write_attempts();
writer_->SetShouldWriteFail();
- writer_->SetWriteError(EMSGSIZE);
+ writer_->SetWriteError(QUIC_EMSGSIZE);
const QuicSocketAddress kNewPeerAddress(QuicIpAddress::Any4(), 12345);
EXPECT_CALL(visitor_, OnConnectionClosed(_, ConnectionCloseSource::FROM_SELF))
.Times(0u);
@@ -12250,7 +12316,7 @@ TEST_P(QuicConnectionTest,
EXPECT_TRUE(connection_.HasPendingPathValidation());
// Connection shouldn't be closed.
EXPECT_TRUE(connection_.connected());
- EXPECT_EQ(1u, writer_->packets_write_attempts());
+ EXPECT_EQ(++num_packets_write_attempts, writer_->packets_write_attempts());
EXPECT_EQ(1u, writer_->path_challenge_frames().size());
EXPECT_EQ(1u, writer_->padding_frames().size());
EXPECT_EQ(kNewPeerAddress, writer_->last_write_peer_address());
@@ -12656,10 +12722,6 @@ TEST_P(QuicConnectionTest, ZeroRttRejectionAndMissingInitialKeys) {
connection_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
std::make_unique<TaggingEncrypter>(0x04));
connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
- if (!GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
- // Retransmit rejected 0-RTT packets.
- connection_.OnCanWrite();
- }
// Advance INITIAL ack delay to trigger initial ACK to be sent AFTER
// the retransmission of rejected 0-RTT packets while the HANDSHAKE
// packet is still in the coalescer, such that the INITIAL key gets
@@ -13576,19 +13638,33 @@ TEST_P(QuicConnectionTest, ServerHelloGetsReordered) {
TEST_P(QuicConnectionTest, MigratePath) {
EXPECT_CALL(visitor_, GetHandshakeState())
- .Times(testing::AtMost(1))
- .WillOnce(Return(HANDSHAKE_CONFIRMED));
+ .Times(testing::AtMost(2))
+ .WillRepeatedly(Return(HANDSHAKE_CONFIRMED));
EXPECT_CALL(visitor_, OnPathDegrading());
connection_.OnPathDegradingDetected();
const QuicSocketAddress kNewSelfAddress(QuicIpAddress::Any4(), 12345);
EXPECT_NE(kNewSelfAddress, connection_.self_address());
+
+ // Buffer a packet.
+ EXPECT_CALL(visitor_, OnWriteBlocked()).Times(1);
+ writer_->SetWriteBlocked();
+ connection_.SendMtuDiscoveryPacket(kMaxOutgoingPacketSize);
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+
TestPacketWriter new_writer(version(), &clock_, Perspective::IS_CLIENT);
EXPECT_CALL(visitor_, OnForwardProgressMadeAfterPathDegrading());
connection_.MigratePath(kNewSelfAddress, connection_.peer_address(),
&new_writer, /*owns_writer=*/false);
+
EXPECT_EQ(kNewSelfAddress, connection_.self_address());
EXPECT_EQ(&new_writer, QuicConnectionPeer::GetWriter(&connection_));
EXPECT_FALSE(connection_.IsPathDegrading());
+ // Buffered packet on the old path should be discarded.
+ if (connection_.connection_migration_use_new_cid()) {
+ EXPECT_EQ(0u, connection_.NumQueuedPackets());
+ } else {
+ EXPECT_EQ(1u, connection_.NumQueuedPackets());
+ }
}
TEST_P(QuicConnectionTest, MigrateToNewPathDuringProbing) {
@@ -14453,9 +14529,11 @@ TEST_P(QuicConnectionTest,
// would fail due to lack of client connection ID.
const QuicSocketAddress kSelfAddress2(QuicIpAddress::Loopback4(),
/*port=*/45678);
- ASSERT_FALSE(connection_.MigratePath(kSelfAddress2,
- connection_.peer_address(), &new_writer,
- /*owns_writer=*/false));
+ auto new_writer2 = std::make_unique<TestPacketWriter>(version(), &clock_,
+ Perspective::IS_CLIENT);
+ ASSERT_FALSE(connection_.MigratePath(
+ kSelfAddress2, connection_.peer_address(), new_writer2.release(),
+ /*owns_writer=*/true));
}
TEST_P(QuicConnectionTest,
@@ -14587,7 +14665,6 @@ TEST_P(
QuicConnectionTest,
ReplacePeerIssuedConnectionIdOnBothPathsTriggeredByNewConnectionIdFrame) {
if (!version().HasIetfQuicFrames() || !connection_.use_path_validator() ||
- !connection_.use_connection_id_on_default_path() ||
!connection_.count_bytes_on_alternative_path_separately()) {
return;
}
@@ -14647,7 +14724,7 @@ TEST_P(
TEST_P(QuicConnectionTest,
CloseConnectionAfterReceiveRetireConnectionIdWhenNoCIDIssued) {
if (!version().HasIetfQuicFrames() ||
- GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
+ !connection_.connection_migration_use_new_cid()) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14668,7 +14745,7 @@ TEST_P(QuicConnectionTest,
TEST_P(QuicConnectionTest, RetireConnectionIdFrameResultsInError) {
if (!version().HasIetfQuicFrames() ||
- GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
+ !connection_.connection_migration_use_new_cid()) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14708,24 +14785,16 @@ TEST_P(QuicConnectionTest,
QuicConnectionId cid0 = connection_id_;
QuicRetireConnectionIdFrame frame;
frame.sequence_number = 0u;
- if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2) ||
- connection_.connection_migration_use_new_cid()) {
+ if (connection_.connection_migration_use_new_cid()) {
EXPECT_CALL(visitor_, OnServerConnectionIdIssued(_)).Times(2);
EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(2);
}
EXPECT_TRUE(connection_.OnRetireConnectionIdFrame(frame));
- if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
- ASSERT_TRUE(retire_self_issued_cid_alarm->IsSet());
- // cid0 is retired when the retire CID alarm fires.
- if (!GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2))
- EXPECT_CALL(visitor_, OnServerConnectionIdRetired(cid0));
- retire_self_issued_cid_alarm->Fire();
- }
}
TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
if (!version().HasIetfQuicFrames() ||
- GetQuicReloadableFlag(quic_use_connection_id_on_default_path_v2)) {
+ !connection_.connection_migration_use_new_cid()) {
return;
}
QuicConnectionPeer::EnableMultipleConnectionIdSupport(&connection_);
@@ -14770,8 +14839,7 @@ TEST_P(QuicConnectionTest, ServerRetireSelfIssuedConnectionId) {
TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoAlternativePath) {
if (!version().HasIetfQuicFrames() ||
- !connection_.support_multiple_connection_ids() ||
- !connection_.use_connection_id_on_default_path()) {
+ !connection_.support_multiple_connection_ids()) {
return;
}
set_perspective(Perspective::IS_SERVER);
@@ -14807,8 +14875,7 @@ TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoAlternativePath) {
TEST_P(QuicConnectionTest, PatchMissingClientConnectionIdOntoDefaultPath) {
if (!version().HasIetfQuicFrames() ||
- !connection_.support_multiple_connection_ids() ||
- !connection_.use_connection_id_on_default_path()) {
+ !connection_.support_multiple_connection_ids()) {
return;
}
set_perspective(Perspective::IS_SERVER);
@@ -14923,23 +14990,13 @@ TEST_P(QuicConnectionTest, LostDataThenGetAcknowledged) {
InvokeWithoutArgs(&notifier_, &SimpleSessionNotifier::OnCanWrite));
QuicIpAddress ip_address;
ASSERT_TRUE(ip_address.FromString("127.0.52.223"));
- if (GetQuicReloadableFlag(quic_donot_write_mid_packet_processing)) {
- EXPECT_QUIC_BUG(
- ProcessFramesPacketWithAddresses(frames, kSelfAddress,
- QuicSocketAddress(ip_address, 1000),
- ENCRYPTION_FORWARD_SECURE),
- "Try to write mid packet processing");
- EXPECT_EQ(1u, writer_->path_challenge_frames().size());
- // Verify stream frame will not be retransmitted.
- EXPECT_TRUE(writer_->stream_frames().empty());
- } else {
- ProcessFramesPacketWithAddresses(frames, kSelfAddress,
- QuicSocketAddress(ip_address, 1000),
- ENCRYPTION_FORWARD_SECURE);
- // In prod, this would cause FAILED_TO_SERIALIZE_PACKET since the stream
- // data has been freed, but simple_data_producer does not free data.
- EXPECT_EQ(1u, writer_->stream_frames().size());
- }
+ EXPECT_QUIC_BUG(ProcessFramesPacketWithAddresses(
+ frames, kSelfAddress, QuicSocketAddress(ip_address, 1000),
+ ENCRYPTION_FORWARD_SECURE),
+ "Try to write mid packet processing");
+ EXPECT_EQ(1u, writer_->path_challenge_frames().size());
+ // Verify stream frame will not be retransmitted.
+ EXPECT_TRUE(writer_->stream_frames().empty());
}
TEST_P(QuicConnectionTest, PtoSendStreamData) {
@@ -14980,12 +15037,320 @@ TEST_P(QuicConnectionTest, PtoSendStreamData) {
ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
connection_.GetRetransmissionAlarm()->Fire();
- if (GetQuicReloadableFlag(quic_donot_pto_half_rtt_data)) {
- // Verify INITIAL and HANDSHAKE get retransmitted.
- EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+ // Verify INITIAL and HANDSHAKE get retransmitted.
+ EXPECT_EQ(0x02020202u, writer_->final_bytes_of_last_packet());
+}
+
+TEST_P(QuicConnectionTest, SendingZeroRttPacketsDoesNotPostponePTO) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ // Send CHLO.
+ connection_.SendCryptoStreamData();
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ // Install 0-RTT keys.
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+
+ // CHLO gets acknowledged after 10ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ QuicAckFrame frame1 = InitAckFrame(1);
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+ ProcessFramePacketAtLevel(1, QuicFrame(&frame1), ENCRYPTION_INITIAL);
+ // Verify PTO is still armed since address validation is not finished yet.
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ QuicTime pto_deadline = connection_.GetRetransmissionAlarm()->deadline();
+
+ // Send 0-RTT packet.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN);
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ if (GetQuicReloadableFlag(
+ quic_donot_rearm_pto_on_application_data_during_handshake)) {
+ // PTO deadline should be unchanged.
+ EXPECT_EQ(pto_deadline, connection_.GetRetransmissionAlarm()->deadline());
} else {
- // Application data preempts handshake data when PTO fires.
- EXPECT_EQ(0x03030303u, writer_->final_bytes_of_last_packet());
+ // PTO gets re-armed.
+ EXPECT_NE(pto_deadline, connection_.GetRetransmissionAlarm()->deadline());
+ }
+}
+
+TEST_P(QuicConnectionTest, QueueingUndecryptablePacketsDoesntPostponePTO) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ QuicConfig config;
+ config.set_max_undecryptable_packets(3);
+ connection_.SetFromConfig(config);
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.RemoveDecrypter(ENCRYPTION_FORWARD_SECURE);
+ // Send CHLO.
+ connection_.SendCryptoStreamData();
+
+ // Send 0-RTT packet.
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN);
+
+ // CHLO gets acknowledged after 10ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ QuicAckFrame frame1 = InitAckFrame(1);
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+ ProcessFramePacketAtLevel(1, QuicFrame(&frame1), ENCRYPTION_INITIAL);
+ // Verify PTO is still armed since address validation is not finished yet.
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ QuicTime pto_deadline = connection_.GetRetransmissionAlarm()->deadline();
+
+ // Receive an undecryptable packets.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ peer_framer_.SetEncrypter(ENCRYPTION_FORWARD_SECURE,
+ std::make_unique<TaggingEncrypter>(0xFF));
+ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+ // Verify PTO deadline is sooner.
+ EXPECT_GT(pto_deadline, connection_.GetRetransmissionAlarm()->deadline());
+ pto_deadline = connection_.GetRetransmissionAlarm()->deadline();
+
+ // PTO fires.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ clock_.AdvanceTime(pto_deadline - clock_.ApproximateNow());
+ connection_.GetRetransmissionAlarm()->Fire();
+ // Verify PTO is still armed since address validation is not finished yet.
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ pto_deadline = connection_.GetRetransmissionAlarm()->deadline();
+
+ // Verify PTO deadline does not change.
+ ProcessDataPacketAtLevel(4, !kHasStopWaiting, ENCRYPTION_FORWARD_SECURE);
+ EXPECT_EQ(pto_deadline, connection_.GetRetransmissionAlarm()->deadline());
+}
+
+TEST_P(QuicConnectionTest, QueueUndecryptableHandshakePackets) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ QuicConfig config;
+ config.set_max_undecryptable_packets(3);
+ connection_.SetFromConfig(config);
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ connection_.RemoveDecrypter(ENCRYPTION_HANDSHAKE);
+ // Send CHLO.
+ connection_.SendCryptoStreamData();
+
+ // Send 0-RTT packet.
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN);
+ EXPECT_EQ(0u, QuicConnectionPeer::NumUndecryptablePackets(&connection_));
+
+ // Receive an undecryptable handshake packet.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(5));
+ peer_framer_.SetEncrypter(ENCRYPTION_HANDSHAKE,
+ std::make_unique<TaggingEncrypter>(0xFF));
+ ProcessDataPacketAtLevel(3, !kHasStopWaiting, ENCRYPTION_HANDSHAKE);
+ // Verify this handshake packet gets queued.
+ EXPECT_EQ(1u, QuicConnectionPeer::NumUndecryptablePackets(&connection_));
+}
+
+TEST_P(QuicConnectionTest, PingNotSentAt0RTTLevelWhenInitialAvailable) {
+ if (!connection_.SupportsMultiplePacketNumberSpaces()) {
+ return;
+ }
+ use_tagging_decrypter();
+ connection_.SetEncrypter(ENCRYPTION_INITIAL,
+ std::make_unique<TaggingEncrypter>(0x01));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_INITIAL);
+ // Send CHLO.
+ connection_.SendCryptoStreamData();
+ // Send 0-RTT packet.
+ connection_.SetEncrypter(ENCRYPTION_ZERO_RTT,
+ std::make_unique<TaggingEncrypter>(0x02));
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_ZERO_RTT);
+ connection_.SendStreamDataWithString(2, "foo", 0, NO_FIN);
+
+ // CHLO gets acknowledged after 10ms.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(10));
+ QuicAckFrame frame1 = InitAckFrame(1);
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+ ProcessFramePacketAtLevel(1, QuicFrame(&frame1), ENCRYPTION_INITIAL);
+ // Verify PTO is still armed since address validation is not finished yet.
+ ASSERT_TRUE(connection_.GetRetransmissionAlarm()->IsSet());
+ QuicTime pto_deadline = connection_.GetRetransmissionAlarm()->deadline();
+
+ // PTO fires.
+ EXPECT_CALL(*send_algorithm_, OnPacketSent(_, _, _, _, _)).Times(1);
+ clock_.AdvanceTime(pto_deadline - clock_.ApproximateNow());
+ connection_.GetRetransmissionAlarm()->Fire();
+ // Verify the PING gets sent in ENCRYPTION_INITIAL.
+ EXPECT_EQ(0x01010101u, writer_->final_bytes_of_last_packet());
+}
+
+TEST_P(QuicConnectionTest, AckElicitingFrames) {
+ QuicConfig config;
+ config.SetConnectionOptionsToSend({kRVCM});
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ connection_.SetFromConfig(config);
+ if (!version().HasIetfQuicFrames() ||
+ !connection_.connection_migration_use_new_cid() ||
+ !GetQuicReloadableFlag(quic_ack_cid_frames) ||
+ !GetQuicReloadableFlag(quic_add_missing_update_ack_timeout)) {
+ return;
+ }
+ EXPECT_CALL(visitor_, SendNewConnectionId(_)).Times(2);
+ EXPECT_CALL(visitor_, OnRstStream(_));
+ EXPECT_CALL(visitor_, OnWindowUpdateFrame(_));
+ EXPECT_CALL(visitor_, OnBlockedFrame(_));
+ EXPECT_CALL(visitor_, OnHandshakeDoneReceived());
+ EXPECT_CALL(visitor_, OnStreamFrame(_));
+ EXPECT_CALL(*send_algorithm_, OnCongestionEvent(_, _, _, _, _));
+ EXPECT_CALL(visitor_, OnMaxStreamsFrame(_));
+ EXPECT_CALL(visitor_, OnStreamsBlockedFrame(_));
+ EXPECT_CALL(visitor_, OnStopSendingFrame(_));
+ EXPECT_CALL(visitor_, OnMessageReceived(""));
+ EXPECT_CALL(visitor_, OnNewTokenReceived(""));
+
+ SetClientConnectionId(TestConnectionId(12));
+ connection_.CreateConnectionIdManager();
+ QuicConnectionPeer::GetSelfIssuedConnectionIdManager(&connection_)
+ ->MaybeSendNewConnectionIds();
+ connection_.set_can_receive_ack_frequency_frame();
+
+ QuicAckFrame ack_frame = InitAckFrame(1);
+ QuicRstStreamFrame rst_stream_frame;
+ QuicWindowUpdateFrame window_update_frame;
+ QuicPathChallengeFrame path_challenge_frame;
+ QuicNewConnectionIdFrame new_connection_id_frame;
+ QuicRetireConnectionIdFrame retire_connection_id_frame;
+ retire_connection_id_frame.sequence_number = 1u;
+ QuicStopSendingFrame stop_sending_frame;
+ QuicPathResponseFrame path_response_frame;
+ QuicMessageFrame message_frame;
+ QuicNewTokenFrame new_token_frame;
+ QuicAckFrequencyFrame ack_frequency_frame;
+ QuicBlockedFrame blocked_frame;
+ size_t packet_number = 1;
+
+ connection_.SetDefaultEncryptionLevel(ENCRYPTION_FORWARD_SECURE);
+
+ for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) {
+ QuicFrameType frame_type = static_cast<QuicFrameType>(i);
+ bool skipped = false;
+ QuicFrame frame;
+ QuicFrames frames;
+ // Add some padding to fullfill the min size requirement of header
+ // protection.
+ frames.push_back(QuicFrame(QuicPaddingFrame(10)));
+ switch (frame_type) {
+ case PADDING_FRAME:
+ frame = QuicFrame(QuicPaddingFrame(10));
+ break;
+ case MTU_DISCOVERY_FRAME:
+ frame = QuicFrame(QuicMtuDiscoveryFrame());
+ break;
+ case PING_FRAME:
+ frame = QuicFrame(QuicPingFrame());
+ break;
+ case MAX_STREAMS_FRAME:
+ frame = QuicFrame(QuicMaxStreamsFrame());
+ break;
+ case STOP_WAITING_FRAME:
+ // Not supported.
+ skipped = true;
+ break;
+ case STREAMS_BLOCKED_FRAME:
+ frame = QuicFrame(QuicStreamsBlockedFrame());
+ break;
+ case STREAM_FRAME:
+ frame = QuicFrame(QuicStreamFrame());
+ break;
+ case HANDSHAKE_DONE_FRAME:
+ frame = QuicFrame(QuicHandshakeDoneFrame());
+ break;
+ case ACK_FRAME:
+ frame = QuicFrame(&ack_frame);
+ break;
+ case RST_STREAM_FRAME:
+ frame = QuicFrame(&rst_stream_frame);
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ // Do not test connection close.
+ skipped = true;
+ break;
+ case GOAWAY_FRAME:
+ // Does not exist in IETF QUIC.
+ skipped = true;
+ break;
+ case BLOCKED_FRAME:
+ frame = QuicFrame(&blocked_frame);
+ break;
+ case WINDOW_UPDATE_FRAME:
+ frame = QuicFrame(&window_update_frame);
+ break;
+ case PATH_CHALLENGE_FRAME:
+ frame = QuicFrame(&path_challenge_frame);
+ break;
+ case STOP_SENDING_FRAME:
+ frame = QuicFrame(&stop_sending_frame);
+ break;
+ case NEW_CONNECTION_ID_FRAME:
+ frame = QuicFrame(&new_connection_id_frame);
+ break;
+ case RETIRE_CONNECTION_ID_FRAME:
+ frame = QuicFrame(&retire_connection_id_frame);
+ break;
+ case PATH_RESPONSE_FRAME:
+ frame = QuicFrame(&path_response_frame);
+ break;
+ case MESSAGE_FRAME:
+ frame = QuicFrame(&message_frame);
+ break;
+ case CRYPTO_FRAME:
+ // CRYPTO_FRAME is ack eliciting is covered by other tests.
+ skipped = true;
+ break;
+ case NEW_TOKEN_FRAME:
+ frame = QuicFrame(&new_token_frame);
+ break;
+ case ACK_FREQUENCY_FRAME:
+ frame = QuicFrame(&ack_frequency_frame);
+ break;
+ case NUM_FRAME_TYPES:
+ skipped = true;
+ break;
+ }
+ if (skipped) {
+ continue;
+ }
+ ASSERT_EQ(frame_type, frame.type);
+ frames.push_back(frame);
+ EXPECT_FALSE(connection_.HasPendingAcks());
+ // Process frame.
+ ProcessFramesPacketAtLevel(packet_number++, frames,
+ ENCRYPTION_FORWARD_SECURE);
+ if (QuicUtils::IsAckElicitingFrame(frame_type)) {
+ ASSERT_TRUE(connection_.HasPendingAcks()) << frame;
+ // Flush ACK.
+ clock_.AdvanceTime(DefaultDelayedAckTime());
+ connection_.GetAckAlarm()->Fire();
+ }
+ EXPECT_FALSE(connection_.HasPendingAcks());
+ ASSERT_TRUE(connection_.connected());
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
index b750abb3a4f..162de8909bd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_constants.h
@@ -295,10 +295,10 @@ QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd;
QUIC_EXPORT_PRIVATE extern const char* const kEPIDGoogleFrontEnd0;
// HTTP/3 Datagrams.
-enum : QuicDatagramFlowId {
- kFirstDatagramFlowIdClient = 0,
- kFirstDatagramFlowIdServer = 1,
- kDatagramFlowIdIncrement = 2,
+enum : QuicDatagramContextId {
+ kFirstDatagramContextIdClient = 0,
+ kFirstDatagramContextIdServer = 1,
+ kDatagramContextIdIncrement = 2,
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
index f41a3560009..42862494745 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.cc
@@ -17,7 +17,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -167,14 +166,14 @@ void QuicControlFrameManager::OnControlFrameSent(const QuicFrame& frame) {
}
if (frame.type == WINDOW_UPDATE_FRAME) {
QuicStreamId stream_id = frame.window_update_frame->stream_id;
- if (QuicContainsKey(window_update_frames_, stream_id) &&
+ if (window_update_frames_.contains(stream_id) &&
id > window_update_frames_[stream_id]) {
// Consider the older window update of the same stream as acked.
OnControlFrameIdAcked(window_update_frames_[stream_id]);
}
window_update_frames_[stream_id] = id;
}
- if (QuicContainsKey(pending_retransmissions_, id)) {
+ if (pending_retransmissions_.contains(id)) {
// This is retransmitted control frame.
pending_retransmissions_.erase(id);
return;
@@ -197,7 +196,7 @@ bool QuicControlFrameManager::OnControlFrameAcked(const QuicFrame& frame) {
}
if (frame.type == WINDOW_UPDATE_FRAME) {
QuicStreamId stream_id = frame.window_update_frame->stream_id;
- if (QuicContainsKey(window_update_frames_, stream_id) &&
+ if (window_update_frames_.contains(stream_id) &&
window_update_frames_[stream_id] == id) {
window_update_frames_.erase(stream_id);
}
@@ -223,7 +222,7 @@ void QuicControlFrameManager::OnControlFrameLost(const QuicFrame& frame) {
// This frame has already been acked.
return;
}
- if (!QuicContainsKey(pending_retransmissions_, id)) {
+ if (!pending_retransmissions_.contains(id)) {
pending_retransmissions_[id] = true;
QUIC_BUG_IF(quic_bug_12727_2,
pending_retransmissions_.size() > control_frames_.size())
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
index 48d228bff31..962733a147d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_control_frame_manager.h
@@ -13,6 +13,7 @@
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_types.h"
#include "common/quiche_circular_deque.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -178,7 +179,8 @@ class QUIC_EXPORT_PRIVATE QuicControlFrameManager {
// TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
// is not used here.
// Lost control frames waiting to be retransmitted.
- QuicLinkedHashMap<QuicControlFrameId, bool> pending_retransmissions_;
+ quiche::QuicheLinkedHashMap<QuicControlFrameId, bool>
+ pending_retransmissions_;
DelegateInterface* delegate_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
index 660663a9acd..ed5da6cb544 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_client_handshaker_test.cc
@@ -105,6 +105,11 @@ class DummyProofSource : public ProofSource {
callback->Run(true, "Dummy signature", /*details=*/nullptr);
}
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override {
+ return {};
+ }
+
TicketCrypter* GetTicketCrypter() override { return nullptr; }
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_handshaker.cc
index 25bf9dcdf15..79142c4681e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_handshaker.cc
@@ -27,10 +27,7 @@ void QuicCryptoHandshaker::SendHandshakeMessage(
session()->OnCryptoHandshakeMessageSent(message);
last_sent_handshake_message_tag_ = message.tag();
const QuicData& data = message.GetSerialized();
- stream_->WriteCryptoData(session_->use_write_or_buffer_data_at_level()
- ? level
- : session_->connection()->encryption_level(),
- data.AsStringPiece());
+ stream_->WriteCryptoData(level, data.AsStringPiece());
}
void QuicCryptoHandshaker::OnError(CryptoFramer* framer) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
index 1dd68995e2f..9bd9c7bc2b9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_server_stream.cc
@@ -287,15 +287,8 @@ void QuicCryptoServerStream::FinishSendServerConfigUpdate(
QUIC_DVLOG(1) << "Server: Sending server config update: "
<< message.DebugString();
- if (!session()->use_write_or_buffer_data_at_level() &&
- !QuicVersionUsesCryptoFrames(transport_version())) {
- const QuicData& data = message.GetSerialized();
- WriteOrBufferData(absl::string_view(data.data(), data.length()), false,
- nullptr);
- } else {
- // Send server config update in ENCRYPTION_FORWARD_SECURE.
- SendHandshakeMessage(message, ENCRYPTION_FORWARD_SECURE);
- }
+ // Send server config update in ENCRYPTION_FORWARD_SECURE.
+ SendHandshakeMessage(message, ENCRYPTION_FORWARD_SECURE);
++num_server_config_update_messages_sent_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
index f8f34dfb22c..a14cef07f27 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_crypto_stream.cc
@@ -144,15 +144,8 @@ bool QuicCryptoStream::ExportKeyingMaterial(absl::string_view label,
void QuicCryptoStream::WriteCryptoData(EncryptionLevel level,
absl::string_view data) {
if (!QuicVersionUsesCryptoFrames(session()->transport_version())) {
- if (session()->use_write_or_buffer_data_at_level()) {
- WriteOrBufferDataAtLevel(data, /*fin=*/false, level,
- /*ack_listener=*/nullptr);
- return;
- }
- // The QUIC crypto handshake takes care of setting the appropriate
- // encryption level before writing data. Since that is the only handshake
- // supported in versions less than 47, |level| can be ignored here.
- WriteOrBufferData(data, /* fin */ false, /* ack_listener */ nullptr);
+ WriteOrBufferDataAtLevel(data, /*fin=*/false, level,
+ /*ack_listener=*/nullptr);
return;
}
if (data.empty()) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc
index d4513e48f69..e6f3e6f427a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue.cc
@@ -4,6 +4,7 @@
#include "quic/core/quic_datagram_queue.h"
+#include "absl/types/span.h"
#include "quic/core/quic_constants.h"
#include "quic/core/quic_session.h"
#include "quic/core/quic_time.h"
@@ -30,8 +31,7 @@ MessageStatus QuicDatagramQueue::SendOrQueueDatagram(QuicMemSlice datagram) {
// the datagrams are sent in the same order that they were sent by the
// application.
if (queue_.empty()) {
- QuicMemSliceSpan span(&datagram);
- MessageResult result = session_->SendMessage(span);
+ MessageResult result = session_->SendMessage(absl::MakeSpan(&datagram, 1));
if (result.status != MESSAGE_STATUS_BLOCKED) {
if (observer_) {
observer_->OnDatagramProcessed(result.status);
@@ -51,8 +51,8 @@ absl::optional<MessageStatus> QuicDatagramQueue::TrySendingNextDatagram() {
return absl::nullopt;
}
- QuicMemSliceSpan span(&queue_.front().datagram);
- MessageResult result = session_->SendMessage(span);
+ MessageResult result =
+ session_->SendMessage(absl::MakeSpan(&queue_.front().datagram, 1));
if (result.status != MESSAGE_STATUS_BLOCKED) {
queue_.pop_front();
if (observer_) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc
index f47bbb883cb..68a876b4cd0 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_datagram_queue_test.cc
@@ -176,8 +176,9 @@ TEST_F(QuicDatagramQueueTest, Expiry) {
std::vector<std::string> messages;
EXPECT_CALL(*connection_, SendMessage(_, _, _))
.WillRepeatedly([&messages](QuicMessageId /*id*/,
- QuicMemSliceSpan message, bool /*flush*/) {
- messages.push_back(std::string(message.GetData(0)));
+ absl::Span<QuicMemSlice> message,
+ bool /*flush*/) {
+ messages.push_back(std::string(message[0].AsStringView()));
return MESSAGE_STATUS_SUCCESS;
});
EXPECT_EQ(2u, queue_.SendDatagrams());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
index e1a999c706a..11f4bcd4b3d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.cc
@@ -205,6 +205,10 @@ class ChloAlpnSniExtractor : public ChloExtractor::Delegate {
if (chlo.GetStringPiece(quic::kSNI, &sni)) {
sni_ = std::string(sni);
}
+ absl::string_view uaid_value;
+ if (chlo.GetStringPiece(quic::kUAID, &uaid_value)) {
+ uaid_ = std::string(uaid_value);
+ }
if (version == LegacyVersionForEncapsulation().transport_version) {
absl::string_view qlve_value;
if (chlo.GetStringPiece(kQLVE, &qlve_value)) {
@@ -217,6 +221,8 @@ class ChloAlpnSniExtractor : public ChloExtractor::Delegate {
std::string&& ConsumeSni() { return std::move(sni_); }
+ std::string&& ConsumeUaid() { return std::move(uaid_); }
+
std::string&& ConsumeLegacyVersionEncapsulationInnerPacket() {
return std::move(legacy_version_encapsulation_inner_packet_);
}
@@ -224,15 +230,14 @@ class ChloAlpnSniExtractor : public ChloExtractor::Delegate {
private:
std::string alpn_;
std::string sni_;
+ std::string uaid_;
std::string legacy_version_encapsulation_inner_packet_;
};
bool MaybeHandleLegacyVersionEncapsulation(
QuicDispatcher* dispatcher,
- ChloAlpnSniExtractor* alpn_extractor,
+ std::string legacy_version_encapsulation_inner_packet,
const ReceivedPacketInfo& packet_info) {
- std::string legacy_version_encapsulation_inner_packet =
- alpn_extractor->ConsumeLegacyVersionEncapsulationInnerPacket();
if (legacy_version_encapsulation_inner_packet.empty()) {
// This CHLO did not contain the Legacy Version Encapsulation tag.
return false;
@@ -335,9 +340,14 @@ QuicDispatcher::QuicDispatcher(
<< "Trying to create dispatcher without any supported versions";
QUIC_DLOG(INFO) << "Created QuicDispatcher with versions: "
<< ParsedQuicVersionVectorToString(GetSupportedVersions());
+ QUIC_RESTART_FLAG_COUNT(quic_alarm_add_permanent_cancel);
}
QuicDispatcher::~QuicDispatcher() {
+ if (GetQuicRestartFlag(quic_alarm_add_permanent_cancel) &&
+ delete_sessions_alarm_ != nullptr) {
+ delete_sessions_alarm_->PermanentCancel();
+ }
reference_counted_session_map_.clear();
closed_ref_counted_session_list_.clear();
if (support_multiple_cid_per_connection_) {
@@ -532,8 +542,10 @@ bool QuicDispatcher::MaybeDispatchPacket(
config_->create_session_tag_indicators(),
&alpn_extractor,
server_connection_id.length())) {
- if (MaybeHandleLegacyVersionEncapsulation(this, &alpn_extractor,
- packet_info)) {
+ if (MaybeHandleLegacyVersionEncapsulation(
+ this,
+ alpn_extractor.ConsumeLegacyVersionEncapsulationInnerPacket(),
+ packet_info)) {
return true;
}
}
@@ -647,76 +659,38 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
packet_info->destination_connection_id;
// Packet's connection ID is unknown. Apply the validity checks.
QuicPacketFate fate = ValidityChecks(*packet_info);
- ChloAlpnSniExtractor alpn_extractor;
- switch (fate) {
- case kFateProcess: {
- if (packet_info->version.handshake_protocol == PROTOCOL_TLS1_3) {
- bool has_full_tls_chlo = false;
- std::string sni;
- std::vector<std::string> alpns;
- if (buffered_packets_.HasBufferedPackets(
- packet_info->destination_connection_id)) {
- // If we already have buffered packets for this connection ID,
- // use the associated TlsChloExtractor to parse this packet.
- has_full_tls_chlo =
- buffered_packets_.IngestPacketForTlsChloExtraction(
- packet_info->destination_connection_id, packet_info->version,
- packet_info->packet, &alpns, &sni);
- } else {
- // If we do not have a BufferedPacketList for this connection ID,
- // create a single-use one to check whether this packet contains a
- // full single-packet CHLO.
- TlsChloExtractor tls_chlo_extractor;
- tls_chlo_extractor.IngestPacket(packet_info->version,
- packet_info->packet);
- if (tls_chlo_extractor.HasParsedFullChlo()) {
- // This packet contains a full single-packet CHLO.
- has_full_tls_chlo = true;
- alpns = tls_chlo_extractor.alpns();
- sni = tls_chlo_extractor.server_name();
- }
- }
- if (has_full_tls_chlo) {
- ProcessChlo(alpns, sni, packet_info);
- } else {
- // This packet does not contain a full CHLO. It could be a 0-RTT
- // packet that arrived before the CHLO (due to loss or reordering),
- // or it could be a fragment of a multi-packet CHLO.
- BufferEarlyPacket(*packet_info);
- }
- break;
- }
- if (GetQuicFlag(FLAGS_quic_allow_chlo_buffering) &&
- !ChloExtractor::Extract(packet_info->packet, packet_info->version,
- config_->create_session_tag_indicators(),
- &alpn_extractor,
- server_connection_id.length())) {
- // Buffer non-CHLO packets.
- BufferEarlyPacket(*packet_info);
- break;
- }
- // We only apply this check for versions that do not use the IETF
- // invariant header because those versions are already checked in
- // QuicDispatcher::MaybeDispatchPacket.
- if (packet_info->version_flag &&
- !packet_info->version.HasIetfInvariantHeader() &&
- crypto_config()->validate_chlo_size() &&
- packet_info->packet.length() < kMinClientInitialPacketLength) {
- QUIC_DVLOG(1) << "Dropping CHLO packet which is too short, length: "
- << packet_info->packet.length();
- QUIC_CODE_COUNT(quic_drop_small_chlo_packets);
- break;
- }
+ if (fate == kFateProcess) {
+ std::string sni, uaid, legacy_version_encapsulation_inner_packet;
+ std::vector<std::string> alpns;
+ if (!TryExtractChloOrBufferEarlyPacket(
+ *packet_info, &sni, &uaid, &alpns,
+ &legacy_version_encapsulation_inner_packet)) {
+ // Client Hello incomplete. Packet has been buffered or (rarely) dropped.
+ return;
+ }
+
+ // Client Hello fully received.
+ fate = ValidityChecksOnFullChlo(*packet_info, sni, uaid, alpns);
- if (MaybeHandleLegacyVersionEncapsulation(this, &alpn_extractor,
- *packet_info)) {
- break;
+ if (fate == kFateProcess) {
+ QUICHE_DCHECK(legacy_version_encapsulation_inner_packet.empty() ||
+ !packet_info->version.UsesTls());
+ if (MaybeHandleLegacyVersionEncapsulation(
+ this, legacy_version_encapsulation_inner_packet, *packet_info)) {
+ return;
}
- ProcessChlo({alpn_extractor.ConsumeAlpn()}, alpn_extractor.ConsumeSni(),
- packet_info);
- } break;
+ ProcessChlo(alpns, sni, packet_info);
+ return;
+ }
+ }
+
+ switch (fate) {
+ case kFateProcess:
+ // kFateProcess have been processed above.
+ QUIC_BUG(quic_dispatcher_bad_packet_fate) << fate;
+ break;
case kFateTimeWait:
// Add this connection_id to the time-wait state, to safely reject
// future packets.
@@ -743,6 +717,81 @@ void QuicDispatcher::ProcessHeader(ReceivedPacketInfo* packet_info) {
}
}
+bool QuicDispatcher::TryExtractChloOrBufferEarlyPacket(
+ const ReceivedPacketInfo& packet_info,
+ std::string* sni,
+ std::string* uaid,
+ std::vector<std::string>* alpns,
+ std::string* legacy_version_encapsulation_inner_packet) {
+ sni->clear();
+ uaid->clear();
+ alpns->clear();
+ legacy_version_encapsulation_inner_packet->clear();
+
+ if (packet_info.version.UsesTls()) {
+ bool has_full_tls_chlo = false;
+ if (buffered_packets_.HasBufferedPackets(
+ packet_info.destination_connection_id)) {
+ // If we already have buffered packets for this connection ID,
+ // use the associated TlsChloExtractor to parse this packet.
+ has_full_tls_chlo = buffered_packets_.IngestPacketForTlsChloExtraction(
+ packet_info.destination_connection_id, packet_info.version,
+ packet_info.packet, alpns, sni);
+ } else {
+ // If we do not have a BufferedPacketList for this connection ID,
+ // create a single-use one to check whether this packet contains a
+ // full single-packet CHLO.
+ TlsChloExtractor tls_chlo_extractor;
+ tls_chlo_extractor.IngestPacket(packet_info.version, packet_info.packet);
+ if (tls_chlo_extractor.HasParsedFullChlo()) {
+ // This packet contains a full single-packet CHLO.
+ has_full_tls_chlo = true;
+ *alpns = tls_chlo_extractor.alpns();
+ *sni = tls_chlo_extractor.server_name();
+ }
+ }
+ if (!has_full_tls_chlo) {
+ // This packet does not contain a full CHLO. It could be a 0-RTT
+ // packet that arrived before the CHLO (due to loss or reordering),
+ // or it could be a fragment of a multi-packet CHLO.
+ BufferEarlyPacket(packet_info);
+ }
+
+ return has_full_tls_chlo;
+ }
+
+ ChloAlpnSniExtractor alpn_extractor;
+ if (GetQuicFlag(FLAGS_quic_allow_chlo_buffering) &&
+ !ChloExtractor::Extract(packet_info.packet, packet_info.version,
+ config_->create_session_tag_indicators(),
+ &alpn_extractor,
+ packet_info.destination_connection_id.length())) {
+ // Buffer non-CHLO packets.
+ BufferEarlyPacket(packet_info);
+ return false;
+ }
+
+ // We only apply this check for versions that do not use the IETF
+ // invariant header because those versions are already checked in
+ // QuicDispatcher::MaybeDispatchPacket.
+ if (packet_info.version_flag &&
+ !packet_info.version.HasIetfInvariantHeader() &&
+ crypto_config()->validate_chlo_size() &&
+ packet_info.packet.length() < kMinClientInitialPacketLength) {
+ QUIC_DVLOG(1) << "Dropping CHLO packet which is too short, length: "
+ << packet_info.packet.length();
+ QUIC_CODE_COUNT(quic_drop_small_chlo_packets);
+ return false;
+ }
+
+ *legacy_version_encapsulation_inner_packet =
+ alpn_extractor.ConsumeLegacyVersionEncapsulationInnerPacket();
+ *sni = alpn_extractor.ConsumeSni();
+ *uaid = alpn_extractor.ConsumeUaid();
+ *alpns = {alpn_extractor.ConsumeAlpn()};
+ return true;
+}
+
std::string QuicDispatcher::SelectAlpn(const std::vector<std::string>& alpns) {
if (alpns.empty()) {
return "";
@@ -1015,7 +1064,8 @@ void QuicDispatcher::OnNewConnectionIdSent(
<< server_connection_id << " new_connection_id: " << new_connection_id;
return;
}
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 5, 5);
+ // Count new connection ID added to the dispatcher map.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 6, 6);
auto insertion_result = reference_counted_session_map_.insert(
std::make_pair(new_connection_id, it->second));
QUICHE_DCHECK(insertion_result.second);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
index 053f856da98..a6ba1a6e975 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher.h
@@ -27,9 +27,9 @@
#include "quic/core/quic_session.h"
#include "quic/core/quic_time_wait_list_manager.h"
#include "quic/core/quic_version_manager.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_reference_counted.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
namespace test {
@@ -45,7 +45,8 @@ class QUIC_NO_EXPORT QuicDispatcher
public QuicBufferedPacketStore::VisitorInterface {
public:
// Ideally we'd have a linked_hash_set: the boolean is unused.
- using WriteBlockedList = QuicLinkedHashMap<QuicBlockedWriterInterface*, bool>;
+ using WriteBlockedList =
+ quiche::QuicheLinkedHashMap<QuicBlockedWriterInterface*, bool>;
QuicDispatcher(
const QuicConfig* config,
@@ -120,10 +121,6 @@ class QUIC_NO_EXPORT QuicDispatcher
void OnConnectionAddedToTimeWaitList(
QuicConnectionId server_connection_id) override;
- using SessionMap = absl::flat_hash_map<QuicConnectionId,
- std::unique_ptr<QuicSession>,
- QuicConnectionIdHash>;
-
using ReferenceCountedSessionMap =
absl::flat_hash_map<QuicConnectionId,
std::shared_ptr<QuicSession>,
@@ -131,8 +128,6 @@ class QUIC_NO_EXPORT QuicDispatcher
size_t NumSessions() const;
- const SessionMap& session_map() const { return session_map_; }
-
// Deletes all sessions on the closed session list and clears the list.
virtual void DeleteSessions();
@@ -229,6 +224,17 @@ class QUIC_NO_EXPORT QuicDispatcher
// TODO(fayang): Merge ValidityChecks into MaybeDispatchPacket.
virtual QuicPacketFate ValidityChecks(const ReceivedPacketInfo& packet_info);
+ // Extra validity checks after the full Client Hello is parsed, this allows
+ // subclasses to reject a connection based on sni or alpn.
+ // Only called if ValidityChecks returns kFateProcess.
+ virtual QuicPacketFate ValidityChecksOnFullChlo(
+ const ReceivedPacketInfo& /*packet_info*/,
+ const std::string& /*sni*/,
+ const std::string& /*uaid*/,
+ const std::vector<std::string>& /*alpns*/) const {
+ return kFateProcess;
+ }
+
// Create and return the time wait list manager for this dispatcher, which
// will be owned by the dispatcher as time_wait_list_manager_
virtual QuicTimeWaitListManager* CreateQuicTimeWaitListManager();
@@ -268,6 +274,10 @@ class QUIC_NO_EXPORT QuicDispatcher
return session_helper_.get();
}
+ const QuicCryptoServerStreamBase::Helper* session_helper() const {
+ return session_helper_.get();
+ }
+
QuicAlarmFactory* alarm_factory() { return alarm_factory_.get(); }
QuicPacketWriter* writer() { return writer_.get(); }
@@ -371,6 +381,21 @@ class QUIC_NO_EXPORT QuicDispatcher
// ProcessValidatedPacketWithUnknownConnectionId.
void ProcessHeader(ReceivedPacketInfo* packet_info);
+ // Try to extract information(sni, alpns, ...) if the full Client Hello has
+ // been parsed.
+ //
+ // If the full Client Hello has been parsed, return true and set |sni|,
+ // |alpns| and |legacy_version_encapsulation_inner_packet|. |uaid| will be
+ // populated for QUIC_CRYPTO only.
+ //
+ // Otherwise return false and either buffer or (rarely) drop the packet.
+ bool TryExtractChloOrBufferEarlyPacket(
+ const ReceivedPacketInfo& packet_info,
+ std::string* sni,
+ std::string* uaid,
+ std::vector<std::string>* alpns,
+ std::string* legacy_version_encapsulation_inner_packet);
+
// Deliver |packets| to |session| for further processing.
void DeliverPacketsToSession(
const std::list<QuicBufferedPacketStore::BufferedPacket>& packets,
@@ -389,7 +414,6 @@ class QUIC_NO_EXPORT QuicDispatcher
// The list of connections waiting to write.
WriteBlockedList write_blocked_list_;
- SessionMap session_map_;
ReferenceCountedSessionMap reference_counted_session_map_;
// Entity that manages connection_ids in time wait state.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
index 5a7a709f91b..3a98be3df90 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_dispatcher_test.cc
@@ -924,10 +924,12 @@ TEST_P(QuicDispatcherTestAllVersions,
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char short_packet[21] = {0x70, 0xa7, 0x02, 0x6b};
- QuicReceivedPacket packet(short_packet, 21, QuicTime::Zero());
- char valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
- QuicReceivedPacket packet2(valid_size_packet, 23, QuicTime::Zero());
+ uint8_t short_packet[21] = {0x70, 0xa7, 0x02, 0x6b};
+ QuicReceivedPacket packet(reinterpret_cast<char*>(short_packet), 21,
+ QuicTime::Zero());
+ uint8_t valid_size_packet[23] = {0x70, 0xa7, 0x02, 0x6c};
+ QuicReceivedPacket packet2(reinterpret_cast<char*>(valid_size_packet), 23,
+ QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(*time_wait_list_manager_, ProcessPacket(_, _, _, _, _, _))
.Times(0);
@@ -1186,10 +1188,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionDraft28WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 0xFF, 0x00, 0x00, 28, /*destination connection ID length*/ 0x08};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1203,10 +1205,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionDraft27WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 0xFF, 0x00, 0x00, 27, /*destination connection ID length*/ 0x08};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1220,10 +1222,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionDraft25WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 0xFF, 0x00, 0x00, 25, /*destination connection ID length*/ 0x08};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1237,10 +1239,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionT050WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 'T', '0', '5', '0', /*destination connection ID length*/ 0x08};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1254,10 +1256,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionQ049WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 'Q', '0', '4', '9', /*destination connection ID length*/ 0x08};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1271,10 +1273,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionQ048WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 'Q', '0', '4', '8', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1288,10 +1290,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionQ047WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 'Q', '0', '4', '7', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1305,10 +1307,10 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionQ045WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet[kMinPacketSizeForVersionNegotiation] = {
0xC0, 'Q', '0', '4', '5', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket received_packet(packet, ABSL_ARRAYSIZE(packet),
- QuicTime::Zero());
+ QuicReceivedPacket received_packet(reinterpret_cast<char*>(packet),
+ ABSL_ARRAYSIZE(packet), QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1322,10 +1324,11 @@ TEST_P(QuicDispatcherTestOneVersion,
RejectDeprecatedVersionQ044WithVersionNegotiation) {
QuicSocketAddress client_address(QuicIpAddress::Loopback4(), 1);
CreateTimeWaitListManager();
- char packet44[kMinPacketSizeForVersionNegotiation] = {
+ uint8_t packet44[kMinPacketSizeForVersionNegotiation] = {
0xFF, 'Q', '0', '4', '4', /*connection ID length byte*/ 0x50};
- QuicReceivedPacket received_packet44(
- packet44, kMinPacketSizeForVersionNegotiation, QuicTime::Zero());
+ QuicReceivedPacket received_packet44(reinterpret_cast<char*>(packet44),
+ kMinPacketSizeForVersionNegotiation,
+ QuicTime::Zero());
EXPECT_CALL(*dispatcher_, CreateQuicSession(_, _, _, _, _, _)).Times(0);
EXPECT_CALL(
*time_wait_list_manager_,
@@ -1549,7 +1552,7 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessSmallCoalescedPacket) {
EXPECT_CALL(*time_wait_list_manager_, SendPacket(_, _, _)).Times(0);
// clang-format off
- char coalesced_packet[1200] = {
+ uint8_t coalesced_packet[1200] = {
// first coalesced packet
// public flags (long header with packet type INITIAL and
// 4-byte packet number)
@@ -1586,7 +1589,8 @@ TEST_P(QuicDispatcherTestAllVersions, ProcessSmallCoalescedPacket) {
0x12, 0x34, 0x56, 0x79,
};
// clang-format on
- QuicReceivedPacket packet(coalesced_packet, 1200, QuicTime::Zero());
+ QuicReceivedPacket packet(reinterpret_cast<char*>(coalesced_packet), 1200,
+ QuicTime::Zero());
dispatcher_->ProcessPacket(server_address_, client_address, packet);
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
index e82e7cb2eab..c3fcb887066 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.cc
@@ -238,6 +238,7 @@ const char* QuicErrorCodeToString(QuicErrorCode error) {
RETURN_STRING_LITERAL(QUIC_HTTP_GOAWAY_ID_LARGER_THAN_PREVIOUS);
RETURN_STRING_LITERAL(QUIC_HTTP_RECEIVE_SPDY_SETTING);
RETURN_STRING_LITERAL(QUIC_HTTP_RECEIVE_SPDY_FRAME);
+ RETURN_STRING_LITERAL(QUIC_HTTP_RECEIVE_SERVER_PUSH);
RETURN_STRING_LITERAL(QUIC_HPACK_INDEX_VARINT_ERROR);
RETURN_STRING_LITERAL(QUIC_HPACK_NAME_LENGTH_VARINT_ERROR);
RETURN_STRING_LITERAL(QUIC_HPACK_VALUE_LENGTH_VARINT_ERROR);
@@ -678,6 +679,9 @@ QuicErrorCodeToIetfMapping QuicErrorCodeToTransportErrorCode(
case QUIC_HTTP_STREAM_LIMIT_TOO_LOW:
return {false, static_cast<uint64_t>(
QuicHttp3ErrorCode::GENERAL_PROTOCOL_ERROR)};
+ case QUIC_HTTP_RECEIVE_SERVER_PUSH:
+ return {false, static_cast<uint64_t>(
+ QuicHttp3ErrorCode::GENERAL_PROTOCOL_ERROR)};
case QUIC_HTTP_ZERO_RTT_RESUMPTION_SETTINGS_MISMATCH:
return {false, static_cast<uint64_t>(QuicHttp3ErrorCode::SETTINGS_ERROR)};
case QUIC_HTTP_ZERO_RTT_REJECTION_SETTINGS_MISMATCH:
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
index 9fa422f578c..53a881014ce 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_error_codes.h
@@ -510,6 +510,9 @@ enum QuicErrorCode {
QUIC_HTTP_RECEIVE_SPDY_SETTING = 169,
// HTTP/3 session received an HTTP/2 only frame.
QUIC_HTTP_RECEIVE_SPDY_FRAME = 171,
+ // HTTP/3 session received SERVER_PUSH stream, which is an error because
+ // PUSH_PROMISE is not accepted.
+ QUIC_HTTP_RECEIVE_SERVER_PUSH = 205,
// HPACK header block decoding errors.
// Index varint beyond implementation limit.
@@ -597,7 +600,7 @@ enum QuicErrorCode {
QUIC_TLS_CERTIFICATE_REQUIRED = 202,
// No error. Used as bound while iterating.
- QUIC_LAST_ERROR = 205,
+ QUIC_LAST_ERROR = 206,
};
// QuicErrorCodes is encoded as four octets on-the-wire when doing Google QUIC,
// or a varint62 when doing IETF QUIC. Ensure that its value does not exceed
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
index df0df50f3fc..9bb54b26abd 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_flags_list.h
@@ -17,30 +17,30 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_testonly_default_true, true)
QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_false, false)
// A testonly restart flag that will always default to true.
QUIC_FLAG(FLAGS_quic_restart_flag_quic_testonly_default_true, true)
-// Fix QUIC BBRv2\'s bandwidth_lo modes to better approximate packet conservation.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode2, false)
-// If true, GFE will consider SNI values which do not contain dots (instead of throwing them away - see b/176998377).
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_and_tls_allow_sni_without_dots, true)
-// If true, QUIC BBRv2\'s PROBE_BW mode will not reduce cwnd below BDP+ack_height.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_avoid_too_low_probe_bw_cwnd, false)
+// If true and a QUIC connection is traced, add ssl events to the trace.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_trace_ssl_events, true)
+// If true, GFE will explicitly configure its signature algorithm preference.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_set_signature_algorithm_prefs, false)
// If true, QUIC will default enable MTU discovery at server, with a target of 1450 bytes.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_mtu_discovery_at_server, false)
-// If true, QuicBatchWriterBase will mark the writer as blocked when the write status is WRITE_STATUS_BLOCKED_DATA_BUFFERED.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_batch_writer_fix_write_blocked, true)
// If true, QuicGsoBatchWriter will support release time if it is available and the process has the permission to do so.
QUIC_FLAG(FLAGS_quic_restart_flag_quic_support_release_time_for_gso, false)
-// If true, TlsHandshaker::AdvanceHandshake will retry SSL_do_handshake when entered early data.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_retry_handshake_on_early_data, true)
-// If true, TlsServerHandshaker will install a packet flusher when async operation completes.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_packet_flusher_on_async_op_done, true)
-// If true, TlsServerHandshaker will use handshake hints(if present) to speed up handshakes.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_server_use_handshake_hints, true)
+// If true, QuicIdleNetworkDetector::SetAlarm will become a noop if dectection has been stopped by QuicIdleNetworkDetector::StopDetection.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_idle_network_detector_no_alarm_after_stopped, true)
+// If true, TlsServerHandshaker::DefaultProofSourceHandle::DefaultSignatureCallback will run at most once.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_run_default_signature_callback_once, true)
// If true, abort async QPACK header decompression in QuicSpdyStream::Reset() and in QuicSpdyStream::OnStreamReset().
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_abort_qpack_on_stream_reset, true)
// If true, ack frequency frame can be sent from server to client.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_can_send_ack_frequency, true)
+// If true, add missing MaybeUpdateAckTimeout for ack-eliciting frames.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_missing_update_ack_timeout, true)
+// If true, allow QuicAlarm to be permanently cancelled.
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_alarm_add_permanent_cancel, false)
// If true, allow client to enable BBRv2 on server via connection option \'B2ON\'.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allow_client_enabled_bbr_v2, false)
+// If true, allow ticket open to be ignored in TlsServerHandshaker. Also fixes TlsServerHandshaker::ResumptionAttempted when handshake hints is used.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_tls_allow_ignore_ticket_open, true)
// If true, close read side but not write side in QuicSpdyStream::OnStreamReset().
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_on_stream_reset, true)
// If true, default on PTO which unifies TLP + RTO loss recovery.
@@ -48,13 +48,15 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_on_pto, false)
// If true, default-enable 5RTO blachole detection.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_enable_5rto_blackhole_detection2, true)
// If true, determine stateless reset packet length based on the received packet length.
-QUIC_FLAG(FLAGS_quic_restart_flag_quic_fix_stateless_reset2, false)
+QUIC_FLAG(FLAGS_quic_restart_flag_quic_fix_stateless_reset2, true)
// If true, disable QUIC version Q043.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q043, false)
// If true, disable QUIC version Q046.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q046, false)
// If true, disable QUIC version Q050.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_q050, false)
+// If true, disable QUIC version h3 (RFCv1).
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_rfcv1, false)
// If true, disable QUIC version h3-29.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_disable_version_draft_29, false)
// If true, disable QUIC version h3-T051.
@@ -67,70 +69,62 @@ QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_initial_packet_with_key_droppe
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_single_ack_in_packet2, false)
// If true, do not count bytes sent/received on the alternative path into the bytes sent/received on the default path.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_count_bytes_on_alternative_path_seperately, true)
-// If true, do not send control frames before encryption is established.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_encrypted_control_frames, false)
-// If true, do not send stream data when PTO fires.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_pto_half_rtt_data, true)
-// If true, do not write stream data and control frames in the middle of packet processing.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_write_mid_packet_processing, true)
+// If true, do not re-arm PTO while sending application data during handshake.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_rearm_pto_on_application_data_during_handshake, true)
// If true, drop unsent PATH_RESPONSEs and rely on peer\'s retry.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_drop_unsent_path_response, true)
-// If true, enable QUIC version h3 (RFCv1).
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_version_rfcv1, false)
// If true, enable server retransmittable on wire PING.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_enable_server_on_wire_ping, true)
+// If true, ignore peer_max_ack_delay during handshake.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_peer_max_ack_delay_during_handshake, true)
+// If true, include non-default port in the origin field of the ACCEPT_CH frame in ALPS.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_include_port_in_alps_origin, true)
// If true, include stream information in idle timeout connection close detail.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_add_stream_info_to_idle_close_detail, true)
// If true, increase the size of stream sequencer buffer block container on demand.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_allocate_stream_sequencer_buffer_blocks_on_demand, false)
// If true, pass the received PATH_RESPONSE payload to path validator to move forward the path validation.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_pass_path_response_to_validator, true)
// If true, quic connection sends/recieives NewConnectionId & RetireConnectionId frames.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_support_multiple_cids_v4, true)
// If true, quic dispatcher discards packets with invalid server connection ID.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_packets_with_invalid_cid, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_discard_packets_with_invalid_cid, true)
// If true, quic dispatcher supports one connection to use multiple connection IDs.
QUIC_FLAG(FLAGS_quic_restart_flag_quic_dispatcher_support_multiple_cid_per_connection_v2, true)
+// If true, receiving server push stream will trigger QUIC connection close.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_decline_server_push_stream, false)
// If true, require handshake confirmation for QUIC connections, functionally disabling 0-rtt handshakes.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_require_handshake_confirmation, false)
+// If true, reset per packet state before processing undecryptable packets.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_reset_per_packet_state_for_undecryptable_packets, true)
// If true, send PATH_RESPONSE upon receiving PATH_CHALLENGE regardless of perspective. --gfe2_reloadable_flag_quic_start_peer_migration_earlier has to be true before turn on this flag.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_path_response2, true)
// If true, set burst token to 2 in cwnd bootstrapping experiment.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_bursts, false)
-// If true, signal error in HttpDecoder upon receiving a PUSH_PROMISE or CANCEL_PUSH frame.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_error_on_http3_push, true)
// If true, stop resetting ideal_next_packet_send_time_ in pacing sender.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_donot_reset_ideal_next_packet_send_time, false)
// If true, time_wait_list can support multiple connection IDs.
QUIC_FLAG(FLAGS_quic_restart_flag_quic_time_wait_list_support_multiple_cid_v2, true)
-// If true, treat old (pre-draft02) PRIORITY_UPDATE frame as unknown frame.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ignore_old_priority_update_frame, true)
+// If true, update ACK timeout for NEW_CONNECTION_ID and RETIRE_CONNECTION_ID frames.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_ack_cid_frames, true)
// If true, upon receiving path challenge, send path response and reverse path challenge in the same function.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer, false)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_group_path_response_and_challenge_sending_closer, true)
// If true, use BBRv2 as the default congestion controller. Takes precedence over --quic_default_to_bbr.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr_v2, false)
-// If true, use ScopedEncryptionLevelContext when sending data.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_encryption_level_context, true)
-// If true, use WriteOrBufferDataAtLevel to send crypto data. Existing WriteOrBufferData is used to send application data.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_write_or_buffer_data_at_level, false)
// If true, use new connection ID in connection migration.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, false)
-// If true, use the connection ID and stateless reset token on default PathState.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_use_connection_id_on_default_path_v2, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_connection_migration_use_new_cid_v2, true)
// If true, uses conservative cwnd gain and pacing gain when cwnd gets bootstrapped.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_conservative_cwnd_and_pacing_gains, false)
// If true, validate that peer owns the new address once the server detects peer migration or is probed from that address, and also apply anti-amplification limit while sending to that address.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, false)
-// If ture, replace the incoming_connection_ids check with original_destination_connection_id check.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_deprecate_incoming_connection_ids, true)
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_server_reverse_validate_new_path3, true)
+// Queue packets to attempt decryption later until the handshake is complete.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_queue_until_handshake_complete, true)
// When the STMP connection option is sent by the client, timestamps in the QUIC ACK frame are sent and processed.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_send_timestamps, false)
-// When true, QuicSpdySession supports draft-ietf-masque-h3-datagram.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_h3_datagram, false)
// When true, defaults to BBR congestion control instead of Cubic.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_default_to_bbr, false)
-// When true, makes the QUIC BBRv2 bw_lo modes more similar to standard BBRv2.
-QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_bbr2_fix_bw_lo_mode, true)
+// When true, prevents QUIC\'s PacingSender from generating bursts when the congestion controller is CWND limited and not pacing limited.
+QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_fix_pacing_sender_bursts, false)
// When true, set the initial congestion control window from connection options in QuicSentPacketManager rather than TcpCubicSenderBytes.
QUIC_FLAG(FLAGS_quic_reloadable_flag_quic_unified_iw_options, false)
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
index e186ce33ecb..24b2be86484 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.cc
@@ -47,7 +47,6 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_stack_trace.h"
#include "common/quiche_text_utils.h"
@@ -399,8 +398,7 @@ std::string GenerateErrorString(std::string initial_error_string,
} // namespace
QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
- QuicTime creation_time,
- Perspective perspective,
+ QuicTime creation_time, Perspective perspective,
uint8_t expected_server_connection_id_length)
: visitor_(nullptr),
error_(QUIC_NO_ERROR),
@@ -430,7 +428,8 @@ QuicFramer::QuicFramer(const ParsedQuicVersionVector& supported_versions,
last_written_packet_number_length_(0),
peer_ack_delay_exponent_(kDefaultAckDelayExponent),
local_ack_delay_exponent_(kDefaultAckDelayExponent),
- current_received_frame_type_(0) {
+ current_received_frame_type_(0),
+ previously_received_frame_type_(0) {
QUICHE_DCHECK(!supported_versions.empty());
version_ = supported_versions_[0];
QUICHE_DCHECK(version_.IsKnown())
@@ -1503,6 +1502,7 @@ QuicFramer::BuildIetfVersionNegotiationPacket(
}
bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
+ QUICHE_DCHECK(!is_processing_packet_) << ENDPOINT << "Nested ProcessPacket";
is_processing_packet_ = true;
bool result = ProcessPacketInternal(packet);
is_processing_packet_ = false;
@@ -1964,8 +1964,10 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
// Handle the payload.
if (VersionHasIetfQuicFrames(version_.transport_version)) {
current_received_frame_type_ = 0;
+ previously_received_frame_type_ = 0;
if (!ProcessIetfFrameData(&reader, *header, decrypted_level)) {
current_received_frame_type_ = 0;
+ previously_received_frame_type_ = 0;
QUICHE_DCHECK_NE(QUIC_NO_ERROR,
error_); // ProcessIetfFrameData sets the error.
QUICHE_DCHECK_NE("", detailed_error_);
@@ -1974,6 +1976,7 @@ bool QuicFramer::ProcessIetfDataPacket(QuicDataReader* encrypted_reader,
return false;
}
current_received_frame_type_ = 0;
+ previously_received_frame_type_ = 0;
} else {
if (!ProcessFrameData(&reader, *header)) {
QUICHE_DCHECK_NE(QUIC_NO_ERROR,
@@ -3215,6 +3218,7 @@ bool QuicFramer::ProcessIetfFrameData(QuicDataReader* reader,
EncryptionLevelToString(decrypted_level)));
return RaiseError(IETF_QUIC_PROTOCOL_VIOLATION);
}
+ previously_received_frame_type_ = current_received_frame_type_;
current_received_frame_type_ = frame_type;
// Is now the number of bytes into which the frame type was encoded.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
index 2920db351c4..31cc756990b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer.h
@@ -650,6 +650,10 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
return current_received_frame_type_;
}
+ uint64_t previously_received_frame_type() const {
+ return previously_received_frame_type_;
+ }
+
// The connection ID length the framer expects on incoming IETF short headers
// on the server.
uint8_t GetExpectedServerConnectionIdLength() {
@@ -1190,6 +1194,11 @@ class QUIC_EXPORT_PRIVATE QuicFramer {
// the Transport Connection Close when there is an error during frame
// processing.
uint64_t current_received_frame_type_;
+
+ // TODO(haoyuewang) Remove this debug utility.
+ // The type of the IETF frame preceding the frame currently being processed. 0
+ // when not processing a frame or only 1 frame has been processed.
+ uint64_t previously_received_frame_type_;
};
// Look for and parse the error code from the "<quic_error_code>:" text that
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
index 63a1ad5ed4f..f36bf5c78c7 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_framer_test.cc
@@ -61,9 +61,10 @@ QuicConnectionId FramerTestConnectionIdPlusOne() {
}
QuicConnectionId FramerTestConnectionIdNineBytes() {
- char connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
- 0x54, 0x32, 0x10, 0x42};
- return QuicConnectionId(connection_id_bytes, sizeof(connection_id_bytes));
+ uint8_t connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
+ 0x54, 0x32, 0x10, 0x42};
+ return QuicConnectionId(reinterpret_cast<char*>(connection_id_bytes),
+ sizeof(connection_id_bytes));
}
const QuicPacketNumber kPacketNumber = QuicPacketNumber(UINT64_C(0x12345678));
@@ -8946,10 +8947,9 @@ TEST_P(QuicFramerTest, BuildMessagePacket) {
header.reset_flag = false;
header.version_flag = false;
header.packet_number = kPacketNumber;
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
- QuicMessageFrame frame(1, MakeSpan(&allocator_, "message", &storage));
- QuicMessageFrame frame2(2, MakeSpan(&allocator_, "message2", &storage));
+ QuicMessageFrame frame(1, MemSliceFromString("message"));
+ QuicMessageFrame frame2(2, MemSliceFromString("message2"));
QuicFrames frames = {QuicFrame(&frame), QuicFrame(&frame2)};
// clang-format off
@@ -13730,9 +13730,9 @@ TEST_P(QuicFramerTest, PacketHeaderWithVariableLengthConnectionId) {
return;
}
SetDecrypterLevel(ENCRYPTION_FORWARD_SECURE);
- char connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
- 0x54, 0x32, 0x10, 0x42};
- QuicConnectionId connection_id(connection_id_bytes,
+ uint8_t connection_id_bytes[9] = {0xFE, 0xDC, 0xBA, 0x98, 0x76,
+ 0x54, 0x32, 0x10, 0x42};
+ QuicConnectionId connection_id(reinterpret_cast<char*>(connection_id_bytes),
sizeof(connection_id_bytes));
QuicFramerPeer::SetLargestPacketNumber(&framer_, kPacketNumber - 2);
QuicFramerPeer::SetExpectedServerConnectionIDLength(&framer_,
@@ -14031,7 +14031,7 @@ TEST_P(QuicFramerTest, ProcessMismatchedHeaderVersion) {
TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
// clang-format off
- static const char expected_packet[1200] = {
+ static const uint8_t expected_packet[1200] = {
// IETF long header with fixed bit set, type initial, all-0 encrypted bits.
0xc0,
// Version, part of the IETF space reserved for negotiation.
@@ -14080,9 +14080,9 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
EXPECT_TRUE(QuicFramer::WriteClientVersionNegotiationProbePacket(
packet, sizeof(packet), destination_connection_id_bytes,
sizeof(destination_connection_id_bytes)));
- quiche::test::CompareCharArraysWithHexError("constructed packet", packet,
- sizeof(packet), expected_packet,
- sizeof(expected_packet));
+ quiche::test::CompareCharArraysWithHexError(
+ "constructed packet", packet, sizeof(packet),
+ reinterpret_cast<const char*>(expected_packet), sizeof(expected_packet));
QuicEncryptedPacket encrypted(reinterpret_cast<const char*>(packet),
sizeof(packet), false);
if (!framer_.version().HasLengthPrefixedConnectionIds()) {
@@ -14102,7 +14102,7 @@ TEST_P(QuicFramerTest, WriteClientVersionNegotiationProbePacket) {
TEST_P(QuicFramerTest, DispatcherParseOldClientVersionNegotiationProbePacket) {
// clang-format off
- static const char packet[1200] = {
+ static const uint8_t packet[1200] = {
// IETF long header with fixed bit set, type initial, all-0 encrypted bits.
0xc0,
// Version, part of the IETF space reserved for negotiation.
@@ -14179,7 +14179,7 @@ TEST_P(QuicFramerTest, DispatcherParseOldClientVersionNegotiationProbePacket) {
TEST_P(QuicFramerTest, DispatcherParseClientVersionNegotiationProbePacket) {
// clang-format off
- static const char packet[1200] = {
+ static const uint8_t packet[1200] = {
// IETF long header with fixed bit set, type initial, all-0 encrypted bits.
0xc0,
// Version, part of the IETF space reserved for negotiation.
@@ -14257,7 +14257,7 @@ TEST_P(QuicFramerTest, DispatcherParseClientVersionNegotiationProbePacket) {
TEST_P(QuicFramerTest, ParseServerVersionNegotiationProbeResponse) {
// clang-format off
- const char packet[] = {
+ const uint8_t packet[] = {
// IETF long header with fixed bit set, type initial, all-0 encrypted bits.
0xc0,
// Version of 0, indicating version negotiation.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc
index 8046e446cee..ac6799ee46d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.cc
@@ -5,6 +5,7 @@
#include "quic/core/quic_idle_network_detector.h"
#include "quic/core/quic_constants.h"
+#include "quic/platform/api/quic_flag_utils.h"
namespace quic {
@@ -26,9 +27,7 @@ class AlarmDelegate : public QuicAlarm::Delegate {
} // namespace
QuicIdleNetworkDetector::QuicIdleNetworkDetector(
- Delegate* delegate,
- QuicTime now,
- QuicConnectionArena* arena,
+ Delegate* delegate, QuicTime now, QuicConnectionArena* arena,
QuicAlarmFactory* alarm_factory)
: delegate_(delegate),
start_time_(now),
@@ -37,7 +36,12 @@ QuicIdleNetworkDetector::QuicIdleNetworkDetector(
time_of_first_packet_sent_after_receiving_(QuicTime::Zero()),
idle_network_timeout_(QuicTime::Delta::Infinite()),
alarm_(
- alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {}
+ alarm_factory->CreateAlarm(arena->New<AlarmDelegate>(this), arena)) {
+ if (no_alarm_after_stopped_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_idle_network_detector_no_alarm_after_stopped, 1, 2);
+ }
+}
void QuicIdleNetworkDetector::OnAlarm() {
if (handshake_timeout_.IsInfinite()) {
@@ -66,9 +70,10 @@ void QuicIdleNetworkDetector::SetTimeouts(
}
void QuicIdleNetworkDetector::StopDetection() {
- alarm_->Cancel();
+ alarm_->PermanentCancel();
handshake_timeout_ = QuicTime::Delta::Infinite();
idle_network_timeout_ = QuicTime::Delta::Infinite();
+ stopped_ = true;
}
void QuicIdleNetworkDetector::OnPacketSent(QuicTime now,
@@ -94,6 +99,17 @@ void QuicIdleNetworkDetector::OnPacketReceived(QuicTime now) {
}
void QuicIdleNetworkDetector::SetAlarm() {
+ if (no_alarm_after_stopped_ && stopped_) {
+ QUIC_RELOADABLE_FLAG_COUNT_N(
+ quic_idle_network_detector_no_alarm_after_stopped, 2, 2);
+
+ // TODO(wub): If this QUIC_BUG fires, it indicates a problem in the
+ // QuicConnection, which somehow called this function while disconnected.
+ // That problem needs to be fixed.
+ QUIC_BUG(quic_idle_detector_set_alarm_after_stopped)
+ << "SetAlarm called after stopped";
+ return;
+ }
// Set alarm to the nearer deadline.
QuicTime new_deadline = QuicTime::Zero();
if (!handshake_timeout_.IsInfinite()) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h
index e138d6a068e..1665104a186 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector.h
@@ -10,6 +10,7 @@
#include "quic/core/quic_one_block_arena.h"
#include "quic/core/quic_time.h"
#include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_flags.h"
namespace quic {
@@ -46,6 +47,7 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector {
void SetTimeouts(QuicTime::Delta handshake_timeout,
QuicTime::Delta idle_network_timeout);
+ // Stop the detection once and for all.
void StopDetection();
// Called when a packet gets sent.
@@ -106,6 +108,12 @@ class QUIC_EXPORT_PRIVATE QuicIdleNetworkDetector {
QuicArenaScopedPtr<QuicAlarm> alarm_;
bool shorter_idle_timeout_on_sent_packet_ = false;
+
+ // Whether |StopDetection| has been called.
+ bool stopped_ = false;
+
+ const bool no_alarm_after_stopped_ =
+ GetQuicReloadableFlag(quic_idle_network_detector_no_alarm_after_stopped);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc
index 271247808c9..11d0cf76777 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_idle_network_detector_test.cc
@@ -5,6 +5,7 @@
#include "quic/core/quic_idle_network_detector.h"
#include "quic/core/quic_one_block_arena.h"
+#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_test.h"
#include "quic/test_tools/quic_test_utils.h"
@@ -181,6 +182,25 @@ TEST_F(QuicIdleNetworkDetectorTest, ShorterIdleTimeoutOnSentPacket) {
EXPECT_EQ(clock_.Now() + QuicTime::Delta::FromSeconds(2), alarm_->deadline());
}
+TEST_F(QuicIdleNetworkDetectorTest, NoAlarmAfterStopped) {
+ detector_->StopDetection();
+
+ if (GetQuicReloadableFlag(
+ quic_idle_network_detector_no_alarm_after_stopped)) {
+ EXPECT_QUIC_BUG(
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20)),
+ "SetAlarm called after stopped");
+ EXPECT_FALSE(alarm_->IsSet());
+ } else {
+ detector_->SetTimeouts(
+ /*handshake_timeout=*/QuicTime::Delta::FromSeconds(30),
+ /*idle_network_timeout=*/QuicTime::Delta::FromSeconds(20));
+ EXPECT_TRUE(alarm_->IsSet());
+ }
+}
+
} // namespace
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
index fef089313fa..d69fa710604 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_interval_set.h
@@ -85,9 +85,7 @@ class QUIC_NO_EXPORT QuicIntervalSet {
bool operator()(T&& point, const value_type& a) const;
};
- using Set = QuicOrderedSet<value_type,
- IntervalLess,
- QuicInlinedVector<value_type, 10>>;
+ using Set = QuicSmallOrderedSet<value_type, IntervalLess>;
public:
using const_iterator = typename Set::const_iterator;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h b/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
index d4b11e0ce5f..67541ee3a23 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_lru_cache.h
@@ -7,11 +7,11 @@
#include <memory>
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -67,7 +67,7 @@ class QUIC_NO_EXPORT QuicLRUCache {
size_t Size() const { return cache_.size(); }
private:
- QuicLinkedHashMap<K, std::unique_ptr<V>> cache_;
+ quiche::QuicheLinkedHashMap<K, std::unique_ptr<V>> cache_;
const size_t capacity_;
};
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
index 5281ffb980a..4dca50832ac 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.cc
@@ -64,8 +64,12 @@ void QuicNetworkBlackholeDetector::OnAlarm() {
UpdateAlarm();
}
-void QuicNetworkBlackholeDetector::StopDetection() {
- alarm_->Cancel();
+void QuicNetworkBlackholeDetector::StopDetection(bool permanent) {
+ if (permanent) {
+ alarm_->PermanentCancel();
+ } else {
+ alarm_->Cancel();
+ }
path_degrading_deadline_ = QuicTime::Zero();
blackhole_deadline_ = QuicTime::Zero();
path_mtu_reduction_deadline_ = QuicTime::Zero();
@@ -108,6 +112,12 @@ QuicTime QuicNetworkBlackholeDetector::GetLastDeadline() const {
}
void QuicNetworkBlackholeDetector::UpdateAlarm() const {
+ // If called after OnBlackholeDetected(), the alarm may have been permanently
+ // cancelled and is not safe to be armed again.
+ if (alarm_->IsPermanentlyCancelled()) {
+ return;
+ }
+
QuicTime next_deadline = GetEarliestDeadline();
QUIC_DVLOG(1) << "Updating alarm. next_deadline:" << next_deadline
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h
index 7010eb581a8..82753f934a6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector.h
@@ -44,8 +44,9 @@ class QUIC_EXPORT_PRIVATE QuicNetworkBlackholeDetector {
QuicConnectionArena* arena,
QuicAlarmFactory* alarm_factory);
- // Called to stop all detections.
- void StopDetection();
+ // Called to stop all detections. If |permanent|, the alarm will be cancelled
+ // permanently and future calls to RestartDetection will be no-op.
+ void StopDetection(bool permanent);
// Called to restart path degrading, path mtu reduction and blackhole
// detections. Please note, if |blackhole_deadline| is set, it must be the
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc
index 3bc6ad73cbb..66bebfd455f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_network_blackhole_detector_test.cc
@@ -106,7 +106,7 @@ TEST_F(QuicNetworkBlackholeDetectorTest, RestartAndStop) {
RestartDetection();
EXPECT_EQ(clock_.Now() + path_degrading_delay_, alarm_->deadline());
- detector_.StopDetection();
+ detector_.StopDetection(/*permanent=*/false);
EXPECT_FALSE(detector_.IsDetectionInProgress());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
index cbca89dae55..94cf48a1d51 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.cc
@@ -34,6 +34,7 @@
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_server_stats.h"
+#include "common/print_elements.h"
namespace quic {
namespace {
@@ -696,6 +697,10 @@ bool QuicPacketCreator::HasPendingFrames() const {
return !queued_frames_.empty();
}
+std::string QuicPacketCreator::GetPendingFramesInfo() const {
+ return QuicFramesToString(queued_frames_);
+}
+
bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
return !packet_.retransmittable_frames.empty();
}
@@ -1522,7 +1527,7 @@ bool QuicPacketCreator::FlushAckFrame(const QuicFrames& frames) {
QUIC_BUG_IF(quic_bug_12398_18,
GetQuicReloadableFlag(quic_single_ack_in_packet2) &&
!frames.empty() && has_ack())
- << ENDPOINT << "Trying to flush " << frames
+ << ENDPOINT << "Trying to flush " << quiche::PrintElements(frames)
<< " when there is ACK queued";
for (const auto& frame : frames) {
QUICHE_DCHECK(frame.type == ACK_FRAME || frame.type == STOP_WAITING_FRAME)
@@ -1596,14 +1601,14 @@ void QuicPacketCreator::SetTransmissionType(TransmissionType type) {
next_transmission_type_ = type;
}
-MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
+MessageStatus QuicPacketCreator::AddMessageFrame(
+ QuicMessageId message_id, absl::Span<QuicMemSlice> message) {
QUIC_BUG_IF(quic_bug_10752_33, !flusher_attached_)
<< ENDPOINT
<< "Packet flusher is not attached when "
"generator tries to add message frame.";
MaybeBundleAckOpportunistically();
- const QuicByteCount message_length = message.total_length();
+ const QuicByteCount message_length = MemSliceSpanTotalSize(message);
if (message_length > GetCurrentLargestMessagePayload()) {
return MESSAGE_STATUS_TOO_LARGE;
}
@@ -1618,6 +1623,8 @@ MessageStatus QuicPacketCreator::AddMessageFrame(QuicMessageId message_id,
delete frame;
return MESSAGE_STATUS_INTERNAL_ERROR;
}
+ QUICHE_DCHECK_EQ(MemSliceSpanTotalSize(message),
+ 0u); // Ensure the old slices are empty.
return MESSAGE_STATUS_SUCCESS;
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
index d4a58055282..9cc4bcae92e 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator.h
@@ -205,6 +205,10 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Returns true if there are frames pending to be serialized.
bool HasPendingFrames() const;
+ // TODO(haoyuewang) Remove this debug utility.
+ // Returns the information of pending frames as a string.
+ std::string GetPendingFramesInfo() const;
+
// Returns true if there are retransmittable frames pending to be serialized.
bool HasPendingRetransmittableFrames() const;
@@ -417,7 +421,7 @@ class QUIC_EXPORT_PRIVATE QuicPacketCreator {
// Tries to add a message frame containing |message| and returns the status.
MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message);
+ absl::Span<QuicMemSlice> message);
// Returns the largest payload that will fit into a single MESSAGE frame.
QuicPacketLength GetCurrentLargestMessagePayload() const;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
index 57d1018d94c..3dc1a4b184b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_packet_creator_test.cc
@@ -423,6 +423,8 @@ TEST_P(QuicPacketCreatorTest, ConsumeDataFinOnly) {
EXPECT_EQ(0u, consumed);
CheckStreamFrame(frame, stream_id, std::string(), 0u, true);
EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_TRUE(absl::StartsWith(creator_.GetPendingFramesInfo(),
+ "type { STREAM_FRAME }"));
}
TEST_P(QuicPacketCreatorTest, CreateAllFreeBytesForStreamFrames) {
@@ -1767,25 +1769,24 @@ TEST_P(QuicPacketCreatorTest, AddMessageFrame) {
.Times(3)
.WillRepeatedly(
Invoke(this, &QuicPacketCreatorTest::ClearSerializedPacketForTests));
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
// Verify that there is enough room for the largest message payload.
EXPECT_TRUE(creator_.HasRoomForMessageFrame(
creator_.GetCurrentLargestMessagePayload()));
- std::string message(creator_.GetCurrentLargestMessagePayload(), 'a');
+ std::string large_message(creator_.GetCurrentLargestMessagePayload(), 'a');
QuicMessageFrame* message_frame =
- new QuicMessageFrame(1, MakeSpan(&allocator_, message, &storage));
+ new QuicMessageFrame(1, MemSliceFromString(large_message));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(message_frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
creator_.FlushCurrentPacket();
QuicMessageFrame* frame2 =
- new QuicMessageFrame(2, MakeSpan(&allocator_, "message", &storage));
+ new QuicMessageFrame(2, MemSliceFromString("message"));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame2), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
// Verify if a new frame is added, 1 byte message length will be added.
EXPECT_EQ(1u, creator_.ExpansionOnNewFrame());
QuicMessageFrame* frame3 =
- new QuicMessageFrame(3, MakeSpan(&allocator_, "message2", &storage));
+ new QuicMessageFrame(3, MemSliceFromString("message2"));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame3), NOT_RETRANSMISSION));
EXPECT_EQ(1u, creator_.ExpansionOnNewFrame());
creator_.FlushCurrentPacket();
@@ -1798,14 +1799,14 @@ TEST_P(QuicPacketCreatorTest, AddMessageFrame) {
stream_id, &iov_, 1u, iov_.iov_len, 0u, 0u, false, false,
NOT_RETRANSMISSION, &frame));
QuicMessageFrame* frame4 =
- new QuicMessageFrame(4, MakeSpan(&allocator_, "message", &storage));
+ new QuicMessageFrame(4, MemSliceFromString("message"));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame4), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
// Verify there is not enough room for largest payload.
EXPECT_FALSE(creator_.HasRoomForMessageFrame(
creator_.GetCurrentLargestMessagePayload()));
// Add largest message will causes the flush of the stream frame.
- QuicMessageFrame frame5(5, MakeSpan(&allocator_, message, &storage));
+ QuicMessageFrame frame5(5, MemSliceFromString(large_message));
EXPECT_FALSE(creator_.AddFrame(QuicFrame(&frame5), NOT_RETRANSMISSION));
EXPECT_FALSE(creator_.HasPendingFrames());
}
@@ -1818,8 +1819,6 @@ TEST_P(QuicPacketCreatorTest, MessageFrameConsumption) {
creator_.SetMaxDatagramFrameSize(kMaxAcceptedDatagramFrameSize);
}
std::string message_data(kDefaultMaxPacketSize, 'a');
- absl::string_view message_buffer(message_data);
- QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
// Test all possible encryption levels of message frames.
for (EncryptionLevel level :
{ENCRYPTION_ZERO_RTT, ENCRYPTION_FORWARD_SECURE}) {
@@ -1828,10 +1827,9 @@ TEST_P(QuicPacketCreatorTest, MessageFrameConsumption) {
for (size_t message_size = 0;
message_size <= creator_.GetCurrentLargestMessagePayload();
++message_size) {
- QuicMessageFrame* frame = new QuicMessageFrame(
- 0, MakeSpan(&allocator_,
- absl::string_view(message_buffer.data(), message_size),
- &storage));
+ QuicMessageFrame* frame =
+ new QuicMessageFrame(0, MemSliceFromString(absl::string_view(
+ message_data.data(), message_size)));
EXPECT_TRUE(creator_.AddFrame(QuicFrame(frame), NOT_RETRANSMISSION));
EXPECT_TRUE(creator_.HasPendingFrames());
@@ -2450,12 +2448,13 @@ class MultiplePacketsTestPacketCreator : public QuicPacketCreator {
}
MessageStatus AddMessageFrame(QuicMessageId message_id,
- QuicMemSliceSpan message) {
+ QuicMemSlice message) {
if (!has_ack() && delegate_->ShouldGeneratePacket(NO_RETRANSMITTABLE_DATA,
NOT_HANDSHAKE)) {
EXPECT_CALL(*delegate_, MaybeBundleAckOpportunistically()).Times(1);
}
- return QuicPacketCreator::AddMessageFrame(message_id, message);
+ return QuicPacketCreator::AddMessageFrame(message_id,
+ absl::MakeSpan(&message, 1));
}
size_t ConsumeCryptoData(EncryptionLevel level,
@@ -3792,7 +3791,6 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest, AddMessageFrame) {
if (framer_.version().UsesTls()) {
creator_.SetMaxDatagramFrameSize(kMaxAcceptedDatagramFrameSize);
}
- quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
delegate_.SetCanWriteAnything();
EXPECT_CALL(delegate_, OnSerializedPacket(_))
.WillOnce(
@@ -3802,30 +3800,23 @@ TEST_F(QuicPacketCreatorMultiplePacketsTest, AddMessageFrame) {
creator_.ConsumeData(QuicUtils::GetFirstBidirectionalStreamId(
framer_.transport_version(), Perspective::IS_CLIENT),
&iov_, 1u, iov_.iov_len, 0, FIN);
- EXPECT_EQ(
- MESSAGE_STATUS_SUCCESS,
- creator_.AddMessageFrame(1, MakeSpan(&allocator_, "message", &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(1, MemSliceFromString("message")));
EXPECT_TRUE(creator_.HasPendingFrames());
EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
// Add a message which causes the flush of current packet.
- EXPECT_EQ(
- MESSAGE_STATUS_SUCCESS,
- creator_.AddMessageFrame(
- 2,
- MakeSpan(&allocator_,
- std::string(creator_.GetCurrentLargestMessagePayload(), 'a'),
- &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_SUCCESS,
+ creator_.AddMessageFrame(
+ 2, MemSliceFromString(std::string(
+ creator_.GetCurrentLargestMessagePayload(), 'a'))));
EXPECT_TRUE(creator_.HasPendingRetransmittableFrames());
// Failed to send messages which cannot fit into one packet.
- EXPECT_EQ(
- MESSAGE_STATUS_TOO_LARGE,
- creator_.AddMessageFrame(
- 3, MakeSpan(&allocator_,
- std::string(
- creator_.GetCurrentLargestMessagePayload() + 10, 'a'),
- &storage)));
+ EXPECT_EQ(MESSAGE_STATUS_TOO_LARGE,
+ creator_.AddMessageFrame(
+ 3, MemSliceFromString(std::string(
+ creator_.GetCurrentLargestMessagePayload() + 10, 'a'))));
}
TEST_F(QuicPacketCreatorMultiplePacketsTest, ConnectionId) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.h b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.h
index ccd3a6cbcaf..9ea1554efa4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_path_validator.h
@@ -7,6 +7,7 @@
#include <ostream>
+#include "absl/container/inlined_vector.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/core/quic_alarm.h"
#include "quic/core/quic_alarm_factory.h"
@@ -145,7 +146,7 @@ class QUIC_EXPORT_PRIVATE QuicPathValidator {
void ResetPathValidation();
// Has at most 3 entries due to validation timeout.
- QuicInlinedVector<QuicPathFrameBuffer, 3> probing_data_;
+ absl::InlinedVector<QuicPathFrameBuffer, 3> probing_data_;
SendDelegate* send_delegate_;
QuicRandom* random_;
std::unique_ptr<QuicPathValidationContext> path_context_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
index 53d9f0eca22..fd1190bde7b 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.cc
@@ -24,7 +24,7 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
+#include "common/print_elements.h"
namespace quic {
@@ -117,7 +117,8 @@ QuicSentPacketManager::QuicSentPacketManager(
use_standard_deviation_for_pto_(false),
pto_multiplier_without_rtt_samples_(3),
num_ptos_for_path_degrading_(0),
- ignore_pings_(false) {
+ ignore_pings_(false),
+ ignore_ack_delay_(false) {
SetSendAlgorithm(congestion_control_type);
if (pto_enabled_) {
QUIC_RELOADABLE_FLAG_COUNT_N(quic_default_on_pto, 1, 2);
@@ -158,7 +159,7 @@ void QuicSentPacketManager::SetFromConfig(const QuicConfig& config) {
}
}
if (config.HasClientSentConnectionOption(kMAD0, perspective)) {
- rtt_stats_.set_ignore_max_ack_delay(true);
+ ignore_ack_delay_ = true;
}
if (config.HasClientSentConnectionOption(kMAD2, perspective)) {
// Set the minimum to the alarm granularity.
@@ -1526,8 +1527,18 @@ void QuicSentPacketManager::OnAckFrameStart(QuicPacketNumber largest_acked,
QuicTime ack_receive_time) {
QUICHE_DCHECK(packets_acked_.empty());
QUICHE_DCHECK_LE(largest_acked, unacked_packets_.largest_sent_packet());
- if (ack_delay_time > peer_max_ack_delay()) {
- ack_delay_time = peer_max_ack_delay();
+ if (GetQuicReloadableFlag(quic_ignore_peer_max_ack_delay_during_handshake) &&
+ supports_multiple_packet_number_spaces() && !handshake_finished_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_ignore_peer_max_ack_delay_during_handshake);
+ // Ignore peer_max_ack_delay and use received ack_delay during
+ // handshake.
+ } else {
+ if (ack_delay_time > peer_max_ack_delay()) {
+ ack_delay_time = peer_max_ack_delay();
+ }
+ if (ignore_ack_delay_) {
+ ack_delay_time = QuicTime::Delta::Zero();
+ }
}
rtt_updated_ =
MaybeUpdateRTT(largest_acked, ack_delay_time, ack_receive_time);
@@ -1601,7 +1612,7 @@ AckResult QuicSentPacketManager::OnAckFrameEnd(
<< acked_packet.packet_number
<< ", last_ack_frame_: " << last_ack_frame_
<< ", least_unacked: " << unacked_packets_.GetLeastUnacked()
- << ", packets_acked_: " << packets_acked_;
+ << ", packets_acked_: " << quiche::PrintElements(packets_acked_);
} else {
QUIC_PEER_BUG(quic_peer_bug_10750_6)
<< "Received " << ack_decrypted_level
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
index 781f6f95b90..eeb474f9f04 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h
@@ -745,6 +745,9 @@ class QUIC_EXPORT_PRIVATE QuicSentPacketManager {
// If true, do not use PING only packets for RTT measurement or congestion
// control.
bool ignore_pings_;
+
+ // Whether to ignore the ack_delay in received ACKs.
+ bool ignore_ack_delay_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
index 388a662096e..e457e09884f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_sent_packet_manager_test.cc
@@ -4637,8 +4637,7 @@ TEST_F(QuicSentPacketManagerTest, ClearDataInMessageFrameAfterPacketSent) {
QuicMessageFrame* message_frame = nullptr;
{
QuicMemSlice slice(MakeUniqueBuffer(&allocator_, 1024), 1024);
- message_frame =
- new QuicMessageFrame(/*message_id=*/1, QuicMemSliceSpan(&slice));
+ message_frame = new QuicMessageFrame(/*message_id=*/1, std::move(slice));
EXPECT_FALSE(message_frame->message_data.empty());
EXPECT_EQ(message_frame->message_length, 1024);
@@ -4684,6 +4683,125 @@ TEST_F(QuicSentPacketManagerTest, BuildAckFrequencyFrame) {
EXPECT_EQ(frame.packet_tolerance, 10u);
}
+TEST_F(QuicSentPacketManagerTest, SmoothedRttIgnoreAckDelay) {
+ QuicConfig config;
+ QuicTagVector options;
+ options.push_back(kMAD0);
+ QuicConfigPeer::SetReceivedConnectionOptions(&config, options);
+ EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
+ EXPECT_CALL(*network_change_visitor_, OnCongestionChange());
+ EXPECT_CALL(*send_algorithm_, CanSend(_)).WillRepeatedly(Return(true));
+ EXPECT_CALL(*send_algorithm_, GetCongestionWindow())
+ .WillRepeatedly(Return(10 * kDefaultTCPMSS));
+ manager_.SetFromConfig(config);
+
+ SendDataPacket(1);
+ // Ack 1.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(300));
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1),
+ QuicTime::Delta::FromMilliseconds(100),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_INITIAL));
+ // Verify that ack_delay is ignored in the first measurement.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->latest_rtt());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->smoothed_rtt());
+
+ SendDataPacket(2);
+ // Ack 2.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(300));
+ ExpectAck(2);
+ manager_.OnAckFrameStart(QuicPacketNumber(2),
+ QuicTime::Delta::FromMilliseconds(100),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_INITIAL));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->latest_rtt());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->smoothed_rtt());
+
+ SendDataPacket(3);
+ // Ack 3.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(300));
+ ExpectAck(3);
+ manager_.OnAckFrameStart(QuicPacketNumber(3),
+ QuicTime::Delta::FromMilliseconds(50), clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(3), QuicPacketNumber(4));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(3),
+ ENCRYPTION_INITIAL));
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->latest_rtt());
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(300),
+ manager_.GetRttStats()->smoothed_rtt());
+
+ SendDataPacket(4);
+ // Ack 4.
+ clock_.AdvanceTime(QuicTime::Delta::FromMilliseconds(200));
+ ExpectAck(4);
+ manager_.OnAckFrameStart(QuicPacketNumber(4),
+ QuicTime::Delta::FromMilliseconds(300),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(4), QuicPacketNumber(5));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(4),
+ ENCRYPTION_INITIAL));
+ // Verify that large erroneous ack_delay does not change Smoothed RTT.
+ EXPECT_EQ(QuicTime::Delta::FromMilliseconds(200),
+ manager_.GetRttStats()->latest_rtt());
+ EXPECT_EQ(QuicTime::Delta::FromMicroseconds(287500),
+ manager_.GetRttStats()->smoothed_rtt());
+}
+
+TEST_F(QuicSentPacketManagerTest, IgnorePeerMaxAckDelayDuringHandshake) {
+ manager_.EnableMultiplePacketNumberSpacesSupport();
+ // 100ms RTT.
+ const QuicTime::Delta kTestRTT = QuicTime::Delta::FromMilliseconds(100);
+
+ // Server sends INITIAL 1 and HANDSHAKE 2.
+ SendDataPacket(1, ENCRYPTION_INITIAL);
+ SendDataPacket(2, ENCRYPTION_HANDSHAKE);
+
+ // Receive client ACK for INITIAL 1 after one RTT.
+ clock_.AdvanceTime(kTestRTT);
+ ExpectAck(1);
+ manager_.OnAckFrameStart(QuicPacketNumber(1), QuicTime::Delta::Infinite(),
+ clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(1), QuicPacketNumber(2));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(1),
+ ENCRYPTION_INITIAL));
+ EXPECT_EQ(kTestRTT, manager_.GetRttStats()->latest_rtt());
+
+ // Assume the cert verification on client takes 50ms, such that the HANDSHAKE
+ // packet is queued for 50ms.
+ const QuicTime::Delta queuing_delay = QuicTime::Delta::FromMilliseconds(50);
+ clock_.AdvanceTime(queuing_delay);
+ // Ack 2.
+ ExpectAck(2);
+ manager_.OnAckFrameStart(QuicPacketNumber(2), queuing_delay, clock_.Now());
+ manager_.OnAckRange(QuicPacketNumber(2), QuicPacketNumber(3));
+ EXPECT_EQ(PACKETS_NEWLY_ACKED,
+ manager_.OnAckFrameEnd(clock_.Now(), QuicPacketNumber(2),
+ ENCRYPTION_HANDSHAKE));
+ if (GetQuicReloadableFlag(quic_ignore_peer_max_ack_delay_during_handshake)) {
+ EXPECT_EQ(kTestRTT, manager_.GetRttStats()->latest_rtt());
+ } else {
+ // Verify the ack_delay gets capped by the peer_max_ack_delay.
+ EXPECT_EQ(kTestRTT + queuing_delay -
+ QuicTime::Delta::FromMilliseconds(kDefaultDelayedAckTimeMs),
+ manager_.GetRttStats()->latest_rtt());
+ }
+}
+
TEST_F(QuicSentPacketManagerTest, BuildAckFrequencyFrameWithSRTT) {
SetQuicReloadableFlag(quic_can_send_ack_frequency, true);
EXPECT_CALL(*send_algorithm_, SetFromConfig(_, _));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
index 1d2a2adb8c9..0c034514ef4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.cc
@@ -7,8 +7,6 @@
#include <string>
#include <tuple>
-#include "quic/platform/api/quic_estimate_memory_usage.h"
-
namespace quic {
QuicServerId::QuicServerId() : QuicServerId("", 0, false) {}
@@ -33,8 +31,8 @@ bool QuicServerId::operator==(const QuicServerId& other) const {
host_ == other.host_ && port_ == other.port_;
}
-size_t QuicServerId::EstimateMemoryUsage() const {
- return QuicEstimateMemoryUsage(host_);
+bool QuicServerId::operator!=(const QuicServerId& other) const {
+ return !(*this == other);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.h b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.h
index 01320014585..fa6b3c3cfdb 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_server_id.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_server_id.h
@@ -23,18 +23,18 @@ class QUIC_EXPORT_PRIVATE QuicServerId {
bool privacy_mode_enabled);
~QuicServerId();
- // Needed to be an element of std::set.
+ // Needed to be an element of an ordered container.
bool operator<(const QuicServerId& other) const;
bool operator==(const QuicServerId& other) const;
+ bool operator!=(const QuicServerId& other) const;
+
const std::string& host() const { return host_; }
uint16_t port() const { return port_; }
bool privacy_mode_enabled() const { return privacy_mode_enabled_; }
- size_t EstimateMemoryUsage() const;
-
private:
std::string host_;
uint16_t port_;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_server_id_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_server_id_test.cc
index 67231abf866..1ad425abbd8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_server_id_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_server_id_test.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "quic/platform/api/quic_estimate_memory_usage.h"
#include "quic/platform/api/quic_test.h"
namespace quic {
@@ -87,6 +86,10 @@ TEST_F(QuicServerIdTest, Equals) {
QuicServerId b_10_https_right_private("b.com", 10, right_privacy);
QuicServerId b_11_https_right_private("b.com", 11, right_privacy);
+ EXPECT_NE(a_10_https_right_private, a_11_https_right_private);
+ EXPECT_NE(a_10_https_right_private, b_10_https_right_private);
+ EXPECT_NE(a_10_https_right_private, b_11_https_right_private);
+
QuicServerId new_a_10_https_left_private("a.com", 10, left_privacy);
QuicServerId new_a_11_https_left_private("a.com", 11, left_privacy);
QuicServerId new_b_10_https_left_private("b.com", 10, left_privacy);
@@ -107,21 +110,13 @@ TEST_F(QuicServerIdTest, Equals) {
QuicServerId new_a_10_https_left_private("a.com", 10, false);
- EXPECT_FALSE(new_a_10_https_left_private == a_11_https_right_private);
- EXPECT_FALSE(new_a_10_https_left_private == b_10_https_right_private);
- EXPECT_FALSE(new_a_10_https_left_private == b_11_https_right_private);
+ EXPECT_NE(new_a_10_https_left_private, a_11_https_right_private);
+ EXPECT_NE(new_a_10_https_left_private, b_10_https_right_private);
+ EXPECT_NE(new_a_10_https_left_private, b_11_https_right_private);
}
QuicServerId a_10_https_private("a.com", 10, true);
QuicServerId new_a_10_https_no_private("a.com", 10, false);
- EXPECT_FALSE(new_a_10_https_no_private == a_10_https_private);
-}
-
-TEST_F(QuicServerIdTest, EstimateMemoryUsage) {
- std::string host = "this is a rather very quite long hostname";
- uint16_t port = 10;
- bool privacy_mode_enabled = true;
- QuicServerId server_id(host, port, privacy_mode_enabled);
- EXPECT_EQ(QuicEstimateMemoryUsage(host), QuicEstimateMemoryUsage(server_id));
+ EXPECT_NE(new_a_10_https_no_private, a_10_https_private);
}
} // namespace
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
index 1bcb9dcb7bd..aef3fc255a8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.cc
@@ -13,6 +13,7 @@
#include "absl/strings/string_view.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#include "quic/core/quic_connection.h"
+#include "quic/core/quic_connection_context.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_flow_controller.h"
#include "quic/core/quic_types.h"
@@ -22,7 +23,6 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_stack_trace.h"
#include "common/quiche_text_utils.h"
@@ -135,11 +135,15 @@ void QuicSession::Initialize() {
connection_->SetDataProducer(this);
connection_->SetUnackedMapInitialCapacity();
connection_->SetFromConfig(config_);
- if (perspective_ == Perspective::IS_CLIENT &&
- config_.HasClientRequestedIndependentOption(kAFFE, perspective_) &&
- version().HasIetfQuicFrames()) {
- connection_->set_can_receive_ack_frequency_frame();
- config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
+ if (perspective_ == Perspective::IS_CLIENT) {
+ if (config_.HasClientRequestedIndependentOption(kAFFE, perspective_) &&
+ version().HasIetfQuicFrames()) {
+ connection_->set_can_receive_ack_frequency_frame();
+ config_.SetMinAckDelayMs(kDefaultMinAckDelayTimeMs);
+ }
+ if (config_.HasClientRequestedIndependentOption(kBPTE, perspective_)) {
+ permutes_tls_extensions_ = true;
+ }
}
connection_->CreateConnectionIdManager();
@@ -162,7 +166,12 @@ void QuicSession::Initialize() {
GetMutableCryptoStream()->id());
}
-QuicSession::~QuicSession() {}
+QuicSession::~QuicSession() {
+ if (GetQuicRestartFlag(quic_alarm_add_permanent_cancel) &&
+ closed_streams_clean_up_alarm_ != nullptr) {
+ closed_streams_clean_up_alarm_->PermanentCancel();
+ }
+}
void QuicSession::PendingStreamOnStreamFrame(const QuicStreamFrame& frame) {
QUICHE_DCHECK(VersionUsesHttp3(transport_version()));
@@ -563,17 +572,14 @@ bool QuicSession::CheckStreamWriteBlocked(QuicStream* stream) const {
}
void QuicSession::OnCanWrite() {
- if (connection_->donot_write_mid_packet_processing()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_donot_write_mid_packet_processing, 1, 3);
- if (connection_->framer().is_processing_packet()) {
- // Do not write data in the middle of packet processing because rest
- // frames in the packet may change the data to write. For example, lost
- // data could be acknowledged. Also, connection is going to emit
- // OnCanWrite signal post packet processing.
- QUIC_BUG(session_write_mid_packet_processing)
- << ENDPOINT << "Try to write mid packet processing.";
- return;
- }
+ if (connection_->framer().is_processing_packet()) {
+ // Do not write data in the middle of packet processing because rest
+ // frames in the packet may change the data to write. For example, lost
+ // data could be acknowledged. Also, connection is going to emit
+ // OnCanWrite signal post packet processing.
+ QUIC_BUG(session_write_mid_packet_processing)
+ << ENDPOINT << "Try to write mid packet processing.";
+ return;
}
if (!RetransmitLostData()) {
// Cannot finish retransmitting lost data, connection is write blocked.
@@ -739,8 +745,8 @@ bool QuicSession::HasPendingHandshake() const {
return GetCryptoStream()->HasPendingCryptoRetransmission() ||
GetCryptoStream()->HasBufferedCryptoFrames();
}
- return QuicContainsKey(streams_with_pending_retransmission_,
- QuicUtils::GetCryptoStreamId(transport_version())) ||
+ return streams_with_pending_retransmission_.contains(
+ QuicUtils::GetCryptoStreamId(transport_version())) ||
write_blocked_streams_.IsStreamBlocked(
QuicUtils::GetCryptoStreamId(transport_version()));
}
@@ -748,19 +754,17 @@ bool QuicSession::HasPendingHandshake() const {
void QuicSession::ProcessUdpPacket(const QuicSocketAddress& self_address,
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet) {
+ QuicConnectionContextSwitcher cs(connection_->context());
connection_->ProcessUdpPacket(self_address, peer_address, packet);
}
-QuicConsumedData QuicSession::WritevData(
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType type,
- absl::optional<EncryptionLevel> level) {
+QuicConsumedData QuicSession::WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ EncryptionLevel level) {
QUICHE_DCHECK(connection_->connected())
<< ENDPOINT << "Try to write stream data when connection is closed.";
- QUICHE_DCHECK(!use_write_or_buffer_data_at_level_ || level.has_value());
if (!IsEncryptionEstablished() &&
!QuicUtils::IsCryptoStreamId(transport_version(), id)) {
// Do not let streams write without encryption. The calling stream will end
@@ -768,11 +772,10 @@ QuicConsumedData QuicSession::WritevData(
if (was_zero_rtt_rejected_ && !OneRttKeysAvailable()) {
QUICHE_DCHECK(version().UsesTls() &&
perspective() == Perspective::IS_CLIENT);
- QUIC_BUG_IF(quic_bug_12435_3, type == NOT_RETRANSMISSION)
- << ENDPOINT << "Try to send new data on stream " << id
- << "before 1-RTT keys are available while 0-RTT is rejected. "
- "Version: "
- << ParsedQuicVersionToString(version());
+ QUIC_DLOG(INFO) << ENDPOINT
+ << "Suppress the write while 0-RTT gets rejected and "
+ "1-RTT keys are not available. Version: "
+ << ParsedQuicVersionToString(version());
} else if (version().UsesTls() || perspective() == Perspective::IS_SERVER) {
QUIC_BUG(quic_bug_10866_2)
<< ENDPOINT << "Try to send data of stream " << id
@@ -793,15 +796,7 @@ QuicConsumedData QuicSession::WritevData(
}
SetTransmissionType(type);
- const auto current_level = connection()->encryption_level();
- if (!use_encryption_level_context()) {
- if (level.has_value()) {
- connection()->SetDefaultEncryptionLevel(level.value());
- }
- }
- QuicConnection::ScopedEncryptionLevelContext context(
- use_encryption_level_context() ? connection() : nullptr,
- use_encryption_level_context() ? level.value() : NUM_ENCRYPTION_LEVELS);
+ QuicConnection::ScopedEncryptionLevelContext context(connection(), level);
QuicConsumedData data =
connection_->SendStreamData(id, write_length, offset, state);
@@ -810,14 +805,6 @@ QuicConsumedData QuicSession::WritevData(
write_blocked_streams_.UpdateBytesForStream(id, data.bytes_consumed);
}
- // Restore the encryption level.
- if (!use_encryption_level_context()) {
- // Restore the encryption level.
- if (level.has_value()) {
- connection()->SetDefaultEncryptionLevel(current_level);
- }
- }
-
return data;
}
@@ -837,18 +824,9 @@ size_t QuicSession::SendCryptoData(EncryptionLevel level,
return 0;
}
SetTransmissionType(type);
- const auto current_level = connection()->encryption_level();
- if (!use_encryption_level_context()) {
- connection_->SetDefaultEncryptionLevel(level);
- }
- QuicConnection::ScopedEncryptionLevelContext context(
- use_encryption_level_context() ? connection() : nullptr, level);
+ QuicConnection::ScopedEncryptionLevelContext context(connection(), level);
const auto bytes_consumed =
connection_->SendCryptoData(level, write_length, offset);
- if (!use_encryption_level_context()) {
- // Restores encryption level.
- connection_->SetDefaultEncryptionLevel(current_level);
- }
return bytes_consumed;
}
@@ -863,21 +841,13 @@ bool QuicSession::WriteControlFrame(const QuicFrame& frame,
TransmissionType type) {
QUICHE_DCHECK(connection()->connected())
<< ENDPOINT << "Try to write control frames when connection is closed.";
- if (connection_->encrypted_control_frames()) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_encrypted_control_frames);
- if (!IsEncryptionEstablished()) {
- QUIC_BUG(quic_bug_10866_4)
- << ENDPOINT << "Tried to send control frame " << frame
- << " before encryption is established. Last decrypted level: "
- << EncryptionLevelToString(connection_->last_decrypted_level());
- return false;
- }
+ if (!IsEncryptionEstablished()) {
+ // Suppress the write before encryption gets established.
+ return false;
}
SetTransmissionType(type);
QuicConnection::ScopedEncryptionLevelContext context(
- use_encryption_level_context() ? connection() : nullptr,
- use_encryption_level_context() ? GetEncryptionLevelToSendApplicationData()
- : NUM_ENCRYPTION_LEVELS);
+ connection(), GetEncryptionLevelToSendApplicationData());
return connection_->SendControlFrame(frame);
}
@@ -1329,8 +1299,7 @@ void QuicSession::OnConfigNegotiated() {
// Or if this session is configured on TLS enabled QUIC versions,
// attempt to retransmit 0-RTT data if there's any.
// TODO(fayang): consider removing this OnCanWrite call.
- if ((!connection_->donot_write_mid_packet_processing() ||
- !connection_->framer().is_processing_packet()) &&
+ if (!connection_->framer().is_processing_packet() &&
(connection_->version().AllowsLowFlowControlLimits() ||
version().UsesTls())) {
QUIC_CODE_COUNT(quic_session_on_can_write_on_config_negotiated);
@@ -1637,8 +1606,7 @@ void QuicSession::SetDefaultEncryptionLevel(EncryptionLevel level) {
// Retransmit old 0-RTT data (if any) with the new 0-RTT keys, since
// they can't be decrypted by the server.
connection_->MarkZeroRttPacketsForRetransmission(0);
- if (!connection_->donot_write_mid_packet_processing() ||
- !connection_->framer().is_processing_packet()) {
+ if (!connection_->framer().is_processing_packet()) {
// TODO(fayang): consider removing this OnCanWrite call.
// Given any streams blocked by encryption a chance to write.
QUIC_CODE_COUNT(
@@ -1817,7 +1785,7 @@ void QuicSession::ActivateStream(std::unique_ptr<QuicStream> stream) {
bool is_static = stream->is_static();
QUIC_DVLOG(1) << ENDPOINT << "num_streams: " << stream_map_.size()
<< ". activating stream " << stream_id;
- QUICHE_DCHECK(!QuicContainsKey(stream_map_, stream_id));
+ QUICHE_DCHECK(!stream_map_.contains(stream_id));
stream_map_[stream_id] = std::move(stream);
if (is_static) {
++num_static_streams_;
@@ -1897,7 +1865,7 @@ QuicStreamCount QuicSession::GetAdvertisedMaxIncomingBidirectionalStreams()
}
QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
- QUICHE_DCHECK(!QuicContainsKey(pending_stream_map_, stream_id));
+ QUICHE_DCHECK(!pending_stream_map_.contains(stream_id));
if (QuicUtils::IsCryptoStreamId(transport_version(), stream_id)) {
return GetMutableCryptoStream();
}
@@ -1936,7 +1904,7 @@ QuicStream* QuicSession::GetOrCreateStream(const QuicStreamId stream_id) {
}
void QuicSession::StreamDraining(QuicStreamId stream_id, bool unidirectional) {
- QUICHE_DCHECK(QuicContainsKey(stream_map_, stream_id));
+ QUICHE_DCHECK(stream_map_.contains(stream_id));
QUIC_DVLOG(1) << ENDPOINT << "Stream " << stream_id << " is draining";
if (VersionHasIetfQuicFrames(transport_version())) {
ietf_streamid_manager_.OnStreamClosed(stream_id);
@@ -2052,7 +2020,7 @@ bool QuicSession::IsOpenStream(QuicStreamId id) {
if (it != stream_map_.end()) {
return !it->second->IsZombie();
}
- if (QuicContainsKey(pending_stream_map_, id) ||
+ if (pending_stream_map_.contains(id) ||
QuicUtils::IsCryptoStreamId(transport_version(), id)) {
// Stream is active
return true;
@@ -2106,14 +2074,16 @@ void QuicSession::SendAckFrequency(const QuicAckFrequencyFrame& frame) {
}
void QuicSession::SendNewConnectionId(const QuicNewConnectionIdFrame& frame) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 1, 5);
+ // Count NEW_CONNECTION_ID frames sent to client.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 1, 6);
control_frame_manager_.WriteOrBufferNewConnectionId(
frame.connection_id, frame.sequence_number, frame.retire_prior_to,
frame.stateless_reset_token);
}
void QuicSession::SendRetireConnectionId(uint64_t sequence_number) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 2, 5);
+ // Count RETIRE_CONNECTION_ID frames sent to client.
+ QUIC_RELOADABLE_FLAG_COUNT_N(quic_connection_migration_use_new_cid_v2, 2, 6);
control_frame_manager_.WriteOrBufferRetireConnectionId(sequence_number);
}
@@ -2272,8 +2242,8 @@ void QuicSession::OnFrameLost(const QuicFrame& frame) {
frame.stream_frame.data_length,
frame.stream_frame.fin);
if (stream->HasPendingRetransmission() &&
- !QuicContainsKey(streams_with_pending_retransmission_,
- frame.stream_frame.stream_id)) {
+ !streams_with_pending_retransmission_.contains(
+ frame.stream_frame.stream_id)) {
streams_with_pending_retransmission_.insert(
std::make_pair(frame.stream_frame.stream_id, true));
}
@@ -2397,8 +2367,8 @@ bool QuicSession::RetransmitLostData() {
}
// Retransmit crypto data in stream 1 frames (version < 47).
if (!uses_crypto_frames &&
- QuicContainsKey(streams_with_pending_retransmission_,
- QuicUtils::GetCryptoStreamId(transport_version()))) {
+ streams_with_pending_retransmission_.contains(
+ QuicUtils::GetCryptoStreamId(transport_version()))) {
// Retransmit crypto data first.
QuicStream* crypto_stream =
GetStream(QuicUtils::GetCryptoStreamId(transport_version()));
@@ -2463,20 +2433,23 @@ void QuicSession::SetTransmissionType(TransmissionType type) {
connection_->SetTransmissionType(type);
}
-MessageResult QuicSession::SendMessage(QuicMemSliceSpan message) {
+MessageResult QuicSession::SendMessage(absl::Span<QuicMemSlice> message) {
return SendMessage(message, /*flush=*/false);
}
-MessageResult QuicSession::SendMessage(QuicMemSliceSpan message, bool flush) {
+MessageResult QuicSession::SendMessage(QuicMemSlice message) {
+ return SendMessage(absl::MakeSpan(&message, 1), /*flush=*/false);
+}
+
+MessageResult QuicSession::SendMessage(absl::Span<QuicMemSlice> message,
+ bool flush) {
QUICHE_DCHECK(connection_->connected())
<< ENDPOINT << "Try to write messages when connection is closed.";
if (!IsEncryptionEstablished()) {
return {MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0};
}
QuicConnection::ScopedEncryptionLevelContext context(
- use_encryption_level_context() ? connection() : nullptr,
- use_encryption_level_context() ? GetEncryptionLevelToSendApplicationData()
- : NUM_ENCRYPTION_LEVELS);
+ connection(), GetEncryptionLevelToSendApplicationData());
MessageStatus result =
connection_->SendMessage(last_message_id_ + 1, message, flush);
if (result == MESSAGE_STATUS_SUCCESS) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session.h b/chromium/net/third_party/quiche/src/quic/core/quic_session.h
index b6c1367019f..9eb7bd1614f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session.h
@@ -17,6 +17,8 @@
#include "absl/container/flat_hash_map.h"
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "quic/core/crypto/tls_connection.h"
#include "quic/core/frames/quic_ack_frequency_frame.h"
#include "quic/core/handshaker_delegate_interface.h"
#include "quic/core/legacy_quic_stream_id_manager.h"
@@ -35,10 +37,11 @@
#include "quic/core/session_notifier_interface.h"
#include "quic/core/stream_delegate_interface.h"
#include "quic/core/uber_quic_stream_id_manager.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_mem_slice.h"
#include "quic/platform/api/quic_socket_address.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -208,31 +211,39 @@ class QUIC_EXPORT_PRIVATE QuicSession
const QuicSocketAddress& peer_address,
const QuicReceivedPacket& packet);
- // Called by application to send |message|. Data copy can be avoided if
- // |message| is provided in reference counted memory.
- // Please note, |message| provided in reference counted memory would be moved
- // internally when message is successfully sent. Thereafter, it would be
- // undefined behavior if callers try to access the slices through their own
- // copy of the span object.
- // Returns the message result which includes the message status and message ID
- // (valid if the write succeeds). SendMessage flushes a message packet even it
- // is not full. If the application wants to bundle other data in the same
- // packet, please consider adding a packet flusher around the SendMessage
- // and/or WritevData calls.
+ // Sends |message| as a QUIC DATAGRAM frame (QUIC MESSAGE frame in gQUIC).
+ // See <https://datatracker.ietf.org/doc/html/draft-ietf-quic-datagram> for
+ // more details.
//
- // OnMessageAcked and OnMessageLost are called when a particular message gets
- // acked or lost.
+ // Returns a MessageResult struct which includes the status of the write
+ // operation and a message ID. The message ID (not sent on the wire) can be
+ // used to track the message; OnMessageAcked and OnMessageLost are called when
+ // a specific message gets acked or lost.
+ //
+ // If the write operation is successful, all of the slices in |message| are
+ // consumed, leaving them empty. If MESSAGE_STATUS_INTERNAL_ERROR is
+ // returned, the slices in question may or may not be consumed; it is no
+ // longer safe to access those. For all other status codes, |message| is kept
+ // intact.
//
// Note that SendMessage will fail with status = MESSAGE_STATUS_BLOCKED
- // if connection is congestion control blocked or underlying socket is write
- // blocked. In this case the caller can retry sending message again when
+ // if the connection is congestion control blocked or the underlying socket is
+ // write blocked. In this case the caller can retry sending message again when
// connection becomes available, for example after getting OnCanWrite()
// callback.
- MessageResult SendMessage(QuicMemSliceSpan message);
+ //
+ // SendMessage flushes the current packet even it is not full; if the
+ // application needs to bundle other data in the same packet, consider using
+ // QuicConnection::ScopedPacketFlusher around the relevant write operations.
+ MessageResult SendMessage(absl::Span<QuicMemSlice> message);
// Same as above SendMessage, except caller can specify if the given |message|
// should be flushed even if the underlying connection is deemed unwritable.
- MessageResult SendMessage(QuicMemSliceSpan message, bool flush);
+ MessageResult SendMessage(absl::Span<QuicMemSlice> message, bool flush);
+
+ // Single-slice version of SendMessage(). Unlike the version above, this
+ // version always takes ownership of the slice.
+ MessageResult SendMessage(QuicMemSlice message);
// Called when message with |message_id| gets acked.
virtual void OnMessageAcked(QuicMessageId message_id,
@@ -327,12 +338,10 @@ class QUIC_EXPORT_PRIVATE QuicSession
// indicating if the fin bit was consumed. This does not indicate the data
// has been sent on the wire: it may have been turned into a packet and queued
// if the socket was unexpectedly blocked.
- QuicConsumedData WritevData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
+ QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset, StreamSendingState state,
TransmissionType type,
- absl::optional<EncryptionLevel> level) override;
+ EncryptionLevel level) override;
size_t SendCryptoData(EncryptionLevel level,
size_t write_length,
@@ -610,14 +619,9 @@ class QUIC_EXPORT_PRIVATE QuicSession
return liveness_testing_in_progress_;
}
- bool use_write_or_buffer_data_at_level() const {
- return use_write_or_buffer_data_at_level_;
- }
+ bool permutes_tls_extensions() const { return permutes_tls_extensions_; }
- bool use_encryption_level_context() const {
- return connection_->use_encryption_level_context() &&
- use_write_or_buffer_data_at_level_;
- }
+ virtual QuicSSLConfig GetSSLConfig() const { return QuicSSLConfig(); }
protected:
using StreamMap =
@@ -925,7 +929,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
// TODO(fayang): switch to linked_hash_set when chromium supports it. The bool
// is not used here.
// List of streams with pending retransmissions.
- QuicLinkedHashMap<QuicStreamId, bool> streams_with_pending_retransmission_;
+ quiche::QuicheLinkedHashMap<QuicStreamId, bool>
+ streams_with_pending_retransmission_;
// Clean up closed_streams_ when this alarm fires.
std::unique_ptr<QuicAlarm> closed_streams_clean_up_alarm_;
@@ -947,8 +952,8 @@ class QUIC_EXPORT_PRIVATE QuicSession
// creation of new outgoing bidirectional streams.
bool liveness_testing_in_progress_;
- const bool use_write_or_buffer_data_at_level_ =
- GetQuicReloadableFlag(quic_use_write_or_buffer_data_at_level);
+ // Whether BoringSSL randomizes the order of TLS extensions.
+ bool permutes_tls_extensions_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
index 81282fe9eeb..84b9e2edc7a 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_session_test.cc
@@ -27,7 +27,6 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_expect_bug.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_mem_slice_storage.h"
#include "quic/platform/api/quic_test.h"
#include "quic/platform/api/quic_test_mem_slice_vector.h"
@@ -314,12 +313,10 @@ class TestSession : public QuicSession {
return GetNumActiveStreams() > 0;
}
- QuicConsumedData WritevData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
+ QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset, StreamSendingState state,
TransmissionType type,
- absl::optional<EncryptionLevel> level) override {
+ EncryptionLevel level) override {
bool fin = state != NO_FIN;
QuicConsumedData consumed(write_length, fin);
if (!writev_consumes_all_data_) {
@@ -452,7 +449,7 @@ class QuicSessionTestBase : public QuicTestWithParam<ParsedQuicVersion> {
QuicUtils::GetCryptoStreamId(connection_->transport_version());
}
for (QuicStreamId i = first_stream_id; i < 100; i++) {
- if (!QuicContainsKey(closed_streams_, i)) {
+ if (closed_streams_.find(i) == closed_streams_.end()) {
EXPECT_FALSE(session_.IsClosedStream(i)) << " stream id: " << i;
} else {
EXPECT_TRUE(session_.IsClosedStream(i)) << " stream id: " << i;
@@ -1529,56 +1526,6 @@ TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedStream) {
EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
}
-TEST_P(QuicSessionTestServer, HandshakeUnblocksFlowControlBlockedCryptoStream) {
- if (QuicVersionUsesCryptoFrames(GetParam().transport_version) ||
- connection_->encrypted_control_frames()) {
- // QUIC version 47 onwards uses CRYPTO frames for the handshake, so this
- // test doesn't make sense for those versions since CRYPTO frames aren't
- // flow controlled.
- return;
- }
- // Test that if the crypto stream is flow control blocked, then if the SHLO
- // contains a larger send window offset, the stream becomes unblocked.
- session_.set_writev_consumes_all_data(true);
- TestCryptoStream* crypto_stream = session_.GetMutableCryptoStream();
- EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- EXPECT_CALL(*connection_, SendControlFrame(_))
- .WillOnce(Invoke(&ClearControlFrame));
- for (QuicStreamId i = 0; !crypto_stream->IsFlowControlBlocked() && i < 1000u;
- i++) {
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
- QuicStreamOffset offset = crypto_stream->stream_bytes_written();
- QuicConfig config;
- CryptoHandshakeMessage crypto_message;
- config.ToHandshakeMessage(&crypto_message, transport_version());
- crypto_stream->SendHandshakeMessage(crypto_message, ENCRYPTION_INITIAL);
- char buf[1000];
- QuicDataWriter writer(1000, buf, quiche::NETWORK_BYTE_ORDER);
- crypto_stream->WriteStreamData(offset, crypto_message.size(), &writer);
- }
- EXPECT_TRUE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_TRUE(session_.IsStreamFlowControlBlocked());
- EXPECT_FALSE(session_.HasDataToWrite());
- EXPECT_TRUE(crypto_stream->HasBufferedData());
-
- // Now complete the crypto handshake, resulting in an increased flow control
- // send window.
- CompleteHandshake();
- EXPECT_TRUE(QuicSessionPeer::IsStreamWriteBlocked(
- &session_,
- QuicUtils::GetCryptoStreamId(connection_->transport_version())));
- // Stream is now unblocked and will no longer have buffered data.
- EXPECT_FALSE(crypto_stream->IsFlowControlBlocked());
- EXPECT_FALSE(session_.IsConnectionFlowControlBlocked());
- EXPECT_FALSE(session_.IsStreamFlowControlBlocked());
-}
-
TEST_P(QuicSessionTestServer, ConnectionFlowControlAccountingRstOutOfOrder) {
CompleteHandshake();
// Test that when we receive an out of order stream RST we correctly adjust
@@ -2451,36 +2398,26 @@ TEST_P(QuicSessionTestServer, RetransmitLostDataCausesConnectionClose) {
TEST_P(QuicSessionTestServer, SendMessage) {
// Cannot send message when encryption is not established.
EXPECT_FALSE(session_.OneRttKeysAvailable());
- quic::QuicMemSliceStorage storage(nullptr, 0, nullptr, 0);
EXPECT_EQ(MessageResult(MESSAGE_STATUS_ENCRYPTION_NOT_ESTABLISHED, 0),
- session_.SendMessage(
- MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
- "", &storage)));
+ session_.SendMessage(MemSliceFromString("")));
CompleteHandshake();
EXPECT_TRUE(session_.OneRttKeysAvailable());
- absl::string_view message;
EXPECT_CALL(*connection_, SendMessage(1, _, false))
.WillOnce(Return(MESSAGE_STATUS_SUCCESS));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 1),
- session_.SendMessage(
- MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
- message, &storage)));
+ session_.SendMessage(MemSliceFromString("")));
// Verify message_id increases.
EXPECT_CALL(*connection_, SendMessage(2, _, false))
.WillOnce(Return(MESSAGE_STATUS_TOO_LARGE));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_TOO_LARGE, 0),
- session_.SendMessage(
- MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
- message, &storage)));
+ session_.SendMessage(MemSliceFromString("")));
// Verify unsent message does not consume a message_id.
EXPECT_CALL(*connection_, SendMessage(2, _, false))
.WillOnce(Return(MESSAGE_STATUS_SUCCESS));
EXPECT_EQ(MessageResult(MESSAGE_STATUS_SUCCESS, 2),
- session_.SendMessage(
- MakeSpan(connection_->helper()->GetStreamSendBufferAllocator(),
- message, &storage)));
+ session_.SendMessage(MemSliceFromString("")));
QuicMessageFrame frame(1);
QuicMessageFrame frame2(2);
@@ -2507,7 +2444,7 @@ TEST_P(QuicSessionTestServer, LocallyResetZombieStreams) {
EXPECT_TRUE(stream2->IsWaitingForAcks());
// Verify stream2 is a zombie streams.
auto& stream_map = QuicSessionPeer::stream_map(&session_);
- ASSERT_TRUE(QuicContainsKey(stream_map, stream2->id()));
+ ASSERT_TRUE(stream_map.contains(stream2->id()));
auto* stream = stream_map.find(stream2->id())->second.get();
EXPECT_TRUE(stream->IsZombie());
@@ -2556,7 +2493,7 @@ TEST_P(QuicSessionTestServer, WriteUnidirectionalStream) {
stream4->WriteOrBufferData(body, false, nullptr);
stream4->WriteOrBufferData(body, true, nullptr);
auto& stream_map = QuicSessionPeer::stream_map(&session_);
- ASSERT_TRUE(QuicContainsKey(stream_map, stream4->id()));
+ ASSERT_TRUE(stream_map.contains(stream4->id()));
auto* stream = stream_map.find(stream4->id())->second.get();
EXPECT_TRUE(stream->IsZombie());
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h b/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h
index cbf73b3dcf4..c2a800d5753 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator.h
@@ -12,6 +12,11 @@ namespace quic {
class QUIC_EXPORT_PRIVATE SimpleBufferAllocator : public QuicBufferAllocator {
public:
+ static SimpleBufferAllocator* Get() {
+ static SimpleBufferAllocator* singleton = new SimpleBufferAllocator();
+ return singleton;
+ }
+
char* New(size_t size) override;
char* New(size_t size, bool flag_enable) override;
void Delete(char* buffer) override;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator_test.cc
index bc3f84437f8..5416cd424ef 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_simple_buffer_allocator_test.cc
@@ -24,5 +24,43 @@ TEST_F(SimpleBufferAllocatorTest, DeleteNull) {
alloc.Delete(nullptr);
}
+TEST_F(SimpleBufferAllocatorTest, MoveBuffersConstructor) {
+ SimpleBufferAllocator alloc;
+ QuicBuffer buffer1(&alloc, 16);
+
+ EXPECT_NE(buffer1.data(), nullptr);
+ EXPECT_EQ(buffer1.size(), 16u);
+
+ QuicBuffer buffer2(std::move(buffer1));
+ EXPECT_EQ(buffer1.data(), nullptr); // NOLINT(bugprone-use-after-move)
+ EXPECT_EQ(buffer1.size(), 0u);
+ EXPECT_NE(buffer2.data(), nullptr);
+ EXPECT_EQ(buffer2.size(), 16u);
+}
+
+TEST_F(SimpleBufferAllocatorTest, MoveBuffersAssignment) {
+ SimpleBufferAllocator alloc;
+ QuicBuffer buffer1(&alloc, 16);
+ QuicBuffer buffer2;
+
+ EXPECT_NE(buffer1.data(), nullptr);
+ EXPECT_EQ(buffer1.size(), 16u);
+ EXPECT_EQ(buffer2.data(), nullptr);
+ EXPECT_EQ(buffer2.size(), 0u);
+
+ buffer2 = std::move(buffer1);
+ EXPECT_EQ(buffer1.data(), nullptr); // NOLINT(bugprone-use-after-move)
+ EXPECT_EQ(buffer1.size(), 0u);
+ EXPECT_NE(buffer2.data(), nullptr);
+ EXPECT_EQ(buffer2.size(), 16u);
+}
+
+TEST_F(SimpleBufferAllocatorTest, CopyBuffer) {
+ SimpleBufferAllocator alloc;
+ const absl::string_view original = "Test string";
+ QuicBuffer copy = QuicBuffer::Copy(&alloc, original);
+ EXPECT_EQ(copy.AsStringView(), original);
+}
+
} // namespace
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
index 3f1b7d94e18..cde50ef214d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.cc
@@ -19,6 +19,7 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
+#include "quic/platform/api/quic_mem_slice.h"
using spdy::SpdyPriority;
@@ -630,23 +631,18 @@ void QuicStream::WriteOrBufferData(
absl::string_view data,
bool fin,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- if (session()->use_write_or_buffer_data_at_level()) {
- QUIC_BUG_IF(quic_bug_12570_4,
- QuicUtils::IsCryptoStreamId(transport_version(), id_))
- << ENDPOINT
- << "WriteOrBufferData is used to send application data, use "
- "WriteOrBufferDataAtLevel to send crypto data.";
- return WriteOrBufferDataAtLevel(
- data, fin, session()->GetEncryptionLevelToSendApplicationData(),
- ack_listener);
- }
- return WriteOrBufferDataInner(data, fin, absl::nullopt, ack_listener);
+ QUIC_BUG_IF(quic_bug_12570_4,
+ QuicUtils::IsCryptoStreamId(transport_version(), id_))
+ << ENDPOINT
+ << "WriteOrBufferData is used to send application data, use "
+ "WriteOrBufferDataAtLevel to send crypto data.";
+ return WriteOrBufferDataAtLevel(
+ data, fin, session()->GetEncryptionLevelToSendApplicationData(),
+ ack_listener);
}
-void QuicStream::WriteOrBufferDataInner(
- absl::string_view data,
- bool fin,
- absl::optional<EncryptionLevel> level,
+void QuicStream::WriteOrBufferDataAtLevel(
+ absl::string_view data, bool fin, EncryptionLevel level,
QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
if (data.empty() && !fin) {
QUIC_BUG(quic_bug_10586_2) << "data.empty() && !fin";
@@ -691,16 +687,6 @@ void QuicStream::WriteOrBufferDataInner(
}
}
-void QuicStream::WriteOrBufferDataAtLevel(
- absl::string_view data,
- bool fin,
- EncryptionLevel level,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener) {
- QUICHE_DCHECK(session()->use_write_or_buffer_data_at_level());
- QUIC_RELOADABLE_FLAG_COUNT(quic_use_write_or_buffer_data_at_level);
- return WriteOrBufferDataInner(data, fin, level, ack_listener);
-}
-
void QuicStream::OnCanWrite() {
if (HasDeadlinePassed()) {
OnDeadlinePassed();
@@ -720,11 +706,7 @@ void QuicStream::OnCanWrite() {
return;
}
if (HasBufferedData() || (fin_buffered_ && !fin_sent_)) {
- absl::optional<EncryptionLevel> send_level = absl::nullopt;
- if (session()->use_write_or_buffer_data_at_level()) {
- send_level = session()->GetEncryptionLevelToSendApplicationData();
- }
- WriteBufferedData(send_level);
+ WriteBufferedData(session()->GetEncryptionLevelToSendApplicationData());
}
if (!fin_buffered_ && !fin_sent_ && CanWriteNewData()) {
// Notify upper layer to write new data when buffered data size is below
@@ -759,6 +741,16 @@ void QuicStream::MaybeSendBlocked() {
}
QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
+ return WriteMemSlicesInner(MemSliceSpanWrapper(span), fin);
+}
+
+QuicConsumedData QuicStream::WriteMemSlices(absl::Span<QuicMemSlice> span,
+ bool fin) {
+ return WriteMemSlicesInner(MemSliceSpanWrapper(span), fin);
+}
+
+QuicConsumedData QuicStream::WriteMemSlicesInner(MemSliceSpanWrapper span,
+ bool fin) {
QuicConsumedData consumed_data(0, false);
if (span.empty() && !fin) {
QUIC_BUG(quic_bug_10586_6) << "span.empty() && !fin";
@@ -786,7 +778,7 @@ QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
if (!span.empty()) {
// Buffer all data if buffered data size is below limit.
QuicStreamOffset offset = send_buffer_.stream_offset();
- consumed_data.bytes_consumed = send_buffer_.SaveMemSliceSpan(span);
+ consumed_data.bytes_consumed = span.SaveTo(send_buffer_);
if (offset > send_buffer_.stream_offset() ||
kMaxStreamLength < send_buffer_.stream_offset()) {
QUIC_BUG(quic_bug_10586_8) << "Write too many data via stream " << id_;
@@ -802,11 +794,7 @@ QuicConsumedData QuicStream::WriteMemSlices(QuicMemSliceSpan span, bool fin) {
if (!had_buffered_data && (HasBufferedData() || fin_buffered_)) {
// Write data if there is no buffered data before.
- absl::optional<EncryptionLevel> send_level = absl::nullopt;
- if (session()->use_write_or_buffer_data_at_level()) {
- send_level = session()->GetEncryptionLevelToSendApplicationData();
- }
- WriteBufferedData(send_level);
+ WriteBufferedData(session()->GetEncryptionLevelToSendApplicationData());
}
return consumed_data;
@@ -1148,10 +1136,6 @@ bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
if (retransmission.Empty() && !retransmit_fin) {
return true;
}
- absl::optional<EncryptionLevel> send_level = absl::nullopt;
- if (session()->use_write_or_buffer_data_at_level()) {
- send_level = session()->GetEncryptionLevelToSendApplicationData();
- }
QuicConsumedData consumed(0, false);
for (const auto& interval : retransmission) {
QuicStreamOffset retransmission_offset = interval.min();
@@ -1161,7 +1145,8 @@ bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
stream_bytes_written());
consumed = stream_delegate_->WritevData(
id_, retransmission_length, retransmission_offset,
- can_bundle_fin ? FIN : NO_FIN, type, send_level);
+ can_bundle_fin ? FIN : NO_FIN, type,
+ session()->GetEncryptionLevelToSendApplicationData());
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " is forced to retransmit stream data ["
<< retransmission_offset << ", "
@@ -1182,8 +1167,9 @@ bool QuicStream::RetransmitStreamData(QuicStreamOffset offset,
if (retransmit_fin) {
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " retransmits fin only frame.";
- consumed = stream_delegate_->WritevData(id_, 0, stream_bytes_written(), FIN,
- type, send_level);
+ consumed = stream_delegate_->WritevData(
+ id_, 0, stream_bytes_written(), FIN, type,
+ session()->GetEncryptionLevelToSendApplicationData());
if (!consumed.fin_consumed) {
return false;
}
@@ -1209,7 +1195,7 @@ bool QuicStream::WriteStreamData(QuicStreamOffset offset,
return send_buffer_.WriteStreamData(offset, data_length, writer);
}
-void QuicStream::WriteBufferedData(absl::optional<EncryptionLevel> level) {
+void QuicStream::WriteBufferedData(EncryptionLevel level) {
QUICHE_DCHECK(!write_side_closed_ && (HasBufferedData() || fin_buffered_));
if (session_->ShouldYield(id())) {
@@ -1333,15 +1319,12 @@ void QuicStream::OnStreamDataConsumed(QuicByteCount bytes_consumed) {
void QuicStream::WritePendingRetransmission() {
while (HasPendingRetransmission()) {
QuicConsumedData consumed(0, false);
- absl::optional<EncryptionLevel> send_level = absl::nullopt;
- if (session()->use_write_or_buffer_data_at_level()) {
- send_level = session()->GetEncryptionLevelToSendApplicationData();
- }
if (!send_buffer_.HasPendingRetransmission()) {
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " retransmits fin only frame.";
consumed = stream_delegate_->WritevData(
- id_, 0, stream_bytes_written(), FIN, LOSS_RETRANSMISSION, send_level);
+ id_, 0, stream_bytes_written(), FIN, LOSS_RETRANSMISSION,
+ session()->GetEncryptionLevelToSendApplicationData());
fin_lost_ = !consumed.fin_consumed;
if (fin_lost_) {
// Connection is write blocked.
@@ -1356,7 +1339,8 @@ void QuicStream::WritePendingRetransmission() {
(pending.offset + pending.length == stream_bytes_written());
consumed = stream_delegate_->WritevData(
id_, pending.length, pending.offset, can_bundle_fin ? FIN : NO_FIN,
- LOSS_RETRANSMISSION, send_level);
+ LOSS_RETRANSMISSION,
+ session()->GetEncryptionLevelToSendApplicationData());
QUIC_DVLOG(1) << ENDPOINT << "stream " << id_
<< " tries to retransmit stream data [" << pending.offset
<< ", " << pending.offset + pending.length
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
index 6e6e623b9f2..6374d8ab6f6 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream.h
@@ -24,6 +24,7 @@
#include "absl/strings/string_view.h"
#include "absl/types/optional.h"
+#include "absl/types/span.h"
#include "quic/core/quic_flow_controller.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_stream_send_buffer.h"
@@ -32,6 +33,7 @@
#include "quic/core/session_notifier_interface.h"
#include "quic/core/stream_delegate_interface.h"
#include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_mem_slice.h"
#include "quic/platform/api/quic_mem_slice_span.h"
#include "quic/platform/api/quic_reference_counted.h"
#include "spdy/core/spdy_protocol.h"
@@ -343,9 +345,13 @@ class QUIC_EXPORT_PRIVATE QuicStream
// succeeds.
bool MaybeSetTtl(QuicTime::Delta ttl);
- // Same as WritevData except data is provided in reference counted memory so
- // that data copy is avoided.
+ // Commits data into the stream write buffer, and potentially sends it over
+ // the wire. This method has all-or-nothing semantics: if the write buffer is
+ // not full, all of the memslices in |span| are moved into it; otherwise,
+ // nothing happens.
+ // TODO(vasilvv): deprecate and remove QuicMemSliceSpan version.
QuicConsumedData WriteMemSlices(QuicMemSliceSpan span, bool fin);
+ QuicConsumedData WriteMemSlices(absl::Span<QuicMemSlice> span, bool fin);
// Returns true if any stream data is lost (including fin) and needs to be
// retransmitted.
@@ -464,6 +470,26 @@ class QUIC_EXPORT_PRIVATE QuicStream
friend class test::QuicStreamPeer;
friend class QuicStreamUtils;
+ // Wraps around either QuicMemSliceSpan or absl::Span<QuicMemSlice>.
+ // TODO(vasilvv): delete this after QuicMemSliceSpan is gone.
+ class QUIC_EXPORT_PRIVATE MemSliceSpanWrapper {
+ public:
+ explicit MemSliceSpanWrapper(QuicMemSliceSpan span) : old_(span) {}
+ explicit MemSliceSpanWrapper(absl::Span<QuicMemSlice> span) : new_(span) {}
+
+ bool empty() { return old_.has_value() ? old_->empty() : new_.empty(); }
+ QuicByteCount SaveTo(QuicStreamSendBuffer& send_buffer) {
+ if (old_.has_value()) {
+ return send_buffer.SaveMemSliceSpan(*old_);
+ }
+ return send_buffer.SaveMemSliceSpan(new_);
+ }
+
+ private:
+ absl::optional<QuicMemSliceSpan> old_;
+ absl::Span<QuicMemSlice> new_;
+ };
+
QuicStream(QuicStreamId id,
QuicSession* session,
QuicStreamSequencer sequencer,
@@ -480,10 +506,8 @@ class QUIC_EXPORT_PRIVATE QuicStream
// controller, marks this stream as connection-level write blocked.
void MaybeSendBlocked();
- // Write buffered data in send buffer.
- // TODO(fayang): Change absl::optional<EncryptionLevel> to EncryptionLevel
- // when deprecating quic_use_write_or_buffer_data_at_level.
- void WriteBufferedData(absl::optional<EncryptionLevel> level);
+ // Write buffered data (in send buffer) at |level|.
+ void WriteBufferedData(EncryptionLevel level);
// Close the read side of the stream. May cause the stream to be closed.
void CloseReadSide();
@@ -491,17 +515,11 @@ class QUIC_EXPORT_PRIVATE QuicStream
// Called when bytes are sent to the peer.
void AddBytesSent(QuicByteCount bytes);
- // TODO(fayang): Inline this function when deprecating
- // quic_use_write_or_buffer_data_at_level.
- void WriteOrBufferDataInner(
- absl::string_view data,
- bool fin,
- absl::optional<EncryptionLevel> level,
- QuicReferenceCountedPointer<QuicAckListenerInterface> ack_listener);
-
// Returns true if deadline_ has passed.
bool HasDeadlinePassed() const;
+ QuicConsumedData WriteMemSlicesInner(MemSliceSpanWrapper span, bool fin);
+
QuicStreamSequencer sequencer_;
QuicStreamId id_;
// Pointer to the owning QuicSession object.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
index 05562125557..40aa3d0f949 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_id_manager.cc
@@ -217,7 +217,7 @@ bool QuicStreamIdManager::IsAvailableStream(QuicStreamId id) const {
return largest_peer_created_stream_id_ ==
QuicUtils::GetInvalidStreamId(version_.transport_version) ||
id > largest_peer_created_stream_id_ ||
- QuicContainsKey(available_streams_, id);
+ available_streams_.contains(id);
}
QuicStreamId QuicStreamIdManager::GetFirstOutgoingStreamId() const {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
index 3b1b37bd1f3..1e32e544cd1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.cc
@@ -12,6 +12,7 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
+#include "quic/platform/api/quic_mem_slice.h"
namespace quic {
@@ -96,6 +97,20 @@ QuicByteCount QuicStreamSendBuffer::SaveMemSliceSpan(QuicMemSliceSpan span) {
[&](QuicMemSlice slice) { SaveMemSlice(std::move(slice)); });
}
+QuicByteCount QuicStreamSendBuffer::SaveMemSliceSpan(
+ absl::Span<QuicMemSlice> span) {
+ QuicByteCount total = 0;
+ for (QuicMemSlice& slice : span) {
+ if (slice.length() == 0) {
+ // Skip empty slices.
+ continue;
+ }
+ total += slice.length();
+ SaveMemSlice(std::move(slice));
+ }
+ return total;
+}
+
void QuicStreamSendBuffer::OnStreamDataConsumed(size_t bytes_consumed) {
stream_bytes_written_ += bytes_consumed;
stream_bytes_outstanding_ += bytes_consumed;
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
index 4b23d3d82cd..f91e4760870 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer.h
@@ -5,6 +5,7 @@
#ifndef QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_
#define QUICHE_QUIC_CORE_QUIC_STREAM_SEND_BUFFER_H_
+#include "absl/types/span.h"
#include "quic/core/frames/quic_stream_frame.h"
#include "quic/core/quic_interval_deque.h"
#include "quic/core/quic_interval_set.h"
@@ -80,6 +81,7 @@ class QUIC_EXPORT_PRIVATE QuicStreamSendBuffer {
// Save all slices in |span| to send buffer. Return total bytes saved.
QuicByteCount SaveMemSliceSpan(QuicMemSliceSpan span);
+ QuicByteCount SaveMemSliceSpan(absl::Span<QuicMemSlice> span);
// Called when |bytes_consumed| bytes has been consumed by the stream.
void OnStreamDataConsumed(size_t bytes_consumed);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
index 25dda04c566..e1a2358acba 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_send_buffer_test.cc
@@ -39,12 +39,12 @@ class QuicStreamSendBufferTest : public QuicTest {
iov[0] = MakeIovec(absl::string_view(data1));
iov[1] = MakeIovec(absl::string_view(data2));
- QuicUniqueBufferPtr buffer1 = MakeUniqueBuffer(&allocator_, 1024);
- memset(buffer1.get(), 'c', 1024);
- QuicMemSlice slice1(std::move(buffer1), 1024);
- QuicUniqueBufferPtr buffer2 = MakeUniqueBuffer(&allocator_, 768);
- memset(buffer2.get(), 'd', 768);
- QuicMemSlice slice2(std::move(buffer2), 768);
+ QuicBuffer buffer1(&allocator_, 1024);
+ memset(buffer1.data(), 'c', buffer1.size());
+ QuicMemSlice slice1(std::move(buffer1));
+ QuicBuffer buffer2(&allocator_, 768);
+ memset(buffer2.data(), 'd', buffer2.size());
+ QuicMemSlice slice2(std::move(buffer2));
// The stream offset should be 0 since nothing is written.
EXPECT_EQ(0u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
@@ -309,9 +309,9 @@ TEST_F(QuicStreamSendBufferTest, EndOffset) {
// Last offset is end offset of last slice.
EXPECT_EQ(3840u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(&allocator_, 60);
- memset(buffer.get(), 'e', 60);
- QuicMemSlice slice(std::move(buffer), 60);
+ QuicBuffer buffer(&allocator_, 60);
+ memset(buffer.data(), 'e', buffer.size());
+ QuicMemSlice slice(std::move(buffer));
send_buffer_.SaveMemSlice(std::move(slice));
EXPECT_EQ(3840u, QuicStreamSendBufferPeer::EndOffset(&send_buffer_));
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
index 2d3298b6fc9..e69b657177d 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_stream_test.cc
@@ -1178,14 +1178,17 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
SetQuicFlag(FLAGS_quic_buffered_data_threshold, 100);
Initialize();
- char data[1024];
- std::vector<std::pair<char*, size_t>> buffers;
- buffers.push_back(std::make_pair(data, ABSL_ARRAYSIZE(data)));
- buffers.push_back(std::make_pair(data, ABSL_ARRAYSIZE(data)));
- QuicTestMemSliceVector vector1(buffers);
- QuicTestMemSliceVector vector2(buffers);
- QuicMemSliceSpan span1 = vector1.span();
- QuicMemSliceSpan span2 = vector2.span();
+ constexpr QuicByteCount kDataSize = 1024;
+ QuicBufferAllocator* allocator =
+ connection_->helper()->GetStreamSendBufferAllocator();
+ std::vector<QuicMemSlice> vector1;
+ vector1.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize)));
+ vector1.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize)));
+ std::vector<QuicMemSlice> vector2;
+ vector2.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize)));
+ vector2.push_back(QuicMemSlice(QuicBuffer(allocator, kDataSize)));
+ absl::Span<QuicMemSlice> span1(vector1);
+ absl::Span<QuicMemSlice> span2(vector2);
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this]() {
@@ -1196,7 +1199,7 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
QuicConsumedData consumed = stream_->WriteMemSlices(span1, false);
EXPECT_EQ(2048u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
+ EXPECT_EQ(2 * kDataSize - 100, stream_->BufferedDataBytes());
EXPECT_FALSE(stream_->fin_buffered());
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _)).Times(0);
@@ -1204,12 +1207,11 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
consumed = stream_->WriteMemSlices(span2, true);
EXPECT_EQ(0u, consumed.bytes_consumed);
EXPECT_FALSE(consumed.fin_consumed);
- EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) - 100, stream_->BufferedDataBytes());
+ EXPECT_EQ(2 * kDataSize - 100, stream_->BufferedDataBytes());
EXPECT_FALSE(stream_->fin_buffered());
QuicByteCount data_to_write =
- 2 * ABSL_ARRAYSIZE(data) - 100 -
- GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
+ 2 * kDataSize - 100 - GetQuicFlag(FLAGS_quic_buffered_data_threshold) + 1;
EXPECT_CALL(*session_, WritevData(_, _, _, _, _, _))
.WillOnce(InvokeWithoutArgs([this, data_to_write]() {
return session_->ConsumeData(stream_->id(), data_to_write, 100u, NO_FIN,
@@ -1225,8 +1227,7 @@ TEST_P(QuicStreamTest, WriteMemSlices) {
consumed = stream_->WriteMemSlices(span2, true);
EXPECT_EQ(2048u, consumed.bytes_consumed);
EXPECT_TRUE(consumed.fin_consumed);
- EXPECT_EQ(2 * ABSL_ARRAYSIZE(data) +
- GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
+ EXPECT_EQ(2 * kDataSize + GetQuicFlag(FLAGS_quic_buffered_data_threshold) - 1,
stream_->BufferedDataBytes());
EXPECT_TRUE(stream_->fin_buffered());
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
index dbaa38bdefe..12f5ef9aae2 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.cc
@@ -22,7 +22,6 @@
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_socket_address.h"
#include "common/quiche_text_utils.h"
@@ -174,7 +173,7 @@ bool QuicTimeWaitListManager::IsConnectionIdInTimeWait(
if (use_indirect_connection_id_map_) {
return indirect_connection_id_map_.contains(connection_id);
}
- return QuicContainsKey(connection_id_map_, connection_id);
+ return connection_id_map_.contains(connection_id);
}
void QuicTimeWaitListManager::OnBlockedWriterCanWrite() {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
index ac371f2c180..fe15159d98c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager.h
@@ -19,8 +19,8 @@
#include "quic/core/quic_packets.h"
#include "quic/core/quic_session.h"
#include "quic/core/quic_types.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_flags.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -285,10 +285,11 @@ class QUIC_NO_EXPORT QuicTimeWaitListManager
TimeWaitConnectionInfo info;
};
- // QuicLinkedHashMap allows lookup by ConnectionId and traversal in add order.
- using ConnectionIdMap = QuicLinkedHashMap<QuicConnectionId,
- ConnectionIdData,
- QuicConnectionIdHash>;
+ // QuicheLinkedHashMap allows lookup by ConnectionId
+ // and traversal in add order.
+ using ConnectionIdMap = quiche::QuicheLinkedHashMap<QuicConnectionId,
+ ConnectionIdData,
+ QuicConnectionIdHash>;
// Do not use find/emplace/erase on this map directly. Use
// FindConnectionIdDataInMap, AddConnectionIdDateToMap,
// RemoveConnectionDataFromMap instead.
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
index 4e9f957182b..f47bdf2fed8 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_time_wait_list_manager_test.cc
@@ -204,13 +204,13 @@ class QuicTimeWaitListManagerTest : public QuicTest {
bool ValidPublicResetPacketPredicate(
QuicConnectionId expected_connection_id,
- const testing::tuple<const char*, int>& packet_buffer) {
+ const std::tuple<const char*, int>& packet_buffer) {
FramerVisitorCapturingPublicReset visitor(expected_connection_id);
QuicFramer framer(AllSupportedVersions(), QuicTime::Zero(),
Perspective::IS_CLIENT, kQuicDefaultConnectionIdLength);
framer.set_visitor(&visitor);
- QuicEncryptedPacket encrypted(testing::get<0>(packet_buffer),
- testing::get<1>(packet_buffer));
+ QuicEncryptedPacket encrypted(std::get<0>(packet_buffer),
+ std::get<1>(packet_buffer));
framer.ProcessPacket(encrypted);
QuicPublicResetPacket packet = visitor.public_reset_packet();
bool public_reset_is_valid =
@@ -230,10 +230,10 @@ bool ValidPublicResetPacketPredicate(
return public_reset_is_valid || stateless_reset_is_valid;
}
-Matcher<const testing::tuple<const char*, int>> PublicResetPacketEq(
+Matcher<const std::tuple<const char*, int>> PublicResetPacketEq(
QuicConnectionId connection_id) {
return Truly(
- [connection_id](const testing::tuple<const char*, int> packet_buffer) {
+ [connection_id](const std::tuple<const char*, int> packet_buffer) {
return ValidPublicResetPacketPredicate(connection_id, packet_buffer);
});
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
index 57163abbe42..f578bb46c36 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.cc
@@ -225,7 +225,6 @@ std::string TransmissionTypeToString(TransmissionType transmission_type) {
return "INVALID_TRANSMISSION_TYPE";
}
return absl::StrCat("Unknown(", static_cast<int>(transmission_type), ")");
- break;
}
}
@@ -267,7 +266,6 @@ std::string MessageStatusToString(MessageStatus message_status) {
RETURN_STRING_LITERAL(MESSAGE_STATUS_INTERNAL_ERROR);
default:
return absl::StrCat("Unknown(", static_cast<int>(message_status), ")");
- break;
}
}
@@ -292,7 +290,6 @@ std::string PacketNumberSpaceToString(PacketNumberSpace packet_number_space) {
default:
return absl::StrCat("Unknown(", static_cast<int>(packet_number_space),
")");
- break;
}
}
@@ -320,7 +317,6 @@ std::string EncryptionLevelToString(EncryptionLevel level) {
RETURN_STRING_LITERAL(ENCRYPTION_FORWARD_SECURE);
default:
return absl::StrCat("Unknown(", static_cast<int>(level), ")");
- break;
}
}
@@ -336,7 +332,6 @@ std::string QuicConnectionCloseTypeString(QuicConnectionCloseType type) {
RETURN_STRING_LITERAL(IETF_QUIC_APPLICATION_CONNECTION_CLOSE);
default:
return absl::StrCat("Unknown(", static_cast<int>(type), ")");
- break;
}
}
@@ -378,7 +373,6 @@ std::string KeyUpdateReasonString(KeyUpdateReason reason) {
RETURN_REASON_LITERAL(kLocalKeyUpdateLimitOverride);
default:
return absl::StrCat("Unknown(", static_cast<int>(reason), ")");
- break;
}
#undef RETURN_REASON_LITERAL
}
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_types.h b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
index 2e65e5f12a4..eb4db074ef4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_types.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_types.h
@@ -12,6 +12,7 @@
#include <ostream>
#include <vector>
+#include "absl/container/inlined_vector.h"
#include "quic/core/quic_connection_id.h"
#include "quic/core/quic_error_codes.h"
#include "quic/core/quic_packet_number.h"
@@ -25,7 +26,13 @@ namespace quic {
using QuicPacketLength = uint16_t;
using QuicControlFrameId = uint32_t;
using QuicMessageId = uint32_t;
-using QuicDatagramFlowId = uint64_t;
+
+// TODO(b/181256914) replace QuicDatagramStreamId with QuicStreamId once we
+// remove support for draft-ietf-masque-h3-datagram-00 in favor of later drafts.
+using QuicDatagramStreamId = uint64_t;
+using QuicDatagramContextId = uint64_t;
+// Note that for draft-ietf-masque-h3-datagram-00, we represent the flow ID as a
+// QuicDatagramStreamId.
// IMPORTANT: IETF QUIC defines stream IDs and stream counts as being unsigned
// 62-bit numbers. However, we have decided to only support up to 2^32-1 streams
@@ -580,7 +587,7 @@ struct QUIC_EXPORT_PRIVATE AckedPacket {
};
// A vector of acked packets.
-using AckedPacketVector = QuicInlinedVector<AckedPacket, 2>;
+using AckedPacketVector = absl::InlinedVector<AckedPacket, 2>;
// Information about a newly lost packet.
struct QUIC_EXPORT_PRIVATE LostPacket {
@@ -597,7 +604,7 @@ struct QUIC_EXPORT_PRIVATE LostPacket {
};
// A vector of lost packets.
-using LostPacketVector = QuicInlinedVector<LostPacket, 2>;
+using LostPacketVector = absl::InlinedVector<LostPacket, 2>;
// Please note, this value cannot used directly for packet serialization.
enum QuicLongHeaderType : uint8_t {
@@ -826,6 +833,16 @@ QUIC_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
QUIC_EXPORT_PRIVATE std::string KeyUpdateReasonString(KeyUpdateReason reason);
+// QuicSSLConfig contains configurations to be applied on a SSL object, which
+// overrides the configurations in SSL_CTX.
+struct QUIC_NO_EXPORT QuicSSLConfig {
+ // Whether TLS early data should be enabled. If not set, default to enabled.
+ absl::optional<bool> early_data_enabled;
+ // If set, used to configure the SSL object with
+ // SSL_set_signing_algorithm_prefs.
+ absl::optional<absl::InlinedVector<uint16_t, 8>> signing_algorithm_prefs;
+};
+
} // namespace quic
#endif // QUICHE_QUIC_CORE_QUIC_TYPES_H_
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
index fbdcd3eeb8a..9f9919c1be9 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.cc
@@ -8,6 +8,7 @@
#include <limits>
#include <type_traits>
+#include "absl/container/inlined_vector.h"
#include "quic/core/quic_connection_stats.h"
#include "quic/core/quic_packet_number.h"
#include "quic/core/quic_types.h"
@@ -174,7 +175,7 @@ void QuicUnackedPacketMap::AddSentPacket(SerializedPacket* mutable_packet,
last_inflight_packet_sent_time_ = sent_time;
last_inflight_packets_sent_time_[packet_number_space] = sent_time;
}
- unacked_packets_.push_back(info);
+ unacked_packets_.push_back(std::move(info));
// Swap the retransmittable frames to avoid allocations.
// TODO(ianswett): Could use emplace_back when Chromium can.
if (has_crypto_handshake) {
@@ -325,9 +326,9 @@ void QuicUnackedPacketMap::RemoveFromInFlight(QuicPacketNumber packet_number) {
RemoveFromInFlight(info);
}
-QuicInlinedVector<QuicPacketNumber, 2>
+absl::InlinedVector<QuicPacketNumber, 2>
QuicUnackedPacketMap::NeuterUnencryptedPackets() {
- QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
+ absl::InlinedVector<QuicPacketNumber, 2> neutered_packets;
QuicPacketNumber packet_number = GetLeastUnacked();
for (QuicUnackedPacketMap::iterator it = begin(); it != end();
++it, ++packet_number) {
@@ -353,9 +354,9 @@ QuicUnackedPacketMap::NeuterUnencryptedPackets() {
return neutered_packets;
}
-QuicInlinedVector<QuicPacketNumber, 2>
+absl::InlinedVector<QuicPacketNumber, 2>
QuicUnackedPacketMap::NeuterHandshakePackets() {
- QuicInlinedVector<QuicPacketNumber, 2> neutered_packets;
+ absl::InlinedVector<QuicPacketNumber, 2> neutered_packets;
QuicPacketNumber packet_number = GetLeastUnacked();
for (QuicUnackedPacketMap::iterator it = begin(); it != end();
++it, ++packet_number) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
index 676f054b1fb..b8f8ffe9c87 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_unacked_packet_map.h
@@ -8,6 +8,7 @@
#include <cstddef>
#include <cstdint>
+#include "absl/container/inlined_vector.h"
#include "absl/strings/str_cat.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_transmission_info.h"
@@ -69,12 +70,12 @@ class QUIC_EXPORT_PRIVATE QuicUnackedPacketMap {
// Called to neuter all unencrypted packets to ensure they do not get
// retransmitted. Returns a vector of neutered packet numbers.
- QuicInlinedVector<QuicPacketNumber, 2> NeuterUnencryptedPackets();
+ absl::InlinedVector<QuicPacketNumber, 2> NeuterUnencryptedPackets();
// Called to neuter packets in handshake packet number space to ensure they do
// not get retransmitted. Returns a vector of neutered packet numbers.
// TODO(fayang): Consider to combine this with NeuterUnencryptedPackets.
- QuicInlinedVector<QuicPacketNumber, 2> NeuterHandshakePackets();
+ absl::InlinedVector<QuicPacketNumber, 2> NeuterHandshakePackets();
// Returns true if |packet_number| has retransmittable frames. This will
// return false if all frames of this packet are either non-retransmittable or
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc b/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
index 1f0137a91bc..98fbf55bdaa 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.cc
@@ -21,6 +21,7 @@
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
+#include "quic/platform/api/quic_mem_slice.h"
#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_prefetch.h"
#include "common/quiche_endian.h"
@@ -693,6 +694,32 @@ bool QuicUtils::IsProbingFrame(QuicFrameType type) {
}
}
+// static
+bool QuicUtils::IsAckElicitingFrame(QuicFrameType type) {
+ switch (type) {
+ case PADDING_FRAME:
+ case STOP_WAITING_FRAME:
+ case ACK_FRAME:
+ case CONNECTION_CLOSE_FRAME:
+ return false;
+ default:
+ return true;
+ }
+}
+
+// static
+bool QuicUtils::AreStatelessResetTokensEqual(
+ const StatelessResetToken& token1,
+ const StatelessResetToken& token2) {
+ char byte = 0;
+ for (size_t i = 0; i < kStatelessResetTokenLength; i++) {
+ // This avoids compiler optimizations that could make us stop comparing
+ // after we find a byte that doesn't match.
+ byte |= (token1[i] ^ token2[i]);
+ }
+ return byte == 0;
+}
+
bool IsValidWebTransportSessionId(WebTransportSessionId id,
ParsedQuicVersion version) {
QUICHE_DCHECK(version.UsesHttp3());
@@ -701,5 +728,13 @@ bool IsValidWebTransportSessionId(WebTransportSessionId id,
QuicUtils::IsClientInitiatedStreamId(version.transport_version, id);
}
+QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span) {
+ QuicByteCount total = 0;
+ for (const QuicMemSlice& slice : span) {
+ total += slice.length();
+ }
+ return total;
+}
+
#undef RETURN_STRING_LITERAL // undef for jumbo builds
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
index 0b089b4bad6..c335bc0e1c1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils.h
@@ -13,6 +13,7 @@
#include "absl/numeric/int128.h"
#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
#include "quic/core/crypto/quic_random.h"
#include "quic/core/frames/quic_frame.h"
#include "quic/core/quic_connection_id.h"
@@ -21,6 +22,7 @@
#include "quic/core/quic_versions.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_iovec.h"
+#include "quic/platform/api/quic_mem_slice.h"
#include "quic/platform/api/quic_socket_address.h"
namespace quic {
@@ -237,6 +239,14 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
// Return true if this frame is an IETF probing frame.
static bool IsProbingFrame(QuicFrameType type);
+
+ // Return true if the two stateless reset tokens are equal. Performs the
+ // comparison in constant time.
+ static bool AreStatelessResetTokensEqual(const StatelessResetToken& token1,
+ const StatelessResetToken& token2);
+
+ // Return ture if this frame is an ack-eliciting frame.
+ static bool IsAckElicitingFrame(QuicFrameType type);
};
// Returns true if the specific ID is a valid WebTransport session ID that our
@@ -244,6 +254,8 @@ class QUIC_EXPORT_PRIVATE QuicUtils {
bool IsValidWebTransportSessionId(WebTransportSessionId id,
ParsedQuicVersion transport_version);
+QuicByteCount MemSliceSpanTotalSize(absl::Span<QuicMemSlice> span);
+
template <typename Mask>
class QUIC_EXPORT_PRIVATE BitMask {
public:
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
index dc1165242f5..a02633046e5 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_utils_test.cc
@@ -320,6 +320,8 @@ TEST_F(QuicUtilsTest, StatelessResetToken) {
QuicUtils::GenerateStatelessResetToken(connection_id2);
EXPECT_EQ(token1a, token1b);
EXPECT_NE(token1a, token2);
+ EXPECT_TRUE(QuicUtils::AreStatelessResetTokensEqual(token1a, token1b));
+ EXPECT_FALSE(QuicUtils::AreStatelessResetTokensEqual(token1a, token2));
}
enum class TestEnumClassBit : uint8_t {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
index 1d4dcca70e4..911370f2618 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.cc
@@ -15,7 +15,7 @@ namespace quic {
QuicVersionManager::QuicVersionManager(
ParsedQuicVersionVector supported_versions)
- : enable_version_rfcv1_(GetQuicReloadableFlag(quic_enable_version_rfcv1)),
+ : disable_version_rfcv1_(GetQuicReloadableFlag(quic_disable_version_rfcv1)),
disable_version_draft_29_(
GetQuicReloadableFlag(quic_disable_version_draft_29)),
disable_version_t051_(GetQuicReloadableFlag(quic_disable_version_t051)),
@@ -49,8 +49,8 @@ const std::vector<std::string>& QuicVersionManager::GetSupportedAlpns() {
void QuicVersionManager::MaybeRefilterSupportedVersions() {
static_assert(SupportedVersions().size() == 6u,
"Supported versions out of sync");
- if (enable_version_rfcv1_ !=
- GetQuicReloadableFlag(quic_enable_version_rfcv1) ||
+ if (disable_version_rfcv1_ !=
+ GetQuicReloadableFlag(quic_disable_version_rfcv1) ||
disable_version_draft_29_ !=
GetQuicReloadableFlag(quic_disable_version_draft_29) ||
disable_version_t051_ !=
@@ -61,7 +61,7 @@ void QuicVersionManager::MaybeRefilterSupportedVersions() {
GetQuicReloadableFlag(quic_disable_version_q046) ||
disable_version_q043_ !=
GetQuicReloadableFlag(quic_disable_version_q043)) {
- enable_version_rfcv1_ = GetQuicReloadableFlag(quic_enable_version_rfcv1);
+ disable_version_rfcv1_ = GetQuicReloadableFlag(quic_disable_version_rfcv1);
disable_version_draft_29_ =
GetQuicReloadableFlag(quic_disable_version_draft_29);
disable_version_t051_ = GetQuicReloadableFlag(quic_disable_version_t051);
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
index f443395e295..da73f37b910 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_version_manager.h
@@ -50,8 +50,8 @@ class QUIC_EXPORT_PRIVATE QuicVersionManager {
private:
// Cached value of reloadable flags.
- // quic_enable_version_rfcv1 flag
- bool enable_version_rfcv1_;
+ // quic_disable_version_rfcv1 flag
+ bool disable_version_rfcv1_;
// quic_disable_version_draft_29 flag
bool disable_version_draft_29_;
// quic_disable_version_t051 flag
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
index ba2ec7ee29e..717932f5a6c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.cc
@@ -47,7 +47,7 @@ void SetVersionFlag(const ParsedQuicVersion& version, bool should_enable) {
const bool enable = should_enable;
const bool disable = !should_enable;
if (version == ParsedQuicVersion::RFCv1()) {
- SetQuicReloadableFlag(quic_enable_version_rfcv1, enable);
+ SetQuicReloadableFlag(quic_disable_version_rfcv1, disable);
} else if (version == ParsedQuicVersion::Draft29()) {
SetQuicReloadableFlag(quic_disable_version_draft_29, disable);
} else if (version == ParsedQuicVersion::T051()) {
@@ -297,6 +297,18 @@ ParsedQuicVersionVector CurrentSupportedVersionsWithTls() {
return versions;
}
+ParsedQuicVersionVector CurrentSupportedHttp3Versions() {
+ ParsedQuicVersionVector versions;
+ for (const ParsedQuicVersion& version : CurrentSupportedVersions()) {
+ if (version.UsesHttp3()) {
+ versions.push_back(version);
+ }
+ }
+ QUIC_BUG_IF(no_version_uses_http3, versions.empty())
+ << "No version speaking Http3 found.";
+ return versions;
+}
+
ParsedQuicVersion ParseQuicVersionLabel(QuicVersionLabel version_label) {
for (const ParsedQuicVersion& version : AllSupportedVersions()) {
if (version_label == CreateQuicVersionLabel(version)) {
@@ -395,7 +407,7 @@ ParsedQuicVersionVector FilterSupportedVersions(
filtered_versions.reserve(versions.size());
for (const ParsedQuicVersion& version : versions) {
if (version == ParsedQuicVersion::RFCv1()) {
- if (GetQuicReloadableFlag(quic_enable_version_rfcv1)) {
+ if (!GetQuicReloadableFlag(quic_disable_version_rfcv1)) {
filtered_versions.push_back(version);
}
} else if (version == ParsedQuicVersion::Draft29()) {
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
index 75a6826ae81..52e829c2275 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions.h
@@ -446,6 +446,10 @@ QUIC_EXPORT_PRIVATE ParsedQuicVersionVector AllSupportedVersionsWithTls();
// PROTOCOL_TLS1_3.
QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedVersionsWithTls();
+// Returns a subset of CurrentSupportedVersions() using HTTP/3 at the HTTP
+// layer.
+QUIC_EXPORT_PRIVATE ParsedQuicVersionVector CurrentSupportedHttp3Versions();
+
// Returns QUIC version of |index| in result of |versions|. Returns
// UnsupportedQuicVersion() if |index| is out of bounds.
QUIC_EXPORT_PRIVATE ParsedQuicVersionVector
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
index c9bc8b311ed..31e365e10c1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_versions_test.cc
@@ -445,6 +445,25 @@ TEST_F(QuicVersionsTest, SupportedVersionsAllDistinct) {
}
}
+TEST_F(QuicVersionsTest, CurrentSupportedHttp3Versions) {
+ ParsedQuicVersionVector h3_versions = CurrentSupportedHttp3Versions();
+ ParsedQuicVersionVector all_current_supported_versions =
+ CurrentSupportedVersions();
+ for (auto& version : all_current_supported_versions) {
+ bool version_is_h3 = false;
+ for (auto& h3_version : h3_versions) {
+ if (version == h3_version) {
+ EXPECT_TRUE(version.UsesHttp3());
+ version_is_h3 = true;
+ break;
+ }
+ }
+ if (!version_is_h3) {
+ EXPECT_FALSE(version.UsesHttp3());
+ }
+ }
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
index dbc2ca9173d..54441e778f1 100644
--- a/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
+++ b/chromium/net/third_party/quiche/src/quic/core/quic_write_blocked_list.h
@@ -9,13 +9,13 @@
#include <cstdint>
#include <utility>
+#include "absl/container/inlined_vector.h"
#include "http2/core/priority_write_scheduler.h"
#include "quic/core/quic_packets.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_export.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -102,7 +102,7 @@ class QUIC_EXPORT_PRIVATE QuicWriteBlockedList {
};
// Optimized for the typical case of 2 static streams per session.
- using StreamsVector = QuicInlinedVector<StreamIdBlockedPair, 2>;
+ using StreamsVector = absl::InlinedVector<StreamIdBlockedPair, 2>;
StreamsVector::const_iterator begin() const { return streams_.cbegin(); }
diff --git a/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h b/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h
index 38b8e5326e7..02b195ef0c4 100644
--- a/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h
+++ b/chromium/net/third_party/quiche/src/quic/core/stream_delegate_interface.h
@@ -28,18 +28,13 @@ class QUIC_EXPORT_PRIVATE StreamDelegateInterface {
virtual void OnStreamError(QuicErrorCode error_code,
QuicIetfTransportErrorCodes ietf_error,
std::string error_details) = 0;
- // Called when the stream needs to write data. If |level| is present, the data
- // will be written at the specified |level|. The data will be written
- // at specified transmission |type|.
- // TODO(fayang): Change absl::optional<EncryptionLevel> to EncryptionLevel
- // when deprecating quic_use_write_or_buffer_data_at_level.
- virtual QuicConsumedData WritevData(
- QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType type,
- absl::optional<EncryptionLevel> level) = 0;
+ // Called when the stream needs to write data at specified |level| and
+ // transmission |type|.
+ virtual QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset,
+ StreamSendingState state,
+ TransmissionType type,
+ EncryptionLevel level) = 0;
// Called to write crypto data.
virtual size_t SendCryptoData(EncryptionLevel level,
size_t write_length,
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
index 1b9de030860..737f449c59f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker.cc
@@ -41,12 +41,16 @@ TlsClientHandshaker::TlsClientHandshaker(
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
has_application_state_(has_application_state),
crypto_config_(crypto_config),
- tls_connection_(crypto_config->ssl_ctx(), this) {
+ tls_connection_(crypto_config->ssl_ctx(), this, session->GetSSLConfig()) {
std::string token =
crypto_config->LookupOrCreate(server_id)->source_address_token();
if (!token.empty()) {
session->SetSourceAddressTokenToSend(token);
}
+ if (crypto_config->tls_signature_algorithms().has_value()) {
+ SSL_set1_sigalgs_list(ssl(),
+ crypto_config->tls_signature_algorithms()->c_str());
+ }
}
TlsClientHandshaker::~TlsClientHandshaker() {}
@@ -68,6 +72,16 @@ bool TlsClientHandshaker::CryptoConnect() {
}
SSL_set_quic_use_legacy_codepoint(ssl(), use_legacy_extension);
+ // TODO(b/193650832) Add SetFromConfig to QUIC handshakers and remove reliance
+ // on session pointer.
+ if (session()->permutes_tls_extensions()) {
+ // Ask BoringSSL to randomize the order of TLS extensions.
+#if BORINGSSL_API_VERSION >= 16
+ QUIC_DLOG(INFO) << "Enabling TLS extension permutation";
+ SSL_set_permute_extensions(ssl(), true);
+#endif // BORINGSSL_API_VERSION
+ }
+
// Set the SNI to send, if any.
SSL_set_connect_state(ssl());
if (QUIC_DLOG_INFO_IS_ON() &&
@@ -444,22 +458,8 @@ void TlsClientHandshaker::OnProofVerifyDetailsAvailable(
void TlsClientHandshaker::FinishHandshake() {
FillNegotiatedParams();
- if (retry_handshake_on_early_data_) {
- QUICHE_CHECK(!SSL_in_early_data(ssl()));
- } else {
- if (SSL_in_early_data(ssl())) {
- // SSL_do_handshake returns after sending the ClientHello if the session
- // is 0-RTT-capable, which means that FinishHandshake will get called
- // twice - the first time after sending the ClientHello, and the second
- // time after the handshake is complete. If we're in the first time
- // FinishHandshake is called, we can't do any end-of-handshake processing.
-
- // If we're attempting a 0-RTT handshake, then we need to let the
- // transport and application know what state to apply to early data.
- PrepareZeroRttConfig(cached_state_.get());
- return;
- }
- }
+ QUICHE_CHECK(!SSL_in_early_data(ssl()));
+
QUIC_LOG(INFO) << "Client: handshake finished";
std::string error_details;
@@ -518,7 +518,6 @@ void TlsClientHandshaker::FinishHandshake() {
}
void TlsClientHandshaker::OnEnterEarlyData() {
- QUICHE_DCHECK(retry_handshake_on_early_data_);
QUICHE_DCHECK(SSL_in_early_data(ssl()));
// TODO(wub): It might be unnecessary to FillNegotiatedParams() at this time,
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
index 8365f633f0f..4bbb4ed6d0f 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_client_handshaker_test.cc
@@ -458,13 +458,6 @@ TEST_P(TlsClientHandshakerTest, ZeroRttResumptionWithAyncProofVerifier) {
proof_verifier->InvokePendingCallback(0);
QuicFramer* framer = QuicConnectionPeer::GetFramer(connection_);
- if (!GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data)) {
- // Client does not have HANDSHAKE key due to b/186438140.
- EXPECT_EQ(nullptr,
- QuicFramerPeer::GetEncrypter(framer, ENCRYPTION_HANDSHAKE));
- return;
- }
-
// Verify client has derived HANDSHAKE key.
EXPECT_NE(nullptr,
QuicFramerPeer::GetEncrypter(framer, ENCRYPTION_HANDSHAKE));
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
index 9ba5f3c12f6..4b2d717befc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.cc
@@ -96,12 +96,10 @@ void TlsHandshaker::AdvanceHandshake() {
return;
}
- QUICHE_BUG_IF(quic_tls_server_async_done_no_flusher,
- SSL_is_server(ssl()) && add_packet_flusher_on_async_op_done_ &&
- !handshaker_delegate_->PacketFlusherAttached())
- << "is_server:" << SSL_is_server(ssl())
- << ", add_packet_flusher_on_async_op_done_:"
- << add_packet_flusher_on_async_op_done_;
+ QUICHE_BUG_IF(
+ quic_tls_server_async_done_no_flusher,
+ SSL_is_server(ssl()) && !handshaker_delegate_->PacketFlusherAttached())
+ << "is_server:" << SSL_is_server(ssl());
QUIC_VLOG(1) << ENDPOINT << "Continuing handshake";
int rv = SSL_do_handshake(ssl());
@@ -111,8 +109,7 @@ void TlsHandshaker::AdvanceHandshake() {
// processed. Retry SSL_do_handshake once will advance the handshake more in
// that case. If there are no unprocessed ServerHello, the retry will return a
// non-positive number.
- if (retry_handshake_on_early_data_ && rv == 1 && SSL_in_early_data(ssl())) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_retry_handshake_on_early_data, 1, 2);
+ if (rv == 1 && SSL_in_early_data(ssl())) {
OnEnterEarlyData();
rv = SSL_do_handshake(ssl());
QUIC_VLOG(1) << ENDPOINT
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
index 0b5ddc36769..72ae0993983 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_handshaker.h
@@ -57,7 +57,7 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
protected:
// Called when a new message is received on the crypto stream and is available
// for the TLS stack to read.
- void AdvanceHandshake();
+ virtual void AdvanceHandshake();
void CloseConnection(QuicErrorCode error, const std::string& reason_phrase);
// Closes the connection, specifying the wire error code |ietf_error|
@@ -71,12 +71,8 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
bool is_connection_closed() const { return is_connection_closed_; }
// Called when |SSL_do_handshake| returns 1, indicating that the handshake has
- // finished. Note that due to 0-RTT, the handshake may "finish" twice;
- // |SSL_in_early_data| can be used to determine whether the handshake is truly
- // done.
- // TODO(wub): When --quic_tls_retry_handshake_on_early_data is true, this
- // function will only be called once when the handshake actually finishes.
- // Update comment when deprecating the flag.
+ // finished. Note that a handshake only finishes once, entering early data
+ // does not count.
virtual void FinishHandshake() = 0;
// Called when |SSL_do_handshake| returns 1 and the connection is in early
@@ -84,7 +80,6 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// retry |SSL_do_handshake| once.
virtual void OnEnterEarlyData() {
// By default, do nothing but check the preconditions.
- QUICHE_DCHECK(retry_handshake_on_early_data_);
QUICHE_DCHECK(SSL_in_early_data(ssl()));
}
@@ -168,11 +163,10 @@ class QUIC_EXPORT_PRIVATE TlsHandshaker : public TlsConnection::Delegate,
// error code corresponding to the TLS alert description |desc|.
void SendAlert(EncryptionLevel level, uint8_t desc) override;
- const bool add_packet_flusher_on_async_op_done_ =
- GetQuicReloadableFlag(quic_add_packet_flusher_on_async_op_done);
-
- const bool retry_handshake_on_early_data_ =
- GetQuicReloadableFlag(quic_tls_retry_handshake_on_early_data);
+ // Informational callback from BoringSSL. Subclasses can override it to do
+ // logging, tracing, etc.
+ // See |SSL_CTX_set_info_callback| for the meaning of |type| and |value|.
+ void InfoCallback(int /*type*/, int /*value*/) override {}
private:
// ProofVerifierCallbackImpl handles the result of an asynchronous certificate
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
index efd4d275013..b2817b15b22 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.cc
@@ -34,17 +34,24 @@
namespace quic {
+namespace {
+
+// Default port for HTTP/3.
+uint16_t kDefaultPort = 443;
+
+} // namespace
+
TlsServerHandshaker::DefaultProofSourceHandle::DefaultProofSourceHandle(
TlsServerHandshaker* handshaker,
ProofSource* proof_source)
: handshaker_(handshaker), proof_source_(proof_source) {}
TlsServerHandshaker::DefaultProofSourceHandle::~DefaultProofSourceHandle() {
- CancelPendingOperation();
+ CloseHandle();
}
-void TlsServerHandshaker::DefaultProofSourceHandle::CancelPendingOperation() {
- QUIC_DVLOG(1) << "CancelPendingOperation. is_signature_pending="
+void TlsServerHandshaker::DefaultProofSourceHandle::CloseHandle() {
+ QUIC_DVLOG(1) << "CloseHandle. is_signature_pending="
<< (signature_callback_ != nullptr);
if (signature_callback_) {
signature_callback_->Cancel();
@@ -62,7 +69,8 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
const std::string& /*alpn*/,
absl::optional<std::string> /*alps*/,
const std::vector<uint8_t>& /*quic_transport_params*/,
- const absl::optional<std::vector<uint8_t>>& /*early_data_context*/) {
+ const absl::optional<std::vector<uint8_t>>& /*early_data_context*/,
+ const QuicSSLConfig& /*ssl_config*/) {
if (!handshaker_ || !proof_source_) {
QUIC_BUG(quic_bug_10341_1)
<< "SelectCertificate called on a detached handle";
@@ -74,7 +82,8 @@ TlsServerHandshaker::DefaultProofSourceHandle::SelectCertificate(
handshaker_->OnSelectCertificateDone(
/*ok=*/true, /*is_sync=*/true, chain.get(),
- /*handshake_hints=*/absl::string_view());
+ /*handshake_hints=*/absl::string_view(),
+ /*ticket_encryption_key=*/absl::string_view());
if (!handshaker_->select_cert_status().has_value()) {
QUIC_BUG(quic_bug_12423_1)
<< "select_cert_status() has no value after a synchronous select cert";
@@ -164,7 +173,7 @@ TlsServerHandshaker::TlsServerHandshaker(
proof_source_(crypto_config->proof_source()),
pre_shared_key_(crypto_config->pre_shared_key()),
crypto_negotiated_params_(new QuicCryptoNegotiatedParameters),
- tls_connection_(crypto_config->ssl_ctx(), this),
+ tls_connection_(crypto_config->ssl_ctx(), this, session->GetSSLConfig()),
crypto_config_(crypto_config) {
QUICHE_DCHECK_EQ(PROTOCOL_TLS1_3,
session->connection()->version().handshake_protocol);
@@ -182,15 +191,19 @@ TlsServerHandshaker::TlsServerHandshaker(
if (GetQuicFlag(FLAGS_quic_disable_server_tls_resumption)) {
SSL_set_options(ssl(), SSL_OP_NO_TICKET);
}
-}
-TlsServerHandshaker::~TlsServerHandshaker() {
- CancelOutstandingCallbacks();
+ if (GetQuicReloadableFlag(quic_trace_ssl_events) &&
+ session->connection()->context()->tracer) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_trace_ssl_events);
+ tls_connection_.EnableInfoCallback();
+ }
}
+TlsServerHandshaker::~TlsServerHandshaker() { CancelOutstandingCallbacks(); }
+
void TlsServerHandshaker::CancelOutstandingCallbacks() {
if (proof_source_handle_) {
- proof_source_handle_->CancelPendingOperation();
+ proof_source_handle_->CloseHandle();
}
if (ticket_decryption_callback_) {
ticket_decryption_callback_->Cancel();
@@ -198,6 +211,40 @@ void TlsServerHandshaker::CancelOutstandingCallbacks() {
}
}
+void TlsServerHandshaker::InfoCallback(int type, int value) {
+ QuicConnectionTracer* tracer =
+ session()->connection()->context()->tracer.get();
+
+ if (tracer == nullptr) {
+ return;
+ }
+
+ if (type & SSL_CB_LOOP) {
+ tracer->PrintString(
+ absl::StrCat("SSL:ACCEPT_LOOP:", SSL_state_string_long(ssl())));
+ } else if (type & SSL_CB_ALERT) {
+ const char* prefix =
+ (type & SSL_CB_READ) ? "SSL:READ_ALERT:" : "SSL:WRITE_ALERT:";
+ tracer->PrintString(absl::StrCat(prefix, SSL_alert_type_string_long(value),
+ ":", SSL_alert_desc_string_long(value)));
+ } else if (type & SSL_CB_EXIT) {
+ const char* prefix =
+ (value == 1) ? "SSL:ACCEPT_EXIT_OK:" : "SSL:ACCEPT_EXIT_FAIL:";
+ tracer->PrintString(absl::StrCat(prefix, SSL_state_string_long(ssl())));
+ } else if (type & SSL_CB_HANDSHAKE_START) {
+ tracer->PrintString(
+ absl::StrCat("SSL:HANDSHAKE_START:", SSL_state_string_long(ssl())));
+ } else if (type & SSL_CB_HANDSHAKE_DONE) {
+ tracer->PrintString(
+ absl::StrCat("SSL:HANDSHAKE_DONE:", SSL_state_string_long(ssl())));
+ } else {
+ QUIC_DLOG(INFO) << "Unknown event type " << type << ": "
+ << SSL_state_string_long(ssl());
+ tracer->PrintString(
+ absl::StrCat("SSL:unknown:", value, ":", SSL_state_string_long(ssl())));
+ }
+}
+
std::unique_ptr<ProofSourceHandle>
TlsServerHandshaker::MaybeCreateProofSourceHandle() {
return std::make_unique<DefaultProofSourceHandle>(this, proof_source_);
@@ -351,18 +398,7 @@ TlsServerHandshaker::CreateCurrentOneRttEncrypter() {
void TlsServerHandshaker::OverrideQuicConfigDefaults(QuicConfig* /*config*/) {}
void TlsServerHandshaker::AdvanceHandshakeFromCallback() {
- std::unique_ptr<QuicConnection::ScopedPacketFlusher> flusher;
- if (add_packet_flusher_on_async_op_done_) {
- if (session()->PacketFlusherAttached()) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 1,
- 2);
- } else {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_add_packet_flusher_on_async_op_done, 2,
- 2);
- }
- flusher = std::make_unique<QuicConnection::ScopedPacketFlusher>(
- session()->connection());
- }
+ QuicConnection::ScopedPacketFlusher flusher(session()->connection());
AdvanceHandshake();
if (!is_connection_closed()) {
@@ -514,27 +550,14 @@ void TlsServerHandshaker::SetWriteSecret(
TlsHandshaker::SetWriteSecret(level, cipher, write_secret);
}
-std::string TlsServerHandshaker::GetAcceptChValueForOrigin(
- const std::string& /*origin*/) const {
+std::string TlsServerHandshaker::GetAcceptChValueForHostname(
+ const std::string& /*hostname*/) const {
return {};
}
void TlsServerHandshaker::FinishHandshake() {
- if (retry_handshake_on_early_data_) {
- QUIC_RELOADABLE_FLAG_COUNT_N(quic_tls_retry_handshake_on_early_data, 2, 2);
- QUICHE_DCHECK(!SSL_in_early_data(ssl()));
- } else {
- if (SSL_in_early_data(ssl())) {
- // If the server accepts early data, SSL_do_handshake returns success
- // twice: once after processing the ClientHello and sending the server's
- // first flight, and then again after the handshake is complete. This
- // results in FinishHandshake getting called twice. On the first call to
- // FinishHandshake, we don't have any confirmation that the client is
- // live, so all end of handshake processing is deferred until the
- // handshake is actually complete.
- return;
- }
- }
+ QUICHE_DCHECK(!SSL_in_early_data(ssl()));
+
if (!valid_alpn_received_) {
QUIC_DLOG(ERROR)
<< "Server: handshake finished without receiving a known ALPN";
@@ -668,7 +691,8 @@ int TlsServerHandshaker::SessionTicketSeal(uint8_t* out,
size_t max_out_len,
absl::string_view in) {
QUICHE_DCHECK(proof_source_->GetTicketCrypter());
- std::vector<uint8_t> ticket = proof_source_->GetTicketCrypter()->Encrypt(in);
+ std::vector<uint8_t> ticket =
+ proof_source_->GetTicketCrypter()->Encrypt(in, ticket_encryption_key_);
if (max_out_len < ticket.size()) {
QUIC_BUG(quic_bug_12423_2)
<< "TicketCrypter returned " << ticket.size()
@@ -689,8 +713,18 @@ ssl_ticket_aead_result_t TlsServerHandshaker::SessionTicketOpen(
absl::string_view in) {
QUICHE_DCHECK(proof_source_->GetTicketCrypter());
+ if (allow_ignore_ticket_open_ && ignore_ticket_open_) {
+ // SetIgnoreTicketOpen has been called. Typically this means the caller is
+ // using handshake hints and expect the hints to contain ticket decryption
+ // results.
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_ignored_1);
+ return ssl_ticket_aead_ignore_ticket;
+ }
+
if (!ticket_decryption_callback_) {
- ticket_received_ = true;
+ if (!allow_ignore_ticket_open_) {
+ ticket_received_ = true;
+ }
ticket_decryption_callback_ = new DecryptCallback(this);
proof_source_->GetTicketCrypter()->Decrypt(
in, std::unique_ptr<DecryptCallback>(ticket_decryption_callback_));
@@ -742,7 +776,7 @@ ssl_ticket_aead_result_t TlsServerHandshaker::FinalizeSessionTicketOpen(
if (decrypted_session_ticket_.empty()) {
QUIC_DLOG(ERROR) << "Session ticket decryption failed; ignoring ticket";
// Ticket decryption failed. Ignore the ticket.
- QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_ignored);
+ QUIC_CODE_COUNT(quic_tls_server_handshaker_tickets_ignored_2);
return ssl_ticket_aead_ignore_ticket;
}
if (max_out_len < decrypted_session_ticket_.size()) {
@@ -783,6 +817,15 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
return ssl_select_cert_error;
}
+ if (allow_ignore_ticket_open_) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_tls_allow_ignore_ticket_open);
+ const uint8_t* unused_extension_bytes;
+ size_t unused_extension_len;
+ ticket_received_ = SSL_early_callback_ctx_extension_get(
+ client_hello, TLSEXT_TYPE_pre_shared_key, &unused_extension_bytes,
+ &unused_extension_len);
+ }
+
// This callback is called very early by Boring SSL, most of the SSL_get_foo
// function do not work at this point, but SSL_get_servername does.
const char* hostname = SSL_get_servername(ssl(), TLSEXT_NAMETYPE_host_name);
@@ -824,37 +867,36 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
absl::string_view ssl_capabilities_view;
absl::optional<std::string> alps;
- if (use_handshake_hints_) {
- QUIC_RELOADABLE_FLAG_COUNT(quic_tls_server_use_handshake_hints);
- if (CryptoUtils::GetSSLCapabilities(ssl(), &ssl_capabilities,
- &ssl_capabilities_len)) {
- ssl_capabilities_view = absl::string_view(
- reinterpret_cast<const char*>(ssl_capabilities.get()),
- ssl_capabilities_len);
- }
- // Enable ALPS for the session's ALPN.
- SetApplicationSettingsResult alps_result =
- SetApplicationSettings(AlpnForVersion(session()->version()));
- if (!alps_result.success) {
- return ssl_select_cert_error;
- }
- alps = alps_result.alps_length > 0
- ? std::string(alps_result.alps_buffer.get(),
- alps_result.alps_length)
- : std::string();
+ if (CryptoUtils::GetSSLCapabilities(ssl(), &ssl_capabilities,
+ &ssl_capabilities_len)) {
+ ssl_capabilities_view =
+ absl::string_view(reinterpret_cast<const char*>(ssl_capabilities.get()),
+ ssl_capabilities_len);
+ }
+
+ // Enable ALPS for the session's ALPN.
+ SetApplicationSettingsResult alps_result =
+ SetApplicationSettings(AlpnForVersion(session()->version()));
+ if (!alps_result.success) {
+ return ssl_select_cert_error;
}
+ alps =
+ alps_result.alps_length > 0
+ ? std::string(alps_result.alps_buffer.get(), alps_result.alps_length)
+ : std::string();
const QuicAsyncStatus status = proof_source_handle_->SelectCertificate(
- session()->connection()->self_address(),
- session()->connection()->peer_address(), ssl_capabilities_view,
- crypto_negotiated_params_->sni,
+ session()->connection()->self_address().Normalized(),
+ session()->connection()->peer_address().Normalized(),
+ ssl_capabilities_view, crypto_negotiated_params_->sni,
absl::string_view(
reinterpret_cast<const char*>(client_hello->client_hello),
client_hello->client_hello_len),
AlpnForVersion(session()->version()), std::move(alps),
set_transport_params_result.quic_transport_params,
- set_transport_params_result.early_data_context);
+ set_transport_params_result.early_data_context,
+ tls_connection_.ssl_config());
QUICHE_DCHECK_EQ(status, select_cert_status().value());
@@ -876,28 +918,28 @@ ssl_select_cert_result_t TlsServerHandshaker::EarlySelectCertCallback(
}
void TlsServerHandshaker::OnSelectCertificateDone(
- bool ok,
- bool is_sync,
- const ProofSource::Chain* chain,
- absl::string_view handshake_hints) {
+ bool ok, bool is_sync, const ProofSource::Chain* chain,
+ absl::string_view handshake_hints,
+ absl::string_view ticket_encryption_key) {
QUIC_DVLOG(1) << "OnSelectCertificateDone. ok:" << ok
<< ", is_sync:" << is_sync
- << ", len(handshake_hints):" << handshake_hints.size();
+ << ", len(handshake_hints):" << handshake_hints.size()
+ << ", len(ticket_encryption_key):"
+ << ticket_encryption_key.size();
+ ticket_encryption_key_ = std::string(ticket_encryption_key);
select_cert_status_ = QUIC_FAILURE;
if (ok) {
if (chain && !chain->certs.empty()) {
tls_connection_.SetCertChain(chain->ToCryptoBuffers().value);
- if (use_handshake_hints_) {
- if (!handshake_hints.empty() &&
- !SSL_set_handshake_hints(
- ssl(), reinterpret_cast<const uint8_t*>(handshake_hints.data()),
- handshake_hints.size())) {
- // If |SSL_set_handshake_hints| fails, the ssl() object will remain
- // intact, it is as if we didn't call it. The handshaker will
- // continue to compute signature/decrypt ticket as normal.
- QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed);
- QUIC_DVLOG(1) << "SSL_set_handshake_hints failed";
- }
+ if (!handshake_hints.empty() &&
+ !SSL_set_handshake_hints(
+ ssl(), reinterpret_cast<const uint8_t*>(handshake_hints.data()),
+ handshake_hints.size())) {
+ // If |SSL_set_handshake_hints| fails, the ssl() object will remain
+ // intact, it is as if we didn't call it. The handshaker will
+ // continue to compute signature/decrypt ticket as normal.
+ QUIC_CODE_COUNT(quic_tls_server_set_handshake_hints_failed);
+ QUIC_DVLOG(1) << "SSL_set_handshake_hints failed";
}
select_cert_status_ = QUIC_SUCCESS;
} else {
@@ -929,6 +971,10 @@ void TlsServerHandshaker::OnSelectCertificateDone(
}
}
+bool TlsServerHandshaker::WillNotCallComputeSignature() const {
+ return SSL_can_release_private_key(ssl());
+}
+
bool TlsServerHandshaker::ValidateHostname(const std::string& hostname) const {
if (!QuicHostnameUtils::IsValidSNI(hostname)) {
// TODO(b/151676147): Include this error string in the CONNECTION_CLOSE
@@ -986,13 +1032,6 @@ int TlsServerHandshaker::SelectAlpn(const uint8_t** out,
return SSL_TLSEXT_ERR_NOACK;
}
- if (!use_handshake_hints_) {
- // Enable ALPS for the selected ALPN protocol.
- if (!SetApplicationSettings(*selected_alpn).success) {
- return SSL_TLSEXT_ERR_NOACK;
- }
- }
-
session()->OnAlpnSelected(*selected_alpn);
valid_alpn_received_ = true;
*out_len = selected_alpn->size();
@@ -1006,8 +1045,17 @@ TlsServerHandshaker::SetApplicationSettings(absl::string_view alpn) {
const uint8_t* alps_data = nullptr;
const std::string& hostname = crypto_negotiated_params_->sni;
- std::string accept_ch_value = GetAcceptChValueForOrigin(hostname);
+ std::string accept_ch_value = GetAcceptChValueForHostname(hostname);
std::string origin = absl::StrCat("https://", hostname);
+ if (GetQuicReloadableFlag(quic_include_port_in_alps_origin)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_include_port_in_alps_origin);
+ uint16_t port = session()->self_address().port();
+ if (port != kDefaultPort) {
+ // This should be rare in production, but useful for test servers.
+ QUIC_CODE_COUNT(quic_server_alps_non_default_port);
+ absl::StrAppend(&origin, ":", port);
+ }
+ }
if (!accept_ch_value.empty()) {
AcceptChFrame frame{{{std::move(origin), std::move(accept_ch_value)}}};
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
index 260b094bda7..998cc15ad7c 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker.h
@@ -19,6 +19,7 @@
#include "quic/core/quic_types.h"
#include "quic/core/tls_handshaker.h"
#include "quic/platform/api/quic_export.h"
+#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
namespace quic {
@@ -82,12 +83,15 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
const SSL_CIPHER* cipher,
const std::vector<uint8_t>& write_secret) override;
- // Called with normalized SNI hostname as |origin|. Return value will be sent
- // in an ACCEPT_CH frame in the TLS ALPS extension, unless empty.
- virtual std::string GetAcceptChValueForOrigin(
- const std::string& origin) const;
+ // Called with normalized SNI hostname as |hostname|. Return value will be
+ // sent in an ACCEPT_CH frame in the TLS ALPS extension, unless empty.
+ virtual std::string GetAcceptChValueForHostname(
+ const std::string& hostname) const;
protected:
+ // Override for tracing.
+ void InfoCallback(int type, int value) override;
+
// Creates a proof source handle for selecting cert and computing signature.
virtual std::unique_ptr<ProofSourceHandle> MaybeCreateProofSourceHandle();
@@ -165,10 +169,10 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
bool HasValidSignature(size_t max_signature_size) const;
// ProofSourceHandleCallback implementation:
- void OnSelectCertificateDone(bool ok,
- bool is_sync,
- const ProofSource::Chain* chain,
- absl::string_view handshake_hints) override;
+ void OnSelectCertificateDone(
+ bool ok, bool is_sync, const ProofSource::Chain* chain,
+ absl::string_view handshake_hints,
+ absl::string_view ticket_encryption_key) override;
void OnComputeSignatureDone(
bool ok,
@@ -176,6 +180,17 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
std::string signature,
std::unique_ptr<ProofSource::Details> details) override;
+ void set_encryption_established(bool encryption_established) {
+ encryption_established_ = encryption_established;
+ }
+
+ bool WillNotCallComputeSignature() const override;
+
+ void SetIgnoreTicketOpen(bool value) { ignore_ticket_open_ = value; }
+
+ const bool allow_ignore_ticket_open_ =
+ GetQuicReloadableFlag(quic_tls_allow_ignore_ticket_open);
+
private:
class QUIC_EXPORT_PRIVATE DecryptCallback
: public ProofSource::DecryptCallback {
@@ -200,8 +215,8 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
~DefaultProofSourceHandle() override;
- // Cancel the pending signature operation, if any.
- void CancelPendingOperation() override;
+ // Close the handle. Cancel the pending signature operation, if any.
+ void CloseHandle() override;
// Delegates to proof_source_->GetCertChain.
// Returns QUIC_SUCCESS or QUIC_FAILURE. Never returns QUIC_PENDING.
@@ -214,8 +229,8 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
const std::string& alpn,
absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
- const absl::optional<std::vector<uint8_t>>& early_data_context)
- override;
+ const absl::optional<std::vector<uint8_t>>& early_data_context,
+ const QuicSSLConfig& ssl_config) override;
// Delegates to proof_source_->ComputeTlsSignature.
// Returns QUIC_SUCCESS, QUIC_FAILURE or QUIC_PENDING.
@@ -243,6 +258,20 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
// Operation has been canceled, or Run has been called.
return;
}
+
+ if (GetQuicReloadableFlag(quic_run_default_signature_callback_once)) {
+ QUIC_RELOADABLE_FLAG_COUNT(quic_run_default_signature_callback_once);
+ DefaultProofSourceHandle* handle = handle_;
+ handle_ = nullptr;
+
+ handle->signature_callback_ = nullptr;
+ if (handle->handshaker_ != nullptr) {
+ handle->handshaker_->OnComputeSignatureDone(
+ ok, is_sync_, std::move(signature), std::move(details));
+ }
+ return;
+ }
+
handle_->signature_callback_ = nullptr;
if (handle_->handshaker_ != nullptr) {
handle_->handshaker_->OnComputeSignatureDone(
@@ -309,6 +338,9 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
// indicates that the client attempted a resumption.
bool ticket_received_ = false;
+ // Force SessionTicketOpen to return ssl_ticket_aead_ignore_ticket if called.
+ bool ignore_ticket_open_ = false;
+
// nullopt means select cert hasn't started.
absl::optional<QuicAsyncStatus> select_cert_status_;
@@ -323,6 +355,9 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
// Pre-shared key used during the handshake.
std::string pre_shared_key_;
+ // (optional) Key to use for encrypting TLS resumption tickets.
+ std::string ticket_encryption_key_;
+
HandshakeState state_ = HANDSHAKE_START;
bool encryption_established_ = false;
bool valid_alpn_received_ = false;
@@ -330,8 +365,6 @@ class QUIC_EXPORT_PRIVATE TlsServerHandshaker
crypto_negotiated_params_;
TlsServerConnection tls_connection_;
const QuicCryptoServerConfig* crypto_config_; // Unowned.
- const bool use_handshake_hints_ =
- GetQuicReloadableFlag(quic_tls_server_use_handshake_hints);
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
index d67c8791d2c..6f8db123c99 100644
--- a/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/tls_server_handshaker_test.cc
@@ -561,6 +561,23 @@ TEST_P(TlsServerHandshakerTest, HostnameForCertSelectionAndComputeSignature) {
EXPECT_EQ(last_compute_signature_args().hostname, "test.example.com");
}
+TEST_P(TlsServerHandshakerTest, SSLConfigForCertSelection) {
+ InitializeServerWithFakeProofSourceHandle();
+
+ // Disable early data.
+ server_session_->ssl_config()->early_data_enabled = false;
+
+ server_handshaker_->SetupProofSourceHandle(
+ /*select_cert_action=*/FakeProofSourceHandle::Action::DELEGATE_SYNC,
+ /*compute_signature_action=*/FakeProofSourceHandle::Action::
+ DELEGATE_SYNC);
+ InitializeFakeClient();
+ CompleteCryptoHandshake();
+ ExpectHandshakeSuccessful();
+
+ EXPECT_FALSE(last_select_cert_args().ssl_config.early_data_enabled);
+}
+
TEST_P(TlsServerHandshakerTest, ConnectionClosedOnTlsError) {
EXPECT_CALL(*server_connection_,
CloseConnection(QUIC_HANDSHAKE_FAILED, _, _, _));
diff --git a/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc
index 78227049dbd..2470aacf4cc 100644
--- a/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc
+++ b/chromium/net/third_party/quiche/src/quic/core/web_transport_stream_adapter.cc
@@ -42,11 +42,8 @@ bool WebTransportStreamAdapter::Write(absl::string_view data) {
return false;
}
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
- session_->connection()->helper()->GetStreamSendBufferAllocator(),
- data.size());
- memcpy(buffer.get(), data.data(), data.size());
- QuicMemSlice memslice(std::move(buffer), data.size());
+ QuicMemSlice memslice(QuicBuffer::Copy(
+ session_->connection()->helper()->GetStreamSendBufferAllocator(), data));
QuicConsumedData consumed =
stream_->WriteMemSlices(QuicMemSliceSpan(&memslice), /*fin=*/false);
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc
index 920372574a1..bb9964e4207 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_bin.cc
@@ -50,8 +50,6 @@ int RunMasqueClient(int argc, char* argv[]) {
return 1;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
-
const bool disable_certificate_verification =
GetQuicFlag(FLAGS_disable_certificate_verification);
QuicEpollServer epoll_server;
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc
index 6eee553e076..0d865692e46 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.cc
@@ -92,11 +92,8 @@ MasqueClientSession::GetOrCreateConnectUdpClientState(
return nullptr;
}
- QuicDatagramFlowId flow_id = GetNextDatagramFlowId();
-
QUIC_DLOG(INFO) << "Sending CONNECT-UDP request for " << target_server_address
- << " using flow ID " << flow_id << " on stream "
- << stream->id();
+ << " on stream " << stream->id();
// Send the request.
spdy::Http2HeaderBlock headers;
@@ -104,7 +101,7 @@ MasqueClientSession::GetOrCreateConnectUdpClientState(
headers[":scheme"] = "masque";
headers[":path"] = "/";
headers[":authority"] = target_server_address.ToString();
- SpdyUtils::AddDatagramFlowIdHeader(&headers, flow_id);
+ SpdyUtils::AddDatagramFlowIdHeader(&headers, stream->id());
size_t bytes_sent =
stream->SendRequest(std::move(headers), /*body=*/"", /*fin=*/false);
if (bytes_sent == 0) {
@@ -112,9 +109,10 @@ MasqueClientSession::GetOrCreateConnectUdpClientState(
return nullptr;
}
+ absl::optional<QuicDatagramContextId> context_id;
connect_udp_client_states_.push_back(
- ConnectUdpClientState(stream, encapsulated_client_session, this, flow_id,
- target_server_address));
+ ConnectUdpClientState(stream, encapsulated_client_session, this,
+ context_id, target_server_address));
return &connect_udp_client_states_.back();
}
@@ -137,12 +135,15 @@ void MasqueClientSession::SendPacket(
return;
}
- QuicDatagramFlowId flow_id = connect_udp->flow_id();
- MessageStatus message_status =
- SendHttp3Datagram(connect_udp->flow_id(), packet);
+ MessageStatus message_status = SendHttp3Datagram(
+ connect_udp->stream()->id(), connect_udp->context_id(), packet);
QUIC_DVLOG(1) << "Sent packet to " << target_server_address
- << " compressed with flow ID " << flow_id
+ << " compressed with stream ID " << connect_udp->stream()->id()
+ << " context ID "
+ << (connect_udp->context_id().has_value()
+ ? connect_udp->context_id().value()
+ : 0)
<< " and got message status "
<< MessageStatusToString(message_status);
}
@@ -178,7 +179,11 @@ void MasqueClientSession::UnregisterConnectionId(
for (auto it = connect_udp_client_states_.begin();
it != connect_udp_client_states_.end();) {
if (it->encapsulated_client_session() == encapsulated_client_session) {
- QUIC_DLOG(INFO) << "Removing state for flow_id " << it->flow_id();
+ QUIC_DLOG(INFO) << "Removing state for stream ID " << it->stream()->id()
+ << " context ID "
+ << (it->context_id().has_value()
+ ? it->context_id().value()
+ : 0);
auto* stream = it->stream();
it = connect_udp_client_states_.erase(it);
if (!stream->write_side_closed()) {
@@ -217,8 +222,10 @@ void MasqueClientSession::OnStreamClosed(QuicStreamId stream_id) {
it != connect_udp_client_states_.end();) {
if (it->stream()->id() == stream_id) {
QUIC_DLOG(INFO) << "Stream " << stream_id
- << " was closed, removing state for flow_id "
- << it->flow_id();
+ << " was closed, removing state for context ID "
+ << (it->context_id().has_value()
+ ? it->context_id().value()
+ : 0);
auto* encapsulated_client_session = it->encapsulated_client_session();
it = connect_udp_client_states_.erase(it);
encapsulated_client_session->CloseConnection(
@@ -233,24 +240,41 @@ void MasqueClientSession::OnStreamClosed(QuicStreamId stream_id) {
QuicSpdyClientSession::OnStreamClosed(stream_id);
}
+bool MasqueClientSession::OnSettingsFrame(const SettingsFrame& frame) {
+ if (!QuicSpdyClientSession::OnSettingsFrame(frame)) {
+ QUIC_DLOG(ERROR) << "Failed to parse received settings";
+ return false;
+ }
+ if (!SupportsH3Datagram()) {
+ QUIC_DLOG(ERROR) << "Refusing to use MASQUE without HTTP/3 Datagrams";
+ return false;
+ }
+ owner_->OnSettingsReceived();
+ return true;
+}
+
MasqueClientSession::ConnectUdpClientState::ConnectUdpClientState(
QuicSpdyClientStream* stream,
EncapsulatedClientSession* encapsulated_client_session,
MasqueClientSession* masque_session,
- QuicDatagramFlowId flow_id,
+ absl::optional<QuicDatagramContextId> context_id,
const QuicSocketAddress& target_server_address)
: stream_(stream),
encapsulated_client_session_(encapsulated_client_session),
masque_session_(masque_session),
- flow_id_(flow_id),
+ context_id_(context_id),
target_server_address_(target_server_address) {
QUICHE_DCHECK_NE(masque_session_, nullptr);
- masque_session_->RegisterHttp3FlowId(this->flow_id(), this);
+ this->stream()->RegisterHttp3DatagramRegistrationVisitor(this);
+ Http3DatagramContextExtensions extensions;
+ this->stream()->RegisterHttp3DatagramContextId(this->context_id(), extensions,
+ this);
}
MasqueClientSession::ConnectUdpClientState::~ConnectUdpClientState() {
- if (flow_id_.has_value()) {
- masque_session_->UnregisterHttp3FlowId(flow_id());
+ if (stream() != nullptr) {
+ stream()->UnregisterHttp3DatagramContextId(context_id());
+ stream()->UnregisterHttp3DatagramRegistrationVisitor();
}
}
@@ -265,23 +289,69 @@ MasqueClientSession::ConnectUdpClientState::operator=(
stream_ = other.stream_;
encapsulated_client_session_ = other.encapsulated_client_session_;
masque_session_ = other.masque_session_;
- flow_id_ = other.flow_id_;
+ context_id_ = other.context_id_;
target_server_address_ = other.target_server_address_;
- other.flow_id_.reset();
- if (flow_id_.has_value()) {
- masque_session_->UnregisterHttp3FlowId(flow_id());
- masque_session_->RegisterHttp3FlowId(flow_id(), this);
+ other.stream_ = nullptr;
+ if (stream() != nullptr) {
+ stream()->MoveHttp3DatagramRegistration(this);
+ stream()->MoveHttp3DatagramContextIdRegistration(context_id(), this);
}
return *this;
}
void MasqueClientSession::ConnectUdpClientState::OnHttp3Datagram(
- QuicDatagramFlowId flow_id,
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) {
- QUICHE_DCHECK_EQ(flow_id, this->flow_id());
+ QUICHE_DCHECK_EQ(stream_id, stream()->id());
+ QUICHE_DCHECK(context_id == context_id_);
encapsulated_client_session_->ProcessPacket(payload, target_server_address_);
QUIC_DVLOG(1) << "Sent " << payload.size()
- << " bytes to connection for flow_id " << flow_id;
+ << " bytes to connection for stream ID " << stream_id
+ << " context ID "
+ << (context_id.has_value() ? context_id.value() : 0);
+}
+
+void MasqueClientSession::ConnectUdpClientState::OnContextReceived(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != stream_->id()) {
+ QUIC_BUG(MASQUE client bad datagram context registration)
+ << "Registered stream ID " << stream_id << ", expected "
+ << stream_->id();
+ return;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << "Ignoring unexpected context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << stream_->id();
+ return;
+ }
+ // Do nothing since the client registers first and we currently ignore
+ // extensions.
+}
+
+void MasqueClientSession::ConnectUdpClientState::OnContextClosed(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != stream_->id()) {
+ QUIC_BUG(MASQUE client bad datagram context registration)
+ << "Closed context on stream ID " << stream_id << ", expected "
+ << stream_->id();
+ return;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << "Ignoring unexpected close of context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << stream_->id();
+ return;
+ }
+ QUIC_DLOG(INFO) << "Received datagram context close on stream ID "
+ << stream_->id() << ", closing stream";
+ masque_session_->ResetStream(stream_->id(), QUIC_STREAM_CANCELLED);
}
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
index e055a7699be..1c130873340 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_client_session.h
@@ -31,6 +31,9 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
// Notifies the owner that the client connection ID is no longer in use.
virtual void UnregisterClientConnectionId(
QuicConnectionId client_connection_id) = 0;
+
+ // Notifies the owner that a settings frame has been received.
+ virtual void OnSettingsReceived() = 0;
};
// Interface meant to be implemented by encapsulated client sessions, i.e.
// the end-to-end QUIC client sessions that run inside MASQUE encapsulation.
@@ -75,6 +78,9 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
ConnectionCloseSource source) override;
void OnStreamClosed(QuicStreamId stream_id) override;
+ // From QuicSpdySession.
+ bool OnSettingsFrame(const SettingsFrame& frame) override;
+
// Send encapsulated packet.
void SendPacket(QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
@@ -101,7 +107,8 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
private:
// State that the MasqueClientSession keeps for each CONNECT-UDP request.
class QUIC_NO_EXPORT ConnectUdpClientState
- : public QuicSpdySession::Http3DatagramVisitor {
+ : public QuicSpdyStream::Http3DatagramRegistrationVisitor,
+ public QuicSpdyStream::Http3DatagramVisitor {
public:
// |stream| and |encapsulated_client_session| must be valid for the lifetime
// of the ConnectUdpClientState.
@@ -109,7 +116,7 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
QuicSpdyClientStream* stream,
EncapsulatedClientSession* encapsulated_client_session,
MasqueClientSession* masque_session,
- QuicDatagramFlowId flow_id,
+ absl::optional<QuicDatagramContextId> context_id,
const QuicSocketAddress& target_server_address);
~ConnectUdpClientState();
@@ -124,26 +131,38 @@ class QUIC_NO_EXPORT MasqueClientSession : public QuicSpdyClientSession {
EncapsulatedClientSession* encapsulated_client_session() const {
return encapsulated_client_session_;
}
- QuicDatagramFlowId flow_id() const {
- QUICHE_DCHECK(flow_id_.has_value());
- return *flow_id_;
+ absl::optional<QuicDatagramContextId> context_id() const {
+ return context_id_;
}
const QuicSocketAddress& target_server_address() const {
return target_server_address_;
}
- // From QuicSpdySession::Http3DatagramVisitor.
- void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ // From QuicSpdyStream::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) override;
+ // From QuicSpdyStream::Http3DatagramRegistrationVisitor.
+ void OnContextReceived(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+ void OnContextClosed(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+
private:
QuicSpdyClientStream* stream_; // Unowned.
EncapsulatedClientSession* encapsulated_client_session_; // Unowned.
MasqueClientSession* masque_session_; // Unowned.
- absl::optional<QuicDatagramFlowId> flow_id_;
+ absl::optional<QuicDatagramContextId> context_id_;
QuicSocketAddress target_server_address_;
};
+ bool ShouldNegotiateHttp3Datagram() override { return true; }
+
const ConnectUdpClientState* GetOrCreateConnectUdpClientState(
const QuicSocketAddress& target_server_address,
EncapsulatedClientSession* encapsulated_client_session);
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc
index b021b41a0a6..035b9f9d030 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.cc
@@ -21,7 +21,7 @@ namespace quic {
namespace {
// |kFlowId0| is used to indicate creation of a new compression context.
-const QuicDatagramFlowId kFlowId0 = 0;
+const QuicDatagramStreamId kFlowId0 = 0;
enum MasqueAddressFamily : uint8_t {
MasqueAddressFamilyIPv4 = 4,
@@ -32,16 +32,16 @@ enum MasqueAddressFamily : uint8_t {
MasqueCompressionEngine::MasqueCompressionEngine(
QuicSpdySession* masque_session)
- : masque_session_(masque_session) {}
+ : masque_session_(masque_session),
+ next_available_flow_id_(
+ masque_session_->perspective() == Perspective::IS_CLIENT ? 0 : 1) {}
-QuicDatagramFlowId MasqueCompressionEngine::FindOrCreateCompressionContext(
+QuicDatagramStreamId MasqueCompressionEngine::FindOrCreateCompressionContext(
QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
- const QuicSocketAddress& server_address,
- bool client_connection_id_present,
- bool server_connection_id_present,
- bool* validated) {
- QuicDatagramFlowId flow_id = kFlowId0;
+ const QuicSocketAddress& server_address, bool client_connection_id_present,
+ bool server_connection_id_present, bool* validated) {
+ QuicDatagramStreamId flow_id = kFlowId0;
*validated = false;
for (const auto& kv : contexts_) {
const MasqueCompressionContext& context = kv.second;
@@ -74,11 +74,8 @@ QuicDatagramFlowId MasqueCompressionEngine::FindOrCreateCompressionContext(
}
// Create new compression context.
- flow_id = masque_session_->GetNextDatagramFlowId();
- if (flow_id == kFlowId0) {
- // Do not use value zero which is reserved in this mode.
- flow_id = masque_session_->GetNextDatagramFlowId();
- }
+ next_available_flow_id_ += 2;
+ flow_id = next_available_flow_id_;
QUIC_DVLOG(1) << "Compression assigning new flow_id " << flow_id << " to "
<< server_address << " client " << client_connection_id
<< " server " << server_connection_id;
@@ -96,13 +93,9 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
QuicConnectionId server_connection_id,
const QuicSocketAddress& server_address,
QuicConnectionId destination_connection_id,
- QuicConnectionId source_connection_id,
- QuicDatagramFlowId flow_id,
- bool validated,
- uint8_t first_byte,
- bool long_header,
- QuicDataReader* reader,
- QuicDataWriter* writer) {
+ QuicConnectionId source_connection_id, QuicDatagramStreamId flow_id,
+ bool validated, uint8_t first_byte, bool long_header,
+ QuicDataReader* reader, QuicDataWriter* writer) {
if (validated) {
QUIC_DVLOG(1) << "Compressing using validated flow_id " << flow_id;
if (!writer->WriteVarInt62(flow_id)) {
@@ -222,8 +215,7 @@ bool MasqueCompressionEngine::WriteCompressedPacketToSlice(
}
void MasqueCompressionEngine::CompressAndSendPacket(
- absl::string_view packet,
- QuicConnectionId client_connection_id,
+ absl::string_view packet, QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
const QuicSocketAddress& server_address) {
QUIC_DVLOG(2) << "Compressing client " << client_connection_id << " server "
@@ -258,7 +250,7 @@ void MasqueCompressionEngine::CompressAndSendPacket(
}
bool validated = false;
- QuicDatagramFlowId flow_id = FindOrCreateCompressionContext(
+ QuicDatagramStreamId flow_id = FindOrCreateCompressionContext(
client_connection_id, server_connection_id, server_address,
client_connection_id_present, server_connection_id_present, &validated);
@@ -276,10 +268,10 @@ void MasqueCompressionEngine::CompressAndSendPacket(
sizeof(server_address.port()) + sizeof(uint8_t) +
server_address.host().ToPackedString().length();
}
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
+ QuicBuffer buffer(
masque_session_->connection()->helper()->GetStreamSendBufferAllocator(),
slice_length);
- QuicDataWriter writer(slice_length, buffer.get());
+ QuicDataWriter writer(buffer.size(), buffer.data());
if (!WriteCompressedPacketToSlice(
client_connection_id, server_connection_id, server_address,
@@ -288,18 +280,16 @@ void MasqueCompressionEngine::CompressAndSendPacket(
return;
}
- QuicMemSlice slice(std::move(buffer), slice_length);
MessageResult message_result =
- masque_session_->SendMessage(QuicMemSliceSpan(&slice));
+ masque_session_->SendMessage(QuicMemSlice(std::move(buffer)));
QUIC_DVLOG(1) << "Sent packet compressed with flow ID " << flow_id
<< " and got message result " << message_result;
}
bool MasqueCompressionEngine::ParseCompressionContext(
- QuicDataReader* reader,
- MasqueCompressionContext* context) {
- QuicDatagramFlowId new_flow_id;
+ QuicDataReader* reader, MasqueCompressionContext* context) {
+ QuicDatagramStreamId new_flow_id;
if (!reader->ReadVarInt62(&new_flow_id)) {
QUIC_DLOG(ERROR) << "Could not read new_flow_id";
return false;
@@ -398,10 +388,8 @@ bool MasqueCompressionEngine::ParseCompressionContext(
}
bool MasqueCompressionEngine::WriteDecompressedPacket(
- QuicDataReader* reader,
- const MasqueCompressionContext& context,
- std::vector<char>* packet,
- bool* version_present) {
+ QuicDataReader* reader, const MasqueCompressionContext& context,
+ std::vector<char>* packet, bool* version_present) {
QuicConnectionId destination_connection_id, source_connection_id;
if (masque_session_->perspective() == Perspective::IS_SERVER) {
destination_connection_id = context.server_connection_id;
@@ -464,16 +452,13 @@ bool MasqueCompressionEngine::WriteDecompressedPacket(
}
bool MasqueCompressionEngine::DecompressDatagram(
- absl::string_view datagram,
- QuicConnectionId* client_connection_id,
- QuicConnectionId* server_connection_id,
- QuicSocketAddress* server_address,
- std::vector<char>* packet,
- bool* version_present) {
+ absl::string_view datagram, QuicConnectionId* client_connection_id,
+ QuicConnectionId* server_connection_id, QuicSocketAddress* server_address,
+ std::vector<char>* packet, bool* version_present) {
QUIC_DVLOG(1) << "Decompressing DATAGRAM frame of length "
<< datagram.length();
QuicDataReader reader(datagram);
- QuicDatagramFlowId flow_id;
+ QuicDatagramStreamId flow_id;
if (!reader.ReadVarInt62(&flow_id)) {
QUIC_DLOG(ERROR) << "Could not read flow_id";
return false;
@@ -525,14 +510,14 @@ bool MasqueCompressionEngine::DecompressDatagram(
void MasqueCompressionEngine::UnregisterClientConnectionId(
QuicConnectionId client_connection_id) {
- std::vector<QuicDatagramFlowId> flow_ids_to_remove;
+ std::vector<QuicDatagramStreamId> flow_ids_to_remove;
for (const auto& kv : contexts_) {
const MasqueCompressionContext& context = kv.second;
if (context.client_connection_id == client_connection_id) {
flow_ids_to_remove.push_back(kv.first);
}
}
- for (QuicDatagramFlowId flow_id : flow_ids_to_remove) {
+ for (QuicDatagramStreamId flow_id : flow_ids_to_remove) {
contexts_.erase(flow_id);
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
index 9bea618ae76..581b9501791 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_compression_engine.h
@@ -63,8 +63,7 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
QuicConnectionId* client_connection_id,
QuicConnectionId* server_connection_id,
QuicSocketAddress* server_address,
- std::vector<char>* packet,
- bool* version_present);
+ std::vector<char>* packet, bool* version_present);
// Clears all entries referencing |client_connection_id| from the
// compression table.
@@ -83,12 +82,11 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
// whether the corresponding connection ID is present in the current packet.
// |validated| will contain whether the compression context that matches
// these arguments is currently validated or not.
- QuicDatagramFlowId FindOrCreateCompressionContext(
+ QuicDatagramStreamId FindOrCreateCompressionContext(
QuicConnectionId client_connection_id,
QuicConnectionId server_connection_id,
const QuicSocketAddress& server_address,
- bool client_connection_id_present,
- bool server_connection_id_present,
+ bool client_connection_id_present, bool server_connection_id_present,
bool* validated);
// Writes compressed packet to |slice| during compression.
@@ -97,11 +95,9 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
const QuicSocketAddress& server_address,
QuicConnectionId destination_connection_id,
QuicConnectionId source_connection_id,
- QuicDatagramFlowId flow_id,
- bool validated,
- uint8_t first_byte,
- bool long_header,
- QuicDataReader* reader,
+ QuicDatagramStreamId flow_id,
+ bool validated, uint8_t first_byte,
+ bool long_header, QuicDataReader* reader,
QuicDataWriter* writer);
// Parses compression context from flow ID 0 during decompression.
@@ -115,7 +111,8 @@ class QUIC_NO_EXPORT MasqueCompressionEngine {
bool* version_present);
QuicSpdySession* masque_session_; // Unowned.
- absl::flat_hash_map<QuicDatagramFlowId, MasqueCompressionContext> contexts_;
+ absl::flat_hash_map<QuicDatagramStreamId, MasqueCompressionContext> contexts_;
+ QuicDatagramStreamId next_available_flow_id_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
index 5ad91cfd9ad..ec475205ac8 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.cc
@@ -81,6 +81,11 @@ std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
return nullptr;
}
+ if (!masque_client->WaitUntilSettingsReceived()) {
+ QUIC_LOG(ERROR) << "Failed to receive settings";
+ return nullptr;
+ }
+
if (masque_client->masque_mode() == MasqueMode::kLegacy) {
// Construct the legacy mode init request.
spdy::Http2HeaderBlock header_block;
@@ -114,6 +119,17 @@ std::unique_ptr<MasqueEpollClient> MasqueEpollClient::Create(
return masque_client;
}
+void MasqueEpollClient::OnSettingsReceived() {
+ settings_received_ = true;
+}
+
+bool MasqueEpollClient::WaitUntilSettingsReceived() {
+ while (connected() && !settings_received_) {
+ network_helper()->RunEventLoop();
+ }
+ return connected() && settings_received_;
+}
+
void MasqueEpollClient::UnregisterClientConnectionId(
QuicConnectionId client_connection_id) {
std::string body(client_connection_id.data(), client_connection_id.length());
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
index 1db161f5aaa..2f5faca0aff 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_epoll_client.h
@@ -35,6 +35,8 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
// Convenience accessor for the underlying connection ID.
QuicConnectionId connection_id();
+ // From MasqueClientSession::Owner.
+ void OnSettingsReceived() override;
// Send a MASQUE client connection ID unregister command to the server.
void UnregisterClientConnectionId(
QuicConnectionId client_connection_id) override;
@@ -50,12 +52,17 @@ class QUIC_NO_EXPORT MasqueEpollClient : public QuicClient,
std::unique_ptr<ProofVerifier> proof_verifier,
const std::string& authority);
+ // Wait synchronously until we receive the peer's settings. Returns whether
+ // they were received.
+ bool WaitUntilSettingsReceived();
+
// Disallow copy and assign.
MasqueEpollClient(const MasqueEpollClient&) = delete;
MasqueEpollClient& operator=(const MasqueEpollClient&) = delete;
MasqueMode masque_mode_;
std::string authority_;
+ bool settings_received_ = false;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
index d5a5d9f7d36..aaccda3722e 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_bin.cc
@@ -52,8 +52,6 @@ int main(int argc, char* argv[]) {
return 0;
}
- SetQuicReloadableFlag(quic_h3_datagram, true);
-
quic::MasqueMode masque_mode = quic::MasqueMode::kOpen;
std::string mode_string = GetQuicFlag(FLAGS_masque_mode);
if (mode_string == "legacy") {
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
index 8a531cab3a0..effc17ff316 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.cc
@@ -58,8 +58,7 @@ class FdWrapper {
};
std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse(
- absl::string_view status,
- absl::string_view error_details) {
+ absl::string_view status, absl::string_view error_details) {
spdy::Http2HeaderBlock response_headers;
response_headers[":status"] = status;
response_headers["masque-debug-info"] = error_details;
@@ -72,24 +71,15 @@ std::unique_ptr<QuicBackendResponse> CreateBackendErrorResponse(
} // namespace
MasqueServerSession::MasqueServerSession(
- MasqueMode masque_mode,
- const QuicConfig& config,
+ MasqueMode masque_mode, const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- QuicConnection* connection,
- QuicSession::Visitor* visitor,
- Visitor* owner,
- QuicEpollServer* epoll_server,
- QuicCryptoServerStreamBase::Helper* helper,
+ QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner,
+ QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
MasqueServerBackend* masque_server_backend)
- : QuicSimpleServerSession(config,
- supported_versions,
- connection,
- visitor,
- helper,
- crypto_config,
- compressed_certs_cache,
+ : QuicSimpleServerSession(config, supported_versions, connection, visitor,
+ helper, crypto_config, compressed_certs_cache,
masque_server_backend),
masque_server_backend_(masque_server_backend),
owner_(owner),
@@ -153,8 +143,7 @@ void MasqueServerSession::OnMessageLost(QuicMessageId message_id) {
}
void MasqueServerSession::OnConnectionClosed(
- const QuicConnectionCloseFrame& frame,
- ConnectionCloseSource source) {
+ const QuicConnectionCloseFrame& frame, ConnectionCloseSource source) {
QuicSimpleServerSession::OnConnectionClosed(frame, source);
QUIC_DLOG(INFO) << "Closing connection for " << connection_id();
masque_server_backend_->RemoveBackendClient(connection_id());
@@ -165,7 +154,7 @@ void MasqueServerSession::OnConnectionClosed(
void MasqueServerSession::OnStreamClosed(QuicStreamId stream_id) {
connect_udp_server_states_.remove_if(
[stream_id](const ConnectUdpServerState& connect_udp) {
- return connect_udp.stream_id() == stream_id;
+ return connect_udp.stream()->id() == stream_id;
});
QuicSimpleServerSession::OnStreamClosed(stream_id);
@@ -213,7 +202,7 @@ std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
QUIC_DLOG(ERROR) << "MASQUE request with bad method \"" << method << "\"";
return CreateBackendErrorResponse("400", "Bad method");
}
- absl::optional<QuicDatagramFlowId> flow_id =
+ absl::optional<QuicDatagramStreamId> flow_id =
SpdyUtils::ParseDatagramFlowIdHeader(request_headers);
if (!flow_id.has_value()) {
QUIC_DLOG(ERROR)
@@ -255,17 +244,36 @@ std::unique_ptr<QuicBackendResponse> MasqueServerSession::HandleMasqueRequest(
QUIC_DLOG(ERROR) << "Socket creation failed";
return CreateBackendErrorResponse("500", "Socket creation failed");
}
- QuicSocketAddress any_v6_address(QuicIpAddress::Any6(), 0);
+ QuicSocketAddress empty_address(QuicIpAddress::Any6(), 0);
+ if (target_server_address.host().IsIPv4()) {
+ empty_address = QuicSocketAddress(QuicIpAddress::Any4(), 0);
+ }
QuicUdpSocketApi socket_api;
- if (!socket_api.Bind(fd_wrapper.fd(), any_v6_address)) {
+ if (!socket_api.Bind(fd_wrapper.fd(), empty_address)) {
QUIC_DLOG(ERROR) << "Socket bind failed";
return CreateBackendErrorResponse("500", "Socket bind failed");
}
epoll_server_->RegisterFDForRead(fd_wrapper.fd(), this);
- connect_udp_server_states_.emplace_back(ConnectUdpServerState(
- *flow_id, request_handler->stream_id(), target_server_address,
- fd_wrapper.extract_fd(), this));
+ absl::optional<QuicDatagramContextId> context_id;
+ QuicSpdyStream* stream = static_cast<QuicSpdyStream*>(
+ GetActiveStream(request_handler->stream_id()));
+ if (stream == nullptr) {
+ QUIC_BUG(bad masque server stream type)
+ << "Unexpected stream type for stream ID "
+ << request_handler->stream_id();
+ return CreateBackendErrorResponse("500", "Bad stream type");
+ }
+ stream->RegisterHttp3DatagramFlowId(*flow_id);
+ connect_udp_server_states_.push_back(
+ ConnectUdpServerState(stream, context_id, target_server_address,
+ fd_wrapper.extract_fd(), this));
+
+ // TODO(b/181256914) remove this when we drop support for
+ // draft-ietf-masque-h3-datagram-00 in favor of later drafts.
+ Http3DatagramContextExtensions extensions;
+ stream->RegisterHttp3DatagramContextId(context_id, extensions,
+ &connect_udp_server_states_.back());
spdy::Http2HeaderBlock response_headers;
response_headers[":status"] = "200";
@@ -326,8 +334,7 @@ void MasqueServerSession::HandlePacketFromServer(
}
void MasqueServerSession::OnRegistration(QuicEpollServer* /*eps*/,
- QuicUdpSocketFd fd,
- int event_mask) {
+ QuicUdpSocketFd fd, int event_mask) {
QUIC_DVLOG(1) << "OnRegistration " << fd << " event_mask " << event_mask;
}
@@ -350,13 +357,12 @@ void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) {
<< event->in_events << " on unknown fd " << fd;
return;
}
- QuicDatagramFlowId flow_id = it->flow_id();
QuicSocketAddress expected_target_server_address =
it->target_server_address();
QUICHE_DCHECK(expected_target_server_address.IsInitialized());
QUIC_DVLOG(1) << "Received readable event on fd " << fd << " (mask "
- << event->in_events << ") flow_id " << flow_id << " server "
- << expected_target_server_address;
+ << event->in_events << ") stream ID " << it->stream()->id()
+ << " server " << expected_target_server_address;
QuicUdpSocketApi socket_api;
BitMask64 packet_info_interested(QuicUdpPacketInfoBit::PEER_ADDRESS);
char packet_buffer[kMaxIncomingPacketSize];
@@ -392,12 +398,14 @@ void MasqueServerSession::OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) {
return;
}
// The packet is valid, send it to the client in a DATAGRAM frame.
- MessageStatus message_status = SendHttp3Datagram(
- flow_id, absl::string_view(read_result.packet_buffer.buffer,
- read_result.packet_buffer.buffer_len));
+ MessageStatus message_status = it->stream()->SendHttp3Datagram(
+ it->context_id(),
+ absl::string_view(read_result.packet_buffer.buffer,
+ read_result.packet_buffer.buffer_len));
QUIC_DVLOG(1) << "Sent UDP packet from " << expected_target_server_address
<< " of length " << read_result.packet_buffer.buffer_len
- << " with flow ID " << flow_id << " and got message status "
+ << " with stream ID " << it->stream()->id()
+ << " and got message status "
<< MessageStatusToString(message_status);
}
}
@@ -417,24 +425,25 @@ std::string MasqueServerSession::Name() const {
}
MasqueServerSession::ConnectUdpServerState::ConnectUdpServerState(
- QuicDatagramFlowId flow_id,
- QuicStreamId stream_id,
- const QuicSocketAddress& target_server_address,
- QuicUdpSocketFd fd,
+ QuicSpdyStream* stream, absl::optional<QuicDatagramContextId> context_id,
+ const QuicSocketAddress& target_server_address, QuicUdpSocketFd fd,
MasqueServerSession* masque_session)
- : flow_id_(flow_id),
- stream_id_(stream_id),
+ : stream_(stream),
+ context_id_(context_id),
target_server_address_(target_server_address),
fd_(fd),
masque_session_(masque_session) {
QUICHE_DCHECK_NE(fd_, kQuicInvalidSocketFd);
QUICHE_DCHECK_NE(masque_session_, nullptr);
- masque_session_->RegisterHttp3FlowId(this->flow_id(), this);
+ this->stream()->RegisterHttp3DatagramRegistrationVisitor(this);
}
MasqueServerSession::ConnectUdpServerState::~ConnectUdpServerState() {
- if (flow_id_.has_value()) {
- masque_session_->UnregisterHttp3FlowId(flow_id());
+ if (stream() != nullptr) {
+ stream()->UnregisterHttp3DatagramRegistrationVisitor();
+ if (context_registered_) {
+ stream()->UnregisterHttp3DatagramContextId(context_id());
+ }
}
if (fd_ == kQuicInvalidSocketFd) {
return;
@@ -460,24 +469,29 @@ MasqueServerSession::ConnectUdpServerState::operator=(
masque_session_->epoll_server()->UnregisterFD(fd_);
socket_api.Destroy(fd_);
}
- flow_id_ = other.flow_id_;
- stream_id_ = other.stream_id_;
+ stream_ = other.stream_;
+ other.stream_ = nullptr;
+ context_id_ = other.context_id_;
target_server_address_ = other.target_server_address_;
fd_ = other.fd_;
masque_session_ = other.masque_session_;
other.fd_ = kQuicInvalidSocketFd;
- other.flow_id_.reset();
- if (flow_id_.has_value()) {
- masque_session_->UnregisterHttp3FlowId(flow_id());
- masque_session_->RegisterHttp3FlowId(flow_id(), this);
+ context_registered_ = other.context_registered_;
+ other.context_registered_ = false;
+ if (stream() != nullptr) {
+ stream()->MoveHttp3DatagramRegistration(this);
+ if (context_registered_) {
+ stream()->MoveHttp3DatagramContextIdRegistration(context_id(), this);
+ }
}
return *this;
}
void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram(
- QuicDatagramFlowId flow_id,
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) {
- QUICHE_DCHECK_EQ(flow_id, this->flow_id());
+ QUICHE_DCHECK_EQ(stream_id, stream()->id());
+ QUICHE_DCHECK(context_id == context_id_);
QuicUdpSocketApi socket_api;
QuicUdpPacketInfo packet_info;
packet_info.SetPeerAddress(target_server_address_);
@@ -487,4 +501,58 @@ void MasqueServerSession::ConnectUdpServerState::OnHttp3Datagram(
<< target_server_address_ << " with result " << write_result;
}
+void MasqueServerSession::ConnectUdpServerState::OnContextReceived(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != stream()->id()) {
+ QUIC_BUG(MASQUE server bad datagram context registration)
+ << "Registered stream ID " << stream_id << ", expected "
+ << stream()->id();
+ return;
+ }
+ if (!context_received_) {
+ context_received_ = true;
+ context_id_ = context_id;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << "Ignoring unexpected context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << stream()->id();
+ return;
+ }
+ if (context_registered_) {
+ QUIC_BUG(MASQUE server double datagram context registration)
+ << "Try to re-register stream ID " << stream_id << " context ID "
+ << (context_id_.has_value() ? context_id_.value() : 0);
+ return;
+ }
+ context_registered_ = true;
+ Http3DatagramContextExtensions reply_extensions;
+ stream()->RegisterHttp3DatagramContextId(context_id_, reply_extensions, this);
+}
+
+void MasqueServerSession::ConnectUdpServerState::OnContextClosed(
+ QuicStreamId stream_id, absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& /*extensions*/) {
+ if (stream_id != stream()->id()) {
+ QUIC_BUG(MASQUE server bad datagram context registration)
+ << "Closed context on stream ID " << stream_id << ", expected "
+ << stream()->id();
+ return;
+ }
+ if (context_id != context_id_) {
+ QUIC_DLOG(INFO) << "Ignoring unexpected close of context ID "
+ << (context_id.has_value() ? context_id.value() : 0)
+ << " instead of "
+ << (context_id_.has_value() ? context_id_.value() : 0)
+ << " on stream ID " << stream()->id();
+ return;
+ }
+ QUIC_DLOG(INFO) << "Received datagram context close on stream ID "
+ << stream()->id() << ", closing stream";
+ masque_session_->ResetStream(stream()->id(), QUIC_STREAM_CANCELLED);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
index 14b8293e9b1..1bec14c5464 100644
--- a/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
+++ b/chromium/net/third_party/quiche/src/quic/masque/masque_server_session.h
@@ -38,14 +38,10 @@ class QUIC_NO_EXPORT MasqueServerSession
};
explicit MasqueServerSession(
- MasqueMode masque_mode,
- const QuicConfig& config,
+ MasqueMode masque_mode, const QuicConfig& config,
const ParsedQuicVersionVector& supported_versions,
- QuicConnection* connection,
- QuicSession::Visitor* visitor,
- Visitor* owner,
- QuicEpollServer* epoll_server,
- QuicCryptoServerStreamBase::Helper* helper,
+ QuicConnection* connection, QuicSession::Visitor* visitor, Visitor* owner,
+ QuicEpollServer* epoll_server, QuicCryptoServerStreamBase::Helper* helper,
const QuicCryptoServerConfig* crypto_config,
QuicCompressedCertsCache* compressed_certs_cache,
MasqueServerBackend* masque_server_backend);
@@ -71,8 +67,7 @@ class QUIC_NO_EXPORT MasqueServerSession
QuicSimpleServerBackend::RequestHandler* request_handler) override;
// From QuicEpollCallbackInterface.
- void OnRegistration(QuicEpollServer* eps,
- QuicUdpSocketFd fd,
+ void OnRegistration(QuicEpollServer* eps, QuicUdpSocketFd fd,
int event_mask) override;
void OnModification(QuicUdpSocketFd fd, int event_mask) override;
void OnEvent(QuicUdpSocketFd fd, QuicEpollEvent* event) override;
@@ -88,15 +83,15 @@ class QUIC_NO_EXPORT MasqueServerSession
private:
// State that the MasqueServerSession keeps for each CONNECT-UDP request.
class QUIC_NO_EXPORT ConnectUdpServerState
- : public QuicSpdySession::Http3DatagramVisitor {
+ : public QuicSpdyStream::Http3DatagramRegistrationVisitor,
+ public QuicSpdyStream::Http3DatagramVisitor {
public:
// ConnectUdpServerState takes ownership of |fd|. It will unregister it
// from |epoll_server| and close the file descriptor when destructed.
explicit ConnectUdpServerState(
- QuicDatagramFlowId flow_id,
- QuicStreamId stream_id,
- const QuicSocketAddress& target_server_address,
- QuicUdpSocketFd fd,
+ QuicSpdyStream* stream,
+ absl::optional<QuicDatagramContextId> context_id,
+ const QuicSocketAddress& target_server_address, QuicUdpSocketFd fd,
MasqueServerSession* masque_session);
~ConnectUdpServerState();
@@ -107,28 +102,42 @@ class QUIC_NO_EXPORT MasqueServerSession
ConnectUdpServerState& operator=(const ConnectUdpServerState&) = delete;
ConnectUdpServerState& operator=(ConnectUdpServerState&&);
- QuicDatagramFlowId flow_id() const {
- QUICHE_DCHECK(flow_id_.has_value());
- return *flow_id_;
+ QuicSpdyStream* stream() const { return stream_; }
+ absl::optional<QuicDatagramContextId> context_id() const {
+ return context_id_;
}
- QuicStreamId stream_id() const { return stream_id_; }
const QuicSocketAddress& target_server_address() const {
return target_server_address_;
}
QuicUdpSocketFd fd() const { return fd_; }
- // From QuicSpdySession::Http3DatagramVisitor.
- void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ // From QuicSpdyStream::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) override;
+ // From QuicSpdyStream::Http3DatagramRegistrationVisitor.
+ void OnContextReceived(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+ void OnContextClosed(
+ QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions) override;
+
private:
- absl::optional<QuicDatagramFlowId> flow_id_;
- QuicStreamId stream_id_;
+ QuicSpdyStream* stream_;
+ absl::optional<QuicDatagramContextId> context_id_;
QuicSocketAddress target_server_address_;
- QuicUdpSocketFd fd_; // Owned.
+ QuicUdpSocketFd fd_; // Owned.
MasqueServerSession* masque_session_; // Unowned.
+ bool context_received_ = false;
+ bool context_registered_ = false;
};
+ bool ShouldNegotiateHttp3Datagram() override { return true; }
+
MasqueServerBackend* masque_server_backend_; // Unowned.
Visitor* owner_; // Unowned.
QuicEpollServer* epoll_server_; // Unowned.
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
index f7fd922f594..eb16bfa18c3 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers.h
@@ -7,25 +7,15 @@
#include "net/quic/platform/impl/quic_containers_impl.h"
-#include "absl/hash/hash.h"
-
namespace quic {
-// A map which offers insertion-ordered iteration.
-template <typename Key, typename Value, typename Hash = absl::Hash<Key>>
-using QuicLinkedHashMap = QuicLinkedHashMapImpl<Key, Value, Hash>;
-
-// A vector optimized for small sizes. Provides the same APIs as a std::vector.
-template <typename T, size_t N, typename A = std::allocator<T>>
-using QuicInlinedVector = QuicInlinedVectorImpl<T, N, A>;
-
-// An ordered set of values.
+// An ordered container optimized for small sets.
+// An implementation with O(n) mutations might be chosen
+// in case it has better memory usage and/or faster access.
//
// DOES NOT GUARANTEE POINTER OR ITERATOR STABILITY!
-template <typename Key,
- typename Compare = std::less<Key>,
- typename Rep = std::vector<Key>>
-using QuicOrderedSet = QuicOrderedSetImpl<Key, Compare, Rep>;
+template <typename Key, typename Compare = std::less<Key>>
+using QuicSmallOrderedSet = QuicSmallOrderedSetImpl<Key, Compare>;
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers_test.cc
deleted file mode 100644
index bc255d36dcf..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_containers_test.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "quic/platform/api/quic_containers.h"
-
-#include "quic/platform/api/quic_test.h"
-
-using ::testing::ElementsAre;
-
-namespace quic {
-namespace test {
-namespace {
-
-TEST(QuicInlinedVectorTest, Swap) {
- {
- // Inline to inline.
- QuicInlinedVector<int, 2> self({1, 2});
- QuicInlinedVector<int, 2> other({3});
-
- self.swap(other);
-
- EXPECT_THAT(self, ElementsAre(3));
- EXPECT_THAT(other, ElementsAre(1, 2));
- }
-
- {
- // Inline to out-of-line.
- QuicInlinedVector<int, 2> self({1, 2});
- QuicInlinedVector<int, 2> other({3, 4, 5, 6});
-
- self.swap(other);
-
- EXPECT_THAT(self, ElementsAre(3, 4, 5, 6));
- EXPECT_THAT(other, ElementsAre(1, 2));
- }
-
- {
- // Out-of-line to inline.
- QuicInlinedVector<int, 2> self({1, 2, 3});
- QuicInlinedVector<int, 2> other({4, 5});
-
- self.swap(other);
-
- EXPECT_THAT(self, ElementsAre(4, 5));
- EXPECT_THAT(other, ElementsAre(1, 2, 3));
- }
-
- {
- // Out-of-line to Out-of-line.
- QuicInlinedVector<int, 2> self({1, 2, 3});
- QuicInlinedVector<int, 2> other({4, 5, 6, 7});
-
- self.swap(other);
-
- EXPECT_THAT(self, ElementsAre(4, 5, 6, 7));
- EXPECT_THAT(other, ElementsAre(1, 2, 3));
- }
-}
-
-} // namespace
-} // namespace test
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_estimate_memory_usage.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_estimate_memory_usage.h
deleted file mode 100644
index a5a093b9f1c..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_estimate_memory_usage.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_ESTIMATE_MEMORY_USAGE_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_ESTIMATE_MEMORY_USAGE_H_
-
-#include <cstddef>
-
-#include "quiche_platform_impl/quiche_estimate_memory_usage_impl.h"
-
-namespace quic {
-
-template <class T>
-size_t QuicEstimateMemoryUsage(const T& object) {
- return quiche::QuicheEstimateMemoryUsageImpl(object);
-}
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_ESTIMATE_MEMORY_USAGE_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc
deleted file mode 100644
index 5cb310baf9f..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.cc
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2019 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "quic/platform/api/quic_file_utils.h"
-
-#include "absl/strings/string_view.h"
-#include "net/quic/platform/impl/quic_file_utils_impl.h"
-
-namespace quic {
-
-// Traverses the directory |dirname| and retuns all of the files
-// it contains.
-std::vector<std::string> ReadFileContents(const std::string& dirname) {
- return ReadFileContentsImpl(dirname);
-}
-
-// Reads the contents of |filename| as a string into |contents|.
-void ReadFileContents(absl::string_view filename, std::string* contents) {
- ReadFileContentsImpl(filename, contents);
-}
-
-} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h
deleted file mode 100644
index a1f881f63a6..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_file_utils.h
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_FILE_UTILS_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_FILE_UTILS_H_
-
-#include <string>
-#include <vector>
-
-#include "absl/strings/string_view.h"
-#include "quic/platform/api/quic_export.h"
-
-namespace quic {
-
-// Traverses the directory |dirname| and returns all of the files it contains.
-QUIC_EXPORT_PRIVATE std::vector<std::string> ReadFileContents(
- const std::string& dirname);
-
-// Reads the contents of |filename| as a string into |contents|.
-QUIC_EXPORT_PRIVATE void ReadFileContents(absl::string_view filename,
- std::string* contents);
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_FILE_UTILS_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
index 788cb2d5425..398f44a4a75 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_hostname_utils_test.cc
@@ -19,10 +19,7 @@ TEST_F(QuicHostnameUtilsTest, IsValidSNI) {
// IP as SNI.
EXPECT_FALSE(QuicHostnameUtils::IsValidSNI("192.168.0.1"));
// SNI without any dot.
- SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots, true);
EXPECT_TRUE(QuicHostnameUtils::IsValidSNI("somedomain"));
- SetQuicReloadableFlag(quic_and_tls_allow_sni_without_dots, false);
- EXPECT_FALSE(QuicHostnameUtils::IsValidSNI("somedomain"));
// Invalid by RFC2396 but unfortunately domains of this form exist.
EXPECT_TRUE(QuicHostnameUtils::IsValidSNI("some_domain.com"));
// An empty string must be invalid otherwise the QUIC client will try sending
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_map_util.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_map_util.h
deleted file mode 100644
index 95daec82c30..00000000000
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_map_util.h
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_QUIC_PLATFORM_API_QUIC_MAP_UTIL_H_
-#define QUICHE_QUIC_PLATFORM_API_QUIC_MAP_UTIL_H_
-
-#include "net/quic/platform/impl/quic_map_util_impl.h"
-
-namespace quic {
-
-template <class Collection, class Key>
-bool QuicContainsKey(const Collection& collection, const Key& key) {
- return QuicContainsKeyImpl(collection, key);
-}
-
-template <typename Collection, typename Value>
-bool QuicContainsValue(const Collection& collection, const Value& value) {
- return QuicContainsValueImpl(collection, value);
-}
-
-} // namespace quic
-
-#endif // QUICHE_QUIC_PLATFORM_API_QUIC_MAP_UTIL_H_
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
index 32e64575b25..adc03d45d8c 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice.h
@@ -6,6 +6,8 @@
#define QUICHE_QUIC_PLATFORM_API_QUIC_MEM_SLICE_H_
#include <memory>
+
+#include "absl/strings/string_view.h"
#include "quic/platform/api/quic_export.h"
#include "net/quic/platform/impl/quic_mem_slice_impl.h"
@@ -31,9 +33,20 @@ class QUIC_EXPORT_PRIVATE QuicMemSlice {
// Constructs a QuicMemSlice that takes ownership of |buffer|. |length| must
// not be zero. To construct an empty QuicMemSlice, use the zero-argument
// constructor instead.
+ // TODO(vasilvv): switch all users to QuicBuffer version, and make this
+ // private.
QuicMemSlice(QuicUniqueBufferPtr buffer, size_t length)
: impl_(std::move(buffer), length) {}
+ // Constructs a QuicMemSlice that takes ownership of |buffer|. The length of
+ // the |buffer| must not be zero. To construct an empty QuicMemSlice, use the
+ // zero-argument constructor instead.
+ explicit QuicMemSlice(QuicBuffer buffer) : QuicMemSlice() {
+ // Store the size of the buffer *before* calling buffer.Release().
+ const size_t size = buffer.size();
+ *this = QuicMemSlice(buffer.Release(), size);
+ }
+
// Constructs a QuicMemSlice that takes ownership of |buffer| allocated on
// heap. |length| must not be zero.
QuicMemSlice(std::unique_ptr<char[]> buffer, size_t length)
@@ -61,6 +74,10 @@ class QUIC_EXPORT_PRIVATE QuicMemSlice {
const char* data() const { return impl_.data(); }
// Returns the length of underlying data buffer.
size_t length() const { return impl_.length(); }
+ // Returns the representation of the underlying data as a string view.
+ absl::string_view AsStringView() const {
+ return absl::string_view(data(), length());
+ }
bool empty() const { return impl_.empty(); }
diff --git a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
index 380c462f880..44095dffa01 100644
--- a/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/platform/api/quic_mem_slice_test.cc
@@ -5,6 +5,9 @@
#include "quic/platform/api/quic_mem_slice.h"
#include <memory>
+
+#include "absl/strings/string_view.h"
+#include "quic/core/quic_buffer_allocator.h"
#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/platform/api/quic_test.h"
@@ -56,6 +59,18 @@ TEST_F(QuicMemSliceTest, SliceAllocatedOnHeap) {
EXPECT_EQ(moved.length(), used_length);
}
+TEST_F(QuicMemSliceTest, SliceFromBuffer) {
+ const absl::string_view kTestString =
+ "RFC 9000 Release Celebration Memorial Test String";
+ auto buffer = QuicBuffer::Copy(&allocator_, kTestString);
+ QuicMemSlice slice(std::move(buffer));
+
+ EXPECT_EQ(buffer.data(), nullptr); // NOLINT(bugprone-use-after-move)
+ EXPECT_EQ(buffer.size(), 0u);
+ EXPECT_EQ(slice.AsStringView(), kTestString);
+ EXPECT_EQ(slice.length(), kTestString.length());
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.cc
index c8a6517a4c3..dd996c5c55b 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.cc
@@ -49,6 +49,10 @@ bool TunDeviceController::UpdateAddress(const IpRange& desired_range) {
if (address_updated) {
current_address_ = desired_address;
+
+ for (const auto& cb : address_update_cbs_) {
+ cb(current_address_);
+ }
}
return address_updated;
@@ -110,6 +114,19 @@ bool TunDeviceController::UpdateRoutes(
return true;
}
+bool TunDeviceController::UpdateRoutesWithRetries(
+ const IpRange& desired_range,
+ const std::vector<IpRange>& desired_routes,
+ int retries) {
+ while (retries-- > 0) {
+ if (UpdateRoutes(desired_range, desired_routes)) {
+ return true;
+ }
+ absl::SleepFor(absl::Milliseconds(100));
+ }
+ return false;
+}
+
bool TunDeviceController::UpdateRules(IpRange desired_range) {
if (!absl::GetFlag(FLAGS_qbone_tun_device_replace_default_routing_rules)) {
return true;
@@ -148,4 +165,9 @@ QuicIpAddress TunDeviceController::current_address() {
return current_address_;
}
+void TunDeviceController::RegisterAddressUpdateCallback(
+ const std::function<void(QuicIpAddress)>& cb) {
+ address_update_cbs_.push_back(cb);
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.h b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.h
index 6854521014f..612e98f5222 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller.h
@@ -39,6 +39,20 @@ class TunDeviceController {
virtual bool UpdateRoutes(const IpRange& desired_range,
const std::vector<IpRange>& desired_routes);
+ // Same as UpdateRoutes, but will wait and retry up to the number of times
+ // given by |retries| before giving up. This is an unpleasant workaround to
+ // deal with older kernels that aren't always able to set a route with a
+ // source address immediately after adding the address to the interface.
+ //
+ // TODO(b/179430548): Remove this once we've root-caused the underlying issue.
+ virtual bool UpdateRoutesWithRetries(
+ const IpRange& desired_range,
+ const std::vector<IpRange>& desired_routes,
+ int retries);
+
+ virtual void RegisterAddressUpdateCallback(
+ const std::function<void(QuicIpAddress)>& cb);
+
virtual QuicIpAddress current_address();
private:
@@ -51,6 +65,8 @@ class TunDeviceController {
NetlinkInterface* netlink_;
QuicIpAddress current_address_;
+
+ std::vector<std::function<void(QuicIpAddress)>> address_update_cbs_;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller_test.cc
index 73a7abc2864..53e5b3c14c2 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/bonnet/tun_device_controller_test.cc
@@ -44,8 +44,10 @@ class TunDeviceControllerTest : public QuicTest {
public:
TunDeviceControllerTest()
: controller_(kIfname, true, &netlink_),
- link_local_range_(
- *QboneConstants::TerminatorLocalAddressRange()) {}
+ link_local_range_(*QboneConstants::TerminatorLocalAddressRange()) {
+ controller_.RegisterAddressUpdateCallback(
+ [this](QuicIpAddress address) { notified_address_ = address; });
+ }
protected:
void ExpectLinkInfo(const std::string& interface_name, int ifindex) {
@@ -60,6 +62,7 @@ class TunDeviceControllerTest : public QuicTest {
MockNetlink netlink_;
TunDeviceController controller_;
+ QuicIpAddress notified_address_;
IpRange link_local_range_;
};
@@ -77,6 +80,7 @@ TEST_F(TunDeviceControllerTest, AddressAppliedWhenNoneExisted) {
.WillOnce(Return(true));
EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
+ EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}
TEST_F(TunDeviceControllerTest, OldAddressesAreRemoved) {
@@ -110,6 +114,7 @@ TEST_F(TunDeviceControllerTest, OldAddressesAreRemoved) {
.WillOnce(Return(true));
EXPECT_TRUE(controller_.UpdateAddress(kIpRange));
+ EXPECT_THAT(notified_address_, Eq(kIpRange.FirstAddressInRange()));
}
TEST_F(TunDeviceControllerTest, UpdateRoutesRemovedOldRoutes) {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
index 52196239d13..985632ab72c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/platform/netlink.cc
@@ -12,7 +12,6 @@
#include "quic/core/crypto/quic_random.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_logging.h"
-#include "net/quic/platform/impl/quic_ip_address_impl.h"
#include "quic/qbone/platform/rtnetlink_message.h"
namespace quic {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
index 944257f7af2..7303b06091a 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_control_stream.cc
@@ -4,6 +4,8 @@
#include "quic/qbone/qbone_control_stream.h"
+#include <cstdint>
+#include <limits>
#include "absl/strings/string_view.h"
#include "quic/core/quic_session.h"
#include "quic/platform/api/quic_bug_tracker.h"
@@ -51,10 +53,10 @@ bool QboneControlStreamBase::SendMessage(const proto2::Message& proto) {
QUIC_BUG(quic_bug_11023_1) << "Failed to serialize QboneControlRequest";
return false;
}
- if (tmp.size() > kuint16max) {
+ if (tmp.size() > std::numeric_limits<uint16_t>::max()) {
QUIC_BUG(quic_bug_11023_2)
<< "QboneControlRequest too large: " << tmp.size() << " > "
- << kuint16max;
+ << std::numeric_limits<uint16_t>::max();
return false;
}
uint16_t size = tmp.size();
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
index 5ee52e1e065..f8acb4f6a86 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger.cc
@@ -14,7 +14,7 @@ bool QbonePacketExchanger::ReadAndDeliverPacket(
std::string error;
std::unique_ptr<QuicData> packet = ReadPacket(&blocked, &error);
if (packet == nullptr) {
- if (!blocked) {
+ if (!blocked && visitor_) {
visitor_->OnReadError(error);
}
return false;
@@ -31,11 +31,14 @@ void QbonePacketExchanger::WritePacketToNetwork(const char* packet,
if (WritePacket(packet, size, &blocked, &error)) {
return;
}
- if (!blocked) {
- visitor_->OnWriteError(error);
- return;
+ if (blocked) {
+ write_blocked_ = true;
+ } else {
+ QUIC_LOG_EVERY_N_SEC(ERROR, 60) << "Packet write failed: " << error;
+ if (visitor_) {
+ visitor_->OnWriteError(error);
+ }
}
- write_blocked_ = true;
}
// Drop the packet on the floor if the queue if full.
@@ -58,7 +61,7 @@ void QbonePacketExchanger::SetWritable() {
packet_queue_.front()->length(), &blocked, &error)) {
packet_queue_.pop_front();
} else {
- if (!blocked) {
+ if (!blocked && visitor_) {
visitor_->OnWriteError(error);
}
write_blocked_ = blocked;
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
index a2b502fa26f..5db87536aba 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_exchanger_test.cc
@@ -251,5 +251,21 @@ TEST(QbonePacketExchangerTest, WriteErrorsGetNotified) {
ASSERT_TRUE(exchanger.packets_written().empty());
}
+TEST(QbonePacketExchangerTest, NullVisitorDoesntCrash) {
+ FakeQbonePacketExchanger exchanger(nullptr, kMaxPendingPackets);
+ MockQboneClient client;
+ std::string packet = "data";
+
+ // Force read error.
+ std::string io_error = "I/O error";
+ exchanger.SetReadError(io_error);
+ EXPECT_FALSE(exchanger.ReadAndDeliverPacket(&client));
+
+ // Force write error
+ exchanger.ForceWriteFailure(false, io_error);
+ exchanger.WritePacketToNetwork(packet.data(), packet.length());
+ EXPECT_TRUE(exchanger.packets_written().empty());
+}
+
} // namespace
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
index 7b45ed1050b..6e83e760f3b 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.cc
@@ -103,6 +103,10 @@ void QbonePacketProcessor::ProcessPacket(std::string* packet,
SendTcpReset(*packet, direction);
stats_->OnPacketDroppedWithTcpReset(direction);
break;
+ case ProcessingResult::TCP_RESET:
+ SendTcpReset(*packet, direction);
+ stats_->OnPacketDroppedWithTcpReset(direction);
+ break;
}
}
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
index c85280fe18f..8c2375a288c 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_packet_processor.h
@@ -46,6 +46,8 @@ class QbonePacketProcessor {
// RST requires information from the current connection state to be
// well-formed.
ICMP_AND_TCP_RESET = 4,
+ // Send a TCP RST.
+ TCP_RESET = 5,
};
class OutputInterface {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
index e984196faf0..2f2f31e3239 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_base.cc
@@ -140,11 +140,9 @@ void QboneSessionBase::SendPacketToPeer(absl::string_view packet) {
}
if (send_packets_as_messages_) {
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(
- connection()->helper()->GetStreamSendBufferAllocator(), packet.size());
- memcpy(buffer.get(), packet.data(), packet.size());
- QuicMemSlice slice(std::move(buffer), packet.size());
- switch (SendMessage(QuicMemSliceSpan(&slice), /*flush=*/true).status) {
+ QuicMemSlice slice(QuicBuffer::Copy(
+ connection()->helper()->GetStreamSendBufferAllocator(), packet));
+ switch (SendMessage(absl::MakeSpan(&slice, 1), /*flush=*/true).status) {
case MESSAGE_STATUS_SUCCESS:
break;
case MESSAGE_STATUS_TOO_LARGE: {
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
index fb9a288cbeb..9887f79a46e 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_session_test.cc
@@ -117,6 +117,14 @@ class IndirectionProofSource : public ProofSource {
std::move(callback));
}
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override {
+ if (!proof_source_) {
+ return {};
+ }
+ return proof_source_->SupportedTlsSignatureAlgorithms();
+ }
+
TicketCrypter* GetTicketCrypter() override { return nullptr; }
private:
diff --git a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
index bcbc5a514e8..fc2ce819d90 100644
--- a/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/qbone/qbone_stream_test.cc
@@ -40,12 +40,10 @@ class MockQuicSession : public QboneSessionBase {
~MockQuicSession() override {}
// Writes outgoing data from QuicStream to a string.
- QuicConsumedData WritevData(QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
+ QuicConsumedData WritevData(QuicStreamId id, size_t write_length,
+ QuicStreamOffset offset, StreamSendingState state,
TransmissionType type,
- absl::optional<EncryptionLevel> level) override {
+ EncryptionLevel level) override {
if (!writable_) {
return QuicConsumedData(0, false);
}
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
index 00264e59a09..d28b4faff85 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/crypto_test_utils.cc
@@ -743,6 +743,12 @@ void MovePackets(PacketSavingConnection* source_conn,
size_t index = *inout_packet_index;
for (; index < source_conn->encrypted_packets_.size(); index++) {
+ if (!dest_conn->connected()) {
+ QUIC_LOG(INFO)
+ << "Destination connection disconnected. Skipping packet at index "
+ << index;
+ continue;
+ }
// In order to properly test the code we need to perform encryption and
// decryption so that the crypters latch when expected. The crypters are in
// |dest_conn|, but we don't want to try and use them there. Instead we swap
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
index 4f771a33ebc..447b77066bd 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/failing_proof_source.h
@@ -34,6 +34,11 @@ class FailingProofSource : public ProofSource {
absl::string_view in,
std::unique_ptr<SignatureCallback> callback) override;
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override {
+ return {};
+ }
+
TicketCrypter* GetTicketCrypter() override { return nullptr; }
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
index bc75678872f..1109d659fac 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.cc
@@ -123,6 +123,11 @@ void FakeProofSource::ComputeTlsSignature(
std::move(callback), delegate_.get()));
}
+absl::InlinedVector<uint16_t, 8>
+FakeProofSource::SupportedTlsSignatureAlgorithms() const {
+ return delegate_->SupportedTlsSignatureAlgorithms();
+}
+
ProofSource::TicketCrypter* FakeProofSource::GetTicketCrypter() {
if (ticket_crypter_) {
return ticket_crypter_.get();
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
index 077f34d074f..c088d43a9bb 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source.h
@@ -52,6 +52,8 @@ class FakeProofSource : public ProofSource {
uint16_t signature_algorithm,
absl::string_view in,
std::unique_ptr<ProofSource::SignatureCallback> callback) override;
+ absl::InlinedVector<uint16_t, 8> SupportedTlsSignatureAlgorithms()
+ const override;
TicketCrypter* GetTicketCrypter() override;
// Sets the TicketCrypter to use. If nullptr, the TicketCrypter from
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
index b1fedf8c161..f34247e9bae 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.cc
@@ -63,9 +63,10 @@ FakeProofSourceHandle::FakeProofSourceHandle(
select_cert_action_(select_cert_action),
compute_signature_action_(compute_signature_action) {}
-void FakeProofSourceHandle::CancelPendingOperation() {
+void FakeProofSourceHandle::CloseHandle() {
select_cert_op_.reset();
compute_signature_op_.reset();
+ closed_ = true;
}
QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
@@ -77,10 +78,12 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
const std::string& alpn,
absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
- const absl::optional<std::vector<uint8_t>>& early_data_context) {
+ const absl::optional<std::vector<uint8_t>>& early_data_context,
+ const QuicSSLConfig& ssl_config) {
+ QUICHE_CHECK(!closed_);
all_select_cert_args_.push_back(SelectCertArgs(
server_address, client_address, ssl_capabilities, hostname, client_hello,
- alpn, alps, quic_transport_params, early_data_context));
+ alpn, alps, quic_transport_params, early_data_context, ssl_config));
if (select_cert_action_ == Action::DELEGATE_ASYNC ||
select_cert_action_ == Action::FAIL_ASYNC) {
@@ -90,7 +93,8 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
} else if (select_cert_action_ == Action::FAIL_SYNC) {
callback()->OnSelectCertificateDone(
/*ok=*/false,
- /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view());
+ /*is_sync=*/true, nullptr, /*handshake_hints=*/absl::string_view(),
+ /*ticket_encryption_key=*/absl::string_view());
return QUIC_FAILURE;
}
@@ -99,8 +103,10 @@ QuicAsyncStatus FakeProofSourceHandle::SelectCertificate(
delegate_->GetCertChain(server_address, client_address, hostname);
bool ok = chain && !chain->certs.empty();
- callback_->OnSelectCertificateDone(ok, /*is_sync=*/true, chain.get(),
- /*handshake_hints=*/absl::string_view());
+ callback_->OnSelectCertificateDone(
+ ok, /*is_sync=*/true, chain.get(),
+ /*handshake_hints=*/absl::string_view(),
+ /*ticket_encryption_key=*/absl::string_view());
return ok ? QUIC_SUCCESS : QUIC_FAILURE;
}
@@ -111,6 +117,7 @@ QuicAsyncStatus FakeProofSourceHandle::ComputeSignature(
uint16_t signature_algorithm,
absl::string_view in,
size_t max_signature_size) {
+ QUICHE_CHECK(!closed_);
all_compute_signature_args_.push_back(
ComputeSignatureArgs(server_address, client_address, hostname,
signature_algorithm, in, max_signature_size));
@@ -171,16 +178,20 @@ FakeProofSourceHandle::SelectCertOperation::SelectCertOperation(
void FakeProofSourceHandle::SelectCertOperation::Run() {
if (action_ == Action::FAIL_ASYNC) {
- callback_->OnSelectCertificateDone(/*ok=*/false,
- /*is_sync=*/false, nullptr,
- /*handshake_hints=*/absl::string_view());
+ callback_->OnSelectCertificateDone(
+ /*ok=*/false,
+ /*is_sync=*/false, nullptr,
+ /*handshake_hints=*/absl::string_view(),
+ /*ticket_encryption_key=*/absl::string_view());
} else if (action_ == Action::DELEGATE_ASYNC) {
QuicReferenceCountedPointer<ProofSource::Chain> chain =
delegate_->GetCertChain(args_.server_address, args_.client_address,
args_.hostname);
bool ok = chain && !chain->certs.empty();
- callback_->OnSelectCertificateDone(ok, /*is_sync=*/false, chain.get(),
- /*handshake_hints=*/absl::string_view());
+ callback_->OnSelectCertificateDone(
+ ok, /*is_sync=*/false, chain.get(),
+ /*handshake_hints=*/absl::string_view(),
+ /*ticket_encryption_key=*/absl::string_view());
} else {
QUIC_BUG(quic_bug_10139_1)
<< "Unexpected action: " << static_cast<int>(action_);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
index d2b991896f8..3d038a4d58b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/fake_proof_source_handle.h
@@ -35,7 +35,7 @@ class FakeProofSourceHandle : public ProofSourceHandle {
~FakeProofSourceHandle() override = default;
- void CancelPendingOperation() override;
+ void CloseHandle() override;
QuicAsyncStatus SelectCertificate(
const QuicSocketAddress& server_address,
@@ -46,7 +46,8 @@ class FakeProofSourceHandle : public ProofSourceHandle {
const std::string& alpn,
absl::optional<std::string> alps,
const std::vector<uint8_t>& quic_transport_params,
- const absl::optional<std::vector<uint8_t>>& early_data_context) override;
+ const absl::optional<std::vector<uint8_t>>& early_data_context,
+ const QuicSSLConfig& ssl_config) override;
QuicAsyncStatus ComputeSignature(const QuicSocketAddress& server_address,
const QuicSocketAddress& client_address,
@@ -70,7 +71,8 @@ class FakeProofSourceHandle : public ProofSourceHandle {
std::string alpn,
absl::optional<std::string> alps,
std::vector<uint8_t> quic_transport_params,
- absl::optional<std::vector<uint8_t>> early_data_context)
+ absl::optional<std::vector<uint8_t>> early_data_context,
+ QuicSSLConfig ssl_config)
: server_address(server_address),
client_address(client_address),
ssl_capabilities(ssl_capabilities),
@@ -79,7 +81,8 @@ class FakeProofSourceHandle : public ProofSourceHandle {
alpn(alpn),
alps(alps),
quic_transport_params(quic_transport_params),
- early_data_context(early_data_context) {}
+ early_data_context(early_data_context),
+ ssl_config(ssl_config) {}
QuicSocketAddress server_address;
QuicSocketAddress client_address;
@@ -90,6 +93,7 @@ class FakeProofSourceHandle : public ProofSourceHandle {
absl::optional<std::string> alps;
std::vector<uint8_t> quic_transport_params;
absl::optional<std::vector<uint8_t>> early_data_context;
+ QuicSSLConfig ssl_config;
};
struct ComputeSignatureArgs {
@@ -171,6 +175,7 @@ class FakeProofSourceHandle : public ProofSourceHandle {
private:
int NumPendingOperations() const;
+ bool closed_ = false;
ProofSource* delegate_;
ProofSourceHandleCallback* callback_;
// Action for the next select cert operation.
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
index 35cc9785209..76dd778734c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/packet_dropping_test_writer.cc
@@ -68,7 +68,14 @@ PacketDroppingTestWriter::PacketDroppingTestWriter()
simple_random_.set_seed(seed);
}
-PacketDroppingTestWriter::~PacketDroppingTestWriter() = default;
+PacketDroppingTestWriter::~PacketDroppingTestWriter() {
+ if (write_unblocked_alarm_ != nullptr) {
+ write_unblocked_alarm_->PermanentCancel();
+ }
+ if (delay_alarm_ != nullptr) {
+ delay_alarm_->PermanentCancel();
+ }
+}
void PacketDroppingTestWriter::Initialize(
QuicConnectionHelperInterface* helper,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
index 0f681fef83a..a7ea1be114b 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/qpack/qpack_offline_decoder.cc
@@ -35,9 +35,9 @@
#include "absl/strings/str_split.h"
#include "absl/strings/string_view.h"
#include "quic/core/quic_types.h"
-#include "quic/platform/api/quic_file_utils.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/test_tools/qpack/qpack_test_utils.h"
+#include "common/platform/api/quiche_file_utils.h"
#include "common/quiche_endian.h"
namespace quic {
@@ -69,8 +69,7 @@ bool QpackOfflineDecoder::DecodeAndVerifyOfflineData(
}
void QpackOfflineDecoder::OnEncoderStreamError(
- QuicErrorCode error_code,
- absl::string_view error_message) {
+ QuicErrorCode error_code, absl::string_view error_message) {
QUIC_LOG(ERROR) << "Encoder stream error: "
<< QuicErrorCodeToString(error_code) << " " << error_message;
encoder_stream_error_detected_ = true;
@@ -87,12 +86,7 @@ bool QpackOfflineDecoder::ParseInputFilename(absl::string_view input_filename) {
auto piece_it = pieces.rbegin();
// Acknowledgement mode: 1 for immediate, 0 for none.
- bool immediate_acknowledgement = false;
- if (*piece_it == "0") {
- immediate_acknowledgement = false;
- } else if (*piece_it == "1") {
- immediate_acknowledgement = true;
- } else {
+ if (*piece_it != "0" && *piece_it != "1") {
QUIC_LOG(ERROR)
<< "Header acknowledgement field must be 0 or 1 in input filename "
<< input_filename;
@@ -136,9 +130,10 @@ bool QpackOfflineDecoder::DecodeHeaderBlocksFromFile(
absl::string_view input_filename) {
// Store data in |input_data_storage|; use a absl::string_view to
// efficiently keep track of remaining portion yet to be decoded.
- std::string input_data_storage;
- ReadFileContents(input_filename, &input_data_storage);
- absl::string_view input_data(input_data_storage);
+ absl::optional<std::string> input_data_storage =
+ quiche::ReadFileContents(input_filename);
+ QUICHE_DCHECK(input_data_storage.has_value());
+ absl::string_view input_data(*input_data_storage);
while (!input_data.empty()) {
// Parse stream_id and length.
@@ -233,9 +228,10 @@ bool QpackOfflineDecoder::VerifyDecodedHeaderLists(
// Store data in |expected_headers_data_storage|; use a
// absl::string_view to efficiently keep track of remaining portion
// yet to be decoded.
- std::string expected_headers_data_storage;
- ReadFileContents(expected_headers_filename, &expected_headers_data_storage);
- absl::string_view expected_headers_data(expected_headers_data_storage);
+ absl::optional<std::string> expected_headers_data_storage =
+ quiche::ReadFileContents(expected_headers_filename);
+ QUICHE_DCHECK(expected_headers_data_storage.has_value());
+ absl::string_view expected_headers_data(*expected_headers_data_storage);
while (!decoded_header_lists_.empty()) {
spdy::Http2HeaderBlock decoded_header_list =
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
index 71036cb2512..43c345094ef 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.cc
@@ -398,11 +398,7 @@ QuicIdleNetworkDetector& QuicConnectionPeer::GetIdleNetworkDetector(
void QuicConnectionPeer::SetServerConnectionId(
QuicConnection* connection,
const QuicConnectionId& server_connection_id) {
- if (connection->use_connection_id_on_default_path_) {
- connection->default_path_.server_connection_id = server_connection_id;
- } else {
- connection->server_connection_id_ = server_connection_id;
- }
+ connection->default_path_.server_connection_id = server_connection_id;
connection->InstallInitialCrypters(server_connection_id);
}
@@ -430,7 +426,7 @@ void QuicConnectionPeer::SendPing(QuicConnection* connection) {
void QuicConnectionPeer::SetLastPacketDestinationAddress(
QuicConnection* connection,
const QuicSocketAddress& address) {
- connection->last_packet_destination_address_ = address;
+ connection->last_received_packet_info_.destination_address = address;
}
// static
@@ -525,5 +521,12 @@ bool QuicConnectionPeer::HasSelfIssuedConnectionIdToConsume(
return connection->self_issued_cid_manager_->HasConnectionIdToConsume();
}
+// static
+QuicSelfIssuedConnectionIdManager*
+QuicConnectionPeer::GetSelfIssuedConnectionIdManager(
+ QuicConnection* connection) {
+ return connection->self_issued_cid_manager_.get();
+}
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
index cbc829a7a65..99b8b94fd74 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_connection_peer.h
@@ -213,6 +213,9 @@ class QuicConnectionPeer {
static bool HasSelfIssuedConnectionIdToConsume(
const QuicConnection* connection);
+
+ static QuicSelfIssuedConnectionIdManager* GetSelfIssuedConnectionIdManager(
+ QuicConnection* connection);
};
} // namespace test
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
index 14cc59418f5..8692a25c685 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_framer_peer.cc
@@ -6,7 +6,6 @@
#include "quic/core/quic_framer.h"
#include "quic/core/quic_packets.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
namespace test {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
index a3dbf843e58..e734a794aea 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_session_peer.cc
@@ -8,7 +8,6 @@
#include "quic/core/quic_session.h"
#include "quic/core/quic_stream.h"
#include "quic/core/quic_utils.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
namespace test {
@@ -152,24 +151,20 @@ bool QuicSessionPeer::IsStreamClosed(QuicSession* session, QuicStreamId id) {
// static
bool QuicSessionPeer::IsStreamCreated(QuicSession* session, QuicStreamId id) {
- return QuicContainsKey(session->stream_map_, id);
+ return session->stream_map_.contains(id);
}
// static
bool QuicSessionPeer::IsStreamAvailable(QuicSession* session, QuicStreamId id) {
if (VersionHasIetfQuicFrames(session->transport_version())) {
if (id % QuicUtils::StreamIdDelta(session->transport_version()) < 2) {
- return QuicContainsKey(
- session->ietf_streamid_manager_.bidirectional_stream_id_manager_
- .available_streams_,
- id);
+ return session->ietf_streamid_manager_.bidirectional_stream_id_manager_
+ .available_streams_.contains(id);
}
- return QuicContainsKey(
- session->ietf_streamid_manager_.unidirectional_stream_id_manager_
- .available_streams_,
- id);
+ return session->ietf_streamid_manager_.unidirectional_stream_id_manager_
+ .available_streams_.contains(id);
}
- return QuicContainsKey(session->stream_id_manager_.available_streams_, id);
+ return session->stream_id_manager_.available_streams_.contains(id);
}
// static
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
index c547ac22610..a27f073e993 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.cc
@@ -106,8 +106,13 @@ void QuicSpdySessionPeer::SetH3DatagramSupported(QuicSpdySession* session,
}
// static
+bool QuicSpdySessionPeer::ShouldNegotiateHttp3Datagram(
+ QuicSpdySession* session) {
+ return session->ShouldNegotiateHttp3Datagram();
+}
+
+// static
void QuicSpdySessionPeer::EnableWebTransport(QuicSpdySession& session) {
- SetQuicReloadableFlag(quic_h3_datagram, true);
QUICHE_DCHECK(session.WillNegotiateWebTransport());
session.h3_datagram_supported_ = true;
session.peer_supports_webtransport_ = true;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
index 9ba54979e9a..0d06c4ddfad 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_spdy_session_peer.h
@@ -52,6 +52,7 @@ class QuicSpdySessionPeer {
QuicSpdySession* session);
static void SetH3DatagramSupported(QuicSpdySession* session,
bool h3_datagram_supported);
+ static bool ShouldNegotiateHttp3Datagram(QuicSpdySession* session);
static void EnableWebTransport(QuicSpdySession& session);
};
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
index 7cc3ff9be3b..598e14cb1b0 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.cc
@@ -618,16 +618,12 @@ const std::string& QuicTestClient::cert_sct() const {
->cert_sct();
}
-QuicTagValueMap QuicTestClient::GetServerConfig() const {
+const QuicTagValueMap& QuicTestClient::GetServerConfig() const {
QuicCryptoClientConfig* config = client_->crypto_config();
- QuicCryptoClientConfig::CachedState* state =
+ const QuicCryptoClientConfig::CachedState* state =
config->LookupOrCreate(client_->server_id());
const CryptoHandshakeMessage* handshake_msg = state->GetServerConfig();
- if (handshake_msg != nullptr) {
- return handshake_msg->tag_value_map();
- } else {
- return QuicTagValueMap();
- }
+ return handshake_msg->tag_value_map();
}
bool QuicTestClient::connected() const {
@@ -786,7 +782,7 @@ void QuicTestClient::OnClose(QuicSpdyStream* stream) {
// written.
client()->OnClose(stream);
++num_responses_;
- if (!QuicContainsKey(open_streams_, stream->id())) {
+ if (open_streams_.find(stream->id()) == open_streams_.end()) {
return;
}
if (latest_created_stream_ == stream) {
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
index d764ca9d2a5..66ebb5bc736 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_client.h
@@ -14,11 +14,10 @@
#include "quic/core/quic_framer.h"
#include "quic/core/quic_packet_creator.h"
#include "quic/core/quic_packets.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_epoll.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/tools/quic_client.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -282,8 +281,8 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
// or the empty std::string if no signed timestamp was presented.
const std::string& cert_sct() const;
- // Get the server config map.
- QuicTagValueMap GetServerConfig() const;
+ // Get the server config map. Server config must exist.
+ const QuicTagValueMap& GetServerConfig() const;
void set_auto_reconnect(bool reconnect) { auto_reconnect_ = reconnect; }
@@ -401,7 +400,8 @@ class QuicTestClient : public QuicSpdyStream::Visitor,
QuicSpdyClientStream* latest_created_stream_;
std::map<QuicStreamId, QuicSpdyClientStream*> open_streams_;
// Received responses of closed streams.
- QuicLinkedHashMap<QuicStreamId, PerStreamState> closed_stream_states_;
+ quiche::QuicheLinkedHashMap<QuicStreamId, PerStreamState>
+ closed_stream_states_;
QuicRstStreamErrorCode stream_error_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
index 5feb6462321..126b87e039c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.cc
@@ -191,7 +191,11 @@ std::unique_ptr<QuicPacket> BuildUnsizedDataPacket(
EncryptionLevel level = HeaderToEncryptionLevel(header);
size_t length =
framer->BuildDataPacket(header, frames, buffer, packet_size, level);
- QUICHE_DCHECK_NE(0u, length);
+
+ if (length == 0) {
+ delete[] buffer;
+ return nullptr;
+ }
// Re-construct the data packet with data ownership.
return std::make_unique<QuicPacket>(
buffer, length, /* owns_buffer */ true,
@@ -1323,10 +1327,12 @@ QuicMemSliceSpan MakeSpan(QuicBufferAllocator* allocator,
}
QuicMemSlice MemSliceFromString(absl::string_view data) {
+ if (data.empty()) {
+ return QuicMemSlice();
+ }
+
static SimpleBufferAllocator* allocator = new SimpleBufferAllocator();
- QuicUniqueBufferPtr buffer = MakeUniqueBuffer(allocator, data.size());
- memcpy(buffer.get(), data.data(), data.size());
- return QuicMemSlice(std::move(buffer), data.size());
+ return QuicMemSlice(QuicBuffer::Copy(allocator, data));
}
bool TaggingEncrypter::EncryptPacket(uint64_t /*packet_number*/,
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
index 9fbffe0b76c..06f3eeca7c2 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/quic_test_utils.h
@@ -282,7 +282,7 @@ class SimpleRandom : public QuicRandom {
private:
uint8_t buffer_[4096];
- size_t buffer_offset_;
+ size_t buffer_offset_ = 0;
uint8_t key_[32];
void FillBuffer();
@@ -763,10 +763,8 @@ class MockQuicConnection : public QuicConnection {
(QuicStreamId, QuicRstStreamErrorCode),
(override));
MOCK_METHOD(bool, SendControlFrame, (const QuicFrame& frame), (override));
- MOCK_METHOD(MessageStatus,
- SendMessage,
- (QuicMessageId, QuicMemSliceSpan, bool),
- (override));
+ MOCK_METHOD(MessageStatus, SendMessage,
+ (QuicMessageId, absl::Span<QuicMemSlice>, bool), (override));
MOCK_METHOD(bool,
SendPathChallenge,
(const QuicPathFrameBuffer&,
@@ -904,14 +902,10 @@ class MockQuicSession : public QuicSession {
CreateIncomingStream,
(PendingStream*),
(override));
- MOCK_METHOD(QuicConsumedData,
- WritevData,
- (QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType type,
- absl::optional<EncryptionLevel> level),
+ MOCK_METHOD(QuicConsumedData, WritevData,
+ (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
+ StreamSendingState state, TransmissionType type,
+ EncryptionLevel level),
(override));
MOCK_METHOD(bool,
WriteControlFrame,
@@ -1042,14 +1036,10 @@ class MockQuicSpdySession : public QuicSpdySession {
MOCK_METHOD(bool, ShouldCreateIncomingStream, (QuicStreamId id), (override));
MOCK_METHOD(bool, ShouldCreateOutgoingBidirectionalStream, (), (override));
MOCK_METHOD(bool, ShouldCreateOutgoingUnidirectionalStream, (), (override));
- MOCK_METHOD(QuicConsumedData,
- WritevData,
- (QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType type,
- absl::optional<EncryptionLevel> level),
+ MOCK_METHOD(QuicConsumedData, WritevData,
+ (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
+ StreamSendingState state, TransmissionType type,
+ EncryptionLevel level),
(override));
MOCK_METHOD(void,
MaybeSendRstStreamFrame,
@@ -1132,10 +1122,6 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor {
(override));
MOCK_METHOD(void,
- OnCancelPushFrameReceived,
- (const CancelPushFrame&),
- (override));
- MOCK_METHOD(void,
OnSettingsFrameReceived,
(const SettingsFrame&),
(override));
@@ -1166,14 +1152,6 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor {
(QuicStreamId, QuicHeaderList),
(override));
MOCK_METHOD(void,
- OnPushPromiseFrameReceived,
- (QuicStreamId, QuicStreamId, QuicByteCount),
- (override));
- MOCK_METHOD(void,
- OnPushPromiseDecoded,
- (QuicStreamId, QuicStreamId, QuicHeaderList),
- (override));
- MOCK_METHOD(void,
OnUnknownFrameReceived,
(QuicStreamId, uint64_t, QuicByteCount),
(override));
@@ -1191,10 +1169,6 @@ class MockHttp3DebugVisitor : public Http3DebugVisitor {
OnHeadersFrameSent,
(QuicStreamId, const spdy::SpdyHeaderBlock&),
(override));
- MOCK_METHOD(void,
- OnPushPromiseFrameSent,
- (QuicStreamId, QuicStreamId, const spdy::SpdyHeaderBlock&),
- (override));
};
class TestQuicSpdyServerSession : public QuicServerSessionBase {
@@ -1241,9 +1215,14 @@ class TestQuicSpdyServerSession : public QuicServerSessionBase {
MockQuicCryptoServerStreamHelper* helper() { return &helper_; }
+ QuicSSLConfig GetSSLConfig() const override { return ssl_config_; }
+
+ QuicSSLConfig* ssl_config() { return &ssl_config_; }
+
private:
MockQuicSessionVisitor visitor_;
MockQuicCryptoServerStreamHelper helper_;
+ QuicSSLConfig ssl_config_;
};
// A test implementation of QuicClientPushPromiseIndex::Delegate.
@@ -2318,31 +2297,49 @@ bool WriteServerVersionNegotiationProbeResponse(
uint8_t source_connection_id_length);
// Implementation of Http3DatagramVisitor which saves all received datagrams.
-class SavingHttp3DatagramVisitor
- : public QuicSpdySession::Http3DatagramVisitor {
+class SavingHttp3DatagramVisitor : public QuicSpdyStream::Http3DatagramVisitor {
public:
struct SavedHttp3Datagram {
- QuicDatagramFlowId flow_id;
+ QuicStreamId stream_id;
+ absl::optional<QuicDatagramContextId> context_id;
std::string payload;
bool operator==(const SavedHttp3Datagram& o) const {
- return flow_id == o.flow_id && payload == o.payload;
+ return stream_id == o.stream_id && context_id == o.context_id &&
+ payload == o.payload;
}
};
const std::vector<SavedHttp3Datagram>& received_h3_datagrams() const {
return received_h3_datagrams_;
}
- // Override from QuicSpdySession::Http3DatagramVisitor.
- void OnHttp3Datagram(QuicDatagramFlowId flow_id,
+ // Override from QuicSpdyStream::Http3DatagramVisitor.
+ void OnHttp3Datagram(QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
absl::string_view payload) override {
received_h3_datagrams_.push_back(
- SavedHttp3Datagram{flow_id, std::string(payload)});
+ SavedHttp3Datagram{stream_id, context_id, std::string(payload)});
}
private:
std::vector<SavedHttp3Datagram> received_h3_datagrams_;
};
+class MockHttp3DatagramRegistrationVisitor
+ : public QuicSpdyStream::Http3DatagramRegistrationVisitor {
+ public:
+ MOCK_METHOD(void, OnContextReceived,
+ (QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions),
+ (override));
+
+ MOCK_METHOD(void, OnContextClosed,
+ (QuicStreamId stream_id,
+ absl::optional<QuicDatagramContextId> context_id,
+ const Http3DatagramContextExtensions& extensions),
+ (override));
+};
+
} // namespace test
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
index 5ef53f4bf23..413a840e32c 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_data_producer.cc
@@ -10,7 +10,6 @@
#include "quic/core/quic_data_writer.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flags.h"
-#include "quic/platform/api/quic_map_util.h"
namespace quic {
@@ -28,7 +27,7 @@ void SimpleDataProducer::SaveStreamData(QuicStreamId id,
if (data_length == 0) {
return;
}
- if (!QuicContainsKey(send_buffer_map_, id)) {
+ if (!send_buffer_map_.contains(id)) {
send_buffer_map_[id] = std::make_unique<QuicStreamSendBuffer>(&allocator_);
}
send_buffer_map_[id]->SaveStreamData(iov, iov_count, iov_offset, data_length);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
index 51d4017948f..a1383b0e41d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.cc
@@ -6,7 +6,6 @@
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/test_tools/quic_test_utils.h"
namespace quic {
@@ -40,7 +39,7 @@ QuicConsumedData SimpleSessionNotifier::WriteOrBufferData(
QuicStreamId id,
QuicByteCount data_length,
StreamSendingState state) {
- if (!QuicContainsKey(stream_map_, id)) {
+ if (!stream_map_.contains(id)) {
stream_map_[id] = StreamState();
}
StreamState& stream_state = stream_map_.find(id)->second;
@@ -163,16 +162,14 @@ void SimpleSessionNotifier::NeuterUnencryptedData() {
}
void SimpleSessionNotifier::OnCanWrite() {
- if (connection_->donot_write_mid_packet_processing()) {
- if (connection_->framer().is_processing_packet()) {
- // Do not write data in the middle of packet processing because rest
- // frames in the packet may change the data to write. For example, lost
- // data could be acknowledged. Also, connection is going to emit
- // OnCanWrite signal post packet processing.
- QUIC_BUG(simple_notifier_write_mid_packet_processing)
- << "Try to write mid packet processing.";
- return;
- }
+ if (connection_->framer().is_processing_packet()) {
+ // Do not write data in the middle of packet processing because rest
+ // frames in the packet may change the data to write. For example, lost
+ // data could be acknowledged. Also, connection is going to emit
+ // OnCanWrite signal post packet processing.
+ QUIC_BUG(simple_notifier_write_mid_packet_processing)
+ << "Try to write mid packet processing.";
+ return;
}
if (!RetransmitLostCryptoData() || !RetransmitLostControlFrames() ||
!RetransmitLostStreamData()) {
@@ -263,7 +260,7 @@ bool SimpleSessionNotifier::OnFrameAcked(const QuicFrame& frame,
if (frame.type != STREAM_FRAME) {
return OnControlFrameAcked(frame);
}
- if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
+ if (!stream_map_.contains(frame.stream_frame.stream_id)) {
return false;
}
auto* state = &stream_map_.find(frame.stream_frame.stream_id)->second;
@@ -304,7 +301,7 @@ void SimpleSessionNotifier::OnFrameLost(const QuicFrame& frame) {
OnControlFrameLost(frame);
return;
}
- if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
+ if (!stream_map_.contains(frame.stream_frame.stream_id)) {
return;
}
auto* state = &stream_map_.find(frame.stream_frame.stream_id)->second;
@@ -359,7 +356,7 @@ void SimpleSessionNotifier::RetransmitFrames(const QuicFrames& frames,
}
continue;
}
- if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
+ if (!stream_map_.contains(frame.stream_frame.stream_id)) {
continue;
}
const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
@@ -437,7 +434,7 @@ bool SimpleSessionNotifier::IsFrameOutstanding(const QuicFrame& frame) const {
if (frame.type != STREAM_FRAME) {
return IsControlFrameOutstanding(frame);
}
- if (!QuicContainsKey(stream_map_, frame.stream_frame.stream_id)) {
+ if (!stream_map_.contains(frame.stream_frame.stream_id)) {
return false;
}
const auto& state = stream_map_.find(frame.stream_frame.stream_id)->second;
@@ -463,8 +460,8 @@ bool SimpleSessionNotifier::HasUnackedCryptoData() const {
}
return false;
}
- if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
- connection_->transport_version()))) {
+ if (!stream_map_.contains(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()))) {
return false;
}
const auto& state =
@@ -521,7 +518,7 @@ void SimpleSessionNotifier::OnControlFrameLost(const QuicFrame& frame) {
kInvalidControlFrameId) {
return;
}
- if (!QuicContainsKey(lost_control_frames_, id)) {
+ if (!lost_control_frames_.contains(id)) {
lost_control_frames_[id] = true;
}
}
@@ -584,8 +581,8 @@ bool SimpleSessionNotifier::RetransmitLostCryptoData() {
}
return true;
}
- if (!QuicContainsKey(stream_map_, QuicUtils::GetCryptoStreamId(
- connection_->transport_version()))) {
+ if (!stream_map_.contains(
+ QuicUtils::GetCryptoStreamId(connection_->transport_version()))) {
return true;
}
auto& state =
@@ -701,7 +698,7 @@ bool SimpleSessionNotifier::HasBufferedStreamData() const {
}
bool SimpleSessionNotifier::StreamIsWaitingForAcks(QuicStreamId id) const {
- if (!QuicContainsKey(stream_map_, id)) {
+ if (!stream_map_.contains(id)) {
return false;
}
const StreamState& state = stream_map_.find(id)->second;
@@ -710,7 +707,7 @@ bool SimpleSessionNotifier::StreamIsWaitingForAcks(QuicStreamId id) const {
}
bool SimpleSessionNotifier::StreamHasBufferedData(QuicStreamId id) const {
- if (!QuicContainsKey(stream_map_, id)) {
+ if (!stream_map_.contains(id)) {
return false;
}
const StreamState& state = stream_map_.find(id)->second;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
index bc76ddc877a..8bdadb2f45d 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simple_session_notifier.h
@@ -10,6 +10,7 @@
#include "quic/core/session_notifier_interface.h"
#include "quic/platform/api/quic_test.h"
#include "common/quiche_circular_deque.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -134,7 +135,7 @@ class SimpleSessionNotifier : public SessionNotifierInterface {
quiche::QuicheCircularDeque<QuicFrame> control_frames_;
- QuicLinkedHashMap<QuicControlFrameId, bool> lost_control_frames_;
+ quiche::QuicheLinkedHashMap<QuicControlFrameId, bool> lost_control_frames_;
// Id of latest saved control frame. 0 if no control frame has been saved.
QuicControlFrameId last_control_frame_id_;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
index c286bf6e853..c7e23cd0711 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/simulator/queue.cc
@@ -26,7 +26,7 @@ Queue::Queue(Simulator* simulator, std::string name, QuicByteCount capacity)
new AggregationAlarmDelegate(this)));
}
-Queue::~Queue() {}
+Queue::~Queue() { aggregation_timeout_alarm_->PermanentCancel(); }
void Queue::set_tx_port(ConstrainedPortInterface* port) {
tx_port_ = port;
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.cc b/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.cc
index 4c4cfbbac2f..be9021a7baa 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.cc
@@ -37,7 +37,8 @@ size_t TestTicketCrypter::MaxOverhead() {
return ticket_prefix_.size();
}
-std::vector<uint8_t> TestTicketCrypter::Encrypt(absl::string_view in) {
+std::vector<uint8_t> TestTicketCrypter::Encrypt(
+ absl::string_view in, absl::string_view /* encryption_key */) {
size_t prefix_len = ticket_prefix_.size();
std::vector<uint8_t> out(prefix_len + in.size());
memcpy(out.data(), ticket_prefix_.data(), prefix_len);
diff --git a/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h b/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h
index 63919c61bba..0300998fa37 100644
--- a/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h
+++ b/chromium/net/third_party/quiche/src/quic/test_tools/test_ticket_crypter.h
@@ -19,7 +19,8 @@ class TestTicketCrypter : public ProofSource::TicketCrypter {
// TicketCrypter interface
size_t MaxOverhead() override;
- std::vector<uint8_t> Encrypt(absl::string_view in) override;
+ std::vector<uint8_t> Encrypt(absl::string_view in,
+ absl::string_view encryption_key) override;
void Decrypt(absl::string_view in,
std::unique_ptr<ProofSource::DecryptCallback> callback) override;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
index 53c6800a2e5..6d10de282cd 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "quic/tools/quic_client_base.h"
+
+#include <algorithm>
#include <memory>
#include "quic/core/crypto/quic_random.h"
@@ -442,13 +444,20 @@ QuicConnectionId QuicClientBase::GetClientConnectionId() {
bool QuicClientBase::CanReconnectWithDifferentVersion(
ParsedQuicVersion* version) const {
if (session_ == nullptr || session_->connection() == nullptr ||
- session_->error() != QUIC_INVALID_VERSION ||
- session_->connection()->server_supported_versions().empty()) {
+ session_->error() != QUIC_INVALID_VERSION) {
return false;
}
+
+ const auto& server_supported_versions =
+ session_->connection()->server_supported_versions();
+ if (server_supported_versions.empty()) {
+ return false;
+ }
+
for (const auto& client_version : supported_versions_) {
- if (QuicContainsValue(session_->connection()->server_supported_versions(),
- client_version)) {
+ if (std::find(server_supported_versions.begin(),
+ server_supported_versions.end(),
+ client_version) != server_supported_versions.end()) {
*version = client_version;
return true;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
index 82ee39256cf..51e3433d90a 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_base.h
@@ -145,6 +145,11 @@ class QuicClientBase {
crypto_config_.set_user_agent_id(user_agent_id);
}
+ void SetTlsSignatureAlgorithms(std::string signature_algorithms) {
+ crypto_config_.set_tls_signature_algorithms(
+ std::move(signature_algorithms));
+ }
+
const ParsedQuicVersionVector& supported_versions() const {
return supported_versions_;
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h
index df0a3b4a4f5..bb8a898384c 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_client_epoll_network_helper.h
@@ -15,9 +15,9 @@
#include "quic/core/http/quic_client_push_promise_index.h"
#include "quic/core/quic_config.h"
#include "quic/core/quic_packet_reader.h"
-#include "quic/platform/api/quic_containers.h"
#include "quic/platform/api/quic_epoll.h"
#include "quic/tools/quic_client_base.h"
+#include "common/quiche_linked_hash_map.h"
namespace quic {
@@ -73,7 +73,8 @@ class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper,
QuicEpollServer* epoll_server() { return epoll_server_; }
- const QuicLinkedHashMap<int, QuicSocketAddress>& fd_address_map() const {
+ const quiche::QuicheLinkedHashMap<int, QuicSocketAddress>& fd_address_map()
+ const {
return fd_address_map_;
}
@@ -110,7 +111,7 @@ class QuicClientEpollNetworkHelper : public QuicClientBase::NetworkHelper,
// Map mapping created UDP sockets to their addresses. By using linked hash
// map, the order of socket creation can be recorded.
- QuicLinkedHashMap<int, QuicSocketAddress> fd_address_map_;
+ quiche::QuicheLinkedHashMap<int, QuicSocketAddress> fd_address_map_;
// If overflow_supported_ is true, this will be the number of packets dropped
// during the lifetime of the server.
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
index de2064831f4..58aa7a94ce8 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend.cc
@@ -12,10 +12,9 @@
#include "absl/strings/string_view.h"
#include "quic/core/http/spdy_utils.h"
#include "quic/platform/api/quic_bug_tracker.h"
-#include "quic/platform/api/quic_file_utils.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/tools/web_transport_test_visitors.h"
+#include "common/platform/api/quiche_file_utils.h"
#include "common/quiche_text_utils.h"
using spdy::Http2HeaderBlock;
@@ -29,7 +28,14 @@ QuicMemoryCacheBackend::ResourceFile::ResourceFile(const std::string& file_name)
QuicMemoryCacheBackend::ResourceFile::~ResourceFile() = default;
void QuicMemoryCacheBackend::ResourceFile::Read() {
- ReadFileContents(file_name_, &file_contents_);
+ absl::optional<std::string> maybe_file_contents =
+ quiche::ReadFileContents(file_name_);
+ if (!maybe_file_contents) {
+ QUIC_LOG(DFATAL) << "Failed to read file for the memory cache backend: "
+ << file_name_;
+ return;
+ }
+ file_contents_ = *maybe_file_contents;
// First read the headers.
size_t start = 0;
@@ -140,8 +146,7 @@ void QuicMemoryCacheBackend::ResourceFile::HandleXOriginalUrl() {
}
const QuicBackendResponse* QuicMemoryCacheBackend::GetResponse(
- absl::string_view host,
- absl::string_view path) const {
+ absl::string_view host, absl::string_view path) const {
QuicWriterMutexLock lock(&response_mutex_);
auto it = responses_.find(GetKey(host, path));
@@ -179,11 +184,8 @@ void QuicMemoryCacheBackend::AddSimpleResponse(absl::string_view host,
}
void QuicMemoryCacheBackend::AddSimpleResponseWithServerPushResources(
- absl::string_view host,
- absl::string_view path,
- int response_code,
- absl::string_view body,
- std::list<ServerPushInfo> push_resources) {
+ absl::string_view host, absl::string_view path, int response_code,
+ absl::string_view body, std::list<ServerPushInfo> push_resources) {
AddSimpleResponse(host, path, response_code, body);
MaybeAddServerPushResources(host, path, push_resources);
}
@@ -214,10 +216,8 @@ void QuicMemoryCacheBackend::AddResponse(absl::string_view host,
}
void QuicMemoryCacheBackend::AddResponseWithEarlyHints(
- absl::string_view host,
- absl::string_view path,
- spdy::Http2HeaderBlock response_headers,
- absl::string_view response_body,
+ absl::string_view host, absl::string_view path,
+ spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
const std::vector<spdy::Http2HeaderBlock>& early_hints) {
AddResponseImpl(host, path, QuicBackendResponse::REGULAR_RESPONSE,
std::move(response_headers), response_body,
@@ -225,18 +225,15 @@ void QuicMemoryCacheBackend::AddResponseWithEarlyHints(
}
void QuicMemoryCacheBackend::AddSpecialResponse(
- absl::string_view host,
- absl::string_view path,
+ absl::string_view host, absl::string_view path,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, Http2HeaderBlock(), "",
Http2HeaderBlock(), std::vector<spdy::Http2HeaderBlock>());
}
void QuicMemoryCacheBackend::AddSpecialResponse(
- absl::string_view host,
- absl::string_view path,
- spdy::Http2HeaderBlock response_headers,
- absl::string_view response_body,
+ absl::string_view host, absl::string_view path,
+ spdy::Http2HeaderBlock response_headers, absl::string_view response_body,
SpecialResponseType response_type) {
AddResponseImpl(host, path, response_type, std::move(response_headers),
response_body, Http2HeaderBlock(),
@@ -254,7 +251,12 @@ bool QuicMemoryCacheBackend::InitializeBackend(
QUIC_LOG(INFO)
<< "Attempting to initialize QuicMemoryCacheBackend from directory: "
<< cache_directory;
- std::vector<std::string> files = ReadFileContents(cache_directory);
+ std::vector<std::string> files;
+ if (!quiche::EnumerateDirectoryRecursively(cache_directory, files)) {
+ QUIC_BUG(QuicMemoryCacheBackend unreadable directory)
+ << "Can't read QuicMemoryCacheBackend directory: " << cache_directory;
+ return false;
+ }
std::list<std::unique_ptr<ResourceFile>> resource_files;
for (const auto& filename : files) {
std::unique_ptr<ResourceFile> resource_file(new ResourceFile(filename));
@@ -402,19 +404,16 @@ QuicMemoryCacheBackend::~QuicMemoryCacheBackend() {
}
void QuicMemoryCacheBackend::AddResponseImpl(
- absl::string_view host,
- absl::string_view path,
- SpecialResponseType response_type,
- Http2HeaderBlock response_headers,
- absl::string_view response_body,
- Http2HeaderBlock response_trailers,
+ absl::string_view host, absl::string_view path,
+ SpecialResponseType response_type, Http2HeaderBlock response_headers,
+ absl::string_view response_body, Http2HeaderBlock response_trailers,
const std::vector<spdy::Http2HeaderBlock>& early_hints) {
QuicWriterMutexLock lock(&response_mutex_);
QUICHE_DCHECK(!host.empty())
<< "Host must be populated, e.g. \"www.google.com\"";
std::string key = GetKey(host, path);
- if (QuicContainsKey(responses_, key)) {
+ if (responses_.contains(key)) {
QUIC_BUG(quic_bug_10932_3)
<< "Response for '" << key << "' already exists!";
return;
@@ -441,8 +440,7 @@ std::string QuicMemoryCacheBackend::GetKey(absl::string_view host,
}
void QuicMemoryCacheBackend::MaybeAddServerPushResources(
- absl::string_view request_host,
- absl::string_view request_path,
+ absl::string_view request_host, absl::string_view request_path,
std::list<ServerPushInfo> push_resources) {
std::string request_url = GetKey(request_host, request_path);
@@ -468,7 +466,7 @@ void QuicMemoryCacheBackend::MaybeAddServerPushResources(
bool found_existing_response = false;
{
QuicWriterMutexLock lock(&response_mutex_);
- found_existing_response = QuicContainsKey(responses_, GetKey(host, path));
+ found_existing_response = responses_.contains(GetKey(host, path));
}
if (!found_existing_response) {
// Add a server push response to responses map, if it is not in the map.
@@ -481,8 +479,7 @@ void QuicMemoryCacheBackend::MaybeAddServerPushResources(
}
bool QuicMemoryCacheBackend::PushResourceExistsInCache(
- std::string original_request_url,
- ServerPushInfo resource) {
+ std::string original_request_url, ServerPushInfo resource) {
QuicWriterMutexLock lock(&response_mutex_);
auto resource_range =
server_push_resources_.equal_range(original_request_url);
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
index d0383e19b6e..71f5dc5bbb4 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_memory_cache_backend_test.cc
@@ -4,12 +4,13 @@
#include "quic/tools/quic_memory_cache_backend.h"
+#include <vector>
+
#include "absl/strings/match.h"
#include "absl/strings/str_cat.h"
-#include "quic/platform/api/quic_file_utils.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/platform/api/quic_test.h"
#include "quic/tools/quic_backend_response.h"
+#include "common/platform/api/quiche_file_utils.h"
namespace quic {
namespace test {
@@ -21,8 +22,7 @@ using ServerPushInfo = QuicBackendResponse::ServerPushInfo;
class QuicMemoryCacheBackendTest : public QuicTest {
protected:
- void CreateRequest(std::string host,
- std::string path,
+ void CreateRequest(std::string host, std::string path,
spdy::Http2HeaderBlock* headers) {
(*headers)[":method"] = "GET";
(*headers)[":path"] = path;
@@ -49,7 +49,7 @@ TEST_F(QuicMemoryCacheBackendTest, AddSimpleResponseGetResponse) {
CreateRequest("www.google.com", "/", &request_headers);
const Response* response = cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
EXPECT_EQ(response_body.size(), response->body().length());
}
@@ -82,10 +82,10 @@ TEST_F(QuicMemoryCacheBackendTest, ReadsCacheDir) {
const Response* response =
cache_.GetResponse("test.example.com", "/index.html");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
// Connection headers are not valid in HTTP/2.
- EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
+ EXPECT_FALSE(response->headers().contains("connection"));
EXPECT_LT(0U, response->body().length());
}
@@ -108,10 +108,10 @@ TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrl) {
const Response* response =
cache_.GetResponse("test.example.com", "/site_map.html");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
// Connection headers are not valid in HTTP/2.
- EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
+ EXPECT_FALSE(response->headers().contains("connection"));
EXPECT_LT(0U, response->body().length());
}
@@ -121,7 +121,9 @@ TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrlOnly) {
// X-Original-Url header's value will be used.
std::string dir;
std::string path = "map.html";
- for (const std::string& file : ReadFileContents(CacheDirectory())) {
+ std::vector<std::string> files;
+ ASSERT_TRUE(quiche::EnumerateDirectoryRecursively(CacheDirectory(), files));
+ for (const std::string& file : files) {
if (absl::EndsWithIgnoreCase(file, "map.html")) {
dir = file;
dir.erase(dir.length() - path.length() - 1);
@@ -134,10 +136,10 @@ TEST_F(QuicMemoryCacheBackendTest, UsesOriginalUrlOnly) {
const Response* response =
cache_.GetResponse("test.example.com", "/site_map.html");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
// Connection headers are not valid in HTTP/2.
- EXPECT_FALSE(QuicContainsKey(response->headers(), "connection"));
+ EXPECT_FALSE(response->headers().contains("connection"));
EXPECT_LT(0U, response->body().length());
}
@@ -157,20 +159,20 @@ TEST_F(QuicMemoryCacheBackendTest, DefaultResponse) {
// Now we should get the default response for the original request.
response = cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
// Now add a set response for / and make sure it is returned
cache_.AddSimpleResponse("www.google.com", "/", 302, "");
response = cache_.GetResponse("www.google.com", "/");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("302", response->headers().find(":status")->second);
// We should get the default response for other requests.
response = cache_.GetResponse("www.google.com", "/asd");
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ("200", response->headers().find(":status")->second);
}
@@ -243,7 +245,7 @@ TEST_F(QuicMemoryCacheBackendTest, GetServerPushResourcesAndPushResponses) {
std::string path = url.path();
const Response* response = cache_.GetResponse(host, path);
ASSERT_TRUE(response);
- ASSERT_TRUE(QuicContainsKey(response->headers(), ":status"));
+ ASSERT_TRUE(response->headers().contains(":status"));
EXPECT_EQ(push_response_status[i++],
response->headers().find(":status")->second);
EXPECT_EQ(push_resource.body, response->body());
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
index d1efcba4fe0..07c46289da8 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.cc
@@ -54,4 +54,8 @@ bool QuicSimpleClientSession::ShouldNegotiateWebTransport() {
return enable_web_transport_;
}
+bool QuicSimpleClientSession::ShouldNegotiateHttp3Datagram() {
+ return enable_web_transport_;
+}
+
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
index aa86d9a83c9..124e56f8bf1 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_client_session.h
@@ -30,6 +30,7 @@ class QuicSimpleClientSession : public QuicSpdyClientSession {
std::unique_ptr<QuicSpdyClientStream> CreateClientStream() override;
bool ShouldNegotiateWebTransport() override;
+ bool ShouldNegotiateHttp3Datagram() override;
private:
const bool drop_response_body_;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
index ac95e46fb97..5cd365298f3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream.cc
@@ -18,7 +18,6 @@
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_logging.h"
-#include "quic/platform/api/quic_map_util.h"
#include "quic/tools/quic_simple_server_session.h"
#include "spdy/core/spdy_protocol.h"
@@ -155,13 +154,13 @@ void QuicSimpleServerStream::SendResponse() {
return;
}
- if (!QuicContainsKey(request_headers_, ":authority")) {
+ if (!request_headers_.contains(":authority")) {
QUIC_DVLOG(1) << "Request headers do not contain :authority.";
SendErrorResponse();
return;
}
- if (!QuicContainsKey(request_headers_, ":path")) {
+ if (!request_headers_.contains(":path")) {
// CONNECT and other CONNECT-like methods (such as CONNECT-UDP) do not all
// require :path to be present.
auto it = request_headers_.find(":method");
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
index 25423114fab..5c9cd2274d9 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_simple_server_stream_test.cc
@@ -16,6 +16,7 @@
#include "quic/core/http/http_encoder.h"
#include "quic/core/http/spdy_utils.h"
#include "quic/core/quic_error_codes.h"
+#include "quic/core/quic_simple_buffer_allocator.h"
#include "quic/core/quic_types.h"
#include "quic/core/quic_utils.h"
#include "quic/platform/api/quic_expect_bug.h"
@@ -156,14 +157,10 @@ class MockQuicSimpleServerSession : public QuicSimpleServerSession {
CreateIncomingStream,
(QuicStreamId id),
(override));
- MOCK_METHOD(QuicConsumedData,
- WritevData,
- (QuicStreamId id,
- size_t write_length,
- QuicStreamOffset offset,
- StreamSendingState state,
- TransmissionType type,
- absl::optional<EncryptionLevel> level),
+ MOCK_METHOD(QuicConsumedData, WritevData,
+ (QuicStreamId id, size_t write_length, QuicStreamOffset offset,
+ StreamSendingState state, TransmissionType type,
+ EncryptionLevel level),
(override));
MOCK_METHOD(void,
OnStreamHeaderList,
@@ -311,11 +308,10 @@ TEST_P(QuicSimpleServerStreamTest, TestFraming) {
.WillRepeatedly(
Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data = UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data =
+ UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -330,11 +326,10 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingOnePacket) {
Invoke(&session_, &MockQuicSimpleServerSession::ConsumeData));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data = UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data =
+ UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -377,20 +372,20 @@ TEST_P(QuicSimpleServerStreamTest, TestFramingExtraData) {
EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
stream_->OnStreamHeaderList(false, kFakeFrameLen, header_list_);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data = UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data =
+ UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
// Content length is still 11. This will register as an error and we won't
// accept the bytes.
- header_length =
- HttpEncoder::SerializeDataFrameHeader(large_body.length(), &buffer);
- header = std::string(buffer.get(), header_length);
- std::string data2 = UsesHttp3() ? header + large_body : large_body;
+ header = HttpEncoder::SerializeDataFrameHeader(large_body.length(),
+ SimpleBufferAllocator::Get());
+ std::string data2 = UsesHttp3()
+ ? absl::StrCat(header.AsStringView(), large_body)
+ : large_body;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/true, data.size(), data2));
EXPECT_EQ("11", StreamHeadersValue("content-length"));
@@ -409,9 +404,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
response_headers_[":status"] = "200 OK";
response_headers_["content-length"] = "5";
std::string body = "Yummm";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -421,7 +415,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+ EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
}
EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
@@ -442,9 +436,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
response_headers_["content-length"] = "5";
std::string body = "Yummm";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -454,7 +447,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithIllegalResponseStatus2) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+ EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
}
EXPECT_CALL(session_, WritevData(_, kErrorLength, _, FIN, _, _));
@@ -507,9 +500,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
response_headers_["content-length"] = "5";
std::string body = "Yummm";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
memory_cache_backend_.AddResponse("www.google.com", "/bar",
std::move(response_headers_), body);
@@ -518,7 +510,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithValidHeaders) {
InSequence s;
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+ EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
}
EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
@@ -538,9 +530,8 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
(*request_headers)[":authority"] = host;
(*request_headers)[":method"] = "GET";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body.length(), &buffer);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body.length(), SimpleBufferAllocator::Get());
std::vector<spdy::Http2HeaderBlock> early_hints;
// Add two Early Hints.
const size_t kNumEarlyHintsResponses = 2;
@@ -562,7 +553,7 @@ TEST_P(QuicSimpleServerStreamTest, SendResponseWithEarlyHints) {
}
EXPECT_CALL(*stream_, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(_, header_length, _, NO_FIN, _, _));
+ EXPECT_CALL(session_, WritevData(_, header.size(), _, NO_FIN, _, _));
}
EXPECT_CALL(session_, WritevData(_, body.length(), _, FIN, _, _));
@@ -608,9 +599,8 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
response_headers_[":status"] = "200";
response_headers_["content-length"] = "5";
const std::string kBody = "Hello";
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(kBody.length(), &buffer);
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
memory_cache_backend_.AddResponse(kHost, kPath, std::move(response_headers_),
kBody);
@@ -620,7 +610,7 @@ TEST_P(QuicSimpleServerStreamTest, PushResponseOnServerInitiatedStream) {
EXPECT_CALL(*server_initiated_stream, WriteHeadersMock(false));
if (UsesHttp3()) {
- EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header_length, _,
+ EXPECT_CALL(session_, WritevData(kServerInitiatedStreamId, header.size(), _,
NO_FIN, _, _));
}
EXPECT_CALL(session_,
@@ -728,27 +718,27 @@ TEST_P(QuicSimpleServerStreamTest,
TEST_P(QuicSimpleServerStreamTest, InvalidHeadersWithFin) {
char arr[] = {
- 0x3a, 0x68, 0x6f, 0x73, // :hos
- 0x74, 0x00, 0x00, 0x00, // t...
- 0x00, 0x00, 0x00, 0x00, // ....
- 0x07, 0x3a, 0x6d, 0x65, // .:me
- 0x74, 0x68, 0x6f, 0x64, // thod
- 0x00, 0x00, 0x00, 0x03, // ....
- 0x47, 0x45, 0x54, 0x00, // GET.
- 0x00, 0x00, 0x05, 0x3a, // ...:
- 0x70, 0x61, 0x74, 0x68, // path
- 0x00, 0x00, 0x00, 0x04, // ....
- 0x2f, 0x66, 0x6f, 0x6f, // /foo
- 0x00, 0x00, 0x00, 0x07, // ....
- 0x3a, 0x73, 0x63, 0x68, // :sch
- 0x65, 0x6d, 0x65, 0x00, // eme.
- 0x00, 0x00, 0x00, 0x00, // ....
- 0x00, 0x00, 0x08, 0x3a, // ...:
- 0x76, 0x65, 0x72, 0x73, // vers
- 0x96, 0x6f, 0x6e, 0x00, // <i(69)>on.
- 0x00, 0x00, 0x08, 0x48, // ...H
- 0x54, 0x54, 0x50, 0x2f, // TTP/
- 0x31, 0x2e, 0x31, // 1.1
+ 0x3a, 0x68, 0x6f, 0x73, // :hos
+ 0x74, 0x00, 0x00, 0x00, // t...
+ 0x00, 0x00, 0x00, 0x00, // ....
+ 0x07, 0x3a, 0x6d, 0x65, // .:me
+ 0x74, 0x68, 0x6f, 0x64, // thod
+ 0x00, 0x00, 0x00, 0x03, // ....
+ 0x47, 0x45, 0x54, 0x00, // GET.
+ 0x00, 0x00, 0x05, 0x3a, // ...:
+ 0x70, 0x61, 0x74, 0x68, // path
+ 0x00, 0x00, 0x00, 0x04, // ....
+ 0x2f, 0x66, 0x6f, 0x6f, // /foo
+ 0x00, 0x00, 0x00, 0x07, // ....
+ 0x3a, 0x73, 0x63, 0x68, // :sch
+ 0x65, 0x6d, 0x65, 0x00, // eme.
+ 0x00, 0x00, 0x00, 0x00, // ....
+ 0x00, 0x00, 0x08, 0x3a, // ...:
+ 0x76, 0x65, 0x72, 0x73, // vers
+ '\x96', 0x6f, 0x6e, 0x00, // <i(69)>on.
+ 0x00, 0x00, 0x08, 0x48, // ...H
+ 0x54, 0x54, 0x50, 0x2f, // TTP/
+ 0x31, 0x2e, 0x31, // 1.1
};
absl::string_view data(arr, ABSL_ARRAYSIZE(arr));
QuicStreamFrame frame(stream_->id(), true, 0, data);
@@ -767,11 +757,10 @@ TEST_P(QuicSimpleServerStreamTest, ConnectSendsResponseBeforeFinReceived) {
header_list.OnHeaderBlockEnd(128, 128);
EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data = UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data =
+ UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
@@ -793,11 +782,10 @@ TEST_P(QuicSimpleServerStreamTest, ConnectWithInvalidHeader) {
header_list.OnHeaderBlockEnd(128, 128);
EXPECT_CALL(*stream_, WriteHeadersMock(/*fin=*/false));
stream_->OnStreamHeaderList(/*fin=*/false, kFakeFrameLen, header_list);
- std::unique_ptr<char[]> buffer;
- QuicByteCount header_length =
- HttpEncoder::SerializeDataFrameHeader(body_.length(), &buffer);
- std::string header = std::string(buffer.get(), header_length);
- std::string data = UsesHttp3() ? header + body_ : body_;
+ QuicBuffer header = HttpEncoder::SerializeDataFrameHeader(
+ body_.length(), SimpleBufferAllocator::Get());
+ std::string data =
+ UsesHttp3() ? absl::StrCat(header.AsStringView(), body_) : body_;
stream_->OnStreamFrame(
QuicStreamFrame(stream_->id(), /*fin=*/false, /*offset=*/0, data));
EXPECT_EQ("CONNECT-SILLY", StreamHeadersValue(":method"));
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
index 4f51eb47eba..464fa70fda7 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.cc
@@ -67,6 +67,10 @@ const QuicSpdyClientSession* QuicSpdyClientBase::client_session() const {
}
void QuicSpdyClientBase::InitializeSession() {
+ if (max_inbound_header_list_size_ > 0) {
+ client_session()->set_max_inbound_header_list_size(
+ max_inbound_header_list_size_);
+ }
client_session()->Initialize();
client_session()->CryptoConnect();
}
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
index 2ba55f11693..c49d0ed84a5 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_spdy_client_base.h
@@ -149,6 +149,10 @@ class QuicSpdyClientBase : public QuicClientBase,
bool EarlyDataAccepted() override;
bool ReceivedInchoateReject() override;
+ void set_max_inbound_header_list_size(size_t size) {
+ max_inbound_header_list_size_ = size;
+ }
+
protected:
int GetNumSentClientHellosFromSession() override;
int GetNumReceivedServerConfigUpdatesFromSession() override;
@@ -223,6 +227,9 @@ class QuicSpdyClientBase : public QuicClientBase,
bool drop_response_body_ = false;
bool enable_web_transport_ = false;
+ // If not zero, used to set client's max inbound header size before session
+ // initialize.
+ size_t max_inbound_header_list_size_ = 0;
};
} // namespace quic
diff --git a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
index 8d227913ce5..0db266b9e11 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/quic_toy_client.cc
@@ -211,6 +211,13 @@ DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t,
-1,
"Length of the client connection ID used.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, max_time_before_crypto_handshake_ms,
+ 10000,
+ "Max time to wait before handshake completes.");
+
+DEFINE_QUIC_COMMAND_LINE_FLAG(int32_t, max_inbound_header_list_size, 128 * 1024,
+ "Max inbound header list size. 0 means default.");
+
namespace quic {
QuicToyClient::QuicToyClient(ClientFactory* client_factory)
@@ -293,6 +300,8 @@ int QuicToyClient::SendRequestsAndPrintResponses(
config.custom_transport_parameters_to_send()[kCustomParameter] =
custom_value;
}
+ config.set_max_time_before_crypto_handshake(QuicTime::Delta::FromMilliseconds(
+ GetQuicFlag(FLAGS_max_time_before_crypto_handshake_ms)));
int address_family_for_lookup = AF_UNSPEC;
if (GetQuicFlag(FLAGS_ip_version_for_host_lookup) == "4") {
@@ -325,6 +334,11 @@ int QuicToyClient::SendRequestsAndPrintResponses(
if (client_connection_id_length >= 0) {
client->set_client_connection_id_length(client_connection_id_length);
}
+ const size_t max_inbound_header_list_size =
+ GetQuicFlag(FLAGS_max_inbound_header_list_size);
+ if (max_inbound_header_list_size > 0) {
+ client->set_max_inbound_header_list_size(max_inbound_header_list_size);
+ }
if (!client->Initialize()) {
std::cerr << "Failed to initialize client." << std::endl;
return 1;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.cc b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.cc
index 0130352ecfd..149adda20ff 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.cc
@@ -38,7 +38,12 @@ size_t SimpleTicketCrypter::MaxOverhead() {
return kEpochSize + kIVSize + kAuthTagSize;
}
-std::vector<uint8_t> SimpleTicketCrypter::Encrypt(absl::string_view in) {
+std::vector<uint8_t> SimpleTicketCrypter::Encrypt(
+ absl::string_view in, absl::string_view encryption_key) {
+ // This class is only used in Chromium, in which the |encryption_key| argument
+ // will never be populated and an internally-cached key should be used for
+ // encrypting tickets.
+ QUICHE_DCHECK(encryption_key.empty());
MaybeRotateKeys();
std::vector<uint8_t> out(in.size() + MaxOverhead());
out[0] = key_epoch_;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h
index d547a25bf9e..052bc5872a3 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h
+++ b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter.h
@@ -24,7 +24,8 @@ class QUIC_NO_EXPORT SimpleTicketCrypter
~SimpleTicketCrypter() override;
size_t MaxOverhead() override;
- std::vector<uint8_t> Encrypt(absl::string_view in) override;
+ std::vector<uint8_t> Encrypt(absl::string_view in,
+ absl::string_view encryption_key) override;
void Decrypt(
absl::string_view in,
std::unique_ptr<quic::ProofSource::DecryptCallback> callback) override;
diff --git a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter_test.cc b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter_test.cc
index ad041c10de8..be71018de23 100644
--- a/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter_test.cc
+++ b/chromium/net/third_party/quiche/src/quic/tools/simple_ticket_crypter_test.cc
@@ -42,7 +42,7 @@ class SimpleTicketCrypterTest : public QuicTest {
TEST_F(SimpleTicketCrypterTest, EncryptDecrypt) {
std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> ciphertext =
- ticket_crypter_.Encrypt(StringPiece(plaintext));
+ ticket_crypter_.Encrypt(StringPiece(plaintext), {});
EXPECT_NE(plaintext, ciphertext);
std::vector<uint8_t> out_plaintext;
@@ -54,16 +54,16 @@ TEST_F(SimpleTicketCrypterTest, EncryptDecrypt) {
TEST_F(SimpleTicketCrypterTest, CiphertextsDiffer) {
std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> ciphertext1 =
- ticket_crypter_.Encrypt(StringPiece(plaintext));
+ ticket_crypter_.Encrypt(StringPiece(plaintext), {});
std::vector<uint8_t> ciphertext2 =
- ticket_crypter_.Encrypt(StringPiece(plaintext));
+ ticket_crypter_.Encrypt(StringPiece(plaintext), {});
EXPECT_NE(ciphertext1, ciphertext2);
}
TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithModifiedCiphertext) {
std::vector<uint8_t> plaintext = {1, 2, 3, 4, 5};
std::vector<uint8_t> ciphertext =
- ticket_crypter_.Encrypt(StringPiece(plaintext));
+ ticket_crypter_.Encrypt(StringPiece(plaintext), {});
EXPECT_NE(plaintext, ciphertext);
// Check that a bit flip in any byte will cause a decryption failure.
@@ -88,7 +88,7 @@ TEST_F(SimpleTicketCrypterTest, DecryptionFailureWithEmptyCiphertext) {
TEST_F(SimpleTicketCrypterTest, KeyRotation) {
std::vector<uint8_t> plaintext = {1, 2, 3};
std::vector<uint8_t> ciphertext =
- ticket_crypter_.Encrypt(StringPiece(plaintext));
+ ticket_crypter_.Encrypt(StringPiece(plaintext), {});
EXPECT_FALSE(ciphertext.empty());
// Advance the clock 8 days, so the key used for |ciphertext| is now the
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
index 3fd6ebcf87d..03db87d2e51 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.cc
@@ -7,7 +7,6 @@
#include "http2/decoder/decode_buffer.h"
#include "http2/decoder/decode_status.h"
#include "common/platform/api/quiche_logging.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
using ::http2::DecodeBuffer;
@@ -118,10 +117,6 @@ void HpackDecoderAdapter::set_max_header_block_bytes(
max_header_block_bytes_ = max_header_block_bytes;
}
-size_t HpackDecoderAdapter::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(hpack_decoder_);
-}
-
HpackDecoderAdapter::ListenerAdapter::ListenerAdapter() : handler_(nullptr) {}
HpackDecoderAdapter::ListenerAdapter::~ListenerAdapter() = default;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
index 98d10fe2c9a..43a762bb757 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter.h
@@ -67,6 +67,12 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
// a SpdyHeadersHandlerInterface.
const SpdyHeaderBlock& decoded_block() const;
+ // Returns the current dynamic table size, including the 32 bytes per entry
+ // overhead mentioned in RFC 7541 section 4.1.
+ size_t GetDynamicTableSize() const {
+ return hpack_decoder_.GetDynamicTableSize();
+ }
+
// Set how much encoded data this decoder is willing to buffer.
// TODO(jamessynge): Resolve definition of this value, as it is currently
// too tied to a single implementation. We probably want to limit one or more
@@ -79,8 +85,6 @@ class QUICHE_EXPORT_PRIVATE HpackDecoderAdapter {
// accepted.
void set_max_header_block_bytes(size_t max_header_block_bytes);
- size_t EstimateMemoryUsage() const;
-
// Error code if an error has occurred, Error::kOk otherwise.
http2::HpackDecodingError error() const { return error_; }
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
index d223ccf9f5a..bab6c481e78 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_decoder_adapter_test.cc
@@ -21,12 +21,12 @@
#include "http2/test_tools/http2_random.h"
#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
+#include "common/quiche_text_utils.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_encoder.h"
#include "spdy/core/hpack/hpack_output_stream.h"
#include "spdy/core/recording_headers_handler.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_string_utils.h"
using ::http2::HpackEntryType;
using ::http2::HpackStringPair;
@@ -135,7 +135,8 @@ class HpackDecoderAdapterTest
}
bool HandleControlFrameHeadersData(absl::string_view str) {
- QUICHE_VLOG(3) << "HandleControlFrameHeadersData:\n" << SpdyHexDump(str);
+ QUICHE_VLOG(3) << "HandleControlFrameHeadersData:\n"
+ << quiche::QuicheTextUtils::HexDump(str);
bytes_passed_in_ += str.size();
return decoder_.HandleControlFrameHeadersData(str.data(), str.size());
}
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
index 27f0444f274..ccf17da20b2 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.cc
@@ -14,7 +14,6 @@
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_header_table.h"
#include "spdy/core/hpack/hpack_output_stream.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -124,11 +123,6 @@ void HpackEncoder::ApplyHeaderTableSizeSetting(size_t size_setting) {
should_emit_table_size_ = true;
}
-size_t HpackEncoder::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(header_table_) +
- SpdyEstimateMemoryUsage(output_stream_);
-}
-
void HpackEncoder::EncodeRepresentations(RepresentationIterator* iter,
std::string* output) {
MaybeEmitTableSize();
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
index d85b98ede0b..5e2ea03980c 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder.h
@@ -95,8 +95,9 @@ class QUICHE_EXPORT_PRIVATE HpackEncoder {
void DisableCompression() { enable_compression_ = false; }
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
+ // Returns the current dynamic table size, including the 32 bytes per entry
+ // overhead mentioned in RFC 7541 section 4.1.
+ size_t GetDynamicTableSize() const { return header_table_.size(); }
private:
friend class test::HpackEncoderPeer;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
index 774a06e8129..dfd8d8fea2c 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_encoder_test.cc
@@ -155,6 +155,7 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
// No further insertions may occur without evictions.
peer_.table()->SetMaxSize(peer_.table()->size());
+ QUICHE_CHECK_EQ(kInitialDynamicTableSize, peer_.table()->size());
}
void SaveHeaders(absl::string_view name, absl::string_view value) {
@@ -254,6 +255,9 @@ class HpackEncoderTest : public QuicheTestWithParam<EncodeStrategy> {
HpackEncoder encoder_;
test::HpackEncoderPeer peer_;
+ // Calculated based on the names and values inserted in SetUp(), above.
+ const size_t kInitialDynamicTableSize = 4 * (10 + 32);
+
const HpackEntry* static_;
const HpackEntry* key_1_;
const HpackEntry* key_2_;
@@ -280,6 +284,7 @@ INSTANTIATE_TEST_SUITE_P(HpackEncoderTests,
::testing::Values(kDefault));
TEST_P(HpackEncoderTestWithDefaultStrategy, EncodeRepresentations) {
+ EXPECT_EQ(kInitialDynamicTableSize, encoder_.GetDynamicTableSize());
encoder_.SetHeaderListener(
[this](absl::string_view name, absl::string_view value) {
this->SaveHeaders(name, value);
@@ -308,6 +313,30 @@ TEST_P(HpackEncoderTestWithDefaultStrategy, EncodeRepresentations) {
Pair("accept", "text/html, text/plain,application/xml"),
Pair("cookie", "val4"),
Pair("withnul", absl::string_view("one\0two", 7))));
+ // Insertions and evictions have happened over the course of the test.
+ EXPECT_GE(kInitialDynamicTableSize, encoder_.GetDynamicTableSize());
+}
+
+TEST_P(HpackEncoderTestWithDefaultStrategy, DynamicTableGrows) {
+ EXPECT_EQ(kInitialDynamicTableSize, encoder_.GetDynamicTableSize());
+ peer_.table()->SetMaxSize(4096);
+ encoder_.SetHeaderListener(
+ [this](absl::string_view name, absl::string_view value) {
+ this->SaveHeaders(name, value);
+ });
+ const std::vector<std::pair<absl::string_view, absl::string_view>>
+ header_list = {{"cookie", "val1; val2;val3"},
+ {":path", "/home"},
+ {"accept", "text/html, text/plain,application/xml"},
+ {"cookie", "val4"},
+ {"withnul", absl::string_view("one\0two", 7)}};
+ std::string out;
+ EXPECT_TRUE(test::HpackEncoderPeer::EncodeRepresentations(&encoder_,
+ header_list, &out));
+
+ EXPECT_FALSE(out.empty());
+ // Insertions have happened over the course of the test.
+ EXPECT_GT(encoder_.GetDynamicTableSize(), kInitialDynamicTableSize);
}
INSTANTIATE_TEST_SUITE_P(HpackEncoderTests,
@@ -479,6 +508,7 @@ TEST_P(HpackEncoderTest, EncodingWithoutCompression) {
Pair("hello", "aloha"),
Pair("multivalue", "value1, value2")));
}
+ EXPECT_EQ(kInitialDynamicTableSize, encoder_.GetDynamicTableSize());
}
TEST_P(HpackEncoderTest, MultipleEncodingPasses) {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
index 4deb0dfcc81..d755214b995 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.cc
@@ -5,7 +5,6 @@
#include "spdy/core/hpack/hpack_entry.h"
#include "absl/strings/str_cat.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -24,8 +23,4 @@ std::string HpackEntry::GetDebugString() const {
return absl::StrCat("{ name: \"", name_, "\", value: \"", value_, "\" }");
}
-size_t HpackEntry::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(name_) + SpdyEstimateMemoryUsage(value_);
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
index 0c263584f66..86e39779b7d 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_entry.h
@@ -71,9 +71,6 @@ class QUICHE_EXPORT_PRIVATE HpackEntry {
std::string GetDebugString() const;
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
private:
std::string name_;
std::string value_;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
index 8536a8523fc..6358003c2ba 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.cc
@@ -9,7 +9,6 @@
#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_static_table.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -186,10 +185,4 @@ const HpackEntry* HpackHeaderTable::TryAddEntry(absl::string_view name,
return &dynamic_entries_.front();
}
-size_t HpackHeaderTable::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(dynamic_entries_) +
- SpdyEstimateMemoryUsage(dynamic_index_) +
- SpdyEstimateMemoryUsage(dynamic_name_index_);
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
index 49478cd35b2..427fc857ef5 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_header_table.h
@@ -98,9 +98,6 @@ class QUICHE_EXPORT_PRIVATE HpackHeaderTable {
const HpackEntry* TryAddEntry(absl::string_view name,
absl::string_view value);
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
private:
// Returns number of evictions required to enter |name| & |value|.
size_t EvictionCountForEntry(absl::string_view name,
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
index 7b925680d4b..bce24fa610d 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "common/platform/api/quiche_logging.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -97,8 +96,4 @@ void HpackOutputStream::BoundedTakeString(size_t max_size,
}
}
-size_t HpackOutputStream::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(buffer_);
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h
index 59e3bb33a42..ec657b54064 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_output_stream.h
@@ -61,9 +61,6 @@ class QUICHE_EXPORT_PRIVATE HpackOutputStream {
// Size in bytes of stream's internal buffer.
size_t size() const { return buffer_.size(); }
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
private:
// The internal bit buffer.
std::string buffer_;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
index 7594943b43e..e5a403d7162 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.cc
@@ -8,7 +8,6 @@
#include "common/platform/api/quiche_logging.h"
#include "spdy/core/hpack/hpack_constants.h"
#include "spdy/core/hpack/hpack_entry.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
@@ -48,10 +47,4 @@ bool HpackStaticTable::IsInitialized() const {
return !static_entries_.empty();
}
-size_t HpackStaticTable::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(static_entries_) +
- SpdyEstimateMemoryUsage(static_index_) +
- SpdyEstimateMemoryUsage(static_name_index_);
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
index 346332e4134..307fc1cc990 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/hpack/hpack_static_table.h
@@ -43,9 +43,6 @@ class QUICHE_EXPORT_PRIVATE HpackStaticTable {
return static_name_index_;
}
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
private:
HpackHeaderTable::StaticEntryTable static_entries_;
// The following two members have string_views that point to strings stored in
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
index b20d0032aff..e2e311dda07 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.cc
@@ -30,8 +30,6 @@
#include "spdy/core/spdy_header_block.h"
#include "spdy/core/spdy_headers_handler_interface.h"
#include "spdy/core/spdy_protocol.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_string_utils.h"
using ::spdy::ExtensionVisitorInterface;
using ::spdy::HpackDecoderAdapter;
@@ -40,7 +38,6 @@ using ::spdy::ParseErrorCode;
using ::spdy::ParseFrameType;
using ::spdy::SpdyAltSvcWireFormat;
using ::spdy::SpdyErrorCode;
-using ::spdy::SpdyEstimateMemoryUsage;
using ::spdy::SpdyFramerDebugVisitorInterface;
using ::spdy::SpdyFramerVisitorInterface;
using ::spdy::SpdyFrameType;
@@ -249,6 +246,8 @@ const char* Http2DecoderAdapter::SpdyFramerErrorToString(
return "HPACK_FRAGMENT_TOO_LONG";
case SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT:
return "HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT";
+ case SPDY_STOP_PROCESSING:
+ return "STOP_PROCESSING";
case LAST_ERROR:
return "UNKNOWN_ERROR";
}
@@ -320,11 +319,9 @@ bool Http2DecoderAdapter::probable_http_response() const {
return latched_probable_http_response_;
}
-size_t Http2DecoderAdapter::EstimateMemoryUsage() const {
- // Skip |frame_decoder_|, |frame_header_| and |hpack_first_frame_header_| as
- // they don't allocate.
- return SpdyEstimateMemoryUsage(alt_svc_origin_) +
- SpdyEstimateMemoryUsage(alt_svc_value_);
+void Http2DecoderAdapter::StopProcessing() {
+ SetSpdyErrorAndNotify(SpdyFramerError::SPDY_STOP_PROCESSING,
+ "Ignoring further events on this connection.");
}
// ===========================================================================
@@ -784,12 +781,12 @@ void Http2DecoderAdapter::OnFrameSizeError(const Http2FrameHeader& header) {
QUICHE_DVLOG(1) << "OnFrameSizeError: " << header;
size_t recv_limit = recv_frame_size_limit_;
if (header.payload_length > recv_limit) {
- SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD, "");
- return;
- }
- if (header.type != Http2FrameType::DATA &&
- header.payload_length > recv_limit) {
- SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE, "");
+ if (header.type == Http2FrameType::DATA) {
+ SetSpdyErrorAndNotify(SpdyFramerError::SPDY_OVERSIZED_PAYLOAD, "");
+ } else {
+ SetSpdyErrorAndNotify(SpdyFramerError::SPDY_CONTROL_PAYLOAD_TOO_LARGE,
+ "");
+ }
return;
}
switch (header.type) {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
index f05152b6468..81f12572c35 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_frame_decoder_adapter.h
@@ -95,6 +95,10 @@ class QUICHE_EXPORT_PRIVATE Http2DecoderAdapter
SPDY_HPACK_FRAGMENT_TOO_LONG,
SPDY_HPACK_COMPRESSED_HEADER_SIZE_EXCEEDS_LIMIT,
+ // Set if the visitor no longer wishes to receive events for this
+ // connection.
+ SPDY_STOP_PROCESSING,
+
LAST_ERROR, // Must be the last entry in the enum.
};
@@ -153,13 +157,17 @@ class QUICHE_EXPORT_PRIVATE Http2DecoderAdapter
// has responded with an HTTP/1.1 (or earlier) response.
bool probable_http_response() const;
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
spdy::HpackDecoderAdapter* GetHpackDecoder();
+ const spdy::HpackDecoderAdapter* GetHpackDecoder() const {
+ return hpack_decoder_.get();
+ }
bool HasError() const;
+ // A visitor may call this method to indicate it no longer wishes to receive
+ // events for this connection.
+ void StopProcessing();
+
private:
bool OnFrameHeader(const Http2FrameHeader& header) override;
void OnDataStart(const Http2FrameHeader& header) override;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/http2_header_block_hpack_listener.h b/chromium/net/third_party/quiche/src/spdy/core/http2_header_block_hpack_listener.h
new file mode 100644
index 00000000000..19352e54058
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/spdy/core/http2_header_block_hpack_listener.h
@@ -0,0 +1,47 @@
+#ifndef QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_
+#define QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_
+
+#include "absl/strings/string_view.h"
+#include "http2/hpack/decoder/hpack_decoder_listener.h"
+#include "common/platform/api/quiche_logging.h"
+#include "spdy/core/spdy_header_block.h"
+
+namespace spdy {
+
+// This class simply gathers the key-value pairs emitted by an HpackDecoder in
+// a SpdyHeaderBlock.
+class Http2HeaderBlockHpackListener : public http2::HpackDecoderListener {
+ public:
+ Http2HeaderBlockHpackListener() {}
+
+ void OnHeaderListStart() override {
+ header_block_.clear();
+ hpack_error_ = false;
+ }
+
+ void OnHeader(const std::string& name, const std::string& value) override {
+ header_block_.AppendValueOrAddHeader(name, value);
+ }
+
+ void OnHeaderListEnd() override {}
+
+ void OnHeaderErrorDetected(absl::string_view error_message) override {
+ QUICHE_VLOG(1) << error_message;
+ hpack_error_ = true;
+ }
+
+ SpdyHeaderBlock release_header_block() {
+ SpdyHeaderBlock block = std::move(header_block_);
+ header_block_ = {};
+ return block;
+ }
+ bool hpack_error() const { return hpack_error_; }
+
+ private:
+ SpdyHeaderBlock header_block_;
+ bool hpack_error_ = false;
+};
+
+} // namespace spdy
+
+#endif // QUICHE_SPDY_CORE_HTTP2_HEADER_BLOCK_HPACK_LISTENER_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.cc b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.cc
new file mode 100644
index 00000000000..12f6af14843
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.cc
@@ -0,0 +1,195 @@
+#include "spdy/core/metadata_extension.h"
+
+#include <list>
+#include <string>
+
+#include "absl/memory/memory.h"
+#include "absl/strings/str_cat.h"
+#include "http2/decoder/decode_buffer.h"
+#include "http2/hpack/decoder/hpack_decoder.h"
+#include "common/platform/api/quiche_bug_tracker.h"
+#include "common/platform/api/quiche_logging.h"
+#include "spdy/core/hpack/hpack_encoder.h"
+#include "spdy/core/http2_header_block_hpack_listener.h"
+
+namespace spdy {
+
+// Non-standard constants related to METADATA frames.
+const SpdySettingsId MetadataVisitor::kMetadataExtensionId = 0x4d44;
+const uint8_t MetadataVisitor::kMetadataFrameType = 0x4d;
+const uint8_t MetadataVisitor::kEndMetadataFlag = 0x4;
+
+namespace {
+
+const size_t kMaxMetadataBlockSize = 1 << 20; // 1 MB
+
+// This class uses an HpackEncoder to serialize a METADATA block as a series of
+// METADATA frames.
+class MetadataFrameSequence : public MetadataSerializer::FrameSequence {
+ public:
+ MetadataFrameSequence(SpdyStreamId stream_id, spdy::SpdyHeaderBlock payload)
+ : stream_id_(stream_id), payload_(std::move(payload)) {
+ // Metadata should not use HPACK compression.
+ encoder_.DisableCompression();
+ HpackEncoder::Representations r;
+ for (const auto& kv_pair : payload_) {
+ r.push_back(kv_pair);
+ }
+ progressive_encoder_ = encoder_.EncodeRepresentations(r);
+ }
+
+ // Copies are not allowed.
+ MetadataFrameSequence(const MetadataFrameSequence& other) = delete;
+ MetadataFrameSequence& operator=(const MetadataFrameSequence& other) = delete;
+
+ std::unique_ptr<spdy::SpdyFrameIR> Next() override;
+
+ private:
+ SpdyStreamId stream_id_;
+ SpdyHeaderBlock payload_;
+ HpackEncoder encoder_;
+ std::unique_ptr<HpackEncoder::ProgressiveEncoder> progressive_encoder_;
+};
+
+std::unique_ptr<spdy::SpdyFrameIR> MetadataFrameSequence::Next() {
+ if (!progressive_encoder_->HasNext()) {
+ return nullptr;
+ }
+ std::string payload;
+ // METADATA frames obey the HTTP/2 maximum frame size.
+ progressive_encoder_->Next(spdy::kHttp2DefaultFramePayloadLimit, &payload);
+ const bool end_metadata = (!progressive_encoder_->HasNext());
+ const uint8_t flags = end_metadata ? MetadataVisitor::kEndMetadataFlag : 0;
+ return absl::make_unique<spdy::SpdyUnknownIR>(
+ stream_id_, MetadataVisitor::kMetadataFrameType, flags,
+ std::move(payload));
+}
+
+} // anonymous namespace
+
+struct MetadataVisitor::MetadataPayloadState {
+ MetadataPayloadState(size_t remaining, bool end)
+ : bytes_remaining(remaining), end_metadata(end) {}
+ std::list<std::string> buffer;
+ size_t bytes_remaining;
+ bool end_metadata;
+};
+
+MetadataVisitor::MetadataVisitor(OnCompletePayload on_payload,
+ OnMetadataSupport on_support)
+ : on_payload_(std::move(on_payload)),
+ on_support_(std::move(on_support)),
+ peer_supports_metadata_(MetadataSupportState::UNSPECIFIED) {}
+
+MetadataVisitor::~MetadataVisitor() {}
+
+void MetadataVisitor::OnSetting(SpdySettingsId id, uint32_t value) {
+ QUICHE_VLOG(1) << "MetadataVisitor::OnSetting(" << id << ", " << value << ")";
+ if (id == kMetadataExtensionId) {
+ if (value == 0) {
+ const MetadataSupportState previous_state = peer_supports_metadata_;
+ peer_supports_metadata_ = MetadataSupportState::NOT_SUPPORTED;
+ if (previous_state == MetadataSupportState::UNSPECIFIED ||
+ previous_state == MetadataSupportState::SUPPORTED) {
+ on_support_(false);
+ }
+ } else if (value == 1) {
+ const MetadataSupportState previous_state = peer_supports_metadata_;
+ peer_supports_metadata_ = MetadataSupportState::SUPPORTED;
+ if (previous_state == MetadataSupportState::UNSPECIFIED ||
+ previous_state == MetadataSupportState::NOT_SUPPORTED) {
+ on_support_(true);
+ }
+ } else {
+ LOG_EVERY_N_SEC(WARNING, 1)
+ << "Unrecognized value for setting " << id << ": " << value;
+ }
+ }
+}
+
+bool MetadataVisitor::OnFrameHeader(SpdyStreamId stream_id, size_t length,
+ uint8_t type, uint8_t flags) {
+ QUICHE_VLOG(1) << "OnFrameHeader(stream_id=" << stream_id
+ << ", length=" << length << ", type=" << static_cast<int>(type)
+ << ", flags=" << static_cast<int>(flags);
+ // TODO(birenroy): Consider disabling METADATA handling until our setting
+ // advertising METADATA support has been acked.
+ if (type != kMetadataFrameType) {
+ return false;
+ }
+ auto it = metadata_map_.find(stream_id);
+ if (it == metadata_map_.end()) {
+ auto state = absl::make_unique<MetadataPayloadState>(
+ length, flags & kEndMetadataFlag);
+ auto result = metadata_map_.insert(std::make_pair(stream_id,
+ std::move(state)));
+ QUICHE_BUG_IF(bug_if_2781_1, !result.second) << "Map insertion failed.";
+ it = result.first;
+ } else {
+ QUICHE_BUG_IF(bug_22051_1, it->second->end_metadata)
+ << "Inconsistent metadata payload state!";
+ QUICHE_BUG_IF(bug_if_2781_2, it->second->bytes_remaining > 0)
+ << "Incomplete metadata block!";
+ }
+
+ if (it->second == nullptr) {
+ QUICHE_BUG(bug_2781_3) << "Null metadata payload state!";
+ return false;
+ }
+ current_stream_ = stream_id;
+ it->second->bytes_remaining = length;
+ it->second->end_metadata = (flags & kEndMetadataFlag);
+ return true;
+}
+
+void MetadataVisitor::OnFramePayload(const char* data, size_t len) {
+ QUICHE_VLOG(1) << "OnFramePayload(stream_id=" << current_stream_
+ << ", len=" << len << ")";
+ auto it = metadata_map_.find(current_stream_);
+ if (it == metadata_map_.end() || it->second == nullptr) {
+ QUICHE_BUG(bug_2781_4) << "Invalid order of operations on MetadataVisitor.";
+ } else {
+ MetadataPayloadState* state = it->second.get(); // For readability.
+ state->buffer.push_back(std::string(data, len));
+ if (len < state->bytes_remaining) {
+ state->bytes_remaining -= len;
+ } else {
+ QUICHE_BUG_IF(bug_22051_2, len > state->bytes_remaining)
+ << "Metadata payload overflow! len: " << len
+ << " bytes_remaining: " << state->bytes_remaining;
+ state->bytes_remaining = 0;
+ if (state->end_metadata) {
+ // The whole process of decoding the HPACK-encoded metadata block,
+ // below, is more cumbersome than it ought to be.
+ spdy::Http2HeaderBlockHpackListener listener;
+ http2::HpackDecoder decoder(&listener, kMaxMetadataBlockSize);
+
+ // If any operations fail, the decode process should be aborted.
+ bool success = decoder.StartDecodingBlock();
+ for (const std::string& slice : state->buffer) {
+ if (!success) {
+ break;
+ }
+ http2::DecodeBuffer buffer(slice.data(), slice.size());
+ success = success && decoder.DecodeFragment(&buffer);
+ }
+ success =
+ success && decoder.EndDecodingBlock() && !listener.hpack_error();
+ if (success) {
+ on_payload_(current_stream_, listener.release_header_block());
+ }
+ // TODO(birenroy): add varz counting metadata decode successes/failures.
+ metadata_map_.erase(it);
+ }
+ }
+ }
+}
+
+std::unique_ptr<MetadataSerializer::FrameSequence>
+MetadataSerializer::FrameSequenceForPayload(SpdyStreamId stream_id,
+ MetadataPayload payload) {
+ return absl::make_unique<MetadataFrameSequence>(stream_id,
+ std::move(payload));
+}
+
+} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.h b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.h
new file mode 100644
index 00000000000..043d6f0ebcd
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension.h
@@ -0,0 +1,116 @@
+#ifndef QUICHE_SPDY_CORE_METADATA_EXTENSION_H_
+#define QUICHE_SPDY_CORE_METADATA_EXTENSION_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "spdy/core/http2_frame_decoder_adapter.h"
+#include "spdy/core/spdy_header_block.h"
+#include "spdy/core/spdy_protocol.h"
+#include "spdy/core/zero_copy_output_buffer.h"
+
+namespace spdy {
+
+// An implementation of the ExtensionVisitorInterface that can parse
+// METADATA frames. METADATA is a non-standard HTTP/2 extension developed and
+// used internally at Google. A peer advertises support for METADATA by sending
+// a setting with a setting ID of kMetadataExtensionId and a value of 1.
+//
+// Metadata is represented as a HPACK header block with literal encoding.
+class MetadataVisitor : public spdy::ExtensionVisitorInterface {
+ public:
+ using MetadataPayload = spdy::SpdyHeaderBlock;
+
+ static_assert(!std::is_copy_constructible<MetadataPayload>::value,
+ "MetadataPayload should be a move-only type!");
+
+ using OnMetadataSupport = std::function<void(bool)>;
+ using OnCompletePayload =
+ std::function<void(spdy::SpdyStreamId, MetadataPayload)>;
+
+ // The HTTP/2 SETTINGS ID that is used to indicate support for METADATA
+ // frames.
+ static const spdy::SpdySettingsId kMetadataExtensionId;
+
+ // The 8-bit frame type code for a METADATA frame.
+ static const uint8_t kMetadataFrameType;
+
+ // The flag that indicates the end of a logical metadata block. Due to frame
+ // size limits, a single metadata block may be emitted as several HTTP/2
+ // frames.
+ static const uint8_t kEndMetadataFlag;
+
+ // |on_payload| is invoked whenever a complete metadata payload is received.
+ // |on_support| is invoked whenever the peer's advertised support for metadata
+ // changes.
+ MetadataVisitor(OnCompletePayload on_payload, OnMetadataSupport on_support);
+ ~MetadataVisitor() override;
+
+ MetadataVisitor(const MetadataVisitor&) = delete;
+ MetadataVisitor& operator=(const MetadataVisitor&) = delete;
+
+ // Interprets the non-standard setting indicating support for METADATA.
+ void OnSetting(spdy::SpdySettingsId id, uint32_t value) override;
+
+ // Returns true iff |type| indicates a METADATA frame.
+ bool OnFrameHeader(spdy::SpdyStreamId stream_id, size_t length, uint8_t type,
+ uint8_t flags) override;
+
+ // Consumes a METADATA frame payload. Invokes the registered callback when a
+ // complete payload has been received.
+ void OnFramePayload(const char* data, size_t len) override;
+
+ // Returns true if the peer has advertised support for METADATA via the
+ // appropriate setting.
+ bool PeerSupportsMetadata() const {
+ return peer_supports_metadata_ == MetadataSupportState::SUPPORTED;
+ }
+
+ private:
+ enum class MetadataSupportState : uint8_t {
+ UNSPECIFIED,
+ SUPPORTED,
+ NOT_SUPPORTED,
+ };
+
+ struct MetadataPayloadState;
+
+ using StreamMetadataMap =
+ absl::flat_hash_map<spdy::SpdyStreamId,
+ std::unique_ptr<MetadataPayloadState>>;
+
+ OnCompletePayload on_payload_;
+ OnMetadataSupport on_support_;
+ StreamMetadataMap metadata_map_;
+ spdy::SpdyStreamId current_stream_;
+ MetadataSupportState peer_supports_metadata_;
+};
+
+// A class that serializes metadata blocks as sequences of frames.
+class MetadataSerializer {
+ public:
+ using MetadataPayload = spdy::SpdyHeaderBlock;
+
+ class FrameSequence {
+ public:
+ virtual ~FrameSequence() {}
+
+ // Returns nullptr once the sequence has been exhausted.
+ virtual std::unique_ptr<spdy::SpdyFrameIR> Next() = 0;
+ };
+
+ MetadataSerializer() {}
+
+ MetadataSerializer(const MetadataSerializer&) = delete;
+ MetadataSerializer& operator=(const MetadataSerializer&) = delete;
+
+ // Returns nullptr on failure.
+ std::unique_ptr<FrameSequence> FrameSequenceForPayload(
+ spdy::SpdyStreamId stream_id, MetadataPayload payload);
+};
+
+} // namespace spdy
+
+#endif // QUICHE_SPDY_CORE_METADATA_EXTENSION_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/core/metadata_extension_test.cc b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension_test.cc
new file mode 100644
index 00000000000..07a5ee1113f
--- /dev/null
+++ b/chromium/net/third_party/quiche/src/spdy/core/metadata_extension_test.cc
@@ -0,0 +1,226 @@
+#include "spdy/core/metadata_extension.h"
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/functional/bind_front.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "common/platform/api/quiche_test.h"
+#include "spdy/core/array_output_buffer.h"
+#include "spdy/core/mock_spdy_framer_visitor.h"
+#include "spdy/core/spdy_framer.h"
+#include "spdy/core/spdy_header_block.h"
+#include "spdy/core/spdy_no_op_visitor.h"
+#include "spdy/core/spdy_protocol.h"
+
+namespace spdy {
+namespace test {
+namespace {
+
+using ::absl::bind_front;
+using ::spdy::SpdyFramer;
+using ::spdy::SpdyHeaderBlock;
+using ::spdy::test::MockSpdyFramerVisitor;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+
+const size_t kBufferSize = 64 * 1024;
+char kBuffer[kBufferSize];
+
+class MetadataExtensionTest : public QuicheTest {
+ protected:
+ MetadataExtensionTest() : test_buffer_(kBuffer, kBufferSize) {}
+
+ void SetUp() override {
+ extension_ = absl::make_unique<MetadataVisitor>(
+ bind_front(&MetadataExtensionTest::OnCompletePayload, this),
+ bind_front(&MetadataExtensionTest::OnMetadataSupport, this));
+ }
+
+ void OnCompletePayload(spdy::SpdyStreamId stream_id,
+ MetadataVisitor::MetadataPayload payload) {
+ ++received_count_;
+ received_payload_map_.insert(std::make_pair(stream_id, std::move(payload)));
+ }
+
+ void OnMetadataSupport(bool peer_supports_metadata) {
+ EXPECT_EQ(peer_supports_metadata, extension_->PeerSupportsMetadata());
+ received_metadata_support_.push_back(peer_supports_metadata);
+ }
+
+ MetadataSerializer::MetadataPayload PayloadForData(absl::string_view data) {
+ SpdyHeaderBlock block;
+ block["example-payload"] = data;
+ return block;
+ }
+
+ std::unique_ptr<MetadataVisitor> extension_;
+ absl::flat_hash_map<spdy::SpdyStreamId, SpdyHeaderBlock>
+ received_payload_map_;
+ std::vector<bool> received_metadata_support_;
+ size_t received_count_ = 0;
+ spdy::ArrayOutputBuffer test_buffer_;
+};
+
+// This test verifies that the MetadataVisitor is initialized to a state where
+// it believes the peer does not support metadata.
+TEST_F(MetadataExtensionTest, MetadataNotSupported) {
+ EXPECT_FALSE(extension_->PeerSupportsMetadata());
+ EXPECT_THAT(received_metadata_support_, IsEmpty());
+}
+
+// This test verifies that upon receiving a specific setting, the extension
+// realizes that the peer supports metadata.
+TEST_F(MetadataExtensionTest, MetadataSupported) {
+ EXPECT_FALSE(extension_->PeerSupportsMetadata());
+ // 3 is not an appropriate value for the metadata extension key.
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 3);
+ EXPECT_FALSE(extension_->PeerSupportsMetadata());
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 1);
+ ASSERT_TRUE(extension_->PeerSupportsMetadata());
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 0);
+ EXPECT_FALSE(extension_->PeerSupportsMetadata());
+ EXPECT_THAT(received_metadata_support_, ElementsAre(true, false));
+}
+
+TEST_F(MetadataExtensionTest, MetadataIgnoredWithoutExtension) {
+ const char kData[] = "some payload";
+ SpdyHeaderBlock payload = PayloadForData(kData);
+
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 1);
+ ASSERT_TRUE(extension_->PeerSupportsMetadata());
+
+ MetadataSerializer serializer;
+ auto sequence = serializer.FrameSequenceForPayload(3, std::move(payload));
+ ASSERT_TRUE(sequence != nullptr);
+
+ http2::Http2DecoderAdapter deframer;
+ ::testing::StrictMock<MockSpdyFramerVisitor> visitor;
+ deframer.set_visitor(&visitor);
+
+ // The Return(true) should not be necessary. http://b/36023792
+ EXPECT_CALL(visitor, OnUnknownFrame(3, MetadataVisitor::kMetadataFrameType))
+ .WillOnce(::testing::Return(true));
+
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ auto frame = sequence->Next();
+ ASSERT_TRUE(frame != nullptr);
+ while (frame != nullptr) {
+ const size_t frame_size = framer.SerializeFrame(*frame, &test_buffer_);
+ ASSERT_GT(frame_size, 0);
+ ASSERT_FALSE(deframer.HasError());
+ ASSERT_EQ(frame_size, test_buffer_.Size());
+ EXPECT_EQ(frame_size, deframer.ProcessInput(kBuffer, frame_size));
+ test_buffer_.Reset();
+ frame = sequence->Next();
+ }
+ EXPECT_FALSE(deframer.HasError());
+ EXPECT_THAT(received_metadata_support_, ElementsAre(true));
+}
+
+// This test verifies that the METADATA frame emitted by a MetadataExtension
+// can be parsed by another SpdyFramer with a MetadataVisitor.
+TEST_F(MetadataExtensionTest, MetadataPayloadEndToEnd) {
+ SpdyHeaderBlock block1;
+ block1["foo"] = "Some metadata value.";
+ SpdyHeaderBlock block2;
+ block2["bar"] =
+ "The color taupe truly represents a triumph of the human spirit over "
+ "adversity.";
+ block2["baz"] =
+ "Or perhaps it represents abject surrender to the implacable and "
+ "incomprehensible forces of the universe.";
+ const absl::string_view binary_payload{"binary\0payload", 14};
+ block2["qux"] = binary_payload;
+ EXPECT_EQ(binary_payload, block2["qux"]);
+ for (const SpdyHeaderBlock& payload_block :
+ {std::move(block1), std::move(block2)}) {
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 1);
+ ASSERT_TRUE(extension_->PeerSupportsMetadata());
+
+ MetadataSerializer serializer;
+ auto sequence =
+ serializer.FrameSequenceForPayload(3, payload_block.Clone());
+ ASSERT_TRUE(sequence != nullptr);
+
+ http2::Http2DecoderAdapter deframer;
+ ::spdy::SpdyNoOpVisitor visitor;
+ deframer.set_visitor(&visitor);
+ deframer.set_extension_visitor(extension_.get());
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ auto frame = sequence->Next();
+ ASSERT_TRUE(frame != nullptr);
+ while (frame != nullptr) {
+ const size_t frame_size = framer.SerializeFrame(*frame, &test_buffer_);
+ ASSERT_GT(frame_size, 0);
+ ASSERT_FALSE(deframer.HasError());
+ ASSERT_EQ(frame_size, test_buffer_.Size());
+ EXPECT_EQ(frame_size, deframer.ProcessInput(kBuffer, frame_size));
+ test_buffer_.Reset();
+ frame = sequence->Next();
+ }
+ EXPECT_EQ(1, received_count_);
+ auto it = received_payload_map_.find(3);
+ ASSERT_TRUE(it != received_payload_map_.end());
+ EXPECT_EQ(payload_block, it->second);
+
+ received_count_ = 0;
+ received_payload_map_.clear();
+ }
+}
+
+// This test verifies that METADATA frames for two different streams can be
+// interleaved and still successfully parsed by another SpdyFramer with a
+// MetadataVisitor.
+TEST_F(MetadataExtensionTest, MetadataPayloadInterleaved) {
+ const std::string kData1 = std::string(65 * 1024, 'a');
+ const std::string kData2 = std::string(65 * 1024, 'b');
+ const SpdyHeaderBlock payload1 = PayloadForData(kData1);
+ const SpdyHeaderBlock payload2 = PayloadForData(kData2);
+
+ extension_->OnSetting(MetadataVisitor::kMetadataExtensionId, 1);
+ ASSERT_TRUE(extension_->PeerSupportsMetadata());
+
+ MetadataSerializer serializer;
+ auto sequence1 = serializer.FrameSequenceForPayload(3, payload1.Clone());
+ ASSERT_TRUE(sequence1 != nullptr);
+
+ auto sequence2 = serializer.FrameSequenceForPayload(5, payload2.Clone());
+ ASSERT_TRUE(sequence2 != nullptr);
+
+ http2::Http2DecoderAdapter deframer;
+ ::spdy::SpdyNoOpVisitor visitor;
+ deframer.set_visitor(&visitor);
+ deframer.set_extension_visitor(extension_.get());
+
+ SpdyFramer framer(SpdyFramer::ENABLE_COMPRESSION);
+ auto frame1 = sequence1->Next();
+ ASSERT_TRUE(frame1 != nullptr);
+ auto frame2 = sequence2->Next();
+ ASSERT_TRUE(frame2 != nullptr);
+ while (frame1 != nullptr || frame2 != nullptr) {
+ for (auto frame : {frame1.get(), frame2.get()}) {
+ if (frame != nullptr) {
+ const size_t frame_size = framer.SerializeFrame(*frame, &test_buffer_);
+ ASSERT_GT(frame_size, 0);
+ ASSERT_FALSE(deframer.HasError());
+ ASSERT_EQ(frame_size, test_buffer_.Size());
+ EXPECT_EQ(frame_size, deframer.ProcessInput(kBuffer, frame_size));
+ test_buffer_.Reset();
+ }
+ }
+ frame1 = sequence1->Next();
+ frame2 = sequence2->Next();
+ }
+ EXPECT_EQ(2, received_count_);
+ auto it = received_payload_map_.find(3);
+ ASSERT_TRUE(it != received_payload_map_.end());
+ EXPECT_EQ(payload1, it->second);
+
+ it = received_payload_map_.find(5);
+ ASSERT_TRUE(it != received_payload_map_.end());
+ EXPECT_EQ(payload2, it->second);
+}
+
+} // anonymous namespace
+} // namespace test
+} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
index 94218f697da..f1cca0da3b1 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_alt_svc_wire_format.cc
@@ -11,7 +11,6 @@
#include "absl/strings/str_cat.h"
#include "common/platform/api/quiche_logging.h"
-#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
index d6f0f889876..1b6eb8a6a9f 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.cc
@@ -18,8 +18,6 @@
#include "spdy/core/spdy_bitmasks.h"
#include "spdy/core/spdy_frame_builder.h"
#include "spdy/core/spdy_frame_reader.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
-#include "spdy/platform/api/spdy_string_utils.h"
namespace spdy {
@@ -303,9 +301,8 @@ size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
const size_t size_without_block =
is_first_frame_ ? GetFrameSizeSansBlock() : kContinuationFrameMinimumSize;
- auto encoding = std::make_unique<std::string>();
- encoder_->Next(kHttp2MaxControlFrameSendSize - size_without_block,
- encoding.get());
+ std::string encoding;
+ encoder_->Next(kHttp2MaxControlFrameSendSize - size_without_block, &encoding);
has_next_frame_ = encoder_->HasNext();
if (framer_->debug_visitor_ != nullptr) {
@@ -316,14 +313,14 @@ size_t SpdyFramer::SpdyFrameIterator::NextFrame(ZeroCopyOutputBuffer* output) {
framer_->debug_visitor_->OnSendCompressedFrame(
frame_ir.stream_id(),
is_first_frame_ ? frame_ir.frame_type() : SpdyFrameType::CONTINUATION,
- header_list_size, size_without_block + encoding->size());
+ header_list_size, size_without_block + encoding.size());
}
const size_t free_bytes_before = output->BytesFree();
bool ok = false;
if (is_first_frame_) {
is_first_frame_ = false;
- ok = SerializeGivenEncoding(*encoding, output);
+ ok = SerializeGivenEncoding(encoding, output);
} else {
SpdyContinuationIR continuation_ir(frame_ir.stream_id());
continuation_ir.take_encoding(std::move(encoding));
@@ -1380,8 +1377,4 @@ size_t SpdyFramer::header_encoder_table_size() const {
}
}
-size_t SpdyFramer::EstimateMemoryUsage() const {
- return SpdyEstimateMemoryUsage(hpack_encoder_);
-}
-
} // namespace spdy
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
index 4e3dc35f1d3..6f7a5dc9bd6 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer.h
@@ -236,8 +236,9 @@ class QUICHE_EXPORT_PRIVATE SpdyFramer {
// Get (and lazily initialize) the HPACK encoder state.
HpackEncoder* GetHpackEncoder();
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
+ // Gets the HPACK encoder state. Returns nullptr if the encoder has not been
+ // initialized.
+ const HpackEncoder* GetHpackEncoder() const { return hpack_encoder_.get(); }
protected:
friend class test::SpdyFramerPeer;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
index c4b5979a874..138c4873b79 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_framer_test.cc
@@ -16,6 +16,7 @@
#include "absl/base/macros.h"
#include "common/platform/api/quiche_logging.h"
#include "common/platform/api/quiche_test.h"
+#include "common/quiche_text_utils.h"
#include "spdy/core/array_output_buffer.h"
#include "spdy/core/mock_spdy_framer_visitor.h"
#include "spdy/core/recording_headers_handler.h"
@@ -24,7 +25,6 @@
#include "spdy/core/spdy_frame_reader.h"
#include "spdy/core/spdy_protocol.h"
#include "spdy/core/spdy_test_utils.h"
-#include "spdy/platform/api/spdy_string_utils.h"
using ::http2::Http2DecoderAdapter;
using ::testing::_;
@@ -287,7 +287,8 @@ class TestSpdyVisitor : public SpdyFramerVisitorInterface,
QUICHE_VLOG(1) << "OnStreamFrameData(" << stream_id << ", data, " << len
<< ", "
<< ") data:\n"
- << SpdyHexDump(absl::string_view(data, len));
+ << quiche::QuicheTextUtils::HexDump(
+ absl::string_view(data, len));
EXPECT_EQ(header_stream_id_, stream_id);
data_bytes_ += len;
@@ -1040,8 +1041,7 @@ TEST_P(SpdyFramerTest, ContinuationWithStreamIdZero) {
deframer_.set_visitor(&visitor);
SpdyContinuationIR continuation(/* stream_id = */ 0);
- auto some_nonsense_encoding =
- std::make_unique<std::string>("some nonsense encoding");
+ std::string some_nonsense_encoding = "some nonsense encoding";
continuation.take_encoding(std::move(some_nonsense_encoding));
continuation.set_end_headers(true);
SpdySerializedFrame frame(framer_.SerializeContinuation(continuation));
@@ -1230,6 +1230,92 @@ TEST_P(SpdyFramerTest, Basic) {
EXPECT_EQ(4, visitor.data_frame_count_);
}
+// Verifies that the decoder stops delivering events after a user error.
+TEST_P(SpdyFramerTest, BasicWithError) {
+ // Send HEADERS frames with PRIORITY and END_HEADERS set.
+ // frame-format off
+ const unsigned char kH2Input[] = {
+ 0x00, 0x00, 0x01, // Length: 1
+ 0x01, // Type: HEADERS
+ 0x04, // Flags: END_HEADERS
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x8c, // :status: 200
+
+ 0x00, 0x00, 0x0c, // Length: 12
+ 0x00, // Type: DATA
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0xde, 0xad, 0xbe, 0xef, // Payload
+ 0xde, 0xad, 0xbe, 0xef, //
+ 0xde, 0xad, 0xbe, 0xef, //
+
+ 0x00, 0x00, 0x06, // Length: 5
+ 0x01, // Type: HEADERS
+ 0x24, // Flags: END_HEADERS|PRIORITY
+ 0x00, 0x00, 0x00, 0x03, // Stream: 3
+ 0x00, 0x00, 0x00, 0x00, // Parent: 0
+ 0x82, // Weight: 131
+ 0x8c, // :status: 200
+
+ 0x00, 0x00, 0x08, // Length: 8
+ 0x00, // Type: DATA
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x03, // Stream: 3
+ 0xde, 0xad, 0xbe, 0xef, // Payload
+ 0xde, 0xad, 0xbe, 0xef, //
+
+ 0x00, 0x00, 0x04, // Length: 4
+ 0x00, // Type: DATA
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0xde, 0xad, 0xbe, 0xef, // Payload
+
+ 0x00, 0x00, 0x04, // Length: 4
+ 0x03, // Type: RST_STREAM
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x01, // Stream: 1
+ 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
+
+ 0x00, 0x00, 0x00, // Length: 0
+ 0x00, // Type: DATA
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x03, // Stream: 3
+
+ 0x00, 0x00, 0x04, // Length: 4
+ 0x03, // Type: RST_STREAM
+ 0x00, // Flags: none
+ 0x00, 0x00, 0x00, 0x03, // Stream: 3
+ 0x00, 0x00, 0x00, 0x08, // Error: CANCEL
+ };
+ // frame-format on
+
+ testing::StrictMock<test::MockSpdyFramerVisitor> visitor;
+
+ deframer_.set_visitor(&visitor);
+
+ testing::InSequence s;
+ EXPECT_CALL(visitor, OnHeaders(1, false, 0, 0, false, false, true));
+ EXPECT_CALL(visitor, OnHeaderFrameStart(1));
+ EXPECT_CALL(visitor, OnHeaderFrameEnd(1));
+ EXPECT_CALL(visitor, OnDataFrameHeader(1, 12, false));
+ EXPECT_CALL(visitor, OnStreamFrameData(1, _, 12));
+ EXPECT_CALL(visitor, OnHeaders(3, true, 131, 0, false, false, true));
+ EXPECT_CALL(visitor, OnHeaderFrameStart(3));
+ EXPECT_CALL(visitor, OnHeaderFrameEnd(3));
+ EXPECT_CALL(visitor, OnDataFrameHeader(3, 8, false))
+ .WillOnce(
+ testing::InvokeWithoutArgs([this]() { deframer_.StopProcessing(); }));
+ // Remaining frames are not processed due to the error.
+ EXPECT_CALL(
+ visitor,
+ OnError(http2::Http2DecoderAdapter::SpdyFramerError::SPDY_STOP_PROCESSING,
+ "Ignoring further events on this connection."));
+
+ size_t processed = deframer_.ProcessInput(
+ reinterpret_cast<const char*>(kH2Input), sizeof(kH2Input));
+ EXPECT_LT(processed, sizeof(kH2Input));
+}
+
// Test that the FIN flag on a data frame signifies EOF.
TEST_P(SpdyFramerTest, FinOnDataFrame) {
// Send HEADERS frames with END_HEADERS set.
@@ -2315,10 +2401,10 @@ TEST_P(SpdyFramerTest, CreateContinuationUncompressed) {
Http2HeaderBlock header_block;
header_block["bar"] = "foo";
header_block["foo"] = "bar";
- auto buffer = std::make_unique<std::string>();
+ std::string buffer;
HpackEncoder encoder;
encoder.DisableCompression();
- encoder.EncodeHeaderSet(header_block, buffer.get());
+ encoder.EncodeHeaderSet(header_block, &buffer);
SpdyContinuationIR continuation(/* stream_id = */ 42);
continuation.take_encoding(std::move(buffer));
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
index b5790470e02..2190c6bbdad 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.cc
@@ -11,7 +11,6 @@
#include "absl/strings/str_cat.h"
#include "common/platform/api/quiche_logging.h"
-#include "spdy/platform/api/spdy_estimate_memory_usage.h"
namespace spdy {
namespace {
@@ -299,12 +298,6 @@ void Http2HeaderBlock::AppendValueOrAddHeader(const absl::string_view key,
iter->second.Append(storage_.Write(value));
}
-size_t Http2HeaderBlock::EstimateMemoryUsage() const {
- // TODO(xunjieli): https://crbug.com/669108. Also include |map_| when EMU()
- // supports linked_hash_map.
- return SpdyEstimateMemoryUsage(storage_);
-}
-
void Http2HeaderBlock::AppendHeader(const absl::string_view key,
const absl::string_view value) {
auto backed_key = WriteKey(key);
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
index 46584191461..c3c5bad7205 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block.h
@@ -20,8 +20,8 @@
#include "absl/strings/string_view.h"
#include "common/platform/api/quiche_export.h"
#include "common/platform/api/quiche_logging.h"
+#include "common/quiche_linked_hash_map.h"
#include "spdy/core/spdy_header_storage.h"
-#include "spdy/platform/api/spdy_containers.h"
namespace spdy {
@@ -108,10 +108,10 @@ class QUICHE_EXPORT_PRIVATE Http2HeaderBlock {
}
};
- typedef SpdyLinkedHashMap<absl::string_view,
- HeaderValue,
- StringPieceCaseHash,
- StringPieceCaseEqual>
+ typedef quiche::QuicheLinkedHashMap<absl::string_view,
+ HeaderValue,
+ StringPieceCaseHash,
+ StringPieceCaseEqual>
MapType;
public:
@@ -201,6 +201,7 @@ class QUICHE_EXPORT_PRIVATE Http2HeaderBlock {
const_iterator find(absl::string_view key) const {
return wrap_const_iterator(map_.find(key));
}
+ bool contains(absl::string_view key) const { return find(key) != end(); }
void erase(absl::string_view key);
// Clears both our MapType member and the memory used to hold headers.
@@ -262,9 +263,6 @@ class QUICHE_EXPORT_PRIVATE Http2HeaderBlock {
// Allows either lookup or mutation of the value associated with a key.
ABSL_MUST_USE_RESULT ValueProxy operator[](const absl::string_view key);
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const;
-
size_t TotalBytesUsed() const { return key_size_ + value_size_; }
private:
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block_test.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block_test.cc
index 2435ea9c043..0767dc9e875 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block_test.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_block_test.cc
@@ -33,6 +33,7 @@ TEST(Http2HeaderBlockTest, EmptyBlock) {
EXPECT_TRUE(block.empty());
EXPECT_EQ(0u, block.size());
EXPECT_EQ(block.end(), block.find("foo"));
+ EXPECT_FALSE(block.contains("foo"));
EXPECT_TRUE(block.end() == block.begin());
// Should have no effect.
@@ -83,6 +84,7 @@ TEST(Http2HeaderBlockTest, AddHeaders) {
std::string qux("qux");
EXPECT_EQ("qux2", block[qux]);
ASSERT_NE(block.end(), block.find("key"));
+ ASSERT_TRUE(block.contains("key"));
EXPECT_EQ(Pair("key", "value"), *block.find("key"));
block.erase("key");
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.h
index 24c64eeae87..54267db51a4 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_header_storage.h
@@ -43,8 +43,6 @@ class QUICHE_EXPORT_PRIVATE SpdyHeaderStorage {
size_t bytes_allocated() const { return arena_.status().bytes_allocated(); }
- size_t EstimateMemoryUsage() const { return bytes_allocated(); }
-
private:
SpdySimpleArena arena_;
};
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_intrusive_list.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_intrusive_list.h
index 2d9f749f7fa..3af20538578 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_intrusive_list.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_intrusive_list.h
@@ -267,9 +267,10 @@ template <typename T, typename ListID = void> class SpdyIntrusiveList {
public:
typedef std::iterator<std::bidirectional_iterator_tag, QualifiedT> base;
- iterator_impl() : link_(nullptr) {}
+ iterator_impl() = default;
iterator_impl(QualifiedLinkT* link) : link_(link) {}
- iterator_impl(const iterator_impl& x) : link_(x.link_) {}
+ iterator_impl(const iterator_impl& x) = default;
+ iterator_impl& operator=(const iterator_impl& x) = default;
// Allow converting and comparing across iterators where the pointer
// assignment and comparisons (respectively) are allowed.
@@ -310,7 +311,7 @@ template <typename T, typename ListID = void> class SpdyIntrusiveList {
// Ensure iterators can access other iterators node directly.
template <typename U, typename V> friend class iterator_impl;
- QualifiedLinkT* link_;
+ QualifiedLinkT* link_ = nullptr;
};
// This bare link acts as the sentinel node.
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
index 4bde56a29d7..12a716e486c 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.cc
@@ -446,7 +446,6 @@ size_t SpdyGoAwayIR::size() const {
SpdyContinuationIR::SpdyContinuationIR(SpdyStreamId stream_id)
: SpdyFrameIR(stream_id), end_headers_(false) {
- encoding_ = std::make_unique<std::string>();
}
SpdyContinuationIR::~SpdyContinuationIR() = default;
diff --git a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
index 16d6b9a7ecd..eafb845883a 100644
--- a/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
+++ b/chromium/net/third_party/quiche/src/spdy/core/spdy_protocol.h
@@ -260,7 +260,7 @@ QUICHE_EXPORT_PRIVATE bool IsValidHTTP2FrameStreamId(
SpdyFrameType frame_type_field);
// Serialize |frame_type| to string for logging/debugging.
-const char* FrameTypeToString(SpdyFrameType frame_type);
+QUICHE_EXPORT_PRIVATE const char* FrameTypeToString(SpdyFrameType frame_type);
// If |wire_setting_id| is the on-the-wire representation of a defined SETTINGS
// parameter, parse it to |*setting_id| and return true.
@@ -328,7 +328,7 @@ const int32_t kInitialStreamWindowSize = 64 * 1024 - 1;
// Initial window size for a session in bytes.
const int32_t kInitialSessionWindowSize = 64 * 1024 - 1;
// The NPN string for HTTP2, "h2".
-extern const char* const kHttp2Npn;
+QUICHE_EXPORT_PRIVATE extern const char* const kHttp2Npn;
// An estimate size of the HPACK overhead for each header field. 1 bytes for
// indexed literal, 1 bytes for key literal and length encoding, and 2 bytes for
// value literal and length encoding.
@@ -351,7 +351,7 @@ QUICHE_EXPORT_PRIVATE size_t GetNumberRequiredContinuationFrames(size_t size);
// exclusive bit}. Templated to allow for use by QUIC code; SPDY and HTTP/2
// code should use the concrete type instantiation SpdyStreamPrecedence.
template <typename StreamIdType>
-class StreamPrecedence {
+class QUICHE_EXPORT_PRIVATE StreamPrecedence {
public:
// Constructs instance that is a SPDY 3.x priority. Clamps priority value to
// the valid range [0, 7].
@@ -427,7 +427,7 @@ class StreamPrecedence {
}
private:
- struct Http2StreamDependency {
+ struct QUICHE_EXPORT_PRIVATE Http2StreamDependency {
StreamIdType parent_id;
int weight;
bool is_exclusive;
@@ -827,14 +827,12 @@ class QUICHE_EXPORT_PRIVATE SpdyContinuationIR : public SpdyFrameIR {
bool end_headers() const { return end_headers_; }
void set_end_headers(bool end_headers) { end_headers_ = end_headers; }
- const std::string& encoding() const { return *encoding_; }
- void take_encoding(std::unique_ptr<std::string> encoding) {
- encoding_ = std::move(encoding);
- }
+ const std::string& encoding() const { return encoding_; }
+ void take_encoding(std::string encoding) { encoding_ = std::move(encoding); }
size_t size() const override;
private:
- std::unique_ptr<std::string> encoding_;
+ std::string encoding_;
bool end_headers_;
};
@@ -920,7 +918,7 @@ class QUICHE_EXPORT_PRIVATE SpdyPriorityUpdateIR : public SpdyFrameIR {
std::string priority_field_value_;
};
-struct AcceptChOriginValuePair {
+struct QUICHE_EXPORT_PRIVATE AcceptChOriginValuePair {
std::string origin;
std::string value;
bool operator==(const AcceptChOriginValuePair& rhs) const {
@@ -1061,9 +1059,6 @@ class QUICHE_EXPORT_PRIVATE SpdySerializedFrame {
return buffer;
}
- // Returns the estimate of dynamically allocated memory in bytes.
- size_t EstimateMemoryUsage() const { return owns_buffer_ ? size_ : 0; }
-
protected:
char* frame_;
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h
deleted file mode 100644
index 2adf3f4b87a..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_containers.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
-
-#include "net/spdy/platform/impl/spdy_containers_impl.h"
-
-namespace spdy {
-
-// A map which offers insertion-ordered iteration.
-template <typename Key, typename Value, typename Hash, typename Eq>
-using SpdyLinkedHashMap = SpdyLinkedHashMapImpl<Key, Value, Hash, Eq>;
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_CONTAINERS_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h
deleted file mode 100644
index 4e22d1eabb0..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_estimate_memory_usage.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_ESTIMATE_MEMORY_USAGE_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_ESTIMATE_MEMORY_USAGE_H_
-
-#include <cstddef>
-
-#include "quiche_platform_impl/quiche_estimate_memory_usage_impl.h"
-
-namespace spdy {
-
-template <class T>
-size_t SpdyEstimateMemoryUsage(const T& object) {
- return quiche::QuicheEstimateMemoryUsageImpl(object);
-}
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_ESTIMATE_MEMORY_USAGE_H_
diff --git a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h b/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h
deleted file mode 100644
index 83660bab06f..00000000000
--- a/chromium/net/third_party/quiche/src/spdy/platform/api/spdy_string_utils.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef QUICHE_SPDY_PLATFORM_API_SPDY_STRING_UTILS_H_
-#define QUICHE_SPDY_PLATFORM_API_SPDY_STRING_UTILS_H_
-
-#include <string>
-
-#include "absl/strings/string_view.h"
-#include "net/spdy/platform/impl/spdy_string_utils_impl.h"
-
-namespace spdy {
-
-inline std::string SpdyHexDump(absl::string_view data) {
- return SpdyHexDumpImpl(data);
-}
-
-} // namespace spdy
-
-#endif // QUICHE_SPDY_PLATFORM_API_SPDY_STRING_UTILS_H_
diff --git a/chromium/net/tools/cachetool/cachetool.cc b/chromium/net/tools/cachetool/cachetool.cc
index dcf94f74d6c..df1a85c8281 100644
--- a/chromium/net/tools/cachetool/cachetool.cc
+++ b/chromium/net/tools/cachetool/cachetool.cc
@@ -8,13 +8,13 @@
#include "base/at_exit.h"
#include "base/command_line.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/format_macros.h"
#include "base/hash/md5.h"
#include "base/logging.h"
#include "base/message_loop/message_pump_type.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
@@ -26,6 +26,7 @@
#include "net/disk_cache/disk_cache_test_util.h"
#include "net/http/http_cache.h"
#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
#include "net/http/http_util.h"
using disk_cache::Backend;
diff --git a/chromium/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc b/chromium/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
index a26f07e476b..d17e8bad5d9 100644
--- a/chromium/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
+++ b/chromium/net/tools/cert_verify_tool/verify_using_cert_verify_proc.cc
@@ -6,7 +6,7 @@
#include <iostream>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
@@ -143,8 +143,8 @@ bool VerifyUsingCertVerifyProc(
net::CertificateList x509_additional_trust_anchors;
for (const auto& cert : root_der_certs) {
scoped_refptr<net::X509Certificate> x509_root =
- net::X509Certificate::CreateFromBytes(cert.der_cert.data(),
- cert.der_cert.size());
+ net::X509Certificate::CreateFromBytes(
+ base::as_bytes(base::make_span(cert.der_cert)));
if (!x509_root)
PrintCertError("ERROR: X509Certificate::CreateFromBytes failed:", cert);
diff --git a/chromium/net/tools/cert_verify_tool/verify_using_path_builder.h b/chromium/net/tools/cert_verify_tool/verify_using_path_builder.h
index 31f0145e716..1e8e8440c80 100644
--- a/chromium/net/tools/cert_verify_tool/verify_using_path_builder.h
+++ b/chromium/net/tools/cert_verify_tool/verify_using_path_builder.h
@@ -5,7 +5,6 @@
#ifndef NET_TOOLS_CERT_VERIFY_TOOL_VERIFY_USING_PATH_BUILDER_H_
#define NET_TOOLS_CERT_VERIFY_TOOL_VERIFY_USING_PATH_BUILDER_H_
-#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
diff --git a/chromium/net/tools/content_decoder_tool/content_decoder_tool_unittest.cc b/chromium/net/tools/content_decoder_tool/content_decoder_tool_unittest.cc
index 4685895f819..de610b33384 100644
--- a/chromium/net/tools/content_decoder_tool/content_decoder_tool_unittest.cc
+++ b/chromium/net/tools/content_decoder_tool/content_decoder_tool_unittest.cc
@@ -9,7 +9,6 @@
#include <ostream>
#include <utility>
-#include "base/bit_cast.h"
#include "base/files/file_util.h"
#include "base/path_service.h"
#include "net/filter/brotli_source_stream.h"
diff --git a/chromium/net/tools/crash_cache/crash_cache.cc b/chromium/net/tools/crash_cache/crash_cache.cc
index 358e29f5ab5..1b500834982 100644
--- a/chromium/net/tools/crash_cache/crash_cache.cc
+++ b/chromium/net/tools/crash_cache/crash_cache.cc
@@ -12,12 +12,12 @@
#include "base/at_exit.h"
#include "base/check.h"
#include "base/command_line.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/message_loop/message_pump_type.h"
#include "base/path_service.h"
#include "base/process/kill.h"
#include "base/process/launch.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/net/tools/dafsa/PRESUBMIT.py b/chromium/net/tools/dafsa/PRESUBMIT.py
index 253fcbbf248..e27e5a16245 100644
--- a/chromium/net/tools/dafsa/PRESUBMIT.py
+++ b/chromium/net/tools/dafsa/PRESUBMIT.py
@@ -2,10 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-
"""Chromium presubmit script for src/net/tools/dafsa."""
+USE_PYTHON3 = True
+
+
def _RunMakeDafsaTests(input_api, output_api):
"""Runs unittest for make_dafsa if any related file has been modified."""
files = ('net/tools/dafsa/make_dafsa.py',
diff --git a/chromium/net/tools/huffman_trie/trie/trie_writer.h b/chromium/net/tools/huffman_trie/trie/trie_writer.h
index 3c824e75f27..9fdc1ee362f 100644
--- a/chromium/net/tools/huffman_trie/trie/trie_writer.h
+++ b/chromium/net/tools/huffman_trie/trie/trie_writer.h
@@ -5,7 +5,6 @@
#ifndef NET_TOOLS_HUFFMAN_TRIE_TRIE_TRIE_WRITER_H_
#define NET_TOOLS_HUFFMAN_TRIE_TRIE_TRIE_WRITER_H_
-#include <string>
#include <vector>
#include "net/tools/huffman_trie/bit_writer.h"
diff --git a/chromium/net/tools/quic/quic_client_message_loop_network_helper.h b/chromium/net/tools/quic/quic_client_message_loop_network_helper.h
index 82aeeddae73..a0ba9adbc00 100644
--- a/chromium/net/tools/quic/quic_client_message_loop_network_helper.h
+++ b/chromium/net/tools/quic/quic_client_message_loop_network_helper.h
@@ -11,7 +11,6 @@
#include <stddef.h>
#include <memory>
-#include <string>
#include "base/command_line.h"
#include "base/macros.h"
diff --git a/chromium/net/tools/quic/quic_simple_client.h b/chromium/net/tools/quic/quic_simple_client.h
index 3ac2841a68d..5e9d4d1ff05 100644
--- a/chromium/net/tools/quic/quic_simple_client.h
+++ b/chromium/net/tools/quic/quic_simple_client.h
@@ -11,7 +11,6 @@
#include <stddef.h>
#include <memory>
-#include <string>
#include "base/command_line.h"
#include "base/macros.h"
diff --git a/chromium/net/tools/quic/quic_simple_server.cc b/chromium/net/tools/quic/quic_simple_server.cc
index f50b948b067..06bfde583d8 100644
--- a/chromium/net/tools/quic/quic_simple_server.cc
+++ b/chromium/net/tools/quic/quic_simple_server.cc
@@ -192,7 +192,10 @@ void QuicSimpleServer::OnReadComplete(int result) {
// packet whose payload is larger than our receive buffer. Do not act on 0
// as that indicates that we received a UDP packet with an empty payload.
// In both cases, the socket should still be usable.
- if (result != ERR_MSG_TOO_BIG && result != 0) {
+ // Also do not act on ERR_CONNECTION_RESET as this is happening when the
+ // network service restarts on Windows.
+ if (result != ERR_MSG_TOO_BIG && result != ERR_CONNECTION_RESET &&
+ result != 0) {
Shutdown();
return;
}
diff --git a/chromium/net/tools/quic/quic_simple_server_test.cc b/chromium/net/tools/quic/quic_simple_server_test.cc
index d6a1e62d0b3..599a56cada1 100644
--- a/chromium/net/tools/quic/quic_simple_server_test.cc
+++ b/chromium/net/tools/quic/quic_simple_server_test.cc
@@ -6,7 +6,7 @@
#include <memory>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/quic/address_utils.h"
#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
diff --git a/chromium/net/tools/quic/quic_transport_simple_server.cc b/chromium/net/tools/quic/quic_transport_simple_server.cc
index 6f9095ab9e1..aa3de30146d 100644
--- a/chromium/net/tools/quic/quic_transport_simple_server.cc
+++ b/chromium/net/tools/quic/quic_transport_simple_server.cc
@@ -59,7 +59,7 @@ class QuicTransportSimpleServerSessionHelper
};
QuicTransportSimpleServer::QuicTransportSimpleServer(
- int port,
+ uint16_t port,
std::vector<url::Origin> accepted_origins,
std::unique_ptr<quic::ProofSource> proof_source)
: port_(port),
diff --git a/chromium/net/tools/quic/quic_transport_simple_server.h b/chromium/net/tools/quic/quic_transport_simple_server.h
index 8cfa26c6b98..df7481bd17c 100644
--- a/chromium/net/tools/quic/quic_transport_simple_server.h
+++ b/chromium/net/tools/quic/quic_transport_simple_server.h
@@ -26,7 +26,7 @@ class QuicTransportSimpleServer {
public:
using ReadErrorCallback = base::OnceCallback<void(int)>;
- QuicTransportSimpleServer(int port,
+ QuicTransportSimpleServer(uint16_t port,
std::vector<url::Origin> accepted_origins,
std::unique_ptr<quic::ProofSource> proof_source);
~QuicTransportSimpleServer();
@@ -49,7 +49,7 @@ class QuicTransportSimpleServer {
// Passes the most recently read packet into the dispatcher.
void ProcessReadPacket(int result);
- const int port_;
+ const uint16_t port_;
ReadErrorCallback read_error_callback_;
diff --git a/chromium/net/tools/quic/quic_transport_simple_server_bin.cc b/chromium/net/tools/quic/quic_transport_simple_server_bin.cc
index f021d1d5b55..74e602a1744 100644
--- a/chromium/net/tools/quic/quic_transport_simple_server_bin.cc
+++ b/chromium/net/tools/quic/quic_transport_simple_server_bin.cc
@@ -9,7 +9,7 @@
#include "net/tools/quic/quic_transport_simple_server.h"
#include "url/gurl.h"
-DEFINE_QUIC_COMMAND_LINE_FLAG(int, port, 20557, "The port to listen on.");
+DEFINE_QUIC_COMMAND_LINE_FLAG(uint16_t, port, 20557, "The port to listen on.");
DEFINE_QUIC_COMMAND_LINE_FLAG(std::string,
accepted_origins,
diff --git a/chromium/net/tools/root_store_tool/BUILD.gn b/chromium/net/tools/root_store_tool/BUILD.gn
new file mode 100644
index 00000000000..bbb0d111f22
--- /dev/null
+++ b/chromium/net/tools/root_store_tool/BUILD.gn
@@ -0,0 +1,26 @@
+# Copyright 2021 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import("//third_party/protobuf/proto_library.gni")
+
+proto_library("root_store_proto_full") {
+ sources = [ "root_store.proto" ]
+
+ # root_store_tool uses the full protobuf library to parse textproto. This
+ # should not be linked into the browser. If the browser needs this protobuf in
+ # the future, make a separate target with cc_generator_options = "lite".
+ use_protobuf_full = true
+ visibility = [ ":root_store_tool" ]
+}
+
+# TODO(https://crbug.com/1216547): add unit tests
+executable("root_store_tool") {
+ sources = [ "root_store_tool.cc" ]
+ deps = [
+ ":root_store_proto_full",
+ "//base",
+ "//crypto",
+ "//third_party/boringssl",
+ ]
+}
diff --git a/chromium/net/tools/root_store_tool/README.md b/chromium/net/tools/root_store_tool/README.md
new file mode 100644
index 00000000000..d1eac4fa048
--- /dev/null
+++ b/chromium/net/tools/root_store_tool/README.md
@@ -0,0 +1,8 @@
+# Root store tool
+
+This directory contains tools for processing the
+[Chrome Root
+Store](https://www.chromium.org/Home/chromium-security/root-ca-policy) data in
+[`//net/data/ssl/chrome_root_store`](/net/data/ssl/chrome_root_store).
+
+TODO(https://crbug.com/1216547): document how to use these tools.
diff --git a/chromium/net/tools/root_store_tool/root_store.proto b/chromium/net/tools/root_store_tool/root_store.proto
new file mode 100644
index 00000000000..bbefffe4115
--- /dev/null
+++ b/chromium/net/tools/root_store_tool/root_store.proto
@@ -0,0 +1,27 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+syntax = "proto3";
+
+package chrome_root_store;
+
+// These structures are currently very simple, but more fields may be added in
+// future to support extra metadata about each trust anchor.
+
+message TrustAnchor {
+ // The human-editable textproto version of the root store uses the filename
+ // field for convenience. It is converted to the DER representation as part of
+ // the build process.
+ oneof certificate {
+ bytes der = 1;
+
+ // This filename is a relative path to a PEM file that stores the
+ // certificate.
+ string filename = 2;
+ }
+}
+
+message RootStore {
+ repeated TrustAnchor trust_anchors = 1;
+}
diff --git a/chromium/net/tools/root_store_tool/root_store_tool.cc b/chromium/net/tools/root_store_tool/root_store_tool.cc
new file mode 100644
index 00000000000..70bed922f40
--- /dev/null
+++ b/chromium/net/tools/root_store_tool/root_store_tool.cc
@@ -0,0 +1,216 @@
+// Copyright 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <iostream>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/logging.h"
+#include "base/path_service.h"
+#include "base/strings/string_piece.h"
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "crypto/openssl_util.h"
+#include "net/tools/root_store_tool/root_store.pb.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/boringssl/src/include/openssl/bio.h"
+#include "third_party/boringssl/src/include/openssl/pem.h"
+#include "third_party/protobuf/src/google/protobuf/text_format.h"
+
+using chrome_root_store::RootStore;
+
+namespace {
+
+absl::optional<std::string> DecodePEM(base::StringPiece pem) {
+ // TODO(https://crbug.com/1216547): net/cert/pem.h has a much nicer API, but
+ // it would require some build refactoring to avoid a circular dependency.
+ // This is assuming that the chrome trust store code goes in
+ // net/cert/internal, which it may not.
+ bssl::UniquePtr<BIO> bio(BIO_new_mem_buf(pem.data(), pem.size()));
+ if (!bio) {
+ return absl::nullopt;
+ }
+ char* name;
+ char* header;
+ unsigned char* data;
+ long len;
+ if (!PEM_read_bio(bio.get(), &name, &header, &data, &len)) {
+ LOG(ERROR) << "Could not find PEM block.";
+ return absl::nullopt;
+ }
+ bssl::UniquePtr<char> scoped_name(name);
+ bssl::UniquePtr<char> scoped_header(header);
+ bssl::UniquePtr<unsigned char> scoped_data(data);
+ if (strcmp(name, "CERTIFICATE") != 0) {
+ LOG(ERROR) << "Found PEM block of type " << name
+ << " instead of CERTIFICATE";
+ return absl::nullopt;
+ }
+ return std::string(data, data + len);
+}
+
+absl::optional<RootStore> ReadTextRootStore(
+ const base::FilePath& root_store_dir) {
+ base::FilePath root_store_path =
+ root_store_dir.AppendASCII("root_store.textproto");
+ std::string root_store_text;
+ if (!base::ReadFileToString(root_store_path, &root_store_text)) {
+ LOG(ERROR) << "Could not read " << root_store_path;
+ return absl::nullopt;
+ }
+
+ RootStore root_store;
+ if (!google::protobuf::TextFormat::ParseFromString(root_store_text,
+ &root_store)) {
+ LOG(ERROR) << "Could not parse " << root_store_path;
+ return absl::nullopt;
+ }
+
+ // Replace the filenames with the actual certificate contents.
+ base::FilePath certs_dir = root_store_dir.AppendASCII("certs");
+ for (auto& anchor : *root_store.mutable_trust_anchors()) {
+ base::FilePath pem_path = certs_dir.AppendASCII(anchor.filename());
+
+ if (!base::PathExists(pem_path)) {
+ LOG(ERROR) << "Error file does not exist: " << pem_path;
+ return absl::nullopt;
+ }
+
+ if (base::DirectoryExists(pem_path)) {
+ LOG(ERROR) << "Error path is a directory: " << pem_path;
+ return absl::nullopt;
+ }
+
+ if (!base::PathIsReadable(pem_path)) {
+ LOG(ERROR) << "Error file is not readable: " << pem_path;
+ return absl::nullopt;
+ }
+
+ std::string pem;
+ if (!base::ReadFileToString(pem_path, &pem)) {
+ LOG(ERROR) << "Error reading " << pem_path;
+ return absl::nullopt;
+ }
+ absl::optional<std::string> der = DecodePEM(pem);
+ if (!der) {
+ LOG(ERROR) << "Error decoding " << pem_path;
+ return absl::nullopt;
+ }
+ anchor.clear_filename();
+ anchor.set_der(*der);
+ }
+ return std::move(root_store);
+}
+
+} // namespace
+
+int main(int argc, char** argv) {
+ base::AtExitManager at_exit_manager;
+ base::CommandLine::Init(argc, argv);
+
+ logging::LoggingSettings settings;
+ settings.logging_dest =
+ logging::LOG_TO_SYSTEM_DEBUG_LOG | logging::LOG_TO_STDERR;
+ logging::InitLogging(settings);
+
+ crypto::EnsureOpenSSLInit();
+
+ base::CommandLine& command_line = *base::CommandLine::ForCurrentProcess();
+ base::FilePath proto_path = command_line.GetSwitchValuePath("write-proto");
+ base::FilePath cpp_path = command_line.GetSwitchValuePath("write-cpp");
+ if ((proto_path.empty() && cpp_path.empty()) ||
+ command_line.HasSwitch("help")) {
+ std::cerr << "Usage: root_store_tool "
+ "[--root-store-dir=<relative-path>]
+ "[--write-proto=PROTO_FILE] "
+ "[--write-cpp=CPP_FILE]"
+ << std::endl;
+ return 1;
+ }
+
+ // Find root store directory. Assumptions:
+ // - Root store directory is relative to base::DIR_SOURCE_ROOT
+ //
+ // - $(ROOT_STORE_DIR)/root_store.textproto contains the textproto definition
+ // of the root store
+ //
+ // - Any certificate files referenced in
+ // $(ROOT_STORE_DIR)/root_store.textproto exist in the
+ // $(ROOT_STORE_DIR)/certs/ subdirectory.
+ base::FilePath root_store_dir =
+ command_line.GetSwitchValuePath("root-store-dir");
+ base::FilePath source_root;
+ CHECK(base::PathService::Get(base::DIR_SOURCE_ROOT, &source_root));
+ if (root_store_dir.empty()) {
+ root_store_dir = source_root.AppendASCII("net")
+ .AppendASCII("data")
+ .AppendASCII("ssl")
+ .AppendASCII("chrome_root_store")
+ .AppendASCII("base");
+ } else {
+ root_store_dir = source_root.Append(root_store_dir);
+ }
+ absl::optional<RootStore> root_store = ReadTextRootStore(root_store_dir);
+ if (!root_store) {
+ return 1;
+ }
+
+ // TODO(https://crbug.com/1216547): Figure out how to use the serialized
+ // proto to support component update.
+ // components/resources/ssl/ssl_error_assistant/push_proto.py
+ // does it through a GCS bucket (I think) so that might be an option.
+ if (!proto_path.empty()) {
+ std::string serialized;
+ if (!root_store->SerializeToString(&serialized)) {
+ LOG(ERROR) << "Error serializing root store proto"
+ << root_store->DebugString();
+ return 1;
+ }
+ if (!base::WriteFile(proto_path, serialized)) {
+ PLOG(ERROR) << "Error writing serialized proto root store";
+ return 1;
+ }
+ }
+
+ if (!cpp_path.empty()) {
+ // Root store should have at least one trust anchors.
+ CHECK_GT(root_store->trust_anchors_size(), 0);
+
+ std::string string_to_write =
+ "// This file is auto-generated, DO NOT EDIT.\n\n"
+ "const ChromeRootCertInfo kChromeRootCertList[] = {\n";
+
+ for (auto& anchor : root_store->trust_anchors()) {
+ // Every trust anchor at this point should have a DER.
+ CHECK(!anchor.der().empty());
+ std::string der = anchor.der();
+
+ // Begin struct. Assumed type of ChromeRootCertInfo:
+ //
+ // struct {
+ // base::span<const uint8_t> der;
+ // };
+ string_to_write += " {{{";
+
+ // Convert each character to hex representation, escaped.
+ for (auto c : der) {
+ base::StringAppendF(&string_to_write, "0x%02xu,",
+ static_cast<uint8_t>(c));
+ }
+
+ // End struct
+ string_to_write += "}}},\n";
+ }
+ string_to_write += "};";
+ if (!base::WriteFile(cpp_path, string_to_write)) {
+ PLOG(ERROR) << "Error writing cpp include file";
+ }
+ }
+
+ return 0;
+}
diff --git a/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc b/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
index ba870b4ac42..cfbfb474aaf 100644
--- a/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
+++ b/chromium/net/tools/tld_cleanup/tld_cleanup_util.cc
@@ -4,9 +4,9 @@
#include "net/tools/tld_cleanup/tld_cleanup_util.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_util.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "url/gurl.h"
diff --git a/chromium/net/tools/transport_security_state_generator/input_file_parsers.cc b/chromium/net/tools/transport_security_state_generator/input_file_parsers.cc
index 7f0ed49b323..be69b564c4f 100644
--- a/chromium/net/tools/transport_security_state_generator/input_file_parsers.cc
+++ b/chromium/net/tools/transport_security_state_generator/input_file_parsers.cc
@@ -345,7 +345,7 @@ bool ParseJSON(base::StringPiece json,
return false;
}
- for (const auto& entry_value : parsed.DictItems()) {
+ for (auto entry_value : parsed.DictItems()) {
if (!base::Contains(valid_keys, entry_value.first)) {
LOG(ERROR) << "The entry for " << entry->hostname
<< " contains an unknown " << entry_value.first << " field";
diff --git a/chromium/net/traffic_annotation/network_traffic_annotation.h b/chromium/net/traffic_annotation/network_traffic_annotation.h
index 9f6547e9f64..69b7c714f3d 100644
--- a/chromium/net/traffic_annotation/network_traffic_annotation.h
+++ b/chromium/net/traffic_annotation/network_traffic_annotation.h
@@ -130,7 +130,7 @@ struct PartialNetworkTrafficAnnotationTag {
// debugging, or auditing tasks. Unique ids should include only alphanumeric
// characters and underline.
// |proto| is a text-encoded NetworkTrafficAnnotation protobuf (see
-// tools/traffic_annotation/traffic_annotation.proto)
+// chrome/browser/privacy/traffic_annotation.proto)
//
// An empty and a sample template for the text-encoded protobuf can be found in
// tools/traffic_annotation/sample_traffic_annotation.cc.
@@ -378,9 +378,6 @@ struct MutablePartialNetworkTrafficAnnotationTag {
#define NO_TRAFFIC_ANNOTATION_YET \
net::DefineNetworkTrafficAnnotation("undefined", "Nothing here yet.")
-#define NO_PARTIAL_TRAFFIC_ANNOTATION_YET \
- net::DefinePartialNetworkTrafficAnnotation("undefined", "undefined", \
- "Nothing here yet.")
#endif
#define MISSING_TRAFFIC_ANNOTATION \
diff --git a/chromium/net/url_request/http_with_dns_over_https_unittest.cc b/chromium/net/url_request/http_with_dns_over_https_unittest.cc
index a9b1169d732..0494b54815d 100644
--- a/chromium/net/url_request/http_with_dns_over_https_unittest.cc
+++ b/chromium/net/url_request/http_with_dns_over_https_unittest.cc
@@ -33,6 +33,7 @@
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#include "url/scheme_host_port.h"
namespace net {
namespace {
@@ -135,8 +136,8 @@ class HttpWithDnsOverHttpsTest : public TestWithTaskEnvironment {
char header_data[kHeaderSize];
base::BigEndianWriter header_writer(header_data, kHeaderSize);
header_writer.WriteU16(query.id()); // Same ID as before
- char flags[] = {0x81, 0x80};
- header_writer.WriteBytes(flags, 2);
+ uint8_t flags[] = {0x81, 0x80};
+ header_writer.WriteBytes(reinterpret_cast<char*>(flags), 2);
header_writer.WriteU16(1); // 1 question
header_writer.WriteU16(1); // 1 answer
header_writer.WriteU16(0); // No authority records
@@ -254,8 +255,7 @@ TEST_F(HttpWithDnsOverHttpsTest, EndToEnd) {
loop.Run();
ClientSocketPool::GroupId group_id(
- HostPortPair(request_info.url.host(), request_info.url.IntPort()),
- ClientSocketPool::SocketType::kHttp, PrivacyMode::PRIVACY_MODE_DISABLED,
+ url::SchemeHostPort(request_info.url), PrivacyMode::PRIVACY_MODE_DISABLED,
NetworkIsolationKey(), SecureDnsPolicy::kAllow);
EXPECT_EQ(network_session
->GetSocketPool(HttpNetworkSession::NORMAL_SOCKET_POOL,
diff --git a/chromium/net/url_request/redirect_info.h b/chromium/net/url_request/redirect_info.h
index 3459a984355..7685caa2baf 100644
--- a/chromium/net/url_request/redirect_info.h
+++ b/chromium/net/url_request/redirect_info.h
@@ -10,6 +10,7 @@
#include "net/base/net_export.h"
#include "net/cookies/site_for_cookies.h"
#include "net/url_request/referrer_policy.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
namespace net {
diff --git a/chromium/net/url_request/report_sender.h b/chromium/net/url_request/report_sender.h
index 7e2f57c9b88..2400db52a6f 100644
--- a/chromium/net/url_request/report_sender.h
+++ b/chromium/net/url_request/report_sender.h
@@ -7,7 +7,6 @@
#include <map>
#include <memory>
-#include <string>
#include "base/callback.h"
#include "base/macros.h"
diff --git a/chromium/net/url_request/url_fetcher.h b/chromium/net/url_request/url_fetcher.h
index 026663b4288..4154656cd2d 100644
--- a/chromium/net/url_request/url_fetcher.h
+++ b/chromium/net/url_request/url_fetcher.h
@@ -22,6 +22,7 @@
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/referrer_policy.h"
#include "net/url_request/url_request.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
@@ -383,7 +384,7 @@ class NET_EXPORT URLFetcher {
// |traffic_annotation| metadata about the network traffic send via this
// URLFetcher, see net::DefineNetworkTrafficAnnotation. Note that:
// - net provides the API for tagging requests with an opaque identifier.
- // - tools/traffic_annotation/traffic_annotation.proto contains the Chrome
+ // - chrome/browser/privacy/traffic_annotation.proto contains the Chrome
// specific .proto describing the verbose annotation format that Chrome's
// callsites are expected to follow.
// - tools/traffic_annotation/ contains sample and template for annotation and
diff --git a/chromium/net/url_request/url_request.cc b/chromium/net/url_request/url_request.cc
index f9f04b5f421..f6beb8346ae 100644
--- a/chromium/net/url_request/url_request.cc
+++ b/chromium/net/url_request/url_request.cc
@@ -12,7 +12,6 @@
#include "base/compiler_specific.h"
#include "base/metrics/histogram_macros.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -26,6 +25,7 @@
#include "net/base/upload_data_stream.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/same_party_context.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/http/http_log_util.h"
#include "net/http/http_util.h"
@@ -549,8 +549,6 @@ URLRequest::URLRequest(const GURL& url,
net_log_(NetLogWithSource::Make(context->net_log(),
NetLogSourceType::URL_REQUEST)),
url_chain_(1, url),
- same_party_cookie_context_type_(
- CookieOptions::SamePartyCookieContextType::kCrossParty),
force_ignore_site_for_cookies_(false),
force_ignore_top_frame_party_for_cookies_(false),
method_("GET"),
@@ -619,13 +617,13 @@ void URLRequest::StartJob(std::unique_ptr<URLRequestJob> job) {
DCHECK(!is_pending_);
DCHECK(!job_);
- set_same_party_cookie_context_type(
+ set_same_party_context(
context()->cookie_store()
? cookie_util::ComputeSamePartyContext(
SchemefulSite(url()), isolation_info(),
context()->cookie_store()->cookie_access_delegate(),
force_ignore_top_frame_party_for_cookies())
- : CookieOptions::SamePartyCookieContextType::kCrossParty);
+ : SamePartyContext());
privacy_mode_ = DeterminePrivacyMode();
net_log_.BeginEvent(NetLogEventType::URL_REQUEST_START_JOB, [&] {
@@ -1026,17 +1024,19 @@ void URLRequest::NotifySSLCertificateError(int net_error,
delegate_->OnSSLCertificateError(this, net_error, ssl_info, fatal);
}
-bool URLRequest::CanGetCookies() const {
- DCHECK_EQ(PrivacyMode::PRIVACY_MODE_DISABLED, privacy_mode_);
+void URLRequest::AnnotateAndMoveUserBlockedCookies(
+ CookieAccessResultList& maybe_included_cookies,
+ CookieAccessResultList& excluded_cookies) const {
+ DCHECK_EQ(privacy_mode_, PrivacyMode::PRIVACY_MODE_DISABLED);
bool can_get_cookies = g_default_can_use_cookies;
if (network_delegate()) {
- can_get_cookies =
- network_delegate()->CanGetCookies(*this, /*allowed_from_caller=*/true);
+ can_get_cookies = network_delegate()->AnnotateAndMoveUserBlockedCookies(
+ *this, maybe_included_cookies, excluded_cookies,
+ /*allowed_from_caller=*/true);
}
if (!can_get_cookies)
net_log_.AddEvent(NetLogEventType::COOKIE_GET_BLOCKED_BY_NETWORK_DELEGATE);
- return can_get_cookies;
}
bool URLRequest::CanSetCookie(const net::CanonicalCookie& cookie,
@@ -1071,7 +1071,8 @@ PrivacyMode URLRequest::DeterminePrivacyMode() const {
bool enable_privacy_mode = !g_default_can_use_cookies;
if (network_delegate()) {
enable_privacy_mode = network_delegate()->ForcePrivacyMode(
- url(), site_for_cookies_, isolation_info_.top_frame_origin());
+ url(), site_for_cookies_, isolation_info_.top_frame_origin(),
+ same_party_context().context_type());
}
return enable_privacy_mode ? PRIVACY_MODE_ENABLED : PRIVACY_MODE_DISABLED;
}
diff --git a/chromium/net/url_request/url_request.h b/chromium/net/url_request/url_request.h
index 66fe2edf22a..5cba78924aa 100644
--- a/chromium/net/url_request/url_request.h
+++ b/chromium/net/url_request/url_request.h
@@ -32,6 +32,7 @@
#include "net/base/request_priority.h"
#include "net/base/upload_progress.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/same_party_context.h"
#include "net/cookies/site_for_cookies.h"
#include "net/dns/public/secure_dns_policy.h"
#include "net/filter/source_stream.h"
@@ -262,12 +263,11 @@ class NET_EXPORT URLRequest : public base::SupportsUserData {
// The party_context_ of this leg of the request. This gets updated on
// redirects.
- CookieOptions::SamePartyCookieContextType same_party_cookie_context_type() {
- return same_party_cookie_context_type_;
+ const SamePartyContext& same_party_context() const {
+ return same_party_context_;
}
- void set_same_party_cookie_context_type(
- CookieOptions::SamePartyCookieContextType context_type) {
- same_party_cookie_context_type_ = context_type;
+ void set_same_party_context(const SamePartyContext& context) {
+ same_party_context_ = context;
}
// Indicate whether SameSite cookies should be attached even though the
@@ -865,7 +865,9 @@ class NET_EXPORT URLRequest : public base::SupportsUserData {
// These functions delegate to the NetworkDelegate if it is not nullptr.
// Otherwise, cookies can be used unless SetDefaultCookiePolicyToBlock() has
// been called.
- bool CanGetCookies() const;
+ void AnnotateAndMoveUserBlockedCookies(
+ CookieAccessResultList& maybe_included_cookies,
+ CookieAccessResultList& excluded_cookies) const;
bool CanSetCookie(const net::CanonicalCookie& cookie,
CookieOptions* options) const;
PrivacyMode DeterminePrivacyMode() const;
@@ -900,7 +902,7 @@ class NET_EXPORT URLRequest : public base::SupportsUserData {
IsolationInfo isolation_info_;
- CookieOptions::SamePartyCookieContextType same_party_cookie_context_type_;
+ SamePartyContext same_party_context_;
bool force_ignore_site_for_cookies_;
bool force_ignore_top_frame_party_for_cookies_;
diff --git a/chromium/net/url_request/url_request_context.cc b/chromium/net/url_request/url_request_context.cc
index 15dc8361800..c7efe012e7d 100644
--- a/chromium/net/url_request/url_request_context.cc
+++ b/chromium/net/url_request/url_request_context.cc
@@ -23,6 +23,7 @@
#include "net/cookies/cookie_store.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_cache.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_transaction_factory.h"
#include "net/socket/ssl_client_socket_impl.h"
#include "net/url_request/url_request.h"
@@ -69,8 +70,8 @@ URLRequestContext::~URLRequestContext() {
this);
}
-const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
- ) const {
+const HttpNetworkSessionParams* URLRequestContext::GetNetworkSessionParams()
+ const {
HttpTransactionFactory* transaction_factory = http_transaction_factory();
if (!transaction_factory)
return nullptr;
@@ -80,7 +81,7 @@ const HttpNetworkSession::Params* URLRequestContext::GetNetworkSessionParams(
return &network_session->params();
}
-const HttpNetworkSession::Context* URLRequestContext::GetNetworkSessionContext()
+const HttpNetworkSessionContext* URLRequestContext::GetNetworkSessionContext()
const {
HttpTransactionFactory* transaction_factory = http_transaction_factory();
if (!transaction_factory)
diff --git a/chromium/net/url_request/url_request_context.h b/chromium/net/url_request/url_request_context.h
index 13ca8512275..9e14a66be77 100644
--- a/chromium/net/url_request/url_request_context.h
+++ b/chromium/net/url_request/url_request_context.h
@@ -21,7 +21,6 @@
#include "build/chromeos_buildflags.h"
#include "net/base/net_export.h"
#include "net/base/request_priority.h"
-#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/transport_security_state.h"
#include "net/net_buildflags.h"
@@ -40,6 +39,8 @@ class CookieStore;
class CTPolicyEnforcer;
class HostResolver;
class HttpAuthHandlerFactory;
+struct HttpNetworkSessionContext;
+struct HttpNetworkSessionParams;
class HttpTransactionFactory;
class HttpUserAgentSettings;
class NetLog;
@@ -77,11 +78,11 @@ class NET_EXPORT URLRequestContext
// May return nullptr if this context doesn't have an associated network
// session.
- const HttpNetworkSession::Params* GetNetworkSessionParams() const;
+ const HttpNetworkSessionParams* GetNetworkSessionParams() const;
// May return nullptr if this context doesn't have an associated network
// session.
- const HttpNetworkSession::Context* GetNetworkSessionContext() const;
+ const HttpNetworkSessionContext* GetNetworkSessionContext() const;
// TODO(crbug.com/1052397): Revisit once build flag switch of lacros-chrome is
// complete.
@@ -101,7 +102,7 @@ class NET_EXPORT URLRequestContext
// |traffic_annotation| is metadata about the network traffic send via this
// URLRequest, see net::DefineNetworkTrafficAnnotation. Note that:
// - net provides the API for tagging requests with an opaque identifier.
- // - tools/traffic_annotation/traffic_annotation.proto contains the Chrome
+ // - chrome/browser/privacy/traffic_annotation.proto contains the Chrome
// specific .proto describing the verbose annotation format that Chrome's
// callsites are expected to follow.
// - tools/traffic_annotation/ contains sample and template for annotation and
diff --git a/chromium/net/url_request/url_request_context_builder.cc b/chromium/net/url_request/url_request_context_builder.cc
index 788d82b5fab..07886a778a1 100644
--- a/chromium/net/url_request/url_request_context_builder.cc
+++ b/chromium/net/url_request/url_request_context_builder.cc
@@ -33,6 +33,7 @@
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_cache.h"
#include "net/http/http_network_layer.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_server_properties_manager.h"
#include "net/http/transport_security_persister.h"
@@ -68,61 +69,6 @@ namespace net {
namespace {
-class BasicNetworkDelegate : public NetworkDelegateImpl {
- public:
- BasicNetworkDelegate() = default;
- ~BasicNetworkDelegate() override = default;
-
- private:
- int OnBeforeURLRequest(URLRequest* request,
- CompletionOnceCallback callback,
- GURL* new_url) override {
- return OK;
- }
-
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
- return OK;
- }
-
- int OnHeadersReceived(
- URLRequest* request,
- CompletionOnceCallback callback,
- const HttpResponseHeaders* original_response_headers,
- scoped_refptr<HttpResponseHeaders>* override_response_headers,
- const IPEndPoint& endpoint,
- absl::optional<GURL>* preserve_fragment_on_redirect_url) override {
- return OK;
- }
-
- void OnBeforeRedirect(URLRequest* request,
- const GURL& new_location) override {}
-
- void OnResponseStarted(URLRequest* request, int net_error) override {}
-
- void OnCompleted(URLRequest* request, bool started, int net_error) override {}
-
- void OnURLRequestDestroyed(URLRequest* request) override {}
-
- void OnPACScriptError(int line_number, const std::u16string& error) override {
- }
-
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
-
- bool OnCanSetCookie(const URLRequest& request,
- const CanonicalCookie& cookie,
- CookieOptions* options,
- bool allowed_from_caller) override {
- return allowed_from_caller;
- }
-
- DISALLOW_COPY_AND_ASSIGN(BasicNetworkDelegate);
-};
-
// A URLRequestContext subclass that owns most of its components
// via a UrlRequestContextStorage object. When URLRequestContextBuilder::Build()
// is called, ownership of all URLRequestContext components is passed to the
@@ -186,7 +132,7 @@ URLRequestContextBuilder::~URLRequestContextBuilder() = default;
void URLRequestContextBuilder::SetHttpNetworkSessionComponents(
const URLRequestContext* request_context,
- HttpNetworkSession::Context* session_context) {
+ HttpNetworkSessionContext* session_context) {
session_context->host_resolver = request_context->host_resolver();
session_context->cert_verifier = request_context->cert_verifier();
session_context->transport_security_state =
@@ -368,7 +314,7 @@ std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
}
if (!network_delegate_)
- network_delegate_ = std::make_unique<BasicNetworkDelegate>();
+ network_delegate_ = std::make_unique<NetworkDelegateImpl>();
storage->set_network_delegate(std::move(network_delegate_));
if (net_log_) {
@@ -432,7 +378,7 @@ std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
storage->set_transport_security_state(
std::make_unique<TransportSecurityState>(hsts_policy_bypass_list_));
- if (!transport_security_persister_path_.empty()) {
+ if (!transport_security_persister_file_path_.empty()) {
// Use a low priority because saving this should not block anything
// user-visible. Block shutdown to ensure it does get persisted to disk,
// since it contains security-relevant information.
@@ -443,8 +389,8 @@ std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
context->set_transport_security_persister(
std::make_unique<TransportSecurityPersister>(
- context->transport_security_state(),
- transport_security_persister_path_, task_runner));
+ context->transport_security_state(), task_runner,
+ transport_security_persister_file_path_));
}
if (http_server_properties_) {
@@ -540,7 +486,7 @@ std::unique_ptr<URLRequestContext> URLRequestContextBuilder::Build() {
storage->set_proxy_delegate(std::move(proxy_delegate_));
}
- HttpNetworkSession::Context network_session_context;
+ HttpNetworkSessionContext network_session_context;
SetHttpNetworkSessionComponents(context.get(), &network_session_context);
// Unlike the other fields of HttpNetworkSession::Context,
// |client_socket_factory| is not mirrored in URLRequestContext.
diff --git a/chromium/net/url_request/url_request_context_builder.h b/chromium/net/url_request/url_request_context_builder.h
index 3f79dc997ea..d0508ddaeff 100644
--- a/chromium/net/url_request/url_request_context_builder.h
+++ b/chromium/net/url_request/url_request_context_builder.h
@@ -150,7 +150,7 @@ class NET_EXPORT URLRequestContextBuilder {
// associated HttpNetworkSession are consistent.
static void SetHttpNetworkSessionComponents(
const URLRequestContext* request_context,
- HttpNetworkSession::Context* session_context);
+ HttpNetworkSessionContext* session_context);
// These functions are mutually exclusive. The ProxyConfigService, if
// set, will be used to construct a ConfiguredProxyResolutionService.
@@ -231,7 +231,7 @@ class NET_EXPORT URLRequestContextBuilder {
// used.
void set_host_resolver_factory(HostResolver::Factory* factory);
- // Uses BasicNetworkDelegate by default. Note that calling Build will unset
+ // Uses NetworkDelegateImpl by default. Note that calling Build will unset
// any custom delegate in builder, so this must be called each time before
// Build is called.
void set_network_delegate(std::unique_ptr<NetworkDelegate> delegate) {
@@ -252,15 +252,16 @@ class NET_EXPORT URLRequestContextBuilder {
void EnableHttpCache(const HttpCacheParams& params);
void DisableHttpCache();
- // Override default HttpNetworkSession::Params settings.
+ // Override default HttpNetworkSessionParams settings.
void set_http_network_session_params(
- const HttpNetworkSession::Params& http_network_session_params) {
+ const HttpNetworkSessionParams& http_network_session_params) {
http_network_session_params_ = http_network_session_params;
}
- void set_transport_security_persister_path(
- const base::FilePath& transport_security_persister_path) {
- transport_security_persister_path_ = transport_security_persister_path;
+ void set_transport_security_persister_file_path(
+ const base::FilePath& transport_security_persister_file_path) {
+ transport_security_persister_file_path_ =
+ transport_security_persister_file_path;
}
void set_hsts_policy_bypass_list(
@@ -354,9 +355,9 @@ class NET_EXPORT URLRequestContextBuilder {
bool cookie_store_set_by_client_ = false;
HttpCacheParams http_cache_params_;
- HttpNetworkSession::Params http_network_session_params_;
+ HttpNetworkSessionParams http_network_session_params_;
CreateHttpTransactionFactoryCallback create_http_network_transaction_factory_;
- base::FilePath transport_security_persister_path_;
+ base::FilePath transport_security_persister_file_path_;
std::vector<std::string> hsts_policy_bypass_list_;
NetLog* net_log_ = nullptr;
std::unique_ptr<HostResolver> host_resolver_;
diff --git a/chromium/net/url_request/url_request_context_storage.cc b/chromium/net/url_request/url_request_context_storage.cc
index 836202ca17c..193d247fb9f 100644
--- a/chromium/net/url_request/url_request_context_storage.cc
+++ b/chromium/net/url_request/url_request_context_storage.cc
@@ -16,10 +16,12 @@
#include "net/cookies/cookie_store.h"
#include "net/dns/host_resolver.h"
#include "net/http/http_auth_handler_factory.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_server_properties.h"
#include "net/http/http_transaction_factory.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
#include "net/quic/quic_context.h"
+#include "net/ssl/ssl_config_service.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_job_factory.h"
#include "net/url_request/url_request_throttler_manager.h"
diff --git a/chromium/net/url_request/url_request_filter.cc b/chromium/net/url_request/url_request_filter.cc
index 77203ddcd82..7ac17525173 100644
--- a/chromium/net/url_request/url_request_filter.cc
+++ b/chromium/net/url_request/url_request_filter.cc
@@ -5,7 +5,6 @@
#include "net/url_request/url_request_filter.h"
#include "base/logging.h"
-#include "base/stl_util.h"
#include "base/task/current_thread.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
diff --git a/chromium/net/url_request/url_request_http_job.cc b/chromium/net/url_request/url_request_http_job.cc
index b2405754498..a6cd1ef45ab 100644
--- a/chromium/net/url_request/url_request_http_job.cc
+++ b/chromium/net/url_request/url_request_http_job.cc
@@ -5,6 +5,7 @@
#include "net/url_request/url_request_http_job.h"
#include <algorithm>
+#include <iterator>
#include <utility>
#include <vector>
@@ -29,6 +30,7 @@
#include "base/time/time.h"
#include "base/trace_event/trace_event.h"
#include "base/values.h"
+#include "build/build_config.h"
#include "net/base/features.h"
#include "net/base/host_port_pair.h"
#include "net/base/http_user_agent_settings.h"
@@ -47,6 +49,7 @@
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
+#include "net/cookies/same_party_context.h"
#include "net/filter/brotli_source_stream.h"
#include "net/filter/filter_source_stream.h"
#include "net/filter/gzip_source_stream.h"
@@ -157,14 +160,14 @@ void RecordCTHistograms(const net::SSLInfo& ssl_info) {
net::CookieOptions CreateCookieOptions(
net::CookieOptions::SameSiteCookieContext same_site_context,
- net::CookieOptions::SamePartyCookieContextType same_party_context,
+ const net::SamePartyContext& same_party_context,
const net::IsolationInfo& isolation_info,
bool is_in_nontrivial_first_party_set) {
net::CookieOptions options;
options.set_return_excluded_cookies();
options.set_include_httponly();
options.set_same_site_cookie_context(same_site_context);
- options.set_same_party_cookie_context_type(same_party_context);
+ options.set_same_party_context(same_party_context);
if (isolation_info.party_context().has_value()) {
// Count the top-frame site since it's not in the party_context.
options.set_full_party_context_size(isolation_info.party_context()->size() +
@@ -391,15 +394,10 @@ void URLRequestHttpJob::StartTransaction() {
if (network_delegate) {
OnCallToDelegate(
NetLogEventType::NETWORK_DELEGATE_BEFORE_START_TRANSACTION);
- // The NetworkDelegate must watch for OnRequestDestroyed and not modify
- // |extra_headers| after it's called.
- // TODO(mattm): change the API to remove the out-params and take the
- // results as params of the callback.
int rv = network_delegate->NotifyBeforeStartTransaction(
- request_,
+ request_, request_info_.extra_headers,
base::BindOnce(&URLRequestHttpJob::NotifyBeforeStartTransactionCallback,
- weak_factory_.GetWeakPtr()),
- &request_info_.extra_headers);
+ weak_factory_.GetWeakPtr()));
// If an extension blocks the request, we rely on the callback to
// MaybeStartTransactionInternal().
if (rv == ERR_IO_PENDING)
@@ -410,10 +408,14 @@ void URLRequestHttpJob::StartTransaction() {
StartTransactionInternal();
}
-void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(int result) {
+void URLRequestHttpJob::NotifyBeforeStartTransactionCallback(
+ int result,
+ const absl::optional<HttpRequestHeaders>& headers) {
// The request should not have been cancelled or have already completed.
DCHECK(!is_done());
+ if (headers)
+ request_info_.extra_headers = headers.value();
MaybeStartTransactionInternal(result);
}
@@ -583,7 +585,7 @@ void URLRequestHttpJob::AddCookieHeaderAndStart() {
bool is_in_nontrivial_first_party_set =
delegate && delegate->IsInNontrivialFirstPartySet(request_site);
CookieOptions options = CreateCookieOptions(
- same_site_context, request_->same_party_cookie_context_type(),
+ same_site_context, request_->same_party_context(),
request_->isolation_info(), is_in_nontrivial_first_party_set);
UMA_HISTOGRAM_ENUMERATION(
@@ -607,82 +609,72 @@ void URLRequestHttpJob::SetCookieHeaderAndStart(
const CookieAccessResultList& excluded_list) {
DCHECK(request_->maybe_sent_cookies().empty());
- bool can_get_cookies =
- (request_info_.privacy_mode == PRIVACY_MODE_DISABLED && CanGetCookies());
- if (!cookies_with_access_result_list.empty() && can_get_cookies) {
- std::string cookie_line =
- CanonicalCookie::BuildCookieLine(cookies_with_access_result_list);
- UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
- request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
- cookie_line);
-
- // TODO(crbug.com/1031664): Reduce the number of times the cookie list is
- // iterated over. Get metrics for every cookie which is included.
- for (const auto& c : cookies_with_access_result_list) {
- bool request_is_secure = request_->url().SchemeIsCryptographic();
- net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme();
- CookieRequestScheme cookie_request_schemes;
-
- switch (cookie_scheme) {
- case net::CookieSourceScheme::kSecure:
- cookie_request_schemes =
- request_is_secure
- ? CookieRequestScheme::kSecureSetSecureRequest
- : CookieRequestScheme::kSecureSetNonsecureRequest;
- break;
-
- case net::CookieSourceScheme::kNonSecure:
- cookie_request_schemes =
- request_is_secure
- ? CookieRequestScheme::kNonsecureSetSecureRequest
- : CookieRequestScheme::kNonsecureSetNonsecureRequest;
- break;
-
- case net::CookieSourceScheme::kUnset:
- cookie_request_schemes = CookieRequestScheme::kUnsetCookieScheme;
- break;
- }
-
- UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSchemeRequestScheme",
- cookie_request_schemes);
- }
- }
-
- // Report status for things in |excluded_list| and
- // |cookies_with_access_result_list|
- // after the delegate got a chance to block them.
- CookieAccessResultList maybe_sent_cookies = excluded_list;
-
- // If the cookie was excluded due to the fix for crbug.com/1166211, this
- // applies a warning to the status that will show up in the netlog.
- // TODO(crbug.com/1166211): Remove once no longer needed.
- if (options.same_site_cookie_context().AffectedByBugfix1166211()) {
- for (auto& cookie_with_access_result : maybe_sent_cookies) {
- options.same_site_cookie_context()
- .MaybeApplyBugfix1166211WarningToStatusAndLogHistogram(
- cookie_with_access_result.access_result.status);
- }
- }
-
- if (!can_get_cookies) {
- for (CookieAccessResultList::iterator it = maybe_sent_cookies.begin();
- it != maybe_sent_cookies.end(); ++it) {
- it->access_result.status.AddExclusionReason(
+ CookieAccessResultList maybe_included_cookies =
+ cookies_with_access_result_list;
+ CookieAccessResultList excluded_cookies = excluded_list;
+
+ if (request_info_.privacy_mode != PRIVACY_MODE_DISABLED) {
+ // If cookies are blocked (without our needing to consult the delegate), we
+ // move them to `excluded_cookies` and ensure that they have the correct
+ // exclusion reason.
+ excluded_cookies.insert(
+ excluded_cookies.end(),
+ std::make_move_iterator(maybe_included_cookies.begin()),
+ std::make_move_iterator(maybe_included_cookies.end()));
+ maybe_included_cookies.clear();
+ for (auto& cookie : excluded_cookies) {
+ cookie.access_result.status.AddExclusionReason(
CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
}
- }
+ } else {
+ AnnotateAndMoveUserBlockedCookies(maybe_included_cookies, excluded_cookies);
+ if (!maybe_included_cookies.empty()) {
+ std::string cookie_line =
+ CanonicalCookie::BuildCookieLine(maybe_included_cookies);
+ UMA_HISTOGRAM_COUNTS_10000("Cookie.HeaderLength", cookie_line.length());
+ request_info_.extra_headers.SetHeader(HttpRequestHeaders::kCookie,
+ cookie_line);
+
+ // TODO(crbug.com/1031664): Reduce the number of times the cookie list
+ // is iterated over. Get metrics for every cookie which is included.
+ for (const auto& c : maybe_included_cookies) {
+ bool request_is_secure = request_->url().SchemeIsCryptographic();
+ net::CookieSourceScheme cookie_scheme = c.cookie.SourceScheme();
+ CookieRequestScheme cookie_request_schemes;
+
+ switch (cookie_scheme) {
+ case net::CookieSourceScheme::kSecure:
+ cookie_request_schemes =
+ request_is_secure
+ ? CookieRequestScheme::kSecureSetSecureRequest
+ : CookieRequestScheme::kSecureSetNonsecureRequest;
+ break;
+
+ case net::CookieSourceScheme::kNonSecure:
+ cookie_request_schemes =
+ request_is_secure
+ ? CookieRequestScheme::kNonsecureSetSecureRequest
+ : CookieRequestScheme::kNonsecureSetNonsecureRequest;
+ break;
+
+ case net::CookieSourceScheme::kUnset:
+ cookie_request_schemes = CookieRequestScheme::kUnsetCookieScheme;
+ break;
+ }
- for (const auto& cookie_with_access_result :
- cookies_with_access_result_list) {
- CookieAccessResult access_result = cookie_with_access_result.access_result;
- if (!can_get_cookies) {
- access_result.status.AddExclusionReason(
- CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ UMA_HISTOGRAM_ENUMERATION("Cookie.CookieSchemeRequestScheme",
+ cookie_request_schemes);
+ }
}
- maybe_sent_cookies.push_back(
- {cookie_with_access_result.cookie, access_result});
}
+ CookieAccessResultList maybe_sent_cookies = std::move(excluded_cookies);
+ maybe_sent_cookies.insert(
+ maybe_sent_cookies.end(),
+ std::make_move_iterator(maybe_included_cookies.begin()),
+ std::make_move_iterator(maybe_included_cookies.end()));
+ maybe_included_cookies.clear();
+
if (request_->net_log().IsCapturing()) {
for (const auto& cookie_with_access_result : maybe_sent_cookies) {
request_->net_log().AddEvent(
@@ -704,7 +696,9 @@ void URLRequestHttpJob::SetCookieHeaderAndStart(
void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
DCHECK(set_cookie_access_result_list_.empty());
- DCHECK_EQ(0, num_cookie_lines_left_);
+ // TODO(crbug.com/1186863): Turn this CHECK into DCHECK once the investigation
+ // is done.
+ CHECK_EQ(0, num_cookie_lines_left_);
// End of the call started in OnStartCompleted.
OnCallToDelegateComplete();
@@ -749,7 +743,7 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
bool is_in_nontrivial_first_party_set =
delegate && delegate->IsInNontrivialFirstPartySet(request_site);
CookieOptions options = CreateCookieOptions(
- same_site_context, request_->same_party_cookie_context_type(),
+ same_site_context, request_->same_party_context(),
request_->isolation_info(), is_in_nontrivial_first_party_set);
UMA_HISTOGRAM_ENUMERATION(
@@ -781,6 +775,8 @@ void URLRequestHttpJob::SaveCookiesAndNotifyHeadersComplete(int result) {
std::unique_ptr<CanonicalCookie> cookie = net::CanonicalCookie::Create(
request_->url(), cookie_string, base::Time::Now(), server_time,
+ net::CookiePartitionKey::FromNetworkIsolationKey(
+ request_->isolation_info().network_isolation_key()),
&returned_status);
absl::optional<CanonicalCookie> cookie_to_return = absl::nullopt;
@@ -830,14 +826,6 @@ void URLRequestHttpJob::OnSetCookieResult(
});
}
- // If the cookie was excluded due to the fix for crbug.com/1166211, this
- // applies a warning to the status that will show up in the netlog.
- // TODO(crbug.com/1166211): Remove once no longer needed.
- if (options.same_site_cookie_context().AffectedByBugfix1166211()) {
- options.same_site_cookie_context()
- .MaybeApplyBugfix1166211WarningToStatusAndLogHistogram(
- access_result.status);
- }
set_cookie_access_result_list_.emplace_back(
std::move(cookie), std::move(cookie_string), access_result);
@@ -893,7 +881,10 @@ void URLRequestHttpJob::ProcessExpectCTHeader() {
HttpResponseHeaders* headers = GetResponseHeaders();
std::string value;
- if (headers->GetNormalizedHeader("Expect-CT", &value)) {
+ bool has_expect_ct_header = headers->GetNormalizedHeader("Expect-CT", &value);
+ base::UmaHistogramBoolean("Net.ExpectCT.HeaderPresentOnResponse",
+ has_expect_ct_header);
+ if (has_expect_ct_header) {
security_state->ProcessExpectCTHeader(
value, HostPortPair::FromURL(request_info_.url), ssl_info,
request_->isolation_info().network_isolation_key());
@@ -1424,10 +1415,18 @@ void URLRequestHttpJob::RecordTimer() {
// bound to connections and which connections offer resumption. We look at all
// TLS 1.3 responses for an apples-to-apples comparison.
//
+ // Additionally record metrics for Google hosts. Most Google hosts are known
+ // to implement 0-RTT, so this gives more targeted metrics as we initially
+ // roll out client support.
+ //
// TODO(https://crbug.com/641225): Remove these metrics after launching 0-RTT.
if (transaction_ && transaction_->GetResponseInfo() &&
IsTLS13OverTCP(*transaction_->GetResponseInfo())) {
base::UmaHistogramMediumTimes("Net.HttpTimeToFirstByte.TLS13", to_start);
+ if (HasGoogleHost(request()->url())) {
+ base::UmaHistogramMediumTimes("Net.HttpTimeToFirstByte.TLS13.Google",
+ to_start);
+ }
}
}
@@ -1498,6 +1497,10 @@ void URLRequestHttpJob::RecordCompletionHistograms(CompletionCause reason) {
// 0-RTT.
if (IsTLS13OverTCP(*response_info_)) {
base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13", total_time);
+ if (is_https_google) {
+ base::UmaHistogramTimes("Net.HttpJob.TotalTime.TLS13.Google",
+ total_time);
+ }
}
UMA_HISTOGRAM_CUSTOM_COUNTS("Net.HttpJob.PrefilterBytesRead",
diff --git a/chromium/net/url_request/url_request_http_job.h b/chromium/net/url_request/url_request_http_job.h
index 6207dc6938b..54afa5c1dbc 100644
--- a/chromium/net/url_request/url_request_http_job.h
+++ b/chromium/net/url_request/url_request_http_job.h
@@ -123,7 +123,9 @@ class NET_EXPORT_PRIVATE URLRequestHttpJob : public URLRequestJob {
void OnHeadersReceivedCallback(int result);
void OnStartCompleted(int result);
void OnReadCompleted(int result);
- void NotifyBeforeStartTransactionCallback(int result);
+ void NotifyBeforeStartTransactionCallback(
+ int result,
+ const absl::optional<HttpRequestHeaders>& headers);
// This just forwards the call to URLRequestJob::NotifyConnected().
// We need it because that method is protected and cannot be bound in a
// callback in this class.
diff --git a/chromium/net/url_request/url_request_http_job_unittest.cc b/chromium/net/url_request/url_request_http_job_unittest.cc
index 64c820821ad..cea14f3dd07 100644
--- a/chromium/net/url_request/url_request_http_job_unittest.cc
+++ b/chromium/net/url_request/url_request_http_job_unittest.cc
@@ -20,12 +20,16 @@
#include "base/strings/string_split.h"
#include "base/test/bind.h"
#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "build/build_config.h"
#include "net/base/auth.h"
+#include "net/base/features.h"
#include "net/base/isolation_info.h"
#include "net/base/network_isolation_key.h"
#include "net/base/request_priority.h"
#include "net/cert/ct_policy_status.h"
+#include "net/cookies/canonical_cookie_test_helpers.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store_test_callbacks.h"
#include "net/cookies/cookie_store_test_helpers.h"
@@ -65,7 +69,9 @@ namespace net {
namespace {
+using ::testing::_;
using ::testing::Return;
+using ::testing::UnorderedElementsAre;
const char kSimpleGetMockWrite[] =
"GET / HTTP/1.1\r\n"
@@ -1374,7 +1380,7 @@ class URLRequestHttpJobWithBrotliSupportTest : public TestWithTaskEnvironment {
protected:
URLRequestHttpJobWithBrotliSupportTest()
: context_(new TestURLRequestContext(true)) {
- auto params = std::make_unique<HttpNetworkSession::Params>();
+ auto params = std::make_unique<HttpNetworkSessionParams>();
context_->set_enable_brotli(true);
context_->set_http_network_session_params(std::move(params));
context_->set_client_socket_factory(&socket_factory_);
@@ -1660,8 +1666,9 @@ bool SetAllCookies(CookieMonster* cm, const CookieList& list) {
bool CreateAndSetCookie(CookieStore* cs,
const GURL& url,
const std::string& cookie_line) {
- auto cookie = CanonicalCookie::Create(url, cookie_line, base::Time::Now(),
- absl::nullopt);
+ auto cookie = CanonicalCookie::Create(
+ url, cookie_line, base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
if (!cookie)
return false;
DCHECK(cs);
@@ -1710,7 +1717,8 @@ TEST_F(URLRequestHttpJobTest, CookieSchemeRequestSchemeHistogram) {
// would normally only happen during an existing cookie DB version upgrade.
std::unique_ptr<CanonicalCookie> unset_cookie1 = CanonicalCookie::Create(
secure_url_for_unset1, "NoSourceSchemeHttps=val", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
unset_cookie1->SetSourceScheme(net::CookieSourceScheme::kUnset);
CookieList list1 = {*unset_cookie1};
@@ -1730,7 +1738,8 @@ TEST_F(URLRequestHttpJobTest, CookieSchemeRequestSchemeHistogram) {
std::unique_ptr<CanonicalCookie> unset_cookie2 = CanonicalCookie::Create(
nonsecure_url_for_unset2, "NoSourceSchemeHttp=val", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
unset_cookie2->SetSourceScheme(net::CookieSourceScheme::kUnset);
CookieList list2 = {*unset_cookie2};
@@ -1775,4 +1784,201 @@ TEST_F(URLRequestHttpJobTest, CookieSchemeRequestSchemeHistogram) {
URLRequestHttpJob::CookieRequestScheme::kNonsecureSetSecureRequest, 1);
}
+// Test that cookies are annotated with the appropriate exclusion reason when
+// privacy mode is enabled.
+TEST_F(URLRequestHttpJobTest, PrivacyMode_ExclusionReason) {
+ HttpTestServer test_server;
+ ASSERT_TRUE(test_server.Start());
+
+ FilteringTestNetworkDelegate network_delegate;
+ CookieMonster cm(nullptr, nullptr);
+ TestURLRequestContext context(true);
+ context.set_cookie_store(&cm);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ // Set cookies.
+ {
+ TestDelegate d;
+ GURL test_url = test_server.GetURL(
+ "/set-cookie?one=1&"
+ "two=2&"
+ "three=3");
+ std::unique_ptr<URLRequest> req(context.CreateFirstPartyRequest(
+ test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
+ req->Start();
+ d.RunUntilComplete();
+ }
+
+ // Get cookies.
+ network_delegate.ResetAnnotateCookiesCalledCount();
+ ASSERT_EQ(0, network_delegate.annotate_cookies_called_count());
+ // We want to fetch cookies from the cookie store, so we use the
+ // NetworkDelegate to override the privacy mode (rather than setting it via
+ // `allow_credentials`, since that skips querying the cookie store).
+ network_delegate.set_force_privacy_mode(true);
+ TestDelegate d;
+ std::unique_ptr<URLRequest> req(context.CreateFirstPartyRequest(
+ test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
+ req->Start();
+ d.RunUntilComplete();
+
+ EXPECT_EQ("None", d.data_received());
+ EXPECT_THAT(
+ req->maybe_sent_cookies(),
+ UnorderedElementsAre(
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("one"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("two"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("three"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}),
+ _, _, _))));
+
+ EXPECT_EQ(0, network_delegate.annotate_cookies_called_count());
+}
+
+// Test that cookies are allowed to be selectively blocked by the network
+// delegate.
+TEST_F(URLRequestHttpJobTest, IndividuallyBlockedCookies) {
+ HttpTestServer test_server;
+ ASSERT_TRUE(test_server.Start());
+
+ FilteringTestNetworkDelegate network_delegate;
+ network_delegate.set_block_get_cookies_by_name(true);
+ network_delegate.SetCookieFilter("blocked_");
+ CookieMonster cm(nullptr, nullptr);
+ TestURLRequestContext context(true);
+ context.set_cookie_store(&cm);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ // Set cookies.
+ {
+ TestDelegate d;
+ GURL test_url = test_server.GetURL(
+ "/set-cookie?blocked_one=1;SameSite=Lax;Secure&"
+ "blocked_two=1;SameSite=Lax;Secure&"
+ "allowed=1;SameSite=Lax;Secure");
+ std::unique_ptr<URLRequest> req(context.CreateFirstPartyRequest(
+ test_url, DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
+ req->Start();
+ d.RunUntilComplete();
+ }
+
+ // Get cookies.
+ TestDelegate d;
+ std::unique_ptr<URLRequest> req(context.CreateFirstPartyRequest(
+ test_server.GetURL("/echoheader?Cookie"), DEFAULT_PRIORITY, &d,
+ TRAFFIC_ANNOTATION_FOR_TESTS));
+ req->Start();
+ d.RunUntilComplete();
+
+ EXPECT_EQ("allowed=1", d.data_received());
+ EXPECT_THAT(
+ req->maybe_sent_cookies(),
+ UnorderedElementsAre(
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("blocked_one"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("blocked_two"),
+ MatchesCookieAccessResult(
+ HasExactlyExclusionReasonsForTesting(
+ std::vector<CookieInclusionStatus::ExclusionReason>{
+ CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}),
+ _, _, _)),
+ MatchesCookieWithAccessResult(
+ MatchesCookieWithName("allowed"),
+ MatchesCookieAccessResult(IsInclude(), _, _, _))));
+}
+
+class PartitionedCookiesURLRequestHttpJobTest
+ : public URLRequestHttpJobTest,
+ public testing::WithParamInterface<bool> {
+ protected:
+ // testing::Test
+ void SetUp() override {
+ if (PartitionedCookiesEnabled())
+ scoped_feature_list_.InitAndEnableFeature(features::kPartitionedCookies);
+ URLRequestHttpJobTest::SetUp();
+ }
+
+ bool PartitionedCookiesEnabled() { return GetParam(); }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+INSTANTIATE_TEST_SUITE_P(/* no label */,
+ PartitionedCookiesURLRequestHttpJobTest,
+ testing::Bool());
+
+TEST_P(PartitionedCookiesURLRequestHttpJobTest, SetPartitionedCookie) {
+ EmbeddedTestServer https_test(EmbeddedTestServer::TYPE_HTTPS);
+ const url::Origin kTopFrameOrigin =
+ url::Origin::Create(GURL("https://www.toplevelsite.com"));
+ const IsolationInfo kTestIsolationInfo =
+ IsolationInfo::CreateForInternalRequest(kTopFrameOrigin);
+
+ https_test.AddDefaultHandlers(base::FilePath());
+ ASSERT_TRUE(https_test.Start());
+ TestURLRequestContext context;
+
+ CookieMonster cookie_monster(nullptr, nullptr);
+ context.set_cookie_store(&cookie_monster);
+
+ GURL test_url = https_test.GetURL(
+ "/set-cookie?__Host-foo=bar;SameSite=None;Secure;Path=/;Partitioned;");
+
+ TestDelegate delegate;
+ std::unique_ptr<URLRequest> request = context.CreateRequest(
+ test_url, DEFAULT_PRIORITY, &delegate, TRAFFIC_ANNOTATION_FOR_TESTS);
+
+ request->set_isolation_info(kTestIsolationInfo);
+ request->Start();
+ ASSERT_TRUE(request->is_pending());
+ delegate.RunUntilComplete();
+
+ base::RunLoop run_loop;
+ bool partitioned_cookies_enabled = PartitionedCookiesEnabled();
+ cookie_monster.GetAllCookiesAsync(base::BindLambdaForTesting(
+ [&partitioned_cookies_enabled, &run_loop](const CookieList& cookies) {
+ EXPECT_EQ(1u, cookies.size());
+ EXPECT_EQ(partitioned_cookies_enabled, cookies[0].IsPartitioned());
+ if (partitioned_cookies_enabled) {
+ EXPECT_EQ(CookiePartitionKey::FromURLForTesting(
+ GURL("https://toplevelsite.com")),
+ cookies[0].PartitionKey().value());
+ } else {
+ EXPECT_FALSE(cookies[0].PartitionKey());
+ }
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+
+ // TODO(crbug.com/1225444) Test that the cookie is available in a cross-site
+ // context on a different top-level site only when partitioned cookies are
+ // disabled.
+}
+
} // namespace net
diff --git a/chromium/net/url_request/url_request_job.cc b/chromium/net/url_request/url_request_job.cc
index a9a44ddcf29..b2458b80375 100644
--- a/chromium/net/url_request/url_request_job.cc
+++ b/chromium/net/url_request/url_request_job.cc
@@ -401,8 +401,11 @@ void URLRequestJob::NotifySSLCertificateError(int net_error,
request_->NotifySSLCertificateError(net_error, ssl_info, fatal);
}
-bool URLRequestJob::CanGetCookies() const {
- return request_->CanGetCookies();
+void URLRequestJob::AnnotateAndMoveUserBlockedCookies(
+ CookieAccessResultList& maybe_included_cookies,
+ CookieAccessResultList& excluded_cookies) const {
+ request_->AnnotateAndMoveUserBlockedCookies(maybe_included_cookies,
+ excluded_cookies);
}
bool URLRequestJob::CanSetCookie(const net::CanonicalCookie& cookie,
diff --git a/chromium/net/url_request/url_request_job.h b/chromium/net/url_request/url_request_job.h
index a1625e6a2a4..7cd566ddaf1 100644
--- a/chromium/net/url_request/url_request_job.h
+++ b/chromium/net/url_request/url_request_job.h
@@ -279,7 +279,9 @@ class NET_EXPORT URLRequestJob {
bool fatal);
// Delegates to URLRequest.
- bool CanGetCookies() const;
+ void AnnotateAndMoveUserBlockedCookies(
+ CookieAccessResultList& maybe_included_cookies,
+ CookieAccessResultList& excluded_cookies) const;
// Delegates to URLRequest.
bool CanSetCookie(const net::CanonicalCookie& cookie,
diff --git a/chromium/net/url_request/url_request_quic_perftest.cc b/chromium/net/url_request/url_request_quic_perftest.cc
index af6cd96f51c..f3291490cfe 100644
--- a/chromium/net/url_request/url_request_quic_perftest.cc
+++ b/chromium/net/url_request/url_request_quic_perftest.cc
@@ -26,6 +26,7 @@
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_network_session.h"
#include "net/http/http_status_code.h"
#include "net/quic/crypto/proof_source_chromium.h"
#include "net/quic/quic_context.h"
@@ -118,10 +119,9 @@ class URLRequestQuicPerfTest : public ::testing::Test {
kOriginHost, tcp_server_->port());
EXPECT_TRUE(host_resolver_->AddRuleFromString(map_rule));
- net::HttpNetworkSession::Context network_session_context;
+ net::HttpNetworkSessionContext network_session_context;
network_session_context.cert_verifier = &cert_verifier_;
- std::unique_ptr<HttpNetworkSession::Params> params(
- new HttpNetworkSession::Params);
+ auto params = std::make_unique<HttpNetworkSessionParams>();
params->enable_quic = true;
params->enable_user_alternate_protocol_ports = true;
quic_context_.params()->allow_remote_alt_svc = true;
diff --git a/chromium/net/url_request/url_request_quic_unittest.cc b/chromium/net/url_request/url_request_quic_unittest.cc
index 9ce7d58b30e..136c94fa1b8 100644
--- a/chromium/net/url_request/url_request_quic_unittest.cc
+++ b/chromium/net/url_request/url_request_quic_unittest.cc
@@ -44,6 +44,7 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
+#include "url/origin.h"
namespace net {
@@ -124,8 +125,7 @@ class URLRequestQuicTest
QuicEnableVersion(version());
StartQuicServer(version());
- std::unique_ptr<HttpNetworkSession::Params> params(
- new HttpNetworkSession::Params);
+ auto params = std::make_unique<HttpNetworkSessionParams>();
CertVerifyResult verify_result;
verify_result.verified_cert = ImportCertFromFile(
GetTestCertsDirectory(), "quic-chain.pem");
@@ -396,15 +396,23 @@ TEST_P(URLRequestQuicTest, TestTwoRequests) {
run_loop.QuitClosure(), /*num_expected_requests=*/2);
SetNetworkDelegate(&network_delegate);
Init();
+
+ GURL url = GURL(UrlFromPath(kHelloPath));
+ auto isolation_info =
+ IsolationInfo::CreateForInternalRequest(url::Origin::Create(url));
+
CheckLoadTimingDelegate delegate(false);
delegate.set_on_complete(base::DoNothing());
std::unique_ptr<URLRequest> request =
- CreateRequest(GURL(UrlFromPath(kHelloPath)), DEFAULT_PRIORITY, &delegate);
+ CreateRequest(url, DEFAULT_PRIORITY, &delegate);
+ request->set_isolation_info(isolation_info);
CheckLoadTimingDelegate delegate2(true);
delegate2.set_on_complete(base::DoNothing());
- std::unique_ptr<URLRequest> request2 = CreateRequest(
- GURL(UrlFromPath(kHelloPath)), DEFAULT_PRIORITY, &delegate2);
+ std::unique_ptr<URLRequest> request2 =
+ CreateRequest(url, DEFAULT_PRIORITY, &delegate2);
+ request2->set_isolation_info(isolation_info);
+
request->Start();
request2->Start();
ASSERT_TRUE(request->is_pending());
diff --git a/chromium/net/url_request/url_request_test_job.cc b/chromium/net/url_request/url_request_test_job.cc
index a3a4ed8b0a8..1ed8dd12da7 100644
--- a/chromium/net/url_request/url_request_test_job.cc
+++ b/chromium/net/url_request/url_request_test_job.cc
@@ -10,10 +10,11 @@
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/containers/cxx20_erase_list.h"
+#include "base/cxx17_backports.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/io_buffer.h"
diff --git a/chromium/net/url_request/url_request_test_job.h b/chromium/net/url_request/url_request_test_job.h
index 9c5906c6a06..6d8b158fe37 100644
--- a/chromium/net/url_request/url_request_test_job.h
+++ b/chromium/net/url_request/url_request_test_job.h
@@ -9,7 +9,6 @@
#include "base/memory/weak_ptr.h"
#include "net/base/load_timing_info.h"
-#include "net/base/net_export.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_job.h"
@@ -37,7 +36,7 @@ namespace net {
//
// Optionally, you can also construct test jobs that advance automatically
// without having to call ProcessOnePendingMessage.
-class NET_EXPORT_PRIVATE URLRequestTestJob : public URLRequestJob {
+class URLRequestTestJob : public URLRequestJob {
public:
// Constructs a job to return one of the canned responses depending on the
// request url.
diff --git a/chromium/net/url_request/url_request_test_util.cc b/chromium/net/url_request/url_request_test_util.cc
index 6bbc6caf23b..0f6c55db0a1 100644
--- a/chromium/net/url_request/url_request_test_util.cc
+++ b/chromium/net/url_request/url_request_test_util.cc
@@ -19,6 +19,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cert/do_nothing_ct_verifier.h"
+#include "net/cookies/same_party_context.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_network_session.h"
#include "net/http/http_response_headers.h"
@@ -132,11 +133,11 @@ void TestURLRequestContext::Init() {
// Make sure we haven't been passed an object we're not going to use.
EXPECT_FALSE(client_socket_factory_);
} else {
- HttpNetworkSession::Params session_params;
+ HttpNetworkSessionParams session_params;
if (http_network_session_params_)
session_params = *http_network_session_params_;
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
if (http_network_session_context_)
session_context = *http_network_session_context_;
session_context.client_socket_factory = client_socket_factory();
@@ -396,7 +397,7 @@ TestNetworkDelegate::TestNetworkDelegate()
completed_requests_(0),
canceled_requests_(0),
cookie_options_bit_mask_(0),
- blocked_get_cookies_count_(0),
+ blocked_annotate_cookies_count_(0),
blocked_set_cookie_count_(0),
set_cookie_count_(0),
before_start_transaction_count_(0),
@@ -450,8 +451,8 @@ int TestNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
int TestNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
if (before_start_transaction_fails_)
return ERR_FAILED;
@@ -599,22 +600,32 @@ void TestNetworkDelegate::OnURLRequestDestroyed(URLRequest* request) {
destroyed_requests_++;
}
-void TestNetworkDelegate::OnPACScriptError(int line_number,
- const std::u16string& error) {}
-
-bool TestNetworkDelegate::OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) {
+bool TestNetworkDelegate::OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) {
bool allow = allowed_from_caller;
if (cookie_options_bit_mask_ & NO_GET_COOKIES)
allow = false;
if (!allow) {
- blocked_get_cookies_count_++;
+ blocked_annotate_cookies_count_++;
+ ExcludeAllCookies(CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
+ maybe_included_cookies, excluded_cookies);
}
return allow;
}
+bool TestNetworkDelegate::OnForcePrivacyMode(
+ const GURL& url,
+ const SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const {
+ return false;
+}
+
bool TestNetworkDelegate::OnCanSetCookie(const URLRequest& request,
const net::CanonicalCookie& cookie,
CookieOptions* options,
@@ -650,6 +661,76 @@ int TestNetworkDelegate::GetRequestId(URLRequest* request) {
return id;
}
+FilteringTestNetworkDelegate::FilteringTestNetworkDelegate() = default;
+FilteringTestNetworkDelegate::~FilteringTestNetworkDelegate() = default;
+
+bool FilteringTestNetworkDelegate::OnCanSetCookie(
+ const URLRequest& request,
+ const net::CanonicalCookie& cookie,
+ CookieOptions* options,
+ bool allowed_from_caller) {
+ // Filter out cookies with the same name as |cookie_name_filter_| and
+ // combine with |allowed_from_caller|.
+ bool allowed = allowed_from_caller && !(cookie.Name() == cookie_name_filter_);
+
+ ++set_cookie_called_count_;
+
+ if (!allowed)
+ ++blocked_set_cookie_count_;
+
+ return TestNetworkDelegate::OnCanSetCookie(request, cookie, options, allowed);
+}
+
+bool FilteringTestNetworkDelegate::OnForcePrivacyMode(
+ const GURL& url,
+ const SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const {
+ if (force_privacy_mode_)
+ return true;
+
+ return TestNetworkDelegate::OnForcePrivacyMode(
+ url, site_for_cookies, top_frame_origin, same_party_context_type);
+}
+
+bool FilteringTestNetworkDelegate::OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) {
+ // Filter out cookies if |block_annotate_cookies_| is set and
+ // combine with |allowed_from_caller|.
+ bool allowed = allowed_from_caller && !block_annotate_cookies_;
+
+ ++annotate_cookies_called_count_;
+
+ if (!allowed) {
+ ++blocked_annotate_cookies_count_;
+ ExcludeAllCookies(net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES,
+ maybe_included_cookies, excluded_cookies);
+ }
+
+ if (allowed && block_get_cookies_by_name_ && !cookie_name_filter_.empty()) {
+ for (auto& cookie : maybe_included_cookies) {
+ if (cookie.cookie.Name().find(cookie_name_filter_) != std::string::npos) {
+ cookie.access_result.status.AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ }
+ }
+ for (auto& cookie : excluded_cookies) {
+ if (cookie.cookie.Name().find(cookie_name_filter_) != std::string::npos) {
+ cookie.access_result.status.AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ }
+ }
+
+ MoveExcludedCookies(maybe_included_cookies, excluded_cookies);
+ }
+
+ return TestNetworkDelegate::OnAnnotateAndMoveUserBlockedCookies(
+ request, maybe_included_cookies, excluded_cookies, allowed);
+}
+
// URLRequestInterceptor that intercepts only the first request it sees,
// returning the provided URLRequestJob.
class TestScopedURLInterceptor::TestRequestInterceptor
diff --git a/chromium/net/url_request/url_request_test_util.h b/chromium/net/url_request/url_request_test_util.h
index 73eaa17e39a..d96034a2a6a 100644
--- a/chromium/net/url_request/url_request_test_util.h
+++ b/chromium/net/url_request/url_request_test_util.h
@@ -29,6 +29,7 @@
#include "net/cert/cert_verifier.h"
#include "net/cert/ct_policy_enforcer.h"
#include "net/cookies/cookie_monster.h"
+#include "net/cookies/same_party_context.h"
#include "net/disk_cache/disk_cache.h"
#include "net/ftp/ftp_network_layer.h"
#include "net/http/http_auth_handler_factory.h"
@@ -37,6 +38,9 @@
#include "net/http/http_network_session.h"
#include "net/http/http_request_headers.h"
#include "net/ssl/ssl_config_service_defaults.h"
+#include "net/test/embedded_test_server/default_handlers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_context.h"
@@ -70,12 +74,12 @@ class TestURLRequestContext : public URLRequestContext {
}
void set_http_network_session_params(
- std::unique_ptr<HttpNetworkSession::Params> session_params) {
+ std::unique_ptr<HttpNetworkSessionParams> session_params) {
http_network_session_params_ = std::move(session_params);
}
void set_http_network_session_context(
- std::unique_ptr<HttpNetworkSession::Context> session_context) {
+ std::unique_ptr<HttpNetworkSessionContext> session_context) {
http_network_session_context_ = std::move(session_context);
}
@@ -100,10 +104,10 @@ class TestURLRequestContext : public URLRequestContext {
bool initialized_ = false;
// Optional parameters to override default values. Note that values in the
- // HttpNetworkSession::Context that point to other objects the
+ // HttpNetworkSessionContext that point to other objects the
// TestURLRequestContext creates will be overwritten.
- std::unique_ptr<HttpNetworkSession::Params> http_network_session_params_;
- std::unique_ptr<HttpNetworkSession::Context> http_network_session_context_;
+ std::unique_ptr<HttpNetworkSessionParams> http_network_session_params_;
+ std::unique_ptr<HttpNetworkSessionContext> http_network_session_context_;
// Not owned:
ClientSocketFactory* client_socket_factory_ = nullptr;
@@ -323,7 +327,9 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int destroyed_requests() const { return destroyed_requests_; }
int completed_requests() const { return completed_requests_; }
int canceled_requests() const { return canceled_requests_; }
- int blocked_get_cookies_count() const { return blocked_get_cookies_count_; }
+ int blocked_annotate_cookies_count() const {
+ return blocked_annotate_cookies_count_;
+ }
int blocked_set_cookie_count() const { return blocked_set_cookie_count_; }
int set_cookie_count() const { return set_cookie_count_; }
@@ -346,9 +352,10 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int OnBeforeURLRequest(URLRequest* request,
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
CompletionOnceCallback callback,
@@ -360,9 +367,16 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
void OnResponseStarted(URLRequest* request, int net_error) override;
void OnCompleted(URLRequest* request, bool started, int net_error) override;
void OnURLRequestDestroyed(URLRequest* request) override;
- void OnPACScriptError(int line_number, const std::u16string& error) override;
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override;
+ bool OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) override;
+ bool OnForcePrivacyMode(
+ const GURL& url,
+ const SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const override;
bool OnCanSetCookie(const URLRequest& request,
const net::CanonicalCookie& cookie,
CookieOptions* options,
@@ -390,7 +404,7 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int completed_requests_;
int canceled_requests_;
int cookie_options_bit_mask_;
- int blocked_get_cookies_count_;
+ int blocked_annotate_cookies_count_;
int blocked_set_cookie_count_;
int set_cookie_count_;
int before_start_transaction_count_;
@@ -415,6 +429,90 @@ class TestNetworkDelegate : public NetworkDelegateImpl {
int next_request_id_;
};
+// ----------------------------------------------------------------------------
+
+class FilteringTestNetworkDelegate : public TestNetworkDelegate {
+ public:
+ FilteringTestNetworkDelegate();
+ ~FilteringTestNetworkDelegate() override;
+
+ bool OnCanSetCookie(const URLRequest& request,
+ const net::CanonicalCookie& cookie,
+ CookieOptions* options,
+ bool allowed_from_caller) override;
+
+ void SetCookieFilter(std::string filter) {
+ cookie_name_filter_ = std::move(filter);
+ }
+
+ int set_cookie_called_count() { return set_cookie_called_count_; }
+
+ int blocked_set_cookie_count() { return blocked_set_cookie_count_; }
+
+ void ResetSetCookieCalledCount() { set_cookie_called_count_ = 0; }
+
+ void ResetBlockedSetCookieCount() { blocked_set_cookie_count_ = 0; }
+
+ bool OnAnnotateAndMoveUserBlockedCookies(
+ const URLRequest& request,
+ net::CookieAccessResultList& maybe_included_cookies,
+ net::CookieAccessResultList& excluded_cookies,
+ bool allowed_from_caller) override;
+
+ bool OnForcePrivacyMode(
+ const GURL& url,
+ const SiteForCookies& site_for_cookies,
+ const absl::optional<url::Origin>& top_frame_origin,
+ SamePartyContext::Type same_party_context_type) const override;
+
+ void set_block_annotate_cookies() { block_annotate_cookies_ = true; }
+
+ void unset_block_annotate_cookies() { block_annotate_cookies_ = false; }
+
+ int annotate_cookies_called_count() const {
+ return annotate_cookies_called_count_;
+ }
+
+ int blocked_annotate_cookies_count() const {
+ return blocked_annotate_cookies_count_;
+ }
+
+ void ResetAnnotateCookiesCalledCount() { annotate_cookies_called_count_ = 0; }
+
+ void ResetBlockedAnnotateCookiesCount() {
+ blocked_annotate_cookies_count_ = 0;
+ }
+
+ void set_block_get_cookies_by_name(bool block) {
+ block_get_cookies_by_name_ = block;
+ }
+
+ void set_force_privacy_mode(bool enabled) { force_privacy_mode_ = enabled; }
+
+ private:
+ std::string cookie_name_filter_ = "";
+ int set_cookie_called_count_ = 0;
+ int blocked_set_cookie_count_ = 0;
+
+ bool block_annotate_cookies_ = false;
+ int annotate_cookies_called_count_ = 0;
+ int blocked_annotate_cookies_count_ = 0;
+ bool block_get_cookies_by_name_ = false;
+
+ bool force_privacy_mode_ = false;
+};
+
+// ----------------------------------------------------------------------------
+
+// Less verbose way of running a simple testserver.
+class HttpTestServer : public EmbeddedTestServer {
+ public:
+ explicit HttpTestServer(const base::FilePath& document_root) {
+ AddDefaultHandlers(document_root);
+ }
+
+ HttpTestServer() { RegisterDefaultHandlers(this); }
+};
//-----------------------------------------------------------------------------
class TestScopedURLInterceptor {
diff --git a/chromium/net/url_request/url_request_throttler_simulation_unittest.cc b/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
index 0c732aad1c1..97b392e44ce 100644
--- a/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
+++ b/chromium/net/url_request/url_request_throttler_simulation_unittest.cc
@@ -17,9 +17,9 @@
#include <memory>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/environment.h"
#include "base/rand_util.h"
-#include "base/stl_util.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "net/base/request_priority.h"
diff --git a/chromium/net/url_request/url_request_throttler_unittest.cc b/chromium/net/url_request/url_request_throttler_unittest.cc
index 0880589b8f3..2b260b115ae 100644
--- a/chromium/net/url_request/url_request_throttler_unittest.cc
+++ b/chromium/net/url_request/url_request_throttler_unittest.cc
@@ -4,9 +4,9 @@
#include <memory>
+#include "base/cxx17_backports.h"
#include "base/metrics/histogram_samples.h"
#include "base/pickle.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/time/time.h"
diff --git a/chromium/net/url_request/url_request_unittest.cc b/chromium/net/url_request/url_request_unittest.cc
index b5868ff6267..786fb062a38 100644
--- a/chromium/net/url_request/url_request_unittest.cc
+++ b/chromium/net/url_request/url_request_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <algorithm>
+#include <iterator>
#include <memory>
#include <utility>
@@ -28,6 +29,7 @@
#include "base/base64url.h"
#include "base/bind.h"
#include "base/compiler_specific.h"
+#include "base/cxx17_backports.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/files/scoped_temp_dir.h"
@@ -38,7 +40,6 @@
#include "base/path_service.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
@@ -122,9 +123,6 @@
#include "net/ssl/ssl_server_config.h"
#include "net/ssl/test_ssl_config_service.h"
#include "net/test/cert_test_util.h"
-#include "net/test/embedded_test_server/default_handlers.h"
-#include "net/test/embedded_test_server/embedded_test_server.h"
-#include "net/test/embedded_test_server/embedded_test_server_connection_listener.h"
#include "net/test/embedded_test_server/http_request.h"
#include "net/test/embedded_test_server/http_response.h"
#include "net/test/gtest_util.h"
@@ -144,6 +142,7 @@
#include "net/url_request/url_request_redirect_job.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "testing/gmock/include/gmock/gmock-matchers.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
@@ -172,9 +171,12 @@
using net::test::IsError;
using net::test::IsOk;
using net::test_server::RegisterDefaultHandlers;
+using testing::_;
using testing::AnyOf;
using testing::ElementsAre;
using testing::IsEmpty;
+using testing::Optional;
+using testing::UnorderedElementsAre;
using base::ASCIIToUTF16;
using base::Time;
@@ -325,16 +327,6 @@ void TestLoadTimingNoHttpResponse(const LoadTimingInfo& load_timing_info) {
}
#endif
-// Less verbose way of running a simple testserver for the tests below.
-class HttpTestServer : public EmbeddedTestServer {
- public:
- explicit HttpTestServer(const base::FilePath& document_root) {
- AddDefaultHandlers(document_root);
- }
-
- HttpTestServer() { RegisterDefaultHandlers(this); }
-};
-
// Job that allows monitoring of its priority.
class PriorityMonitoringURLRequestJob : public URLRequestTestJob {
public:
@@ -445,9 +437,10 @@ class BlockingNetworkDelegate : public TestNetworkDelegate {
CompletionOnceCallback callback,
GURL* new_url) override;
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override;
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override;
int OnHeadersReceived(
URLRequest* request,
@@ -546,13 +539,19 @@ int BlockingNetworkDelegate::OnBeforeURLRequest(URLRequest* request,
int BlockingNetworkDelegate::OnBeforeStartTransaction(
URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) {
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, base::NullCallback(), headers));
+ request, headers, base::NullCallback()));
- return MaybeBlockStage(ON_BEFORE_SEND_HEADERS, std::move(callback));
+ return MaybeBlockStage(
+ ON_BEFORE_SEND_HEADERS,
+ base::BindOnce(
+ [](OnBeforeStartTransactionCallback callback, int result) {
+ std::move(callback).Run(result, absl::nullopt);
+ },
+ std::move(callback)));
}
int BlockingNetworkDelegate::OnHeadersReceived(
@@ -1586,7 +1585,7 @@ TEST_F(URLRequestTest, DelayedCookieCallback) {
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(1, network_delegate.set_cookie_count());
}
@@ -1604,89 +1603,11 @@ TEST_F(URLRequestTest, DelayedCookieCallback) {
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
-class FilteringTestNetworkDelegate : public TestNetworkDelegate {
- public:
- FilteringTestNetworkDelegate()
- : set_cookie_called_count_(0),
- blocked_set_cookie_count_(0),
- block_get_cookies_(false),
- get_cookie_called_count_(0),
- blocked_get_cookie_count_(0) {}
- ~FilteringTestNetworkDelegate() override = default;
-
- bool OnCanSetCookie(const URLRequest& request,
- const net::CanonicalCookie& cookie,
- CookieOptions* options,
- bool allowed_from_caller) override {
- // Filter out cookies with the same name as |cookie_name_filter_| and
- // combine with |allowed_from_caller|.
- bool allowed =
- allowed_from_caller && !(cookie.Name() == cookie_name_filter_);
-
- ++set_cookie_called_count_;
-
- if (!allowed)
- ++blocked_set_cookie_count_;
-
- return TestNetworkDelegate::OnCanSetCookie(request, cookie, options,
- allowed);
- }
-
- void SetCookieFilter(std::string filter) {
- cookie_name_filter_ = std::move(filter);
- }
-
- int set_cookie_called_count() { return set_cookie_called_count_; }
-
- int blocked_set_cookie_count() { return blocked_set_cookie_count_; }
-
- void ResetSetCookieCalledCount() { set_cookie_called_count_ = 0; }
-
- void ResetBlockedSetCookieCount() { blocked_set_cookie_count_ = 0; }
-
- bool OnCanGetCookies(const URLRequest& request,
- bool allowed_from_caller) override {
- // Filter out cookies if |block_get_cookies_| is set and
- // combine with |allowed_from_caller|.
- bool allowed = allowed_from_caller && !block_get_cookies_;
-
- ++get_cookie_called_count_;
-
- if (!allowed)
- ++blocked_get_cookie_count_;
-
- return TestNetworkDelegate::OnCanGetCookies(request, allowed);
- }
-
- void set_block_get_cookies() { block_get_cookies_ = true; }
-
- void unset_block_get_cookies() { block_get_cookies_ = false; }
-
- int get_cookie_called_count() const { return get_cookie_called_count_; }
-
- int blocked_get_cookie_count() const { return blocked_get_cookie_count_; }
-
- void ResetGetCookieCalledCount() { get_cookie_called_count_ = 0; }
-
- void ResetBlockedGetCookieCount() { blocked_get_cookie_count_ = 0; }
-
- private:
- std::string cookie_name_filter_;
- int set_cookie_called_count_;
- int blocked_set_cookie_count_;
-
- bool block_get_cookies_;
- int get_cookie_called_count_;
- int blocked_get_cookie_count_;
-
- DISALLOW_COPY_AND_ASSIGN(FilteringTestNetworkDelegate);
-};
-
TEST_F(URLRequestTest, DelayedCookieCallbackAsync) {
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
@@ -1715,15 +1636,17 @@ TEST_F(URLRequestTest, DelayedCookieCallbackAsync) {
replace_scheme.SetSchemeStr("https");
GURL url = test_server.base_url().ReplaceComponents(replace_scheme);
- auto cookie1 = CanonicalCookie::Create(url, "AlreadySetCookie=1;Secure",
- base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie1 = CanonicalCookie::Create(
+ url, "AlreadySetCookie=1;Secure", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
delayed_cm->SetCanonicalCookieAsync(std::move(cookie1), url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
- auto cookie2 = CanonicalCookie::Create(url, "AlreadySetCookie=1;Secure",
- base::Time::Now(),
- absl::nullopt /* server_time */);
+ auto cookie2 = CanonicalCookie::Create(
+ url, "AlreadySetCookie=1;Secure", base::Time::Now(),
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(std::move(cookie2), url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
@@ -1809,7 +1732,7 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
&d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -1826,7 +1749,7 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -1845,8 +1768,9 @@ TEST_F(URLRequestTest, DoNotSendCookies) {
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
- // When credentials are blocked, OnGetCookies() is not invoked.
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ // When credentials are blocked, OnAnnotateAndMoveUserBlockedCookies() is
+ // not invoked.
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -1866,7 +1790,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(1, network_delegate.set_cookie_count());
}
@@ -1885,7 +1809,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
d.RunUntilComplete();
// LOAD_DO_NOT_SAVE_COOKIES does not trigger OnSetCookie.
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(0, network_delegate.set_cookie_count());
}
@@ -1906,7 +1830,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies) {
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(0, network_delegate.set_cookie_count());
}
@@ -1927,7 +1851,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -1945,7 +1869,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
auto entries = net_log_.GetEntries();
for (const auto& entry : entries) {
@@ -1969,7 +1893,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy) {
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
- EXPECT_EQ(1, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(1, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
auto entries = net_log_.GetEntries();
ExpectLogContainsSomewhereAfter(
@@ -1999,7 +1923,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
auto entries = net_log_.GetEntries();
for (const auto& entry : entries) {
@@ -2021,7 +1945,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(2, network_delegate.blocked_set_cookie_count());
auto entries = net_log_.GetEntries();
ExpectLogContainsSomewhereAfter(
@@ -2045,7 +1969,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy) {
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -2065,7 +1989,7 @@ TEST_F(URLRequestTest, DoNotSaveEmptyCookies) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(0, network_delegate.set_cookie_count());
}
@@ -2086,7 +2010,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2104,7 +2028,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
EXPECT_TRUE(d.data_received().find("CookieToNotSend=1") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2123,7 +2047,7 @@ TEST_F(URLRequestTest, DoNotSendCookies_ViaPolicy_Async) {
EXPECT_TRUE(d.data_received().find("Cookie: CookieToNotSend=1") ==
std::string::npos);
- EXPECT_EQ(1, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(1, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -2143,7 +2067,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2160,7 +2084,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(2, network_delegate.blocked_set_cookie_count());
}
@@ -2180,7 +2104,7 @@ TEST_F(URLRequestTest, DoNotSaveCookies_ViaPolicy_Async) {
EXPECT_TRUE(d.data_received().find("CookieToNotUpdate=2") !=
std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -2236,7 +2160,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
req->set_initiator(kOrigin);
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
EXPECT_EQ(2, network_delegate.set_cookie_count());
}
@@ -2262,7 +2186,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2280,7 +2204,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2299,7 +2223,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_NE(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2317,7 +2241,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2340,7 +2264,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_NE(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2364,7 +2288,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -2388,7 +2312,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
EXPECT_EQ(std::string::npos,
d.data_received().find("StrictSameSiteCookie=1"));
EXPECT_EQ(std::string::npos, d.data_received().find("LaxSameSiteCookie=1"));
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
// Check that the appropriate cookie inclusion status is set.
@@ -2400,8 +2324,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SameSiteCookies) {
CookieInclusionStatus expected_lax_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
- {CookieInclusionStatus::
- WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211});
+ {} /* warning_reasons */);
EXPECT_EQ(expected_strict_status,
req->maybe_sent_cookies()[0].access_result.status);
EXPECT_EQ(expected_lax_status,
@@ -2878,8 +2801,7 @@ TEST_P(URLRequestSameSiteCookiesTest, SettingSameSiteCookies) {
CookieInclusionStatus expected_lax_status =
CookieInclusionStatus::MakeFromReasonsForTesting(
{CookieInclusionStatus::EXCLUDE_SAMESITE_LAX},
- {CookieInclusionStatus::
- WARN_SAMESITE_LAX_EXCLUDED_AFTER_BUGFIX_1166211});
+ {} /* warning_reasons */);
EXPECT_EQ(expected_strict_status,
req->maybe_stored_cookies()[0].access_result.status);
EXPECT_EQ(expected_lax_status,
@@ -3290,7 +3212,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) {
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -3307,7 +3229,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixOnNonsecureOrigin) {
EXPECT_EQ(d.data_received().find("__Secure-nonsecure-origin=1"),
std::string::npos);
EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -3331,7 +3253,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) {
req->Start();
d.RunUntilComplete();
EXPECT_EQ(0, network_delegate.set_cookie_count());
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -3345,7 +3267,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixNonsecure) {
d.RunUntilComplete();
EXPECT_EQ(d.data_received().find("__Secure-foo=1"), std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -3368,7 +3290,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixSecure) {
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -3382,7 +3304,7 @@ TEST_F(URLRequestTest, SecureCookiePrefixSecure) {
d.RunUntilComplete();
EXPECT_NE(d.data_received().find("__Secure-bar=1"), std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -3413,7 +3335,7 @@ TEST_F(URLRequestTest, StrictSecureCookiesOnNonsecureOrigin) {
DEFAULT_PRIORITY, &d, TRAFFIC_ANNOTATION_FOR_TESTS));
req->Start();
d.RunUntilComplete();
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
@@ -3428,7 +3350,7 @@ TEST_F(URLRequestTest, StrictSecureCookiesOnNonsecureOrigin) {
EXPECT_EQ(d.data_received().find("nonsecure-origin=1"), std::string::npos);
EXPECT_NE(d.data_received().find("cookienotsecure=1"), std::string::npos);
- EXPECT_EQ(0, network_delegate.blocked_get_cookies_count());
+ EXPECT_EQ(0, network_delegate.blocked_annotate_cookies_count());
EXPECT_EQ(0, network_delegate.blocked_set_cookie_count());
}
}
@@ -4878,13 +4800,19 @@ class AsyncLoggingNetworkDelegate : public TestNetworkDelegate {
return RunCallbackAsynchronously(request, std::move(callback));
}
- int OnBeforeStartTransaction(URLRequest* request,
- CompletionOnceCallback callback,
- HttpRequestHeaders* headers) override {
+ int OnBeforeStartTransaction(
+ URLRequest* request,
+ const HttpRequestHeaders& headers,
+ OnBeforeStartTransactionCallback callback) override {
// TestNetworkDelegate always completes synchronously.
CHECK_NE(ERR_IO_PENDING, TestNetworkDelegate::OnBeforeStartTransaction(
- request, base::NullCallback(), headers));
- return RunCallbackAsynchronously(request, std::move(callback));
+ request, headers, base::NullCallback()));
+ return RunCallbackAsynchronously(
+ request, base::BindOnce(
+ [](OnBeforeStartTransactionCallback callback, int result) {
+ std::move(callback).Run(result, absl::nullopt);
+ },
+ std::move(callback)));
}
int OnHeadersReceived(
@@ -7489,8 +7417,8 @@ TEST_F(URLRequestTestHTTP, AuthWithNetworkIsolationKey) {
for (bool key_auth_cache_by_network_isolation_key : {false, true}) {
TestURLRequestContext url_request_context(true /* delay_initialization */);
- std::unique_ptr<HttpNetworkSession::Params> http_network_session_params =
- std::make_unique<HttpNetworkSession::Params>();
+ auto http_network_session_params =
+ std::make_unique<HttpNetworkSessionParams>();
http_network_session_params
->key_auth_cache_server_entries_by_network_isolation_key =
key_auth_cache_by_network_isolation_key;
@@ -7554,7 +7482,7 @@ TEST_F(URLRequestTest, ReportCookieActivity) {
FilteringTestNetworkDelegate network_delegate;
network_delegate.SetCookieFilter("not_stored_cookie");
- network_delegate.set_block_get_cookies();
+ network_delegate.set_block_annotate_cookies();
RecordingTestNetLog net_log;
TestURLRequestContext context(true);
context.set_network_delegate(&network_delegate);
@@ -7676,7 +7604,7 @@ TEST_F(URLRequestTest, ReportCookieActivity) {
net_log.SetObserverCaptureMode(NetLogCaptureMode::kIncludeSensitive);
}
- network_delegate.unset_block_get_cookies();
+ network_delegate.unset_block_annotate_cookies();
{
// Now with sending cookies re-enabled, it should actually be sent.
TestDelegate d;
@@ -7716,8 +7644,6 @@ TEST_F(URLRequestTest, ReportCookieActivity) {
// set if the cookie would have been rejected for other reasons.
// Regression test for https://crbug.com/1027318.
TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitAndEnableFeature(features::kSameSiteByDefaultCookies);
HttpTestServer test_server;
ASSERT_TRUE(test_server.Start());
@@ -7787,11 +7713,12 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) {
}
// Get cookies (blocked by user preference)
- network_delegate.set_block_get_cookies();
+ network_delegate.set_block_annotate_cookies();
{
GURL url = test_server.GetURL("/");
- auto cookie1 = CanonicalCookie::Create(url, "cookienosamesite=1",
- base::Time::Now(), absl::nullopt);
+ auto cookie1 = CanonicalCookie::Create(
+ url, "cookienosamesite=1", base::Time::Now(), absl::nullopt,
+ absl::nullopt /* cookie_partition_key */);
base::RunLoop run_loop;
CookieAccessResult access_result;
cm.SetCanonicalCookieAsync(
@@ -7827,13 +7754,14 @@ TEST_F(URLRequestTest, NoCookieInclusionStatusWarningIfWouldBeExcludedAnyway) {
EXPECT_FALSE(
req->maybe_sent_cookies()[0].access_result.status.ShouldWarn());
}
- network_delegate.unset_block_get_cookies();
+ network_delegate.unset_block_annotate_cookies();
// Get cookies
{
GURL url = test_server.GetURL("/");
- auto cookie2 = CanonicalCookie::Create(url, "cookiewithpath=1;path=/foo",
- base::Time::Now(), absl::nullopt);
+ auto cookie2 = CanonicalCookie::Create(
+ url, "cookiewithpath=1;path=/foo", base::Time::Now(), absl::nullopt,
+ absl::nullopt /* cookie_partition_key */);
base::RunLoop run_loop;
// Note: cookie1 from the previous testcase is still in the cookie store.
CookieAccessResult access_result;
@@ -7970,7 +7898,7 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
// Check maybe_sent_cookies on first round trip (and cleared for the second).
{
FilteringTestNetworkDelegate filtering_network_delegate;
- filtering_network_delegate.set_block_get_cookies();
+ filtering_network_delegate.set_block_annotate_cookies();
TestURLRequestContext context(true);
context.set_network_delegate(&filtering_network_delegate);
@@ -7978,7 +7906,8 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
std::make_unique<CookieMonster>(nullptr, nullptr);
auto another_cookie = CanonicalCookie::Create(
url_requiring_auth_wo_cookies, "another_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(std::move(another_cookie),
url_requiring_auth_wo_cookies,
net::CookieOptions::MakeAllInclusive(),
@@ -8010,7 +7939,8 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
cm->DeleteAllAsync(CookieStore::DeleteCallback());
auto one_more_cookie = CanonicalCookie::Create(
url_requiring_auth_wo_cookies, "one_more_cookie=true",
- base::Time::Now(), absl::nullopt /* server_time */);
+ base::Time::Now(), absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
url_requiring_auth_wo_cookies,
net::CookieOptions::MakeAllInclusive(),
@@ -8028,7 +7958,7 @@ TEST_F(URLRequestTestHTTP, AuthChallengeWithFilteredCookies) {
delegate.data_received().find("Cookie: one_more_cookie=true"));
// got_challenged was set after the first request and blocked on the second,
// so it should only have been blocked this time
- EXPECT_EQ(2, filtering_network_delegate.blocked_get_cookie_count());
+ EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
// // The number of cookies blocked from the most recent round trip.
ASSERT_EQ(1u, request->maybe_sent_cookies().size());
@@ -8382,14 +8312,15 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) {
// Check maybe_sent_cookies on first round trip.
{
FilteringTestNetworkDelegate filtering_network_delegate;
- filtering_network_delegate.set_block_get_cookies();
+ filtering_network_delegate.set_block_annotate_cookies();
TestURLRequestContext context(true);
context.set_network_delegate(&filtering_network_delegate);
std::unique_ptr<CookieMonster> cm =
std::make_unique<CookieMonster>(nullptr, nullptr);
auto another_cookie = CanonicalCookie::Create(
original_url, "another_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(std::move(another_cookie), original_url,
net::CookieOptions::MakeAllInclusive(),
CookieStore::SetCookiesCallback());
@@ -8418,7 +8349,8 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) {
cm->DeleteAllAsync(CookieStore::DeleteCallback());
auto one_more_cookie = CanonicalCookie::Create(
original_url_wo_cookie, "one_more_cookie=true", base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
cm->SetCanonicalCookieAsync(std::move(one_more_cookie),
original_url_wo_cookie,
net::CookieOptions::MakeAllInclusive(),
@@ -8431,7 +8363,7 @@ TEST_F(URLRequestTestHTTP, RedirectWithFilteredCookies) {
// There are DCHECKs in URLRequestHttpJob that would fail if
// maybe_sent_cookies and maybe_stored_cookies we not cleared properly.
- EXPECT_EQ(2, filtering_network_delegate.blocked_get_cookie_count());
+ EXPECT_EQ(2, filtering_network_delegate.blocked_annotate_cookies_count());
// The number of cookies blocked from the most recent round trip.
ASSERT_EQ(1u, request->maybe_sent_cookies().size());
@@ -10139,7 +10071,7 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
}
// Now create a new HttpCache with a different ssl_session_cache_shard value.
- HttpNetworkSession::Context session_context;
+ HttpNetworkSessionContext session_context;
session_context.host_resolver = default_context_.host_resolver();
session_context.cert_verifier = default_context_.cert_verifier();
session_context.transport_security_state =
@@ -10154,7 +10086,7 @@ TEST_F(HTTPSRequestTest, SSLSessionCacheShardTest) {
default_context_.http_server_properties();
session_context.quic_context = default_context_.quic_context();
- HttpNetworkSession network_session(HttpNetworkSession::Params(),
+ HttpNetworkSession network_session(HttpNetworkSessionParams(),
session_context);
std::unique_ptr<HttpCache> cache(
new HttpCache(&network_session, HttpCache::DefaultBackend::InMemory(0),
@@ -10515,11 +10447,13 @@ class HTTPSOCSPTest : public HTTPSCertNetFetchingTest {
static bool UsingBuiltinCertVerifier() {
#if defined(OS_FUCHSIA) || defined(OS_LINUX) || defined(OS_CHROMEOS)
return true;
-#elif BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+#else
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
if (base::FeatureList::IsEnabled(features::kCertVerifierBuiltinFeature))
return true;
#endif
return false;
+#endif
}
// SystemSupportsHardFailRevocationChecking returns true iff the current
@@ -12590,7 +12524,7 @@ class HTTPSEarlyDataTest : public TestWithTaskEnvironment {
public:
HTTPSEarlyDataTest()
: context_(true), test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {
- auto params = std::make_unique<HttpNetworkSession::Params>();
+ auto params = std::make_unique<HttpNetworkSessionParams>();
params->enable_early_data = true;
context_.set_http_network_session_params(std::move(params));
diff --git a/chromium/net/websockets/websocket_basic_handshake_stream.cc b/chromium/net/websockets/websocket_basic_handshake_stream.cc
index ab5b44d2173..302b6c4b8cf 100644
--- a/chromium/net/websockets/websocket_basic_handshake_stream.cc
+++ b/chromium/net/websockets/websocket_basic_handshake_stream.cc
@@ -15,7 +15,6 @@
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/metrics/histogram_functions.h"
-#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_util.h"
diff --git a/chromium/net/websockets/websocket_basic_stream_adapters_test.cc b/chromium/net/websockets/websocket_basic_stream_adapters_test.cc
index f23d13ba030..eac58f094df 100644
--- a/chromium/net/websockets/websocket_basic_stream_adapters_test.cc
+++ b/chromium/net/websockets/websocket_basic_stream_adapters_test.cc
@@ -42,6 +42,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using testing::Test;
using testing::StrictMock;
@@ -54,8 +56,7 @@ namespace test {
class WebSocketClientSocketHandleAdapterTest : public TestWithTaskEnvironment {
protected:
WebSocketClientSocketHandleAdapterTest()
- : host_port_pair_("www.example.org", 443),
- network_session_(
+ : network_session_(
SpdySessionDependencies::SpdyCreateSession(&session_deps_)),
websocket_endpoint_lock_manager_(
network_session_->websocket_endpoint_lock_manager()) {}
@@ -70,7 +71,7 @@ class WebSocketClientSocketHandleAdapterTest : public TestWithTaskEnvironment {
TestCompletionCallback callback;
int rv = connection->Init(
ClientSocketPool::GroupId(
- host_port_pair_, ClientSocketPool::SocketType::kSsl,
+ url::SchemeHostPort(url::kHttpsScheme, "www.example.org", 443),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
socks_params, TRAFFIC_ANNOTATION_FOR_TESTS /* proxy_annotation_tag */,
@@ -83,7 +84,6 @@ class WebSocketClientSocketHandleAdapterTest : public TestWithTaskEnvironment {
return rv == OK;
}
- const HostPortPair host_port_pair_;
SpdySessionDependencies session_deps_;
std::unique_ptr<HttpNetworkSession> network_session_;
WebSocketEndpointLockManager* websocket_endpoint_lock_manager_;
diff --git a/chromium/net/websockets/websocket_basic_stream_test.cc b/chromium/net/websockets/websocket_basic_stream_test.cc
index cc056aad8f2..e83f4518f65 100644
--- a/chromium/net/websockets/websocket_basic_stream_test.cc
+++ b/chromium/net/websockets/websocket_basic_stream_test.cc
@@ -15,7 +15,7 @@
#include "base/big_endian.h"
#include "base/containers/span.h"
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/io_buffer.h"
#include "net/base/privacy_mode.h"
#include "net/base/test_completion_callback.h"
@@ -30,6 +30,8 @@
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/abseil-cpp/absl/types/optional.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using net::test::IsError;
using net::test::IsOk;
@@ -145,7 +147,7 @@ class WebSocketBasicStreamSocketTest : public TestWithTaskEnvironment {
auto transport_socket = std::make_unique<ClientSocketHandle>();
scoped_refptr<ClientSocketPool::SocketParams> null_params;
ClientSocketPool::GroupId group_id(
- HostPortPair("a", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "a", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow);
transport_socket->Init(
diff --git a/chromium/net/websockets/websocket_channel.cc b/chromium/net/websockets/websocket_channel.cc
index 7311f33fa51..5107a5a79af 100644
--- a/chromium/net/websockets/websocket_channel.cc
+++ b/chromium/net/websockets/websocket_channel.cc
@@ -14,12 +14,11 @@
#include "base/big_endian.h"
#include "base/bind.h"
#include "base/containers/circular_deque.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_functions.h"
#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -134,59 +133,6 @@ class DependentIOBuffer : public WrappedIOBuffer {
scoped_refptr<IOBuffer> buffer_;
};
-void LogCloseCodeForUma(uint16_t code) {
- // From RFC6455: "The status code is an integer number between 1000 and 4999
- // (inclusive)". In practice, any 16-bit unsigned integer may be sent. For UMA
- // purposes, we bucket codes whose meanings are not standardised. This enum is
- // emitted to UMA, so don't remove entries or renumber it. It's better not to
- // add new entries at all, since it will make older records incompatible with
- // newer records.
- enum class BucketedCloseCode {
- kNormalClosure = 0, // 1000
- kGoingAway = 1, // 1001
- kProtocolError = 2, // 1002
- kUnsupportedData = 3, // 1003
- kReserved = 4, // 1004
- kNoStatusRcvd = 5, // 1005
- kAbnormalClosure = 6, // 1006
- kInvalidFramePayloadData = 7, // 1007
- kPolicyViolation = 8, // 1008
- kMessageTooBig = 9, // 1009
- kMandatoryExt = 10, // 1010
- kInternalError = 11, // 1011
- kServiceRestart = 12, // 1012
- kTryAgainLater = 13, // 1013
- kBadGateway = 14, // 1014
- kTlsHandshake = 15, // 1015
- kOther1000Range = 16, // 1016-1999
- k2000Range = 17, // 2000-2999
- k3000Range = 18, // 3000-3999
- k4000Range = 19, // 4000-4999
- kUnder1000 = 20, // 0-999
- k5000AndOver = 21, // 5000-65535
- kMaxValue = k5000AndOver
- };
-
- BucketedCloseCode bucketed_code;
- if (code >= 1000 && code <= 1015) {
- bucketed_code = static_cast<BucketedCloseCode>(code - 1000);
- } else if (code < 1000) {
- bucketed_code = BucketedCloseCode::kUnder1000;
- } else if (code < 2000) {
- bucketed_code = BucketedCloseCode::kOther1000Range;
- } else if (code < 3000) {
- bucketed_code = BucketedCloseCode::k2000Range;
- } else if (code < 4000) {
- bucketed_code = BucketedCloseCode::k3000Range;
- } else if (code < 5000) {
- bucketed_code = BucketedCloseCode::k4000Range;
- } else {
- bucketed_code = BucketedCloseCode::k5000AndOver;
- }
-
- base::UmaHistogramEnumeration("Net.WebSocket.CloseCode", bucketed_code);
-}
-
} // namespace
// A class to encapsulate a set of frames and information about the size of
@@ -1046,7 +992,6 @@ bool WebSocketChannel::ParseClose(base::span<const char> payload,
void WebSocketChannel::DoDropChannel(bool was_clean,
uint16_t code,
const std::string& reason) {
- LogCloseCodeForUma(code);
event_interface_->OnDropChannel(was_clean, code, reason);
}
diff --git a/chromium/net/websockets/websocket_channel_test.cc b/chromium/net/websockets/websocket_channel_test.cc
index 878aa77e471..5605be06798 100644
--- a/chromium/net/websockets/websocket_channel_test.cc
+++ b/chromium/net/websockets/websocket_channel_test.cc
@@ -18,11 +18,11 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/callback_helpers.h"
+#include "base/cxx17_backports.h"
#include "base/location.h"
#include "base/memory/weak_ptr.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/threading/thread_task_runner_handle.h"
#include "net/base/completion_once_callback.h"
@@ -705,28 +705,12 @@ class ResetOnWriteFakeWebSocketStream : public FakeWebSocketStream {
// the extent that they are implemented in WebSocketCommon).
class MockWebSocketStream : public WebSocketStream {
public:
- // GMock cannot save or forward move-only types like CompletionOnceCallback,
- // therefore they have to be converted into a copyable type like
- // CompletionRepeatingCallback.
- int ReadFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
- CompletionOnceCallback callback) {
- return ReadFramesInternal(
- frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
- : CompletionRepeatingCallback());
- }
- int WriteFrames(std::vector<std::unique_ptr<WebSocketFrame>>* frames,
- CompletionOnceCallback callback) {
- return WriteFramesInternal(
- frames, callback ? base::AdaptCallbackForRepeating(std::move(callback))
- : CompletionRepeatingCallback());
- }
-
- MOCK_METHOD2(ReadFramesInternal,
+ MOCK_METHOD2(ReadFrames,
int(std::vector<std::unique_ptr<WebSocketFrame>>*,
- const CompletionRepeatingCallback&));
- MOCK_METHOD2(WriteFramesInternal,
+ CompletionOnceCallback));
+ MOCK_METHOD2(WriteFrames,
int(std::vector<std::unique_ptr<WebSocketFrame>>*,
- const CompletionRepeatingCallback&));
+ CompletionOnceCallback));
MOCK_METHOD0(Close, void());
MOCK_CONST_METHOD0(GetSubProtocol, std::string());
@@ -1761,7 +1745,7 @@ TEST_F(WebSocketChannelStreamTest, PendingDataFrameStopsReadFrames) {
InSequence s;
EXPECT_CALL(*event_interface_, HasPendingDataFrames())
.WillOnce(Return(false));
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_));
EXPECT_CALL(*event_interface_, HasPendingDataFrames())
.WillOnce(Return(true));
@@ -1771,7 +1755,7 @@ TEST_F(WebSocketChannelStreamTest, PendingDataFrameStopsReadFrames) {
EXPECT_CALL(checkpoint, Call(2));
EXPECT_CALL(*event_interface_, HasPendingDataFrames())
.WillOnce(Return(false));
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(Return(ERR_IO_PENDING));
}
@@ -1874,9 +1858,8 @@ TEST_F(WebSocketChannelStreamTest, SentFramesAreMasked) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText,
MASKED, "NEEDS MASKING"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1891,9 +1874,8 @@ TEST_F(WebSocketChannelStreamTest, NothingIsSentAfterClose) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Success")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1912,10 +1894,10 @@ TEST_F(WebSocketChannelStreamTest, CloseIsEchoedBack) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(NORMAL_CLOSURE, "Close")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -1940,14 +1922,16 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
Checkpoint checkpoint;
{
InSequence s;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(DoAll(SaveArg<0>(&frames), SaveArg<1>(&read_callback),
- Return(ERR_IO_PENDING)));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce([&](auto f, auto cb) {
+ frames = f;
+ read_callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
EXPECT_CALL(checkpoint, Call(1));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(Return(ERR_IO_PENDING));
EXPECT_CALL(checkpoint, Call(3));
// WriteFrames() must not be called again. GoogleMock will ensure that the
@@ -1959,6 +1943,7 @@ TEST_F(WebSocketChannelStreamTest, CloseOnlySentOnce) {
ASSERT_EQ(CHANNEL_ALIVE,
channel_->StartClosingHandshake(kWebSocketNormalClosure, "Close"));
checkpoint.Call(2);
+ ASSERT_TRUE(frames);
*frames = CreateFrameVector(frames_init, &result_frame_data_);
std::move(read_callback).Run(OK);
checkpoint.Call(3);
@@ -1970,10 +1955,9 @@ TEST_F(WebSocketChannelStreamTest, InvalidCloseStatusCodeNotSent) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
CreateChannelAndConnectSuccessfully();
ASSERT_EQ(CHANNEL_ALIVE, channel_->StartClosingHandshake(999, ""));
@@ -1986,10 +1970,9 @@ TEST_F(WebSocketChannelStreamTest, LongCloseReasonNotSent) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(SERVER_ERROR, "")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _));
CreateChannelAndConnectSuccessfully();
ASSERT_EQ(CHANNEL_ALIVE,
@@ -2006,10 +1989,10 @@ TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoed) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, ""}};
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -2020,10 +2003,10 @@ TEST_F(WebSocketChannelStreamTest, Code1005IsNotEchoedNull) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, NOT_MASKED, nullptr}};
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED, ""}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -2039,10 +2022,10 @@ TEST_F(WebSocketChannelStreamTest, CloseFrameInvalidUtf8) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in Close frame")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close());
@@ -2061,10 +2044,10 @@ TEST_F(WebSocketChannelStreamTest, PingRepliedWithPong) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong,
MASKED, "Application data"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -2077,10 +2060,10 @@ TEST_F(WebSocketChannelStreamTest, NullPingRepliedWithNullPong) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodePing, NOT_MASKED, nullptr}};
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodePong, MASKED, nullptr}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
CreateChannelAndConnectSuccessfully();
@@ -2100,18 +2083,21 @@ TEST_F(WebSocketChannelStreamTest, PongInTheMiddleOfDataMessage) {
MASKED, "World"}};
std::vector<std::unique_ptr<WebSocketFrame>>* read_frames;
CompletionOnceCallback read_callback;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
- Return(ERR_IO_PENDING)))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce([&](auto frames, auto cb) {
+ read_frames = std::move(frames);
+ read_callback = std::move(cb);
+ return ERR_IO_PENDING;
+ })
.WillRepeatedly(Return(ERR_IO_PENDING));
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
.WillOnce(Return(OK));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(OK));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected3), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected3), _))
.WillOnce(Return(OK));
}
@@ -2136,15 +2122,17 @@ TEST_F(WebSocketChannelStreamTest, WriteFramesOneAtATime) {
CompletionOnceCallback write_callback;
Checkpoint checkpoint;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
{
InSequence s;
EXPECT_CALL(checkpoint, Call(1));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
- .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
+ .WillOnce([&](auto, auto cb) {
+ write_callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
EXPECT_CALL(checkpoint, Call(2));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(ERR_IO_PENDING));
EXPECT_CALL(checkpoint, Call(3));
}
@@ -2176,13 +2164,15 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, MASKED, "o"}};
CompletionOnceCallback write_callback;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected1), _))
- .WillOnce(DoAll(SaveArg<1>(&write_callback), Return(ERR_IO_PENDING)));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected2), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected1), _))
+ .WillOnce([&](auto, auto cb) {
+ write_callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected2), _))
.WillOnce(Return(ERR_IO_PENDING));
}
@@ -2202,9 +2192,8 @@ TEST_F(WebSocketChannelStreamTest, WaitingMessagesAreBatched) {
TEST_F(WebSocketChannelStreamTest, WrittenBinaryFramesAre8BitClean) {
std::vector<std::unique_ptr<WebSocketFrame>>* frames = nullptr;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _)).WillOnce(Return(ERR_IO_PENDING));
+ EXPECT_CALL(*mock_stream_, WriteFrames(_, _))
.WillOnce(DoAll(SaveArg<0>(&frames), Return(ERR_IO_PENDING)));
CreateChannelAndConnectSuccessfully();
@@ -2383,9 +2372,9 @@ TEST_F(WebSocketChannelStreamTest, InvalidUtf8TextFrameNotSent) {
static const InitFrame expected[] = {{FINAL_FRAME,
WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(GOING_AWAY, "")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
@@ -2409,10 +2398,10 @@ TEST_F(WebSocketChannelReceiveUtf8Test, InvalidTextFrameRejected) {
CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
{
InSequence s;
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
}
@@ -2428,10 +2417,10 @@ TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
@@ -2442,7 +2431,7 @@ TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterReceived) {
TEST_F(WebSocketChannelReceiveUtf8Test, IncompleteCharacterIncompleteMessage) {
static const InitFrame frames[] = {
{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xc2"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
@@ -2457,10 +2446,10 @@ TEST_F(WebSocketChannelReceiveUtf8Test, TricksyIncompleteCharacter) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
@@ -2474,7 +2463,7 @@ TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedParsingContextRetained) {
{NOT_FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "\xf1"},
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
NOT_MASKED, "\x80\xa0\xbf"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
@@ -2490,10 +2479,10 @@ TEST_F(WebSocketChannelReceiveUtf8Test, SplitInvalidCharacterReceived) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
@@ -2511,10 +2500,10 @@ TEST_F(WebSocketChannelReceiveUtf8Test, InvalidReceivedIncontinuation) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose, MASKED,
CLOSE_DATA(PROTOCOL_ERROR, "Invalid UTF-8 in text frame")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
@@ -2529,7 +2518,7 @@ TEST_F(WebSocketChannelReceiveUtf8Test, ReceivedBinaryNotUtf8Tested) {
NOT_MASKED, "bar"},
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeContinuation,
NOT_MASKED, "\xff"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
@@ -2541,7 +2530,7 @@ TEST_F(WebSocketChannelReceiveUtf8Test, ValidateMultipleReceived) {
static const InitFrame frames[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "foo"},
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeText, NOT_MASKED, "bar"}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
@@ -2657,7 +2646,7 @@ TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
{
@@ -2666,7 +2655,7 @@ TEST_F(WebSocketChannelStreamTest, PingAfterCloseIsRejected) {
// frame before calling ReadFrames() again, but that is an implementation
// detail and better not to consider required behaviour.
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).Times(1);
}
@@ -2680,9 +2669,9 @@ TEST_F(WebSocketChannelStreamTest, ProtocolError) {
static const InitFrame expected[] = {
{FINAL_FRAME, WebSocketFrameHeader::kOpCodeClose,
MASKED, CLOSE_DATA(PROTOCOL_ERROR, "WebSocket Protocol Error")}};
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(Return(ERR_WS_PROTOCOL_ERROR));
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close());
@@ -2722,14 +2711,14 @@ TEST_F(WebSocketChannelStreamTimeoutTest, ServerInitiatedCloseTimesOut) {
MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(ReturnFrames(&frames, &result_frame_data_))
.WillRepeatedly(Return(ERR_IO_PENDING));
Checkpoint checkpoint;
TestClosure completion;
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(checkpoint, Call(1));
EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
@@ -2750,12 +2739,12 @@ TEST_F(WebSocketChannelStreamTimeoutTest, ClientInitiatedCloseTimesOut) {
MASKED, CLOSE_DATA(NORMAL_CLOSURE, "OK")}};
EXPECT_CALL(*mock_stream_, GetSubProtocol()).Times(AnyNumber());
EXPECT_CALL(*mock_stream_, GetExtensions()).Times(AnyNumber());
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillRepeatedly(Return(ERR_IO_PENDING));
TestClosure completion;
{
InSequence s;
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
}
@@ -2786,17 +2775,21 @@ TEST_F(WebSocketChannelStreamTimeoutTest, ConnectionCloseTimesOut) {
InSequence s;
// Copy the arguments to ReadFrames so that the test can call the callback
// after it has send the close message.
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
- .WillOnce(DoAll(SaveArg<0>(&read_frames), SaveArg<1>(&read_callback),
- Return(ERR_IO_PENDING)));
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
+ .WillOnce([&](auto frames, auto cb) {
+ read_frames = frames;
+ read_callback = std::move(cb);
+ return ERR_IO_PENDING;
+ });
+
// The first real event that happens is the client sending the Close
// message.
- EXPECT_CALL(*mock_stream_, WriteFramesInternal(EqualsFrames(expected), _))
+ EXPECT_CALL(*mock_stream_, WriteFrames(EqualsFrames(expected), _))
.WillOnce(Return(OK));
// The |read_frames| callback is called (from this test case) at this
// point. ReadFrames is called again by WebSocketChannel, waiting for
// ERR_CONNECTION_CLOSED.
- EXPECT_CALL(*mock_stream_, ReadFramesInternal(_, _))
+ EXPECT_CALL(*mock_stream_, ReadFrames(_, _))
.WillOnce(Return(ERR_IO_PENDING));
// The timeout happens and so WebSocketChannel closes the stream.
EXPECT_CALL(*mock_stream_, Close()).WillOnce(InvokeClosure(&completion));
diff --git a/chromium/net/websockets/websocket_deflate_parameters_test.cc b/chromium/net/websockets/websocket_deflate_parameters_test.cc
index 0396d3c58fc..4e6c6b5249f 100644
--- a/chromium/net/websockets/websocket_deflate_parameters_test.cc
+++ b/chromium/net/websockets/websocket_deflate_parameters_test.cc
@@ -7,7 +7,7 @@
#include <string>
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/websockets/websocket_extension_parser.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/websockets/websocket_extension_parser_test.cc b/chromium/net/websockets/websocket_extension_parser_test.cc
index c4bc17131ff..77eb589b4be 100644
--- a/chromium/net/websockets/websocket_extension_parser_test.cc
+++ b/chromium/net/websockets/websocket_extension_parser_test.cc
@@ -6,7 +6,7 @@
#include <string>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/websockets/websocket_extension.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/websockets/websocket_frame_parser_test.cc b/chromium/net/websockets/websocket_frame_parser_test.cc
index 32eba4b4f0b..22262adc7de 100644
--- a/chromium/net/websockets/websocket_frame_parser_test.cc
+++ b/chromium/net/websockets/websocket_frame_parser_test.cc
@@ -8,7 +8,7 @@
#include <algorithm>
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "net/base/io_buffer.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/websockets/websocket_frame_perftest.cc b/chromium/net/websockets/websocket_frame_perftest.cc
index 5c31b1c1fd1..e156a0e13e4 100644
--- a/chromium/net/websockets/websocket_frame_perftest.cc
+++ b/chromium/net/websockets/websocket_frame_perftest.cc
@@ -7,7 +7,7 @@
#include <algorithm>
#include <vector>
-#include "base/stl_util.h"
+#include "base/cxx17_backports.h"
#include "base/timer/elapsed_timer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/perf/perf_result_reporter.h"
diff --git a/chromium/net/websockets/websocket_frame_test.cc b/chromium/net/websockets/websocket_frame_test.cc
index d2cf0feab2d..cd0009ffcfb 100644
--- a/chromium/net/websockets/websocket_frame_test.cc
+++ b/chromium/net/websockets/websocket_frame_test.cc
@@ -8,8 +8,8 @@
#include <algorithm>
#include <vector>
+#include "base/cxx17_backports.h"
#include "base/memory/aligned_memory.h"
-#include "base/stl_util.h"
#include "net/base/net_errors.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
index 6db1feb520f..a0b8bafbab2 100644
--- a/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
+++ b/chromium/net/websockets/websocket_handshake_stream_create_helper_test.cc
@@ -48,6 +48,8 @@
#include "third_party/abseil-cpp/absl/types/optional.h"
#include "url/gurl.h"
#include "url/origin.h"
+#include "url/scheme_host_port.h"
+#include "url/url_constants.h"
using ::net::test::IsError;
using ::net::test::IsOk;
@@ -92,7 +94,7 @@ class MockClientSocketHandleFactory {
auto socket_handle = std::make_unique<ClientSocketHandle>();
socket_handle->Init(
ClientSocketPool::GroupId(
- HostPortPair("a", 80), ClientSocketPool::SocketType::kHttp,
+ url::SchemeHostPort(url::kHttpScheme, "a", 80),
PrivacyMode::PRIVACY_MODE_DISABLED, NetworkIsolationKey(),
SecureDnsPolicy::kAllow),
scoped_refptr<ClientSocketPool::SocketParams>(),
diff --git a/chromium/net/websockets/websocket_http2_handshake_stream.cc b/chromium/net/websockets/websocket_http2_handshake_stream.cc
index 60526b5ac87..407e2fbdff1 100644
--- a/chromium/net/websockets/websocket_http2_handshake_stream.cc
+++ b/chromium/net/websockets/websocket_http2_handshake_stream.cc
@@ -168,7 +168,17 @@ void WebSocketHttp2HandshakeStream::Close(bool not_reusable) {
stream_closed_ = true;
stream_error_ = ERR_CONNECTION_CLOSED;
}
+
+ // The method needs to be idempotent as it may be called multiple times.
+ if (!stream_adapter_)
+ return;
+
stream_adapter_.reset();
+
+ // TODO(ricea): Remove these two lines once https://crbug.com/1215989 is
+ // resolved.
+ CHECK(!stream_adapter_reset_by_close_);
+ stream_adapter_reset_by_close_ = true;
}
bool WebSocketHttp2HandshakeStream::IsResponseBodyComplete() const {
@@ -251,10 +261,25 @@ base::StringPiece WebSocketHttp2HandshakeStream::GetAcceptChViaAlps() const {
std::unique_ptr<WebSocketStream> WebSocketHttp2HandshakeStream::Upgrade() {
DCHECK(extension_params_.get());
+ // These checks are here to find the cause of https://crbug.com/1215989.
+ // TODO(ricea): Remove them once the cause has been determined.
+ CHECK(!stream_adapter_reset_by_onclose_);
+
+ // The above blank line exists because stack traces often have annoying
+ // off-by-one errors in the line numbers.
+ CHECK(!stream_adapter_reset_by_close_);
+
+ // Above blank line is also intentional.
+ CHECK(!stream_adapter_moved_by_upgrade_);
+
+ // This should definitely be true if we get this far.
+ CHECK(stream_adapter_);
+
stream_adapter_->DetachDelegate();
std::unique_ptr<WebSocketStream> basic_stream =
std::make_unique<WebSocketBasicStream>(
std::move(stream_adapter_), nullptr, sub_protocol_, extensions_);
+ stream_adapter_moved_by_upgrade_ = true;
if (!extension_params_->deflate_enabled)
return basic_stream;
@@ -302,7 +327,9 @@ void WebSocketHttp2HandshakeStream::OnHeadersReceived(
}
void WebSocketHttp2HandshakeStream::OnClose(int status) {
- DCHECK(stream_adapter_);
+ // TODO(ricea): Change this CHECK back to a DCHECK when
+ // https://crbug.com/1215989 is fixed.
+ CHECK(stream_adapter_);
DCHECK_GT(ERR_IO_PENDING, status);
stream_closed_ = true;
@@ -311,6 +338,11 @@ void WebSocketHttp2HandshakeStream::OnClose(int status) {
stream_adapter_.reset();
+ // TODO(ricea): Remove these two lines once https://crbug.com/1215989 is
+ // resolved.
+ CHECK(!stream_adapter_reset_by_close_);
+ stream_adapter_reset_by_close_ = true;
+
// If response headers have already been received,
// then ValidateResponse() sets |result_|.
if (!response_headers_complete_)
diff --git a/chromium/net/websockets/websocket_http2_handshake_stream.h b/chromium/net/websockets/websocket_http2_handshake_stream.h
index 0f22df5971a..19edfd243ad 100644
--- a/chromium/net/websockets/websocket_http2_handshake_stream.h
+++ b/chromium/net/websockets/websocket_http2_handshake_stream.h
@@ -159,6 +159,13 @@ class NET_EXPORT_PRIVATE WebSocketHttp2HandshakeStream
// This can be passed on to WebSocketBasicStream when created.
std::unique_ptr<WebSocketSpdyStreamAdapter> stream_adapter_;
+ // Temporary variables to track where stream_adapter_ was reset.
+ // TODO(ricea): Remove these once the cause of https://crbug.com/1215989
+ // is established.
+ bool stream_adapter_reset_by_onclose_ = false;
+ bool stream_adapter_reset_by_close_ = false;
+ bool stream_adapter_moved_by_upgrade_ = false;
+
// True if |stream_| has been created then closed.
bool stream_closed_;
diff --git a/chromium/net/websockets/websocket_stream_cookie_test.cc b/chromium/net/websockets/websocket_stream_cookie_test.cc
index e0ffcc6730f..3bce53c3823 100644
--- a/chromium/net/websockets/websocket_stream_cookie_test.cc
+++ b/chromium/net/websockets/websocket_stream_cookie_test.cc
@@ -155,7 +155,8 @@ TEST_P(WebSocketStreamClientUseCookieTest, ClientUseCookie) {
base::RunLoop run_loop;
auto cookie =
CanonicalCookie::Create(cookie_url, cookie_line, base::Time::Now(),
- absl::nullopt /* server_time */);
+ absl::nullopt /* server_time */,
+ absl::nullopt /* cookie_partition_key */);
store->SetCanonicalCookieAsync(
std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
base::BindOnce(&SetCookieHelperFunction, run_loop.QuitClosure(),
diff --git a/chromium/net/websockets/websocket_stream_create_test_base.h b/chromium/net/websockets/websocket_stream_create_test_base.h
index 3c86a1adf4e..3ec3374f591 100644
--- a/chromium/net/websockets/websocket_stream_create_test_base.h
+++ b/chromium/net/websockets/websocket_stream_create_test_base.h
@@ -18,6 +18,7 @@
#include "net/test/test_with_task_environment.h"
#include "net/websockets/websocket_event_interface.h"
#include "net/websockets/websocket_test_util.h"
+#include "third_party/abseil-cpp/absl/types/optional.h"
class GURL;
diff --git a/chromium/net/websockets/websocket_stream_test.cc b/chromium/net/websockets/websocket_stream_test.cc
index 0c7257fe42b..d1030d044ec 100644
--- a/chromium/net/websockets/websocket_stream_test.cc
+++ b/chromium/net/websockets/websocket_stream_test.cc
@@ -11,12 +11,12 @@
#include "base/compiler_specific.h"
#include "base/containers/span.h"
+#include "base/cxx17_backports.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_samples.h"
#include "base/metrics/statistics_recorder.h"
#include "base/run_loop.h"
-#include "base/stl_util.h"
#include "base/strings/string_piece.h"
#include "base/strings/stringprintf.h"
#include "base/test/metrics/histogram_tester.h"
diff --git a/chromium/net/websockets/websocket_test_util.cc b/chromium/net/websockets/websocket_test_util.cc
index 23722ce16b0..c37c17b8c4e 100644
--- a/chromium/net/websockets/websocket_test_util.cc
+++ b/chromium/net/websockets/websocket_test_util.cc
@@ -228,7 +228,7 @@ void WebSocketMockClientSocketFactoryMaker::AddSSLSocketDataProvider(
WebSocketTestURLRequestContextHost::WebSocketTestURLRequestContextHost()
: url_request_context_(true), url_request_context_initialized_(false) {
url_request_context_.set_client_socket_factory(maker_.factory());
- auto params = std::make_unique<HttpNetworkSession::Params>();
+ auto params = std::make_unique<HttpNetworkSessionParams>();
params->enable_spdy_ping_based_connection_checking = false;
params->enable_quic = false;
params->enable_websocket_over_http2 = true;