summaryrefslogtreecommitdiff
path: root/chromium/services
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/services')
-rw-r--r--chromium/services/BUILD.gn2
-rw-r--r--chromium/services/audio/BUILD.gn1
-rw-r--r--chromium/services/audio/audio_sandbox_hook_linux.cc1
-rw-r--r--chromium/services/audio/group_coordinator.h2
-rw-r--r--chromium/services/audio/input_stream_unittest.cc8
-rw-r--r--chromium/services/audio/input_sync_writer.cc1
-rw-r--r--chromium/services/audio/input_sync_writer.h1
-rw-r--r--chromium/services/audio/output_controller.cc10
-rw-r--r--chromium/services/audio/output_stream_unittest.cc8
-rw-r--r--chromium/services/audio/public/cpp/device_factory.cc9
-rw-r--r--chromium/services/audio/public/cpp/device_factory.h6
-rw-r--r--chromium/services/audio/snooper_node_unittest.cc1
-rw-r--r--chromium/services/audio/sync_reader.cc1
-rw-r--r--chromium/services/cert_verifier/BUILD.gn6
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.cc3
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc71
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h18
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service.cc33
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service.h14
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service_factory.cc75
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service_factory.h21
-rw-r--r--chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc168
-rw-r--r--chromium/services/cert_verifier/integration_tests/DEPS3
-rw-r--r--chromium/services/cert_verifier/integration_tests/network_context_unittest.cc287
-rw-r--r--chromium/services/cert_verifier/integration_tests/network_service_unittest.cc479
-rw-r--r--chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc201
-rw-r--r--chromium/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom14
-rw-r--r--chromium/services/cert_verifier/test_cert_verifier_service_factory.cc12
-rw-r--r--chromium/services/cert_verifier/test_cert_verifier_service_factory.h6
-rw-r--r--chromium/services/device/BUILD.gn1
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc151
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc26
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider_linux.h9
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_winrt.cc14
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h2
-rw-r--r--chromium/services/device/geolocation/BUILD.gn2
-rw-r--r--chromium/services/device/geolocation/geolocation_context.cc3
-rw-r--r--chromium/services/device/geolocation/geolocation_context.h4
-rw-r--r--chromium/services/device/geolocation/geolocation_service_unittest.cc2
-rw-r--r--chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc7
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_chromeos.cc1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_common.h1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_linux.cc1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_linux_unittest.cc1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_mac.mm1
-rw-r--r--chromium/services/device/geolocation/wifi_data_provider_win.cc1
-rw-r--r--chromium/services/device/hid/hid_service.h2
-rw-r--r--chromium/services/device/hid/hid_service_linux.cc157
-rw-r--r--chromium/services/device/hid/hid_service_mac.cc6
-rw-r--r--chromium/services/device/hid/hid_service_win.cc187
-rw-r--r--chromium/services/device/hid/hid_service_win.h3
-rw-r--r--chromium/services/device/media_transfer_protocol/mtp_device_manager.h1
-rw-r--r--chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NfcBlocklistTest.java4
-rw-r--r--chromium/services/device/public/cpp/device_feature_list.cc1
-rw-r--r--chromium/services/device/public/cpp/generic_sensor/platform_sensor_configuration.h1
-rw-r--r--chromium/services/device/public/cpp/hid/fake_hid_manager.cc10
-rw-r--r--chromium/services/device/public/cpp/hid/fake_hid_manager.h5
-rw-r--r--chromium/services/device/public/cpp/hid/hid_report_descriptor_item.cc4
-rw-r--r--chromium/services/device/public/mojom/BUILD.gn1
-rw-r--r--chromium/services/device/public/mojom/geolocation_context.mojom7
-rw-r--r--chromium/services/device/public/mojom/nfc_provider.mojom2
-rw-r--r--chromium/services/device/public/mojom/serial.mojom36
-rw-r--r--chromium/services/device/public/mojom/usb_manager.mojom6
-rw-r--r--chromium/services/device/serial/serial_device_enumerator.cc8
-rw-r--r--chromium/services/device/serial/serial_device_enumerator.h5
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_linux.cc125
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_mac.cc117
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_mac.h7
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_win.cc130
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix.cc12
-rw-r--r--chromium/services/device/serial/serial_io_handler_win.cc49
-rw-r--r--chromium/services/device/serial/serial_port_impl.cc54
-rw-r--r--chromium/services/device/serial/serial_port_impl.h7
-rw-r--r--chromium/services/device/serial/serial_port_impl_unittest.cc56
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.cc4
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.h1
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl_unittest.cc2
-rw-r--r--chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc2
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl.cc5
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl.h1
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.cc41
-rw-r--r--chromium/services/device/usb/usb_device_handle_usbfs.h4
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.cc24
-rw-r--r--chromium/services/device/usb/usb_service.h2
-rw-r--r--chromium/services/device/usb/usb_service_linux.cc12
-rw-r--r--chromium/services/device/usb/usb_service_win.cc49
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/BUILD.gn1
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc28
-rw-r--r--chromium/services/image_annotation/annotator.cc5
-rw-r--r--chromium/services/image_annotation/annotator.h1
-rw-r--r--chromium/services/image_annotation/annotator_unittest.cc101
-rw-r--r--chromium/services/metrics/public/cpp/ukm_source.cc29
-rw-r--r--chromium/services/metrics/public/cpp/ukm_source.h1
-rw-r--r--chromium/services/metrics/public/cpp/ukm_source_id_unittest.cc6
-rw-r--r--chromium/services/network/BUILD.gn7
-rw-r--r--chromium/services/network/README.md79
-rw-r--r--chromium/services/network/cert_verifier_with_trust_anchors.cc28
-rw-r--r--chromium/services/network/cert_verifier_with_trust_anchors.h7
-rw-r--r--chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc12
-rw-r--r--chromium/services/network/chunked_data_pipe_upload_data_stream.cc4
-rw-r--r--chromium/services/network/chunked_data_pipe_upload_data_stream.h2
-rw-r--r--chromium/services/network/cookie_manager_unittest.cc66
-rw-r--r--chromium/services/network/cookie_settings.cc13
-rw-r--r--chromium/services/network/cookie_settings_unittest.cc31
-rw-r--r--chromium/services/network/cors/cors_url_loader.cc33
-rw-r--r--chromium/services/network/cors/cors_url_loader.h5
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.cc77
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.h2
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory_unittest.cc5
-rw-r--r--chromium/services/network/cors/cors_url_loader_unittest.cc110
-rw-r--r--chromium/services/network/cors/preflight_controller.cc31
-rw-r--r--chromium/services/network/cors/preflight_controller.h4
-rw-r--r--chromium/services/network/cors/preflight_controller_unittest.cc103
-rw-r--r--chromium/services/network/crl_set_distributor.cc11
-rw-r--r--chromium/services/network/expect_ct_reporter.cc25
-rw-r--r--chromium/services/network/expect_ct_reporter.h27
-rw-r--r--chromium/services/network/expect_ct_reporter_unittest.cc126
-rw-r--r--chromium/services/network/http_cache_data_counter_unittest.cc5
-rw-r--r--chromium/services/network/http_cache_data_remover_unittest.cc5
-rw-r--r--chromium/services/network/ignore_errors_cert_verifier.cc44
-rw-r--r--chromium/services/network/ignore_errors_cert_verifier.h26
-rw-r--r--chromium/services/network/ignore_errors_cert_verifier_unittest.cc23
-rw-r--r--chromium/services/network/legacy_tls_config_distributor.h1
-rw-r--r--chromium/services/network/net_log_exporter.cc4
-rw-r--r--chromium/services/network/network_context.cc145
-rw-r--r--chromium/services/network/network_context.h33
-rw-r--r--chromium/services/network/network_context_unittest.cc328
-rw-r--r--chromium/services/network/network_service.cc116
-rw-r--r--chromium/services/network/network_service.h51
-rw-r--r--chromium/services/network/network_service_network_delegate.cc5
-rw-r--r--chromium/services/network/network_service_network_delegate.h1
-rw-r--r--chromium/services/network/network_service_unittest.cc334
-rw-r--r--chromium/services/network/origin_policy/origin_policy_manager_unittest.cc5
-rw-r--r--chromium/services/network/p2p/socket.h5
-rw-r--r--chromium/services/network/p2p/socket_manager.cc15
-rw-r--r--chromium/services/network/p2p/socket_manager.h3
-rw-r--r--chromium/services/network/p2p/socket_tcp.cc13
-rw-r--r--chromium/services/network/p2p/socket_tcp.h3
-rw-r--r--chromium/services/network/p2p/socket_tcp_server.cc10
-rw-r--r--chromium/services/network/p2p/socket_tcp_server.h3
-rw-r--r--chromium/services/network/p2p/socket_tcp_server_unittest.cc4
-rw-r--r--chromium/services/network/p2p/socket_tcp_unittest.cc101
-rw-r--r--chromium/services/network/p2p/socket_udp.cc3
-rw-r--r--chromium/services/network/p2p/socket_udp.h3
-rw-r--r--chromium/services/network/p2p/socket_udp_unittest.cc16
-rw-r--r--chromium/services/network/proxy_resolving_client_socket.cc8
-rw-r--r--chromium/services/network/proxy_resolving_client_socket.h4
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_factory.cc4
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_factory.h20
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_unittest.cc241
-rw-r--r--chromium/services/network/proxy_resolving_socket_factory_mojo.cc5
-rw-r--r--chromium/services/network/proxy_resolving_socket_factory_mojo.h2
-rw-r--r--chromium/services/network/proxy_resolving_socket_mojo_unittest.cc5
-rw-r--r--chromium/services/network/public/cpp/BUILD.gn23
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc8
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h4
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc9
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc46
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.h21
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc61
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc42
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc7
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc85
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.h55
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc38
-rw-r--r--chromium/services/network/public/cpp/cors/cors.cc1
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_cache.cc8
-rw-r--r--chromium/services/network/public/cpp/crash_keys.cc31
-rw-r--r--chromium/services/network/public/cpp/crash_keys.h23
-rw-r--r--chromium/services/network/public/cpp/data_element.cc2
-rw-r--r--chromium/services/network/public/cpp/data_element.h2
-rw-r--r--chromium/services/network/public/cpp/empty_url_loader_client.cc (renamed from chromium/services/network/empty_url_loader_client.cc)41
-rw-r--r--chromium/services/network/public/cpp/empty_url_loader_client.h (renamed from chromium/services/network/empty_url_loader_client.h)61
-rw-r--r--chromium/services/network/public/cpp/features.cc43
-rw-r--r--chromium/services/network/public/cpp/features.h16
-rw-r--r--chromium/services/network/public/cpp/host_resolver_mojom_traits.cc2
-rw-r--r--chromium/services/network/public/cpp/http_request_headers_mojom_traits.cc9
-rw-r--r--chromium/services/network/public/cpp/isolation_info_mojom_traits.cc17
-rw-r--r--chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc6
-rw-r--r--chromium/services/network/public/cpp/load_timing_info_mojom_traits.h15
-rw-r--r--chromium/services/network/public/cpp/net_ipc_param_traits.cc4
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.h6
-rw-r--r--chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc3
-rw-r--r--chromium/services/network/public/cpp/origin_isolation_parser.cc15
-rw-r--r--chromium/services/network/public/cpp/origin_isolation_parser.h23
-rw-r--r--chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc31
-rw-r--r--chromium/services/network/public/cpp/parsed_headers.cc11
-rw-r--r--chromium/services/network/public/cpp/quic_transport_error_mojom_traits.cc30
-rw-r--r--chromium/services/network/public/cpp/quic_transport_error_mojom_traits.h36
-rw-r--r--chromium/services/network/public/cpp/resource_request.cc1
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.h8
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_unittest.cc7
-rw-r--r--chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc15
-rw-r--r--chromium/services/network/public/cpp/spki_hash_set.cc30
-rw-r--r--chromium/services/network/public/cpp/spki_hash_set.h28
-rw-r--r--chromium/services/network/public/cpp/trust_token_operation_authorization.h41
-rw-r--r--chromium/services/network/public/cpp/trust_token_parameterization.h29
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.cc50
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.h5
-rw-r--r--chromium/services/network/public/mojom/BUILD.gn47
-rw-r--r--chromium/services/network/public/mojom/cert_verifier_service.mojom19
-rw-r--r--chromium/services/network/public/mojom/content_security_policy.mojom10
-rw-r--r--chromium/services/network/public/mojom/cookie_manager.mojom25
-rw-r--r--chromium/services/network/public/mojom/cross_origin_opener_policy.mojom23
-rw-r--r--chromium/services/network/public/mojom/fetch_api.mojom12
-rw-r--r--chromium/services/network/public/mojom/load_timing_info.mojom11
-rw-r--r--chromium/services/network/public/mojom/network_context.mojom102
-rw-r--r--chromium/services/network/public/mojom/network_service.mojom15
-rw-r--r--chromium/services/network/public/mojom/parsed_headers.mojom3
-rw-r--r--chromium/services/network/public/mojom/proxy_resolving_socket.mojom21
-rw-r--r--chromium/services/network/public/mojom/quic_transport.mojom11
-rw-r--r--chromium/services/network/public/mojom/referrer_policy.mojom5
-rw-r--r--chromium/services/network/public/mojom/restricted_cookie_manager.mojom9
-rw-r--r--chromium/services/network/public/mojom/ssl_config.mojom2
-rw-r--r--chromium/services/network/public/mojom/trust_tokens.mojom15
-rw-r--r--chromium/services/network/public/mojom/url_loader.mojom15
-rw-r--r--chromium/services/network/public/mojom/url_loader_factory.mojom13
-rw-r--r--chromium/services/network/public/mojom/url_response_head.mojom32
-rw-r--r--chromium/services/network/public/mojom/websocket.mojom19
-rw-r--r--chromium/services/network/quic_transport.cc54
-rw-r--r--chromium/services/network/quic_transport.h16
-rw-r--r--chromium/services/network/quic_transport_unittest.cc156
-rw-r--r--chromium/services/network/restricted_cookie_manager.cc78
-rw-r--r--chromium/services/network/restricted_cookie_manager.h18
-rw-r--r--chromium/services/network/restricted_cookie_manager_unittest.cc334
-rw-r--r--chromium/services/network/ssl_config_service_mojo_unittest.cc74
-rw-r--r--chromium/services/network/tls_client_socket_unittest.cc3
-rw-r--r--chromium/services/network/trust_tokens/BUILD.gn1
-rw-r--r--chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc1
-rw-r--r--chromium/services/network/trust_tokens/signed_redemption_record_serialization.h1
-rw-r--r--chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc6
-rw-r--r--chromium/services/network/trust_tokens/sqlite_trust_token_persister.h3
-rw-r--r--chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc31
-rw-r--r--chromium/services/network/trust_tokens/trust_token_http_headers.cc3
-rw-r--r--chromium/services/network/trust_tokens/trust_token_http_headers.h5
-rw-r--r--chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_parameterization.h13
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc7
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc16
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc1
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc1
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc55
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper.h18
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc118
-rw-r--r--chromium/services/network/trust_tokens/trust_token_store.cc1
-rw-r--r--chromium/services/network/trust_tokens/trust_token_store_unittest.cc1
-rw-r--r--chromium/services/network/trust_tokens/types.cc12
-rw-r--r--chromium/services/network/url_loader.cc103
-rw-r--r--chromium/services/network/url_loader.h15
-rw-r--r--chromium/services/network/url_loader.md7
-rw-r--r--chromium/services/network/url_loader_factory.cc5
-rw-r--r--chromium/services/network/url_loader_unittest.cc523
-rw-r--r--chromium/services/network/websocket.cc152
-rw-r--r--chromium/services/network/websocket.h44
-rw-r--r--chromium/services/network/websocket_factory.cc1
-rw-r--r--chromium/services/preferences/tracked/pref_hash_filter_unittest.cc2
-rw-r--r--chromium/services/preferences/tracked/registry_hash_store_contents_win.cc1
-rw-r--r--chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h2
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/graph.h6
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/graph_processor.h6
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h31
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc7
-rw-r--r--chromium/services/service_manager/embedder/main.cc3
-rw-r--r--chromium/services/service_manager/embedder/main_delegate.cc3
-rw-r--r--chromium/services/service_manager/embedder/main_delegate.h5
-rw-r--r--chromium/services/service_manager/embedder/switches.cc3
-rw-r--r--chromium/services/service_manager/embedder/switches.h3
-rw-r--r--chromium/services/service_manager/public/cpp/binder_registry.h14
-rw-r--r--chromium/services/service_manager/public/cpp/connector.h13
-rw-r--r--chromium/services/service_manager/public/cpp/interface_binder.h27
-rw-r--r--chromium/services/service_manager/public/cpp/interface_provider.h35
-rw-r--r--chromium/services/service_manager/public/cpp/local_interface_provider.h15
-rw-r--r--chromium/services/service_manager/sandbox/BUILD.gn2
-rw-r--r--chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc4
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.cc34
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.h27
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_linux.h2
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc4
-rw-r--r--chromium/services/service_manager/sandbox/sandbox_type.cc13
-rw-r--r--chromium/services/service_manager/sandbox/sandbox_type.h5
-rw-r--r--chromium/services/service_manager/sandbox/switches.cc3
-rw-r--r--chromium/services/service_manager/sandbox/switches.h2
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h1
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_win.cc95
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_win.h3
-rw-r--r--chromium/services/service_manager/service_instance.h1
-rw-r--r--chromium/services/service_manager/service_manager.cc5
-rw-r--r--chromium/services/service_manager/service_process_launcher.cc16
-rw-r--r--chromium/services/service_manager/service_process_launcher.h9
-rw-r--r--chromium/services/service_manager/zygote/BUILD.gn82
-rw-r--r--chromium/services/service_manager/zygote/DEPS3
-rw-r--r--chromium/services/service_manager/zygote/OWNERS7
-rw-r--r--chromium/services/service_manager/zygote/common/common_sandbox_support_linux.cc38
-rw-r--r--chromium/services/service_manager/zygote/common/common_sandbox_support_linux.h42
-rw-r--r--chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.cc20
-rw-r--r--chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.h18
-rw-r--r--chromium/services/service_manager/zygote/common/zygote_commands_linux.h54
-rw-r--r--chromium/services/service_manager/zygote/common/zygote_features.gni5
-rw-r--r--chromium/services/service_manager/zygote/common/zygote_fork_delegate_linux.h90
-rw-r--r--chromium/services/service_manager/zygote/common/zygote_handle.h49
-rw-r--r--chromium/services/service_manager/zygote/host/zygote_communication_linux.cc321
-rw-r--r--chromium/services/service_manager/zygote/host/zygote_communication_linux.h107
-rw-r--r--chromium/services/service_manager/zygote/host/zygote_handle_linux.cc44
-rw-r--r--chromium/services/service_manager/zygote/host/zygote_host_impl_linux.cc292
-rw-r--r--chromium/services/service_manager/zygote/host/zygote_host_impl_linux.h75
-rw-r--r--chromium/services/service_manager/zygote/zygote_host_linux.h42
-rw-r--r--chromium/services/service_manager/zygote/zygote_linux.cc659
-rw-r--r--chromium/services/service_manager/zygote/zygote_linux.h152
-rw-r--r--chromium/services/service_manager/zygote/zygote_main.h25
-rw-r--r--chromium/services/service_manager/zygote/zygote_main_linux.cc245
-rw-r--r--chromium/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java2
-rw-r--r--chromium/services/shape_detection/barcode_detection_impl_mac_vision_api.h1
-rw-r--r--chromium/services/shape_detection/detection_utils_win.cc1
-rw-r--r--chromium/services/tracing/BUILD.gn3
-rw-r--r--chromium/services/tracing/DEPS5
-rw-r--r--chromium/services/tracing/perfetto/consumer_host.cc10
-rw-r--r--chromium/services/tracing/perfetto/perfetto_service.h1
-rw-r--r--chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h25
-rw-r--r--chromium/services/tracing/perfetto/system_perfetto_unittest.cc79
-rw-r--r--chromium/services/tracing/public/cpp/BUILD.gn25
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/macros.h73
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/macros_internal.cc61
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/macros_internal.h213
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc149
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_config.h13
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/posix_system_producer.cc8
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.cc46
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.h14
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc161
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h94
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h2
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc61
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h36
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc204
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_time.h12
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc75
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h82
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.cc71
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h42
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc104
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc4
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc189
-rw-r--r--chromium/services/tracing/public/cpp/trace_event_agent.cc13
-rw-r--r--chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc (renamed from chromium/services/tracing/public/cpp/trace_event_args_whitelist.cc)49
-rw-r--r--chromium/services/tracing/public/cpp/trace_event_args_allowlist.h (renamed from chromium/services/tracing/public/cpp/trace_event_args_whitelist.h)14
-rw-r--r--chromium/services/tracing/public/cpp/trace_startup.cc2
-rw-r--r--chromium/services/tracing/public/mojom/perfetto_service.mojom2
-rw-r--r--chromium/services/video_capture/broadcasting_receiver_unittest.cc4
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom3
-rw-r--r--chromium/services/viz/privileged/mojom/gl/BUILD.gn6
-rw-r--r--chromium/services/viz/privileged/mojom/gl/gpu_host.mojom5
-rw-r--r--chromium/services/viz/privileged/mojom/gl/gpu_service.mojom2
-rw-r--r--chromium/services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom18
-rw-r--r--chromium/services/viz/public/cpp/BUILD.gn15
-rw-r--r--chromium/services/viz/public/cpp/DEPS3
-rw-r--r--chromium/services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.cc6
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc35
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h6
-rw-r--r--chromium/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc31
-rw-r--r--chromium/services/viz/public/cpp/compositing/copy_output_request_mojom_traits.cc60
-rw-r--r--chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc33
-rw-r--r--chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h58
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc20
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h5
-rw-r--r--chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc13
-rw-r--r--chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.h3
-rw-r--r--chromium/services/viz/public/cpp/crash_keys.cc16
-rw-r--r--chromium/services/viz/public/cpp/crash_keys.h18
-rw-r--r--chromium/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc26
-rw-r--r--chromium/services/viz/public/mojom/BUILD.gn60
-rw-r--r--chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom16
-rw-r--r--chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom18
372 files changed, 8201 insertions, 5747 deletions
diff --git a/chromium/services/BUILD.gn b/chromium/services/BUILD.gn
index c64868ed935..cab26e2e9fe 100644
--- a/chromium/services/BUILD.gn
+++ b/chromium/services/BUILD.gn
@@ -105,11 +105,13 @@ if (is_android) {
deps = [
"$google_play_services_package:google_play_services_base_java",
"$google_play_services_package:google_play_services_basement_java",
+ "$google_play_services_package:google_play_services_location_java",
"$google_play_services_package:google_play_services_vision_common_java",
"$google_play_services_package:google_play_services_vision_java",
"//base:base_java",
"//base:base_java_test_support",
"//base:base_junit_test_support",
+ "//mojo/public/java:base_java",
"//mojo/public/java:bindings_java",
"//mojo/public/java:system_java",
"//services/device/generic_sensor:java",
diff --git a/chromium/services/audio/BUILD.gn b/chromium/services/audio/BUILD.gn
index a2e3952a651..dd4911729ab 100644
--- a/chromium/services/audio/BUILD.gn
+++ b/chromium/services/audio/BUILD.gn
@@ -157,7 +157,6 @@ source_set("tests") {
":audio",
"//base/test:test_support",
"//media:test_support",
- "//mojo/core/embedder",
"//services/audio/public/cpp",
"//services/audio/public/cpp:test_support",
"//services/audio/public/mojom",
diff --git a/chromium/services/audio/audio_sandbox_hook_linux.cc b/chromium/services/audio/audio_sandbox_hook_linux.cc
index 8220b54f7a8..dad4537c4c6 100644
--- a/chromium/services/audio/audio_sandbox_hook_linux.cc
+++ b/chromium/services/audio/audio_sandbox_hook_linux.cc
@@ -12,6 +12,7 @@
#include "base/environment.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/stringprintf.h"
diff --git a/chromium/services/audio/group_coordinator.h b/chromium/services/audio/group_coordinator.h
index 3f8ce11ba2b..a47f5019979 100644
--- a/chromium/services/audio/group_coordinator.h
+++ b/chromium/services/audio/group_coordinator.h
@@ -10,7 +10,7 @@
#include <vector>
#include "base/callback.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/macros.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
diff --git a/chromium/services/audio/input_stream_unittest.cc b/chromium/services/audio/input_stream_unittest.cc
index 8662875f5e8..6f080d8c359 100644
--- a/chromium/services/audio/input_stream_unittest.cc
+++ b/chromium/services/audio/input_stream_unittest.cc
@@ -9,16 +9,17 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/memory/read_only_shared_memory_region.h"
#include "base/test/task_environment.h"
#include "media/audio/audio_io.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_thread.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/functions.h"
#include "services/audio/stream_factory.h"
#include "services/audio/test/mock_log.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -128,14 +129,13 @@ class AudioServiceInputStreamTest : public testing::Test {
~AudioServiceInputStreamTest() override { audio_manager_.Shutdown(); }
void SetUp() override {
- mojo::core::SetDefaultProcessErrorCallback(
+ mojo::SetDefaultProcessErrorHandler(
base::BindRepeating(&AudioServiceInputStreamTest::BadMessageCallback,
base::Unretained(this)));
}
void TearDown() override {
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
mojo::PendingRemote<media::mojom::AudioInputStream> CreateStream(
diff --git a/chromium/services/audio/input_sync_writer.cc b/chromium/services/audio/input_sync_writer.cc
index 250c1802f63..8d122b77462 100644
--- a/chromium/services/audio/input_sync_writer.cc
+++ b/chromium/services/audio/input_sync_writer.cc
@@ -8,6 +8,7 @@
#include <utility>
#include "base/format_macros.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
diff --git a/chromium/services/audio/input_sync_writer.h b/chromium/services/audio/input_sync_writer.h
index 1345702c3f4..b5e88e0882a 100644
--- a/chromium/services/audio/input_sync_writer.h
+++ b/chromium/services/audio/input_sync_writer.h
@@ -12,7 +12,6 @@
#include <string>
#include <vector>
-#include "base/containers/circular_deque.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/read_only_shared_memory_region.h"
diff --git a/chromium/services/audio/output_controller.cc b/chromium/services/audio/output_controller.cc
index c154a0ebb97..3a84f463900 100644
--- a/chromium/services/audio/output_controller.cc
+++ b/chromium/services/audio/output_controller.cc
@@ -14,6 +14,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/compiler_specific.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/stl_util.h"
@@ -150,7 +151,7 @@ OutputController::OutputController(media::AudioManager* audio_manager,
task_runner_(audio_manager->GetTaskRunner()),
construction_time_(base::TimeTicks::Now()),
output_device_id_(output_device_id),
- stream_(NULL),
+ stream_(nullptr),
disable_local_output_(false),
volume_(1.0),
state_(kEmpty),
@@ -183,7 +184,6 @@ bool OutputController::CreateStream() {
void OutputController::RecreateStreamWithTimingUMA(
OutputController::RecreateReason reason) {
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CreateTime");
RecreateStream(reason);
}
@@ -300,7 +300,6 @@ void OutputController::RecreateStream(OutputController::RecreateReason reason) {
void OutputController::Play() {
DCHECK(task_runner_->BelongsToCurrentThread());
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PlayTime");
TRACE_EVENT0("audio", "OutputController::Play");
SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
@@ -347,7 +346,6 @@ void OutputController::StopStream() {
void OutputController::Pause() {
DCHECK(task_runner_->BelongsToCurrentThread());
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.PauseTime");
TRACE_EVENT0("audio", "OutputController::Pause");
SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
@@ -384,7 +382,6 @@ void OutputController::Flush() {
void OutputController::Close() {
DCHECK(task_runner_->BelongsToCurrentThread());
TRACE_EVENT0("audio", "OutputController::Close");
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.CloseTime");
SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
if (state_ != kClosed) {
@@ -530,7 +527,7 @@ void OutputController::StopCloseAndClearStream() {
stream_->Close();
stats_tracker_.reset();
- stream_ = NULL;
+ stream_ = nullptr;
}
state_ = kEmpty;
@@ -612,7 +609,6 @@ void OutputController::OnDeviceChange() {
if (disable_local_output_)
return; // No actions need to be taken while local output is disabled.
- SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioOutputController.DeviceChangeTime");
SendLogMessage("%s([state=%s])", __func__, StateToString(state_));
// TODO(dalecurtis): Notify the renderer side that a device change has
diff --git a/chromium/services/audio/output_stream_unittest.cc b/chromium/services/audio/output_stream_unittest.cc
index 4385a693e0d..912fbddf9e5 100644
--- a/chromium/services/audio/output_stream_unittest.cc
+++ b/chromium/services/audio/output_stream_unittest.cc
@@ -7,15 +7,16 @@
#include <utility>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/test/mock_callback.h"
#include "base/test/task_environment.h"
#include "base/unguessable_token.h"
#include "media/audio/audio_io.h"
#include "media/audio/mock_audio_manager.h"
#include "media/audio/test_audio_thread.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
#include "mojo/public/cpp/bindings/receiver.h"
+#include "mojo/public/cpp/system/functions.h"
#include "services/audio/stream_factory.h"
#include "services/audio/test/mock_log.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -122,13 +123,12 @@ class TestEnvironment {
stream_factory_receiver_(
&stream_factory_,
remote_stream_factory_.BindNewPipeAndPassReceiver()) {
- mojo::core::SetDefaultProcessErrorCallback(bad_message_callback_.Get());
+ mojo::SetDefaultProcessErrorHandler(bad_message_callback_.Get());
}
~TestEnvironment() {
audio_manager_.Shutdown();
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
using MockDeleteCallback = base::MockCallback<OutputStream::DeleteCallback>;
diff --git a/chromium/services/audio/public/cpp/device_factory.cc b/chromium/services/audio/public/cpp/device_factory.cc
index 3ecbe054180..0271211f693 100644
--- a/chromium/services/audio/public/cpp/device_factory.cc
+++ b/chromium/services/audio/public/cpp/device_factory.cc
@@ -16,18 +16,21 @@ namespace audio {
scoped_refptr<media::AudioCapturerSource> CreateInputDevice(
mojo::PendingRemote<mojom::StreamFactory> stream_factory,
const std::string& device_id,
+ DeadStreamDetection detect_dead_stream,
mojo::PendingRemote<media::mojom::AudioLog> log) {
std::unique_ptr<media::AudioInputIPC> ipc = std::make_unique<InputIPC>(
std::move(stream_factory), device_id, std::move(log));
return base::MakeRefCounted<media::AudioInputDevice>(
- std::move(ipc), media::AudioInputDevice::Purpose::kUserInput);
+ std::move(ipc), media::AudioInputDevice::Purpose::kUserInput,
+ detect_dead_stream);
}
scoped_refptr<media::AudioCapturerSource> CreateInputDevice(
mojo::PendingRemote<mojom::StreamFactory> stream_factory,
- const std::string& device_id) {
+ const std::string& device_id,
+ DeadStreamDetection detect_dead_stream) {
return CreateInputDevice(std::move(stream_factory), device_id,
- mojo::NullRemote());
+ detect_dead_stream, mojo::NullRemote());
}
} // namespace audio
diff --git a/chromium/services/audio/public/cpp/device_factory.h b/chromium/services/audio/public/cpp/device_factory.h
index a079a470fbc..843fbc5e85e 100644
--- a/chromium/services/audio/public/cpp/device_factory.h
+++ b/chromium/services/audio/public/cpp/device_factory.h
@@ -14,13 +14,17 @@
namespace audio {
+using DeadStreamDetection = media::AudioInputDevice::DeadStreamDetection;
+
scoped_refptr<media::AudioCapturerSource> CreateInputDevice(
mojo::PendingRemote<mojom::StreamFactory> stream_factory,
- const std::string& device_id);
+ const std::string& device_id,
+ DeadStreamDetection detect_dead_stream);
scoped_refptr<media::AudioCapturerSource> CreateInputDevice(
mojo::PendingRemote<mojom::StreamFactory> stream_factory,
const std::string& device_id,
+ DeadStreamDetection detect_dead_stream,
mojo::PendingRemote<media::mojom::AudioLog>);
} // namespace audio
diff --git a/chromium/services/audio/snooper_node_unittest.cc b/chromium/services/audio/snooper_node_unittest.cc
index 07f5f0164ed..63ac9c0aba9 100644
--- a/chromium/services/audio/snooper_node_unittest.cc
+++ b/chromium/services/audio/snooper_node_unittest.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
+#include "base/logging.h"
#include "base/memory/scoped_refptr.h"
#include "base/optional.h"
#include "base/strings/string_piece.h"
diff --git a/chromium/services/audio/sync_reader.cc b/chromium/services/audio/sync_reader.cc
index 17889fb4b83..fbd4b1dc4ab 100644
--- a/chromium/services/audio/sync_reader.cc
+++ b/chromium/services/audio/sync_reader.cc
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/format_macros.h"
+#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/stringprintf.h"
diff --git a/chromium/services/cert_verifier/BUILD.gn b/chromium/services/cert_verifier/BUILD.gn
index c3a2a899cd6..65d56915897 100644
--- a/chromium/services/cert_verifier/BUILD.gn
+++ b/chromium/services/cert_verifier/BUILD.gn
@@ -29,6 +29,9 @@ source_set("tests") {
sources = [
"cert_verifier_service_factory_unittest.cc",
"cert_verifier_service_unittest.cc",
+ "integration_tests/network_context_unittest.cc",
+ "integration_tests/network_service_unittest.cc",
+ "integration_tests/ssl_config_service_mojo_unittest.cc",
]
deps = [
@@ -37,8 +40,11 @@ source_set("tests") {
"//base/test:test_support",
"//net",
"//net:test_support",
+ "//services/cert_verifier/cert_net_url_loader:cert_net_url_loader",
"//services/cert_verifier/public/mojom",
+ "//services/network:network_service",
"//services/network:test_support",
+ "//services/network/public/cpp/cert_verifier:mojo_cert_verifier",
"//services/network/public/mojom",
"//testing/gtest",
]
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.cc b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.cc
index 7e198036355..70ef0ff8a2c 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.cc
+++ b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.cc
@@ -17,7 +17,8 @@ CertNetFetcherTestUtil::CertNetFetcherTestUtil() {
pending_receiver_ =
pending_remote_url_loader_factory.InitWithNewPipeAndPassReceiver();
- fetcher_ = base::MakeRefCounted<CertNetFetcherURLLoader>(
+ fetcher_ = base::MakeRefCounted<CertNetFetcherURLLoader>();
+ fetcher_->SetURLLoaderFactoryAndReconnector(
std::move(pending_remote_url_loader_factory),
base::BindRepeating(
&CertNetFetcherTestUtil::RebindURLLoaderFactoryTrampoline,
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
index 10af79f7d33..91e3c981d96 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
+++ b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.cc
@@ -75,6 +75,7 @@
#include "base/synchronization/waitable_event.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/timer/timer.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/load_flags.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/http/http_request_headers.h"
@@ -142,6 +143,10 @@ class CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader {
// requests have completed or Shutdown() is called.
~AsyncCertNetFetcherURLLoader();
+ // Disconnects |factory_|, and calls FlushForTesting() in order to
+ // synchronously disconnect.
+ void DisconnectURLLoaderFactoryForTesting();
+
// Starts an asynchronous request to fetch the given URL. On completion
// request->OnJobCompleted() will be invoked.
void Fetch(std::unique_ptr<RequestParams> request_params,
@@ -156,8 +161,8 @@ class CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader {
void Shutdown();
private:
- // Callback for disconnection of |factory_|. Attempts to use
- // |bind_new_url_loader_factory_cb_| to reconnect.
+ // Attempts to use |bind_new_url_loader_factory_cb_| to reconnect |factory_|.
+ // There's no guarantee that |bind_new_url_loader_factory_cb_| will succeed.
void RebindURLLoaderFactory();
// Finds a job with a matching RequestPararms or returns nullptr if there was
@@ -592,15 +597,7 @@ CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
BindNewURLLoaderFactoryCallback bind_new_url_loader_factory_cb)
: factory_(std::move(factory_pending_remote)),
bind_new_url_loader_factory_cb_(
- std::move(bind_new_url_loader_factory_cb)) {
- // If the URLLoaderFactory disconnects, try to rebind immediately in case this
- // was a deliberate disconnection to force a restart. Safe to use
- // base::Unretained(this) because |this| owns |factory_|.
- factory_.set_disconnect_handler(
- base::BindOnce(&CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
- RebindURLLoaderFactory,
- base::Unretained(this)));
-}
+ std::move(bind_new_url_loader_factory_cb)) {}
CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
~AsyncCertNetFetcherURLLoader() {
@@ -611,6 +608,16 @@ CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
DCHECK(jobs_.empty());
}
+void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
+ DisconnectURLLoaderFactoryForTesting() {
+ // Sadly, there's no good way to disconnect a Mojo remote other than resetting
+ // it, binding it to a new pipe, and dropping the PendingReceiver on the
+ // floor.
+ factory_.reset();
+ ignore_result(factory_.BindNewPipeAndPassReceiver());
+ factory_.FlushForTesting();
+}
+
bool JobComparator::operator()(const Job* job1, const Job* job2) const {
return job1->request_params() < job2->request_params();
}
@@ -628,6 +635,10 @@ void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::Fetch(
return;
}
+ if (!factory_.is_connected()) {
+ RebindURLLoaderFactory();
+ }
+
job = new Job(std::move(request_params), this);
jobs_[job] = base::WrapUnique(job);
// Attach the request before calling |StartURLLoader()|; this ensures that the
@@ -655,12 +666,12 @@ void CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
// trying to reconnect a URLLoaderFactory.
DCHECK(factory_);
+ if (!bind_new_url_loader_factory_cb_) {
+ return;
+ }
+
factory_.reset();
bind_new_url_loader_factory_cb_.Run(factory_.BindNewPipeAndPassReceiver());
- factory_.set_disconnect_handler(
- base::BindOnce(&CertNetFetcherURLLoader::AsyncCertNetFetcherURLLoader::
- RebindURLLoaderFactory,
- base::Unretained(this)));
}
namespace {
@@ -726,21 +737,30 @@ class CertNetFetcherRequestImpl : public net::CertNetFetcher::Request {
} // namespace
-CertNetFetcherURLLoader::CertNetFetcherURLLoader(
- mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
- BindNewURLLoaderFactoryCallback bind_new_url_loader_factory_cb)
- : task_runner_(base::SequencedTaskRunnerHandle::Get()),
- impl_(std::make_unique<AsyncCertNetFetcherURLLoader>(
- std::move(factory),
- std::move(bind_new_url_loader_factory_cb))) {}
+CertNetFetcherURLLoader::CertNetFetcherURLLoader()
+ : task_runner_(base::SequencedTaskRunnerHandle::Get()) {}
CertNetFetcherURLLoader::~CertNetFetcherURLLoader() = default;
+void CertNetFetcherURLLoader::SetURLLoaderFactoryAndReconnector(
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
+ base::RepeatingCallback<
+ void(mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
+ bind_new_url_loader_factory_cb) {
+ DCHECK(!impl_);
+ impl_ = std::make_unique<AsyncCertNetFetcherURLLoader>(
+ std::move(factory), std::move(bind_new_url_loader_factory_cb));
+}
+
// static
base::TimeDelta CertNetFetcherURLLoader::GetDefaultTimeoutForTesting() {
return GetTimeout(CertNetFetcher::DEFAULT);
}
+void CertNetFetcherURLLoader::DisconnectURLLoaderFactoryForTesting() {
+ impl_->DisconnectURLLoaderFactoryForTesting();
+}
+
void CertNetFetcherURLLoader::Shutdown() {
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (impl_) {
@@ -800,9 +820,10 @@ void CertNetFetcherURLLoader::DoFetchOnTaskRunner(
DCHECK(task_runner_->RunsTasksInCurrentSequence());
if (!impl_) {
- // The fetcher might have been shutdown (which resets |impl_|) between when
- // this task was posted and when it is running. In this case, signal the
- // request and do not start a network request.
+ // |SetURLLoaderFactoryAndReconnector| may not have been called yet, or the
+ // fetcher might have been shutdown between when this task was posted and
+ // when it is running. In this case, signal the request and do not start a
+ // network request.
request->SignalImmediateError();
return;
}
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h
index f273a527adc..ae99c772aec 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h
+++ b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h
@@ -30,10 +30,17 @@ class COMPONENT_EXPORT(CERT_VERIFIER_CPP) CertNetFetcherURLLoader
class RequestCore;
struct RequestParams;
- // Creates the CertNetFetcherURLLoader, using the provided URLLoaderFactory.
- // If the other side of the remote disconnects, the CertNetFetcherURLLoader
- // will attempt that reconnect using |bind_new_url_loader_factory_cb|.
- explicit CertNetFetcherURLLoader(
+ // The CertNetFetcherURLLoader will immediately fail all requests until
+ // SetURLLoaderFactoryAndReconnector() is called.
+ CertNetFetcherURLLoader();
+
+ // Enables this CertNetFetcher to load URLs using |factory|.
+ // If the other side of the |factory| remote disconnects, the
+ // CertNetFetcherURLLoader will attempt to reconnect using
+ // |bind_new_url_loader_factory_cb|. This must be called before ever
+ // performing a fetch. It is recommended, but not required, to provide a
+ // functional |bind_new_url_loader_factory_cb|.
+ void SetURLLoaderFactoryAndReconnector(
mojo::PendingRemote<network::mojom::URLLoaderFactory> factory,
base::RepeatingCallback<
void(mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
@@ -42,6 +49,9 @@ class COMPONENT_EXPORT(CERT_VERIFIER_CPP) CertNetFetcherURLLoader
// Returns the default timeout value. Intended for test use only.
static base::TimeDelta GetDefaultTimeoutForTesting();
+ // Disconnects the URLLoaderFactory used for fetches.
+ void DisconnectURLLoaderFactoryForTesting();
+
// CertNetFetcher impl:
void Shutdown() override;
std::unique_ptr<Request> FetchCaIssuers(const GURL& url,
diff --git a/chromium/services/cert_verifier/cert_verifier_service.cc b/chromium/services/cert_verifier/cert_verifier_service.cc
index 344805da6f4..8d1f932c136 100644
--- a/chromium/services/cert_verifier/cert_verifier_service.cc
+++ b/chromium/services/cert_verifier/cert_verifier_service.cc
@@ -4,9 +4,12 @@
#include "services/cert_verifier/cert_verifier_service.h"
+#include "base/bind.h"
#include "base/logging.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
+#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
namespace cert_verifier {
namespace internal {
@@ -65,12 +68,18 @@ class CertVerifyResultHelper {
std::unique_ptr<net::CertVerifier::Request> local_request_;
};
+void ReconnectURLLoaderFactory(
+ mojo::Remote<mojom::URLLoaderFactoryConnector>* reconnector,
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
+ (*reconnector)->CreateURLLoaderFactory(std::move(receiver));
+}
+
} // namespace
CertVerifierServiceImpl::CertVerifierServiceImpl(
std::unique_ptr<net::CertVerifier> verifier,
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- scoped_refptr<net::CertNetFetcher> cert_net_fetcher)
+ scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher)
: verifier_(std::move(verifier)),
receiver_(this, std::move(receiver)),
cert_net_fetcher_(std::move(cert_net_fetcher)) {
@@ -95,6 +104,20 @@ void CertVerifierServiceImpl::SetConfig(
verifier_->SetConfig(config);
}
+void CertVerifierServiceImpl::EnableNetworkAccess(
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
+ mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector) {
+ if (cert_net_fetcher_) {
+ auto reconnect_cb =
+ std::make_unique<mojo::Remote<mojom::URLLoaderFactoryConnector>>(
+ std::move(reconnector));
+ cert_net_fetcher_->SetURLLoaderFactoryAndReconnector(
+ std::move(url_loader_factory),
+ base::BindRepeating(&ReconnectURLLoaderFactory,
+ base::Owned(std::move(reconnect_cb))));
+ }
+}
+
void CertVerifierServiceImpl::Verify(
const net::CertVerifier::RequestParams& params,
mojo::PendingRemote<mojom::CertVerifierRequest> cert_verifier_request) {
@@ -115,9 +138,11 @@ void CertVerifierServiceImpl::Verify(
base::BindOnce(&CertVerifyResultHelper::CompleteCertVerifierRequest,
std::move(result_helper));
- int net_err =
- verifier_->Verify(params, result.get(), std::move(callback),
- result_helper_ptr->local_request(), null_net_log_);
+ int net_err = verifier_->Verify(
+ params, result.get(), std::move(callback),
+ result_helper_ptr->local_request(),
+ net::NetLogWithSource::Make(net::NetLog::Get(),
+ net::NetLogSourceType::CERT_VERIFIER_JOB));
if (net_err == net::ERR_IO_PENDING) {
// If this request is to be completely asynchronously, give the callback
// ownership of our mojom::CertVerifierRequest and net::CertVerifyResult.
diff --git a/chromium/services/cert_verifier/cert_verifier_service.h b/chromium/services/cert_verifier/cert_verifier_service.h
index cfaeec51af2..c4492b8648d 100644
--- a/chromium/services/cert_verifier/cert_verifier_service.h
+++ b/chromium/services/cert_verifier/cert_verifier_service.h
@@ -13,7 +13,9 @@
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "net/cert/cert_net_fetcher.h"
#include "net/log/net_log_with_source.h"
+#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
// Defines an implementation of a Cert Verifier Service to be queried by network
// service or others.
@@ -26,13 +28,17 @@ class CertVerifierServiceImpl : public mojom::CertVerifierService {
explicit CertVerifierServiceImpl(
std::unique_ptr<net::CertVerifier> verifier,
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- scoped_refptr<net::CertNetFetcher> cert_net_fetcher);
+ scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher);
// mojom::CertVerifierService implementation:
void Verify(const net::CertVerifier::RequestParams& params,
mojo::PendingRemote<mojom::CertVerifierRequest>
cert_verifier_request) override;
void SetConfig(const net::CertVerifier::Config& config) override;
+ void EnableNetworkAccess(
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>,
+ mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector)
+ override;
private:
~CertVerifierServiceImpl() override;
@@ -41,11 +47,7 @@ class CertVerifierServiceImpl : public mojom::CertVerifierService {
std::unique_ptr<net::CertVerifier> verifier_;
mojo::Receiver<mojom::CertVerifierService> receiver_;
- scoped_refptr<net::CertNetFetcher> cert_net_fetcher_;
-
- // A null NetLog for |verifier_->Verify()|. Initialized with a non-capturing
- // NetLog.
- const net::NetLogWithSource null_net_log_;
+ scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_;
};
} // namespace internal
diff --git a/chromium/services/cert_verifier/cert_verifier_service_factory.cc b/chromium/services/cert_verifier/cert_verifier_service_factory.cc
index 33183453138..74abd3e07f0 100644
--- a/chromium/services/cert_verifier/cert_verifier_service_factory.cc
+++ b/chromium/services/cert_verifier/cert_verifier_service_factory.cc
@@ -20,58 +20,19 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
namespace cert_verifier {
-
namespace {
-void ReconnectCertNetFetcher(
- mojo::Remote<mojom::URLLoaderFactoryConnector>* connector,
- mojo::PendingReceiver<network::mojom::URLLoaderFactory>
- url_loader_factory) {
- (*connector)->CreateURLLoaderFactory(std::move(url_loader_factory));
-}
-} // namespace
-
-CertVerifierServiceFactoryImpl::CertVerifierServiceFactoryImpl(
- mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver)
- : receiver_(this, std::move(receiver)) {}
-
-CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
-
-// static
-scoped_refptr<CertNetFetcherURLLoader>
-CertVerifierServiceFactoryImpl::CreateCertNetFetcher(
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector) {
- auto connector =
- std::make_unique<mojo::Remote<mojom::URLLoaderFactoryConnector>>(
- std::move(cert_net_fetcher_url_loader_factory_connector));
- // The callback will own the CertNetFetcherReconnector, and the callback
- // will be owned by the CertNetFetcherURLLoader. Only the
- // CertNetFetcherURLLoader uses the CertNetFetcherReconnector.
- auto reconnector_cb = base::BindRepeating(&ReconnectCertNetFetcher,
- base::Owned(std::move(connector)));
- return base::MakeRefCounted<CertNetFetcherURLLoader>(
- std::move(url_loader_factory), std::move(reconnector_cb));
-}
-void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
+void GetNewCertVerifierImpl(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector,
- network::mojom::CertVerifierCreationParamsPtr creation_params) {
+ network::mojom::CertVerifierCreationParamsPtr creation_params,
+ scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher;
// Sometimes the cert_net_fetcher isn't used by CreateCertVerifier.
// But losing the last ref without calling Shutdown() will cause a CHECK
// failure, so keep a ref.
- if (network::IsUsingCertNetFetcher()) {
- DCHECK(url_loader_factory.is_valid());
- DCHECK(cert_net_fetcher_url_loader_factory_connector.is_valid());
- cert_net_fetcher = CreateCertNetFetcher(
- std::move(url_loader_factory),
- std::move(cert_net_fetcher_url_loader_factory_connector));
- }
+ if (network::IsUsingCertNetFetcher())
+ cert_net_fetcher = base::MakeRefCounted<CertNetFetcherURLLoader>();
// Create a new CertVerifier to back our service. This will be instantiated
// without the coalescing or caching layers, because those layers will work
@@ -87,10 +48,36 @@ void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
cert_net_fetcher.reset();
}
+ if (cert_net_fetcher_ptr)
+ *cert_net_fetcher_ptr = cert_net_fetcher;
+
// The service will delete itself upon disconnection.
new internal::CertVerifierServiceImpl(std::move(cert_verifier),
std::move(receiver),
std::move(cert_net_fetcher));
}
+} // namespace
+
+CertVerifierServiceFactoryImpl::CertVerifierServiceFactoryImpl(
+ mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver)
+ : receiver_(this, std::move(receiver)) {}
+
+CertVerifierServiceFactoryImpl::~CertVerifierServiceFactoryImpl() = default;
+
+void CertVerifierServiceFactoryImpl::GetNewCertVerifier(
+ mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+ network::mojom::CertVerifierCreationParamsPtr creation_params) {
+ GetNewCertVerifierImpl(std::move(receiver), std::move(creation_params),
+ nullptr);
+}
+
+void CertVerifierServiceFactoryImpl::GetNewCertVerifierForTesting(
+ mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+ network::mojom::CertVerifierCreationParamsPtr creation_params,
+ scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr) {
+ GetNewCertVerifierImpl(std::move(receiver), std::move(creation_params),
+ cert_net_fetcher_ptr);
+}
+
} // namespace cert_verifier
diff --git a/chromium/services/cert_verifier/cert_verifier_service_factory.h b/chromium/services/cert_verifier/cert_verifier_service_factory.h
index 373417afe3e..875862ea5ac 100644
--- a/chromium/services/cert_verifier/cert_verifier_service_factory.h
+++ b/chromium/services/cert_verifier/cert_verifier_service_factory.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/gtest_prod_util.h"
+#include "base/memory/scoped_refptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
@@ -28,23 +29,19 @@ class CertVerifierServiceFactoryImpl
mojo::PendingReceiver<mojom::CertVerifierServiceFactory> receiver);
~CertVerifierServiceFactoryImpl() override;
- // Creates a CertNetFetcherURLLoader using the given URLLoaderFactory, that
- // will try to reconnect its URLLoaderFactory using the
- // URLLoaderFactoryConnector in case the original URLLoaderFactory
- // disconnects.
- static scoped_refptr<CertNetFetcherURLLoader> CreateCertNetFetcher(
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector);
-
// mojom::CertVerifierServiceFactory implementation:
void GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) override;
+ // Performs the same function as above, but stores a ref to the new
+ // CertNetFetcherURLLoader in |*cert_net_fetcher_ptr|, if the
+ // CertNetFetcherURLLoader is in use.
+ void GetNewCertVerifierForTesting(
+ mojo::PendingReceiver<mojom::CertVerifierService> receiver,
+ network::mojom::CertVerifierCreationParamsPtr creation_params,
+ scoped_refptr<CertNetFetcherURLLoader>* cert_net_fetcher_ptr);
+
private:
mojo::Receiver<mojom::CertVerifierServiceFactory> receiver_;
};
diff --git a/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc b/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc
index 9d44bfdb3bf..b19e5372239 100644
--- a/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc
+++ b/chromium/services/cert_verifier/cert_verifier_service_factory_unittest.cc
@@ -13,113 +13,25 @@
#include "base/check_op.h"
#include "base/memory/scoped_refptr.h"
#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/task/post_task.h"
-#include "base/task/task_traits.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/net_errors.h"
-#include "net/cert/cert_net_fetcher.h"
#include "net/cert/cert_status_flags.h"
-#include "net/cert/cert_verifier.h"
#include "net/test/cert_test_util.h"
#include "net/test/test_data_directory.h"
#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
-#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
namespace cert_verifier {
namespace {
-const char kMockURL[] = "http://mock.invalid/";
-
-class TestReconnector : public mojom::URLLoaderFactoryConnector {
- public:
- explicit TestReconnector(
- network::TestURLLoaderFactory* test_url_loader_factory)
- : test_url_loader_factory_(test_url_loader_factory) {}
- void CreateURLLoaderFactory(
- mojo::PendingReceiver<network::mojom::URLLoaderFactory>
- url_loader_factory_receiver) override {
- num_connects_++;
- receiver_set_.Add(test_url_loader_factory_,
- std::move(url_loader_factory_receiver));
- }
-
- void DisconnectAll() { receiver_set_.Clear(); }
-
- size_t num_connects() const { return num_connects_; }
-
- private:
- network::TestURLLoaderFactory* test_url_loader_factory_;
- mojo::ReceiverSet<network::mojom::URLLoaderFactory> receiver_set_;
-
- size_t num_connects_ = 0;
-};
-
-std::unique_ptr<net::CertNetFetcher::Request>
-PerformCertNetFetcherRequestOnTaskRunner(
- scoped_refptr<base::SequencedTaskRunner> runner,
- scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher) {
- std::unique_ptr<net::CertNetFetcher::Request> request;
- base::RunLoop run_loop;
- runner->PostTask(FROM_HERE, base::BindLambdaForTesting([&]() {
- request = cert_net_fetcher->FetchCaIssuers(
- GURL(kMockURL), net::CertNetFetcher::DEFAULT,
- net::CertNetFetcher::DEFAULT);
- run_loop.QuitWhenIdle();
- }));
- run_loop.Run();
- return request;
-}
-
-class CertVerifierServiceFactoryTest : public PlatformTest {
- public:
- CertVerifierServiceFactoryTest()
- : test_reconnector_(&test_url_loader_factory_),
- test_reconnector_receiver_(&test_reconnector_) {
- test_reconnector_.CreateURLLoaderFactory(
- test_url_loader_factory_remote_.InitWithNewPipeAndPassReceiver());
- EXPECT_EQ(test_reconnector_.num_connects(), 1ul);
- }
-
- TestReconnector* test_reconnector() { return &test_reconnector_; }
- mojo::PendingRemote<network::mojom::URLLoaderFactory>
- TakeURLLoaderFactoryPendingRemote() {
- return std::move(test_url_loader_factory_remote_);
- }
- mojo::Receiver<mojom::URLLoaderFactoryConnector>&
- test_reconnector_receiver() {
- return test_reconnector_receiver_;
- }
- network::TestURLLoaderFactory* test_url_loader_factory() {
- return &test_url_loader_factory_;
- }
-
- private:
- base::test::TaskEnvironment task_environment_;
-
- // Instantiate a TestURLLoaderFactory which we can use to respond and unpause
- // network requests.
- network::TestURLLoaderFactory test_url_loader_factory_;
- mojo::PendingRemote<network::mojom::URLLoaderFactory>
- test_url_loader_factory_remote_;
-
- // Instantiate a dummy URLLoaderFactoryConnector that can disconnect at will
- // and will automatically reconnect to the |test_url_loader_factory| above.
- TestReconnector test_reconnector_;
- mojo::Receiver<mojom::URLLoaderFactoryConnector> test_reconnector_receiver_;
-};
-
struct DummyCVServiceRequest : public mojom::CertVerifierRequest {
explicit DummyCVServiceRequest(base::RepeatingClosure on_finish)
: on_finish_(std::move(on_finish)) {}
@@ -138,83 +50,9 @@ struct DummyCVServiceRequest : public mojom::CertVerifierRequest {
};
} // namespace
-// Test that the CertNetFetcherURLLoader handed to the CertVerifierService
-// successfully tries to reconnect after URLLoaderFactory disconnection.
-TEST_F(CertVerifierServiceFactoryTest,
- CertNetFetcherReconnectAfterURLLoaderFactoryReset) {
- scoped_refptr<base::SequencedTaskRunner> caller_task_runner =
- base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
-
- // Pass mojo::Remote's for |test_url_loader_factory| and
- // |test_reconnector| to the CertNetFetcherURLLoader
- // created by the CertVerifierServiceFactoryImpl.
- scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher =
- CertVerifierServiceFactoryImpl::CreateCertNetFetcher(
- TakeURLLoaderFactoryPendingRemote(),
- test_reconnector_receiver().BindNewPipeAndPassRemote());
-
- // Now run the test.
- auto request1 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
- cert_net_fetcher);
- EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
- EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
-
- EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest(
- kMockURL, "", net::HTTP_NOT_FOUND));
- EXPECT_EQ(test_url_loader_factory()->NumPending(), 0);
-
- // Disconnect the test_url_loader_factory to test reconnection.
- test_reconnector()->DisconnectAll();
-
- // Now run the test.
- auto request2 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
- cert_net_fetcher);
-
- EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
- EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
-
- EXPECT_TRUE(test_url_loader_factory()->SimulateResponseForPendingRequest(
- kMockURL, "", net::HTTP_NOT_FOUND));
- EXPECT_EQ(test_reconnector()->num_connects(), 2ul);
-
- // Disconnect the test_url_loader_factory to test reconnection one more time.
- test_reconnector()->DisconnectAll();
-
- // Now run the test.
- auto request3 = PerformCertNetFetcherRequestOnTaskRunner(caller_task_runner,
- cert_net_fetcher);
-
- EXPECT_EQ(test_url_loader_factory()->NumPending(), 1);
- EXPECT_TRUE(test_url_loader_factory()->IsPending(kMockURL));
-
- EXPECT_EQ(test_reconnector()->num_connects(), 3ul);
-
- // The test simulated responses for at least the first two requests, so they
- // should complete without hanging. The response content is not important, but
- // the test sent error responses, so check that net::OK wasn't returned.
- // The third request may have attached to a previous job, but cancelling it
- // should not cause problems.
- {
- net::Error error1, error2;
- std::vector<uint8_t> bytes1, bytes2;
- base::RunLoop run_loop;
- caller_task_runner->PostTask(
- FROM_HERE, base::BindLambdaForTesting([&]() {
- base::ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync;
- request1->WaitForResult(&error1, &bytes1);
- request2->WaitForResult(&error2, &bytes2);
- request3.reset();
- run_loop.Quit();
- }));
- run_loop.Run();
- EXPECT_NE(error1, net::OK);
- EXPECT_NE(error2, net::OK);
- }
-
- cert_net_fetcher->Shutdown();
-}
+TEST(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
+ base::test::TaskEnvironment task_environment;
-TEST_F(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
base::FilePath certs_dir = net::GetTestCertsDirectory();
scoped_refptr<net::X509Certificate> test_cert(
net::ImportCertFromFile(certs_dir, "ok_cert.pem"));
@@ -230,8 +68,6 @@ TEST_F(CertVerifierServiceFactoryTest, GetNewCertVerifier) {
cv_service_factory_remote->GetNewCertVerifier(
cv_service_remote.BindNewPipeAndPassReceiver(),
- TakeURLLoaderFactoryPendingRemote(),
- test_reconnector_receiver().BindNewPipeAndPassRemote(),
std::move(cv_creation_params));
base::RunLoop request_completed_run_loop;
diff --git a/chromium/services/cert_verifier/integration_tests/DEPS b/chromium/services/cert_verifier/integration_tests/DEPS
new file mode 100644
index 00000000000..288ba20350c
--- /dev/null
+++ b/chromium/services/cert_verifier/integration_tests/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+services/network"
+]
diff --git a/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc b/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc
new file mode 100644
index 00000000000..98483552717
--- /dev/null
+++ b/chromium/services/cert_verifier/integration_tests/network_context_unittest.cc
@@ -0,0 +1,287 @@
+// Copyright 2020 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 <memory>
+
+#include "base/feature_list.h"
+#include "base/test/metrics/histogram_tester.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "net/base/features.h"
+#include "net/test/embedded_test_server/default_handlers.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "services/cert_verifier/cert_verifier_service_factory.h"
+#include "services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cert_verifier {
+namespace {
+
+mojo::PendingRemote<mojom::CertVerifierService> GetNewCertVerifierServiceRemote(
+ mojom::CertVerifierServiceFactory* cert_verifier_service_factory,
+ network::mojom::CertVerifierCreationParamsPtr creation_params) {
+ mojo::PendingRemote<mojom::CertVerifierService> cert_verifier_remote;
+ cert_verifier_service_factory->GetNewCertVerifier(
+ cert_verifier_remote.InitWithNewPipeAndPassReceiver(),
+ std::move(creation_params));
+ return cert_verifier_remote;
+}
+
+} // namespace
+
+class NetworkContextTest : public testing::Test {
+ public:
+ explicit NetworkContextTest(
+ base::test::TaskEnvironment::TimeSource time_source =
+ base::test::TaskEnvironment::TimeSource::DEFAULT)
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO,
+ time_source),
+ network_change_notifier_(
+ net::NetworkChangeNotifier::CreateMockIfNeeded()),
+ network_service_(network::NetworkService::CreateForTesting()) {}
+ ~NetworkContextTest() override = default;
+
+ std::unique_ptr<network::NetworkContext> CreateContextWithParams(
+ network::mojom::NetworkContextParamsPtr context_params) {
+ network_context_remote_.reset();
+ return std::make_unique<network::NetworkContext>(
+ network_service_.get(),
+ network_context_remote_.BindNewPipeAndPassReceiver(),
+ std::move(context_params));
+ }
+
+ network::mojom::CertVerifierParamsPtr GetCertVerifierParams(
+ network::mojom::CertVerifierCreationParamsPtr
+ cert_verifier_creation_params =
+ network::mojom::CertVerifierCreationParams::New()) {
+ if (!base::FeatureList::IsEnabled(
+ network::features::kCertVerifierService)) {
+ return network::mojom::CertVerifierParams::NewCreationParams(
+ std::move(cert_verifier_creation_params));
+ }
+
+ if (!cert_verifier_service_factory_) {
+ cert_verifier_service_factory_ =
+ std::make_unique<CertVerifierServiceFactoryImpl>(
+ cert_verifier_service_factory_remote_
+ .BindNewPipeAndPassReceiver());
+ }
+
+ auto cv_service_remote_params =
+ network::mojom::CertVerifierServiceRemoteParams::New();
+
+ // Create a cert verifier service.
+ cv_service_remote_params->cert_verifier_service =
+ GetNewCertVerifierServiceRemote(
+ cert_verifier_service_factory_.get(),
+ std::move(cert_verifier_creation_params));
+
+ return network::mojom::CertVerifierParams::NewRemoteParams(
+ std::move(cv_service_remote_params));
+ }
+
+ network::mojom::NetworkService* network_service() const {
+ return network_service_.get();
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<net::NetworkChangeNotifier> network_change_notifier_;
+ std::unique_ptr<network::NetworkService> network_service_;
+ // Stores the mojo::Remote<NetworkContext> of the most recently created
+ // NetworkContext. Not strictly needed, but seems best to mimic real-world
+ // usage.
+ mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
+
+ mojo::Remote<mojom::CertVerifierServiceFactory>
+ cert_verifier_service_factory_remote_;
+ std::unique_ptr<mojom::CertVerifierServiceFactory>
+ cert_verifier_service_factory_;
+};
+
+#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+namespace {
+
+network::mojom::NetworkContextParamsPtr CreateContextParams() {
+ network::mojom::NetworkContextParamsPtr params =
+ network::mojom::NetworkContextParams::New();
+ // Use a fixed proxy config, to avoid dependencies on local network
+ // configuration.
+ params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
+ return params;
+}
+
+std::unique_ptr<network::TestURLLoaderClient> FetchRequest(
+ const network::ResourceRequest& request,
+ network::NetworkContext* network_context,
+ int url_loader_options = network::mojom::kURLLoadOptionNone,
+ int process_id = network::mojom::kBrowserProcessId,
+ network::mojom::URLLoaderFactoryParamsPtr params = nullptr) {
+ mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
+ if (!params)
+ params = network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = process_id;
+ params->is_corb_enabled = false;
+
+ // If |site_for_cookies| is null, any non-empty NIK is fine. Otherwise, the
+ // NIK must be consistent with |site_for_cookies|.
+ if (request.site_for_cookies.IsNull()) {
+ params->isolation_info = net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateNothing,
+ url::Origin::Create(GURL("https://abc.invalid")),
+ url::Origin::Create(GURL("https://xyz.invalid")),
+ request.site_for_cookies);
+ } else {
+ params->isolation_info = net::IsolationInfo::CreateForInternalRequest(
+ url::Origin::Create(request.site_for_cookies.RepresentativeUrl()));
+ }
+
+ network_context->CreateURLLoaderFactory(
+ loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
+
+ auto client = std::make_unique<network::TestURLLoaderClient>();
+ mojo::PendingRemote<network::mojom::URLLoader> loader;
+ loader_factory->CreateLoaderAndStart(
+ loader.InitWithNewPipeAndPassReceiver(), 0 /* routing_id */,
+ 0 /* request_id */, url_loader_options, request, client->CreateRemote(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+
+ client->RunUntilComplete();
+ return client;
+}
+
+} // namespace
+
+class UseCertVerifierBuiltinTest : public NetworkContextTest,
+ public testing::WithParamInterface<bool> {
+ public:
+ UseCertVerifierBuiltinTest() = default;
+ ~UseCertVerifierBuiltinTest() override = default;
+
+ void SetUp() override {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kCertVerifierService);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kCertVerifierService);
+ }
+ NetworkContextTest::SetUp();
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_P(UseCertVerifierBuiltinTest, UseCertVerifierBuiltin) {
+ net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ net::test_server::RegisterDefaultHandlers(&test_server);
+ ASSERT_TRUE(test_server.Start());
+
+ // This just happens to be the only histogram that directly records which
+ // verifier was used.
+ const char kBuiltinVerifierHistogram[] =
+ "Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
+
+ for (bool builtin_verifier_enabled : {false, true}) {
+ SCOPED_TRACE(builtin_verifier_enabled);
+
+ network::mojom::NetworkContextParamsPtr params = CreateContextParams();
+ auto creation_params = network::mojom::CertVerifierCreationParams::New();
+ creation_params->use_builtin_cert_verifier =
+ builtin_verifier_enabled ? network::mojom::CertVerifierCreationParams::
+ CertVerifierImpl::kBuiltin
+ : network::mojom::CertVerifierCreationParams::
+ CertVerifierImpl::kSystem;
+ params->cert_verifier_params =
+ GetCertVerifierParams(std::move(creation_params));
+ std::unique_ptr<network::NetworkContext> network_context =
+ CreateContextWithParams(std::move(params));
+
+ network::ResourceRequest request;
+ request.url = test_server.GetURL("/nocontent");
+ base::HistogramTester histogram_tester;
+ std::unique_ptr<network::TestURLLoaderClient> client =
+ FetchRequest(request, network_context.get());
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
+ builtin_verifier_enabled ? 1 : 0);
+ }
+}
+
+INSTANTIATE_TEST_SUITE_P(All, UseCertVerifierBuiltinTest, ::testing::Bool());
+
+class NetworkContextCertVerifierBuiltinFeatureFlagTest
+ : public NetworkContextTest,
+ public testing::WithParamInterface<std::tuple<bool, bool>> {
+ public:
+ NetworkContextCertVerifierBuiltinFeatureFlagTest()
+ : use_builtin_cert_verifier_feature_(std::get<0>(GetParam())),
+ use_cert_verifier_service_feature_(std::get<1>(GetParam())) {
+ std::vector<base::Feature> enabled_features, disabled_features;
+ if (use_builtin_cert_verifier_feature_) {
+ enabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
+ } else {
+ disabled_features.push_back(net::features::kCertVerifierBuiltinFeature);
+ }
+ if (use_cert_verifier_service_feature_) {
+ enabled_features.push_back(network::features::kCertVerifierService);
+ } else {
+ disabled_features.push_back(network::features::kCertVerifierService);
+ }
+ scoped_feature_list_.InitWithFeatures(enabled_features, disabled_features);
+ }
+
+ bool use_builtin_cert_verifier_feature() const {
+ return use_builtin_cert_verifier_feature_;
+ }
+
+ private:
+ const bool use_builtin_cert_verifier_feature_;
+ const bool use_cert_verifier_service_feature_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+};
+
+TEST_P(NetworkContextCertVerifierBuiltinFeatureFlagTest,
+ DefaultNetworkContextParamsUsesCorrectVerifier) {
+ net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ net::test_server::RegisterDefaultHandlers(&test_server);
+ ASSERT_TRUE(test_server.Start());
+
+ // This just happens to be the only histogram that directly records which
+ // verifier was used.
+ const char kBuiltinVerifierHistogram[] =
+ "Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
+
+ // Test creating a NetworkContextParams without specifying a value for
+ // use_builtin_cert_verifier. Should use whatever the default cert verifier
+ // implementation is according to the feature flag.
+ network::mojom::NetworkContextParamsPtr params = CreateContextParams();
+ params->cert_verifier_params = GetCertVerifierParams();
+ std::unique_ptr<network::NetworkContext> network_context =
+ CreateContextWithParams(std::move(params));
+
+ network::ResourceRequest request;
+ request.url = test_server.GetURL("/nocontent");
+ base::HistogramTester histogram_tester;
+ std::unique_ptr<network::TestURLLoaderClient> client =
+ FetchRequest(request, network_context.get());
+ EXPECT_EQ(net::OK, client->completion_status().error_code);
+ histogram_tester.ExpectTotalCount(
+ kBuiltinVerifierHistogram, use_builtin_cert_verifier_feature() ? 1 : 0);
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+ NetworkContextCertVerifierBuiltinFeatureFlagTest,
+ ::testing::Combine(::testing::Bool(),
+ ::testing::Bool()));
+#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
+} // namespace cert_verifier
diff --git a/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc
new file mode 100644
index 00000000000..1ce0aa5c0aa
--- /dev/null
+++ b/chromium/services/cert_verifier/integration_tests/network_service_unittest.cc
@@ -0,0 +1,479 @@
+// Copyright 2020 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 <memory>
+
+#include "base/feature_list.h"
+#include "base/files/file_util.h"
+#include "base/run_loop.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task/task_traits.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/test_completion_callback.h"
+#include "net/cert/asn1_util.h"
+#include "net/cert/test_root_certs.h"
+#include "net/cert/x509_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/embedded_test_server/embedded_test_server.h"
+#include "net/test/gtest_util.h"
+#include "net/test/test_data_directory.h"
+#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request_context.h"
+#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
+#include "services/cert_verifier/cert_verifier_service_factory.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/ssl_config_service_mojo.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
+#include "services/network/test/test_url_loader_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "url/gurl.h"
+
+namespace cert_verifier {
+namespace {
+const base::FilePath::CharType kServicesTestData[] =
+ FILE_PATH_LITERAL("services/test/data");
+} // namespace
+
+// Base class for any tests that just need a NetworkService and a
+// TaskEnvironment, and to create NetworkContexts using the NetworkService.
+// Parametrized on whether or not the CertVerifierService feature is enabled.
+class NetworkServiceIntegrationTest : public testing::TestWithParam<bool> {
+ public:
+ NetworkServiceIntegrationTest()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
+ service_(network::NetworkService::CreateForTesting()),
+ cert_verifier_service_impl_(
+ cert_verifier_service_remote_.BindNewPipeAndPassReceiver()) {}
+ ~NetworkServiceIntegrationTest() override = default;
+
+ void SetUp() override {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kCertVerifierService);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kCertVerifierService);
+ }
+ }
+
+ void DestroyService() { service_.reset(); }
+
+ network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
+ network::mojom::CertVerifierCreationParamsPtr
+ cert_verifier_creation_params =
+ network::mojom::CertVerifierCreationParams::New();
+ network::mojom::CertVerifierParamsPtr cert_verifier_params;
+ if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
+ mojo::PendingRemote<mojom::CertVerifierService> cv_service_remote;
+
+ auto cv_service_remote_params =
+ network::mojom::CertVerifierServiceRemoteParams::New();
+
+ // Create a cert verifier service.
+ cert_verifier_service_impl_.GetNewCertVerifierForTesting(
+ cv_service_remote.InitWithNewPipeAndPassReceiver(),
+ std::move(cert_verifier_creation_params),
+ &cert_net_fetcher_url_loader_);
+
+ cv_service_remote_params->cert_verifier_service =
+ std::move(cv_service_remote);
+
+ cert_verifier_params =
+ network::mojom::CertVerifierParams::NewRemoteParams(
+ std::move(cv_service_remote_params));
+ } else {
+ cert_verifier_params =
+ network::mojom::CertVerifierParams::NewCreationParams(
+ std::move(cert_verifier_creation_params));
+ }
+
+ network::mojom::NetworkContextParamsPtr params =
+ network::mojom::NetworkContextParams::New();
+ params->cert_verifier_params = std::move(cert_verifier_params);
+ // Use a fixed proxy config, to avoid dependencies on local network
+ // configuration.
+ params->initial_proxy_config =
+ net::ProxyConfigWithAnnotation::CreateDirect();
+ return params;
+ }
+
+ void CreateNetworkContext(network::mojom::NetworkContextParamsPtr params) {
+ network_context_ = std::make_unique<network::NetworkContext>(
+ service_.get(), network_context_remote_.BindNewPipeAndPassReceiver(),
+ std::move(params));
+ }
+
+ void LoadURL(const GURL& url,
+ int options = network::mojom::kURLLoadOptionNone) {
+ network::ResourceRequest request;
+ request.url = url;
+ request.method = "GET";
+ request.request_initiator = url::Origin();
+ StartLoadingURL(request, 0 /* process_id */, options);
+ client_->RunUntilComplete();
+ }
+
+ void StartLoadingURL(const network::ResourceRequest& request,
+ uint32_t process_id,
+ int options = network::mojom::kURLLoadOptionNone) {
+ client_ = std::make_unique<network::TestURLLoaderClient>();
+ mojo::Remote<network::mojom::URLLoaderFactory> loader_factory;
+ network::mojom::URLLoaderFactoryParamsPtr params =
+ network::mojom::URLLoaderFactoryParams::New();
+ params->process_id = process_id;
+ params->is_corb_enabled = false;
+ network_context_->CreateURLLoaderFactory(
+ loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
+
+ loader_.reset();
+ loader_factory->CreateLoaderAndStart(
+ loader_.BindNewPipeAndPassReceiver(), 1, 1, options, request,
+ client_->CreateRemote(),
+ net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS));
+ }
+
+ network::TestURLLoaderClient* client() { return client_.get(); }
+
+ base::test::TaskEnvironment* task_environment() { return &task_environment_; }
+
+ network::NetworkService* service() const { return service_.get(); }
+
+ network::NetworkContext* network_context() { return network_context_.get(); }
+
+ mojo::Remote<network::mojom::NetworkContext>& network_context_remote() {
+ return network_context_remote_;
+ }
+
+ CertNetFetcherURLLoader* cert_net_fetcher_url_loader() {
+ return cert_net_fetcher_url_loader_.get();
+ }
+
+ private:
+ base::test::ScopedFeatureList scoped_feature_list_;
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<network::NetworkService> service_;
+
+ mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
+ std::unique_ptr<network::NetworkContext> network_context_;
+
+ mojo::Remote<mojom::CertVerifierServiceFactory> cert_verifier_service_remote_;
+ CertVerifierServiceFactoryImpl cert_verifier_service_impl_;
+ scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_url_loader_;
+
+ std::unique_ptr<network::TestURLLoaderClient> client_;
+ mojo::Remote<network::mojom::URLLoader> loader_;
+};
+
+// CRLSets are not supported on iOS and Android system verifiers.
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+
+class NetworkServiceCRLSetTest : public NetworkServiceIntegrationTest {
+ public:
+ NetworkServiceCRLSetTest()
+ : test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+ ~NetworkServiceCRLSetTest() override = default;
+
+ void SetUp() override {
+ NetworkServiceIntegrationTest::SetUp();
+ test_server_.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
+ test_server_.AddDefaultHandlers(base::FilePath(kServicesTestData));
+ ASSERT_TRUE(test_server_.Start());
+ }
+
+ GURL GetURL(std::string url) { return test_server_.GetURL(std::move(url)); }
+
+ private:
+ net::EmbeddedTestServer test_server_;
+};
+
+// Verifies CRLSets take effect if configured on the service.
+TEST_P(NetworkServiceCRLSetTest, CRLSetIsApplied) {
+ CreateNetworkContext(CreateNetworkContextParams());
+
+ uint32_t options =
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
+ network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+ // Make sure the test server loads fine with no CRLSet.
+ LoadURL(GetURL("/echo"), options);
+ ASSERT_EQ(net::OK, client()->completion_status().error_code);
+
+ // Send a CRLSet that blocks the leaf cert.
+ std::string crl_set_bytes;
+ EXPECT_TRUE(base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
+ &crl_set_bytes));
+
+ {
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Flush all connections in the context, to force a new connection. A new
+ // verification should be attempted, due to the configuration having
+ // changed, thus forcing the CRLSet to be checked.
+ {
+ base::RunLoop run_loop;
+ network_context()->CloseAllConnections(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Make sure the connection fails, due to the certificate being revoked.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+}
+
+// Verifies CRLSets configured before creating a new network context are
+// applied to that network context.
+TEST_P(NetworkServiceCRLSetTest, CRLSetIsPassedToNewContexts) {
+ // Send a CRLSet that blocks the leaf cert, even while no NetworkContexts
+ // exist.
+ std::string crl_set_bytes;
+ EXPECT_TRUE(base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
+ &crl_set_bytes));
+
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+
+ // Configure a new NetworkContext.
+ CreateNetworkContext(CreateNetworkContextParams());
+
+ uint32_t options =
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
+ network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+ // Make sure the connection fails, due to the certificate being revoked.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+}
+
+// Verifies newer CRLSets (by sequence number) are applied.
+TEST_P(NetworkServiceCRLSetTest, CRLSetIsUpdatedIfNewer) {
+ // Send a CRLSet that only allows the root cert if it matches a known SPKI
+ // hash (that matches the test server chain)
+ std::string crl_set_bytes;
+ ASSERT_TRUE(base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
+ &crl_set_bytes));
+
+ {
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ CreateNetworkContext(CreateNetworkContextParams());
+
+ uint32_t options =
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
+ network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+ // Make sure the connection loads, due to the root being permitted.
+ LoadURL(GetURL("/echo"), options);
+ ASSERT_EQ(net::OK, client()->completion_status().error_code);
+
+ // Send a new CRLSet that removes trust in the root.
+ ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
+ "crlset_by_root_subject_no_spki.raw"),
+ &crl_set_bytes));
+
+ {
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Flush all connections in the context, to force a new connection. A new
+ // verification should be attempted, due to the configuration having
+ // changed, thus forcing the CRLSet to be checked.
+ {
+ base::RunLoop run_loop;
+ network_context()->CloseAllConnections(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Make sure the connection fails, due to the certificate being revoked.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+}
+
+// Verifies that attempting to send an older CRLSet (by sequence number)
+// does not apply to existing or new contexts.
+TEST_P(NetworkServiceCRLSetTest, CRLSetDoesNotDowngrade) {
+ // Send a CRLSet that blocks the root certificate by subject name.
+ std::string crl_set_bytes;
+ ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
+ "crlset_by_root_subject_no_spki.raw"),
+ &crl_set_bytes));
+
+ {
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ CreateNetworkContext(CreateNetworkContextParams());
+
+ uint32_t options =
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse |
+ network::mojom::kURLLoadOptionSendSSLInfoForCertificateError;
+ // Make sure the connection fails, due to the certificate being revoked.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+
+ // Attempt to configure an older CRLSet that allowed trust in the root.
+ ASSERT_TRUE(base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
+ &crl_set_bytes));
+
+ {
+ base::RunLoop run_loop;
+ service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
+ run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Flush all connections in the context, to force a new connection. A new
+ // verification should be attempted, due to the configuration having
+ // changed, thus forcing the CRLSet to be checked.
+ {
+ base::RunLoop run_loop;
+ network_context()->CloseAllConnections(run_loop.QuitClosure());
+ run_loop.Run();
+ }
+
+ // Make sure the connection still fails, due to the newer CRLSet still
+ // applying.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+
+ // Create a new NetworkContext and ensure the latest CRLSet is still
+ // applied.
+ network_context_remote().reset();
+ CreateNetworkContext(CreateNetworkContextParams());
+
+ // The newer CRLSet that blocks the connection should still apply, even to
+ // new NetworkContexts.
+ LoadURL(GetURL("/echo"), options);
+ EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
+ client()->completion_status().error_code);
+ ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
+ EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
+ net::CERT_STATUS_REVOKED);
+}
+
+INSTANTIATE_TEST_SUITE_P(All, NetworkServiceCRLSetTest, ::testing::Bool());
+#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
+
+// TODO(crbug.com/860189): AIA tests fail on iOS
+#if defined(OS_IOS)
+#define MAYBE(test_name) DISABLED_##test_name
+#else
+#define MAYBE(test_name) test_name
+#endif
+
+class NetworkServiceAIATest : public NetworkServiceIntegrationTest {
+ public:
+ NetworkServiceAIATest() : test_server_(net::EmbeddedTestServer::TYPE_HTTPS) {}
+ ~NetworkServiceAIATest() override = default;
+
+ void SetUp() override {
+ NetworkServiceIntegrationTest::SetUp();
+ network::mojom::NetworkContextParamsPtr context_params =
+ CreateNetworkContextParams();
+ CreateNetworkContext(std::move(context_params));
+
+ net::EmbeddedTestServer::ServerCertificateConfig cert_config;
+ cert_config.intermediate =
+ net::EmbeddedTestServer::IntermediateType::kByAIA;
+ test_server_.SetSSLConfig(cert_config);
+ test_server_.AddDefaultHandlers(base::FilePath(kServicesTestData));
+ ASSERT_TRUE(test_server_.Start());
+ }
+
+ void PerformAIATest() {
+ LoadURL(test_server_.GetURL("/echo"),
+ network::mojom::kURLLoadOptionSendSSLInfoWithResponse);
+ EXPECT_EQ(net::OK, client()->completion_status().error_code);
+ ASSERT_TRUE(client()->response_head());
+ EXPECT_EQ(0u, client()->response_head()->cert_status &
+ net::CERT_STATUS_ALL_ERRORS);
+ ASSERT_TRUE(client()->ssl_info());
+ ASSERT_TRUE(client()->ssl_info()->cert);
+ EXPECT_EQ(2u, client()->ssl_info()->cert->intermediate_buffers().size());
+ ASSERT_TRUE(client()->ssl_info()->unverified_cert);
+ EXPECT_EQ(
+ 0u,
+ client()->ssl_info()->unverified_cert->intermediate_buffers().size());
+ }
+
+ private:
+ net::EmbeddedTestServer test_server_;
+};
+
+TEST_P(NetworkServiceAIATest, MAYBE(AIAFetching)) {
+ PerformAIATest();
+}
+
+// Check that AIA fetching still succeeds even after the URLLoaderFactory
+// backing the CertNetFetcherURLLoader disconnects.
+// Only relevant if testing with the CertVerifierService, and the underlying
+// CertVerifier uses the CertNetFetcher.
+TEST_P(NetworkServiceAIATest,
+ MAYBE(AIAFetchingWithURLLoaderFactoryDisconnect)) {
+ if (!base::FeatureList::IsEnabled(network::features::kCertVerifierService) ||
+ !cert_net_fetcher_url_loader()) {
+ // TODO(crbug.com/1015706): Switch to GTEST_SKIP().
+ LOG(WARNING) << "Skipping AIA reconnection test because the underlying "
+ "cert verifier does not use a CertNetFetcherURLLoader.";
+ return;
+ }
+ PerformAIATest();
+ // Disconnect the URLLoaderFactory used by the CertNetFetcherURLLoader.
+ cert_net_fetcher_url_loader()->DisconnectURLLoaderFactoryForTesting();
+ // Try running the test again to test reconnection of the
+ // CertNetFetcherURLLoader.
+ PerformAIATest();
+ // Repeat one more time to be sure.
+ cert_net_fetcher_url_loader()->DisconnectURLLoaderFactoryForTesting();
+ PerformAIATest();
+}
+
+INSTANTIATE_TEST_SUITE_P(All, NetworkServiceAIATest, ::testing::Bool());
+} // namespace cert_verifier
diff --git a/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc b/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc
new file mode 100644
index 00000000000..5b100c8c3e8
--- /dev/null
+++ b/chromium/services/cert_verifier/integration_tests/ssl_config_service_mojo_unittest.cc
@@ -0,0 +1,201 @@
+// Copyright 2020 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 <memory>
+
+#include "base/files/file_util.h"
+#include "base/sequenced_task_runner.h"
+#include "base/task/task_traits.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/test_completion_callback.h"
+#include "net/cert/test_root_certs.h"
+#include "net/cert/x509_util.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/gtest_util.h"
+#include "net/test/test_data_directory.h"
+#include "net/url_request/url_request_context.h"
+#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader.h"
+#include "services/cert_verifier/cert_verifier_service_factory.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/cert_verifier_service.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/ssl_config_service_mojo.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace cert_verifier {
+
+// Base class for any tests that just need a NetworkService and a
+// TaskEnvironment, and to create NetworkContexts using the NetworkService.
+class SSLConfigServiceMojoTestWithCertVerifier
+ : public testing::TestWithParam<bool> {
+ public:
+ SSLConfigServiceMojoTestWithCertVerifier()
+ : task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
+ service_(network::NetworkService::CreateForTesting()),
+ cert_verifier_service_impl_(
+ cert_verifier_service_remote_.BindNewPipeAndPassReceiver()) {}
+ ~SSLConfigServiceMojoTestWithCertVerifier() override = default;
+
+ void SetUp() override {
+ if (GetParam()) {
+ scoped_feature_list_.InitAndEnableFeature(
+ network::features::kCertVerifierService);
+ } else {
+ scoped_feature_list_.InitAndDisableFeature(
+ network::features::kCertVerifierService);
+ }
+ }
+
+ void DestroyService() { service_.reset(); }
+
+ network::mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
+ network::mojom::CertVerifierCreationParamsPtr
+ cert_verifier_creation_params =
+ network::mojom::CertVerifierCreationParams::New();
+ network::mojom::CertVerifierParamsPtr cert_verifier_params;
+ if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
+ mojo::PendingRemote<mojom::CertVerifierService> cv_service_remote;
+
+ auto cv_service_remote_params =
+ network::mojom::CertVerifierServiceRemoteParams::New();
+
+ // Create a cert verifier service.
+ cert_verifier_service_impl_.GetNewCertVerifierForTesting(
+ cv_service_remote.InitWithNewPipeAndPassReceiver(),
+ std::move(cert_verifier_creation_params),
+ &cert_net_fetcher_url_loader_);
+
+ cv_service_remote_params->cert_verifier_service =
+ std::move(cv_service_remote);
+
+ cert_verifier_params =
+ network::mojom::CertVerifierParams::NewRemoteParams(
+ std::move(cv_service_remote_params));
+ } else {
+ cert_verifier_params =
+ network::mojom::CertVerifierParams::NewCreationParams(
+ std::move(cert_verifier_creation_params));
+ }
+
+ network::mojom::NetworkContextParamsPtr params =
+ network::mojom::NetworkContextParams::New();
+ params->cert_verifier_params = std::move(cert_verifier_params);
+ // Use a fixed proxy config, to avoid dependencies on local network
+ // configuration.
+ params->initial_proxy_config =
+ net::ProxyConfigWithAnnotation::CreateDirect();
+ return params;
+ }
+
+ void CreateNetworkContext(network::mojom::NetworkContextParamsPtr params) {
+ network_context_ = std::make_unique<network::NetworkContext>(
+ service_.get(), network_context_remote_.BindNewPipeAndPassReceiver(),
+ std::move(params));
+ }
+
+ base::test::TaskEnvironment* task_environment() { return &task_environment_; }
+
+ network::NetworkService* service() const { return service_.get(); }
+
+ network::NetworkContext* network_context() { return network_context_.get(); }
+
+ mojo::Remote<network::mojom::NetworkContext>& network_context_remote() {
+ return network_context_remote_;
+ }
+
+ CertNetFetcherURLLoader* cert_net_fetcher_url_loader() {
+ return cert_net_fetcher_url_loader_.get();
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+ std::unique_ptr<network::NetworkService> service_;
+ base::test::ScopedFeatureList scoped_feature_list_;
+
+ mojo::Remote<network::mojom::NetworkContext> network_context_remote_;
+ std::unique_ptr<network::NetworkContext> network_context_;
+
+ mojo::Remote<mojom::CertVerifierServiceFactory> cert_verifier_service_remote_;
+ CertVerifierServiceFactoryImpl cert_verifier_service_impl_;
+ scoped_refptr<CertNetFetcherURLLoader> cert_net_fetcher_url_loader_;
+};
+
+#if !defined(OS_IOS) && !defined(OS_ANDROID)
+TEST_P(SSLConfigServiceMojoTestWithCertVerifier, CRLSetIsApplied) {
+ mojo::Remote<network::mojom::SSLConfigClient> ssl_config_client;
+
+ network::mojom::NetworkContextParamsPtr context_params =
+ CreateNetworkContextParams();
+ context_params->ssl_config_client_receiver =
+ ssl_config_client.BindNewPipeAndPassReceiver();
+ CreateNetworkContext(std::move(context_params));
+
+ network::SSLConfigServiceMojo* config_service =
+ static_cast<network::SSLConfigServiceMojo*>(
+ network_context()->url_request_context()->ssl_config_service());
+
+ scoped_refptr<net::X509Certificate> root_cert =
+ net::CreateCertificateChainFromFile(
+ net::GetTestCertsDirectory(), "root_ca_cert.pem",
+ net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+ ASSERT_TRUE(root_cert);
+ net::ScopedTestRoot test_root(root_cert.get());
+
+ scoped_refptr<net::X509Certificate> leaf_cert =
+ net::CreateCertificateChainFromFile(
+ net::GetTestCertsDirectory(), "ok_cert.pem",
+ net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
+ ASSERT_TRUE(leaf_cert);
+
+ // Ensure that |leaf_cert| is trusted without any CRLSet explicitly
+ // configured.
+ net::TestCompletionCallback callback1;
+ net::CertVerifyResult cert_verify_result1;
+ std::unique_ptr<net::CertVerifier::Request> request1;
+ int result =
+ network_context()->url_request_context()->cert_verifier()->Verify(
+ net::CertVerifier::RequestParams(leaf_cert, "127.0.0.1",
+ /*flags=*/0,
+ /*ocsp_response=*/std::string(),
+ /*sct_list=*/std::string()),
+ &cert_verify_result1, callback1.callback(), &request1,
+ net::NetLogWithSource());
+ ASSERT_THAT(callback1.GetResult(result), net::test::IsOk());
+
+ // Load a CRLSet that removes trust in |leaf_cert| by SPKI.
+ scoped_refptr<net::CRLSet> crl_set;
+ std::string crl_set_bytes;
+ ASSERT_TRUE(base::ReadFileToString(
+ net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
+ &crl_set_bytes));
+ ASSERT_TRUE(net::CRLSet::ParseAndStoreUnparsedData(crl_set_bytes, &crl_set));
+
+ config_service->OnNewCRLSet(crl_set);
+
+ // Ensure that |leaf_cert| is revoked, due to the CRLSet being applied.
+ net::TestCompletionCallback callback2;
+ net::CertVerifyResult cert_verify_result2;
+ std::unique_ptr<net::CertVerifier::Request> request2;
+ result = network_context()->url_request_context()->cert_verifier()->Verify(
+ net::CertVerifier::RequestParams(leaf_cert, "127.0.0.1",
+ /*flags=*/0,
+ /*ocsp_response=*/std::string(),
+ /*sct_list=*/std::string()),
+ &cert_verify_result2, callback2.callback(), &request2,
+ net::NetLogWithSource());
+ ASSERT_THAT(callback2.GetResult(result),
+ net::test::IsError(net::ERR_CERT_REVOKED));
+}
+
+INSTANTIATE_TEST_SUITE_P(All,
+ SSLConfigServiceMojoTestWithCertVerifier,
+ ::testing::Bool());
+#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
+
+} // namespace cert_verifier
diff --git a/chromium/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom b/chromium/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
index dc15c52a0b5..c9eda673a7f 100644
--- a/chromium/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
+++ b/chromium/services/cert_verifier/public/mojom/cert_verifier_service_factory.mojom
@@ -15,19 +15,5 @@ interface CertVerifierServiceFactory {
// Gets a new CertVerifierFactory, which //net code can interface with using
// cert_verifier::MojoCertVerifier.
GetNewCertVerifier(pending_receiver<CertVerifierService> receiver,
- pending_remote<network.mojom.URLLoaderFactory>?
- cert_net_fetcher_url_loader_factory,
- pending_remote<URLLoaderFactoryConnector>?
- cert_net_fetcher_url_loader_factory_connector,
network.mojom.CertVerifierCreationParams? creation_params);
};
-
-// Allows the CertVerifierService to connect a new URLLoaderFactory if its
-// existing URLLoaderFactory is disconnected. The CertVerifierService uses the
-// URLLoaderFactory for AIA and OCSP fetching.
-interface URLLoaderFactoryConnector {
- // Binds a URLLoaderFactory. The implementer of this interface is in charge
- // of choosing the URLLoaderFactoryParams.
- CreateURLLoaderFactory(
- pending_receiver<network.mojom.URLLoaderFactory> url_loader_factory);
-};
diff --git a/chromium/services/cert_verifier/test_cert_verifier_service_factory.cc b/chromium/services/cert_verifier/test_cert_verifier_service_factory.cc
index a851f76ccce..f06f4365824 100644
--- a/chromium/services/cert_verifier/test_cert_verifier_service_factory.cc
+++ b/chromium/services/cert_verifier/test_cert_verifier_service_factory.cc
@@ -32,9 +32,6 @@ TestCertVerifierServiceFactoryImpl::~TestCertVerifierServiceFactoryImpl() =
void TestCertVerifierServiceFactoryImpl::GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) {
if (!delegate_) {
InitDelegate();
@@ -42,9 +39,6 @@ void TestCertVerifierServiceFactoryImpl::GetNewCertVerifier(
GetNewCertVerifierParams params;
params.receiver = std::move(receiver);
- params.url_loader_factory = std::move(url_loader_factory);
- params.cert_net_fetcher_url_loader_factory_connector =
- std::move(cert_net_fetcher_url_loader_factory_connector);
params.creation_params = std::move(creation_params);
captured_params_.push_front(std::move(params));
@@ -60,10 +54,8 @@ void TestCertVerifierServiceFactoryImpl::ReleaseNextCertVerifierParams() {
DCHECK(delegate_);
GetNewCertVerifierParams params = std::move(captured_params_.back());
captured_params_.pop_back();
- delegate_remote_->GetNewCertVerifier(
- std::move(params.receiver), std::move(params.url_loader_factory),
- std::move(params.cert_net_fetcher_url_loader_factory_connector),
- std::move(params.creation_params));
+ delegate_remote_->GetNewCertVerifier(std::move(params.receiver),
+ std::move(params.creation_params));
}
void TestCertVerifierServiceFactoryImpl::InitDelegate() {
diff --git a/chromium/services/cert_verifier/test_cert_verifier_service_factory.h b/chromium/services/cert_verifier/test_cert_verifier_service_factory.h
index 70daa06be1f..3aa9ae2a69d 100644
--- a/chromium/services/cert_verifier/test_cert_verifier_service_factory.h
+++ b/chromium/services/cert_verifier/test_cert_verifier_service_factory.h
@@ -38,18 +38,12 @@ class TestCertVerifierServiceFactoryImpl
~GetNewCertVerifierParams();
mojo::PendingReceiver<mojom::CertVerifierService> receiver;
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory;
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector;
network::mojom::CertVerifierCreationParamsPtr creation_params;
};
// mojom::CertVerifierServiceFactory implementation:
void GetNewCertVerifier(
mojo::PendingReceiver<mojom::CertVerifierService> receiver,
- mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
- mojo::PendingRemote<mojom::URLLoaderFactoryConnector>
- cert_net_fetcher_url_loader_factory_connector,
network::mojom::CertVerifierCreationParamsPtr creation_params) override;
// Pops the first request off the back of the list and forwards it to the
diff --git a/chromium/services/device/BUILD.gn b/chromium/services/device/BUILD.gn
index d478ddab846..05d4696dc52 100644
--- a/chromium/services/device/BUILD.gn
+++ b/chromium/services/device/BUILD.gn
@@ -158,7 +158,6 @@ source_set("tests") {
"//base/test:test_support",
"//base/third_party/dynamic_annotations",
"//device/base/synchronization",
- "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//net",
"//net:test_support",
diff --git a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
index 3846c1587d8..b43c55c56b8 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc
@@ -56,10 +56,6 @@ constexpr double kMagnetometerFrequencyValue = 7.0;
constexpr double kMagnetometerOffsetValue = 3.0;
constexpr double kMagnetometerScalingValue = 0.000001;
-void DeleteFile(const base::FilePath& file) {
- EXPECT_TRUE(base::DeleteFileRecursively(file));
-}
-
void WriteValueToFile(const base::FilePath& path, double value) {
const std::string str = base::NumberToString(value);
int bytes_written = base::WriteFile(path, str.data(), str.size());
@@ -90,9 +86,40 @@ double RoundGyroscopeValue(double value) {
// to SensorDeviceManager.
class MockSensorDeviceManager : public SensorDeviceManager {
public:
- MockSensorDeviceManager(base::WeakPtr<SensorDeviceManager::Delegate> delegate)
- : SensorDeviceManager(std::move(delegate)) {}
- ~MockSensorDeviceManager() override {}
+ ~MockSensorDeviceManager() override = default;
+
+ // static
+ static std::unique_ptr<NiceMock<MockSensorDeviceManager>> Create(
+ base::WeakPtr<SensorDeviceManager::Delegate> delegate) {
+ auto device_manager =
+ std::make_unique<NiceMock<MockSensorDeviceManager>>(delegate);
+ {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ if (!device_manager->sensors_dir_.CreateUniqueTempDir())
+ return nullptr;
+ }
+
+ const base::FilePath& base_path = device_manager->GetSensorsBasePath();
+
+ ON_CALL(*device_manager, GetUdevDeviceGetSubsystem(IsNull()))
+ .WillByDefault(Invoke([](udev_device*) { return "iio"; }));
+
+ ON_CALL(*device_manager, GetUdevDeviceGetSyspath(IsNull()))
+ .WillByDefault(
+ Invoke([base_path](udev_device*) { return base_path.value(); }));
+
+ ON_CALL(*device_manager, GetUdevDeviceGetDevnode(IsNull()))
+ .WillByDefault(Invoke([](udev_device*) { return "/dev/test"; }));
+
+ ON_CALL(*device_manager, GetUdevDeviceGetSysattrValue(IsNull(), _))
+ .WillByDefault(
+ Invoke([base_path](udev_device*, const std::string& attribute) {
+ base::ScopedAllowBlockingForTesting allow_blocking;
+ return ReadValueFromFile(base_path, attribute);
+ }));
+
+ return device_manager;
+ }
MOCK_METHOD1(GetUdevDeviceGetSubsystem, std::string(udev_device*));
MOCK_METHOD1(GetUdevDeviceGetSyspath, std::string(udev_device*));
@@ -101,6 +128,10 @@ class MockSensorDeviceManager : public SensorDeviceManager {
std::string(udev_device*, const std::string&));
MOCK_METHOD0(Start, void());
+ const base::FilePath& GetSensorsBasePath() const {
+ return sensors_dir_.GetPath();
+ }
+
void EnumerationReady() {
bool success = delegate_task_runner_->PostTask(
FROM_HERE,
@@ -117,7 +148,14 @@ class MockSensorDeviceManager : public SensorDeviceManager {
SensorDeviceManager::OnDeviceRemoved(nullptr /* unused */);
}
+ protected:
+ explicit MockSensorDeviceManager(
+ base::WeakPtr<SensorDeviceManager::Delegate> delegate)
+ : SensorDeviceManager(std::move(delegate)) {}
+
private:
+ base::ScopedTempDir sensors_dir_;
+
DISALLOW_COPY_AND_ASSIGN(MockSensorDeviceManager);
};
@@ -154,27 +192,16 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
public:
void SetUp() override {
provider_ = base::WrapUnique(new PlatformSensorProviderLinux);
-
- auto manager = std::make_unique<NiceMock<MockSensorDeviceManager>>(
- provider_->weak_ptr_factory_.GetWeakPtr());
- manager_ = manager.get();
- provider_->SetSensorDeviceManagerForTesting(std::move(manager));
-
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- ASSERT_TRUE(sensors_dir_.CreateUniqueTempDir());
- }
+ provider_->SetSensorDeviceManagerForTesting(MockSensorDeviceManager::Create(
+ provider_->weak_ptr_factory_.GetWeakPtr()));
}
- void TearDown() override {
- {
- base::ScopedAllowBlockingForTesting allow_blocking;
- ASSERT_TRUE(sensors_dir_.Delete());
- }
- base::RunLoop().RunUntilIdle();
+ protected:
+ MockSensorDeviceManager* mock_sensor_device_manager() const {
+ return static_cast<MockSensorDeviceManager*>(
+ provider_->sensor_device_manager_.get());
}
- protected:
// Sensor creation is asynchronous, therefore inner loop is used to wait for
// PlatformSensorProvider::CreateSensorCallback completion.
scoped_refptr<PlatformSensor> CreateSensor(mojom::SensorType type) {
@@ -204,7 +231,8 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
{
base::ScopedAllowBlockingForTesting allow_blocking;
- base::FilePath sensor_dir = sensors_dir_.GetPath();
+ const base::FilePath& sensor_dir =
+ mock_sensor_device_manager()->GetSensorsBasePath();
if (!data.sensor_scale_name.empty() && scaling != 0) {
base::FilePath sensor_scale_file =
base::FilePath(sensor_dir).Append(data.sensor_scale_name);
@@ -239,34 +267,13 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
}
}
- // Initializes mock udev methods that emulate system methods by
- // just reading values from files, which SensorDeviceService has specified
- // calling udev methods.
- void InitializeMockUdevMethods(const base::FilePath& sensor_dir) {
- ON_CALL(*manager_, GetUdevDeviceGetSubsystem(IsNull()))
- .WillByDefault(Invoke([](udev_device* dev) { return "iio"; }));
-
- ON_CALL(*manager_, GetUdevDeviceGetSyspath(IsNull()))
- .WillByDefault(Invoke(
- [sensor_dir](udev_device* dev) { return sensor_dir.value(); }));
-
- ON_CALL(*manager_, GetUdevDeviceGetDevnode(IsNull()))
- .WillByDefault(Invoke([](udev_device* dev) { return "/dev/test"; }));
-
- ON_CALL(*manager_, GetUdevDeviceGetSysattrValue(IsNull(), _))
- .WillByDefault(Invoke(
- [sensor_dir](udev_device* dev, const std::string& attribute) {
- base::ScopedAllowBlockingForTesting allow_blocking;
- return ReadValueFromFile(sensor_dir, attribute);
- }));
- }
-
// Emulates device enumerations and initial udev events. Once all
// devices are added, tells manager its ready.
void SetServiceStart() {
- EXPECT_CALL(*manager_, Start()).WillOnce(Invoke([this]() {
- manager_->DeviceAdded();
- manager_->EnumerationReady();
+ auto* manager = mock_sensor_device_manager();
+ EXPECT_CALL(*manager, Start()).WillOnce(Invoke([manager]() {
+ manager->DeviceAdded();
+ manager->EnumerationReady();
}));
}
@@ -292,8 +299,9 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
// been added.
void GenerateDeviceAddedEvent() {
bool success = provider_->blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&MockSensorDeviceManager::DeviceAdded,
- base::Unretained(manager_)));
+ FROM_HERE,
+ base::BindOnce(&MockSensorDeviceManager::DeviceAdded,
+ base::Unretained(mock_sensor_device_manager())));
ASSERT_TRUE(success);
// Make sure all tasks have been delivered (including SensorDeviceManager
// notifying PlatformSensorProviderLinux of a device addition).
@@ -305,11 +313,12 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
void GenerateDeviceRemovedEvent(const base::FilePath& sensor_dir) {
{
base::ScopedAllowBlockingForTesting allow_blocking;
- DeleteFile(sensor_dir);
+ EXPECT_TRUE(base::DeleteFileRecursively(sensor_dir));
}
bool success = provider_->blocking_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&MockSensorDeviceManager::DeviceRemoved,
- base::Unretained(manager_)));
+ FROM_HERE,
+ base::BindOnce(&MockSensorDeviceManager::DeviceRemoved,
+ base::Unretained(mock_sensor_device_manager())));
ASSERT_TRUE(success);
// Make sure all tasks have been delivered (including SensorDeviceManager
// notifying PlatformSensorProviderLinux of a device removal).
@@ -318,10 +327,7 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
base::test::TaskEnvironment task_environment_;
- MockSensorDeviceManager* manager_;
std::unique_ptr<PlatformSensorProviderLinux> provider_;
- // Holds base dir where a sensor dir is located.
- base::ScopedTempDir sensors_dir_;
// Used to simulate the non-test scenario where we're running in an IO thread
// that forbids blocking operations.
@@ -351,7 +357,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorIsSupported) {
double sensor_value[3] = {5};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -365,7 +370,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, StartFails) {
double sensor_value[3] = {5};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -383,7 +387,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorStarted) {
double sensor_value[3] = {5};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -402,7 +405,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorRemoved) {
double sensor_value[3] = {1};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -412,7 +414,8 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorRemoved) {
std::make_unique<NiceMock<LinuxMockPlatformSensorClient>>(sensor);
PlatformSensorConfiguration configuration(5);
EXPECT_TRUE(sensor->StartListening(client.get(), configuration));
- GenerateDeviceRemovedEvent(sensors_dir_.GetPath());
+ GenerateDeviceRemovedEvent(
+ mock_sensor_device_manager()->GetSensorsBasePath());
WaitOnSensorErrorEvent(client.get());
}
@@ -422,7 +425,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, SensorAddedAndRemoved) {
double sensor_value[3] = {1, 2, 4};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto als_sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -453,7 +455,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckAllSupportedSensors) {
InitializeSupportedSensor(
SensorType::MAGNETOMETER, kMagnetometerFrequencyValue,
kMagnetometerOffsetValue, kMagnetometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto als_sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -487,7 +488,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, GetMaximumSupportedFrequency) {
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::ACCELEROMETER);
@@ -503,7 +503,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
double sensor_value[3] = {5};
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -524,7 +523,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckAmbientLightReadings) {
InitializeSupportedSensor(SensorType::AMBIENT_LIGHT, kZero, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -566,7 +564,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
kAccelerometerOffsetValue,
kAccelerometerScalingValue, sensor_values);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::ACCELEROMETER);
@@ -610,7 +607,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
// not available.
TEST_F(PlatformSensorAndProviderLinuxTest,
CheckLinearAccelerationSensorNotCreatedIfNoAccelerometer) {
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::LINEAR_ACCELERATION);
@@ -633,7 +629,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckLinearAcceleration) {
kAccelerometerFrequencyValue, kZero, kZero,
sensor_values);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::LINEAR_ACCELERATION);
@@ -679,7 +674,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckGyroscopeReadingConversion) {
InitializeSupportedSensor(SensorType::GYROSCOPE, kZero, kGyroscopeOffsetValue,
kGyroscopeScalingValue, sensor_values);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::GYROSCOPE);
@@ -740,7 +734,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest, CheckMagnetometerReadingConversion) {
kMagnetometerOffsetValue, kMagnetometerScalingValue,
sensor_values);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::MAGNETOMETER);
@@ -784,7 +777,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
kAmbientLightFrequencyValue, kZero, kZero,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::AMBIENT_LIGHT);
@@ -812,7 +804,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
TEST_F(
PlatformSensorAndProviderLinuxTest,
CheckAbsoluteOrientationSensorNotCreatedIfNoAccelerometerAndNoMagnetometer) {
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
{
@@ -834,7 +825,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::MAGNETOMETER, kMagnetometerFrequencyValue,
kMagnetometerOffsetValue, kMagnetometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
{
@@ -856,7 +846,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
{
@@ -880,7 +869,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::MAGNETOMETER, kMagnetometerFrequencyValue,
kMagnetometerOffsetValue, kMagnetometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION_EULER_ANGLES);
@@ -897,7 +885,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::MAGNETOMETER, kMagnetometerFrequencyValue,
kMagnetometerOffsetValue, kMagnetometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::ABSOLUTE_ORIENTATION_QUATERNION);
@@ -909,7 +896,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
TEST_F(
PlatformSensorAndProviderLinuxTest,
CheckRelativeOrientationSensorNotCreatedIfNoAccelerometerAndNoGyroscope) {
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
{
@@ -931,7 +917,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(SensorType::GYROSCOPE, kGyroscopeFrequencyValue,
kGyroscopeOffsetValue, kGyroscopeScalingValue,
sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
{
@@ -957,7 +942,6 @@ TEST_F(
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::RELATIVE_ORIENTATION_EULER_ANGLES);
@@ -972,7 +956,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::RELATIVE_ORIENTATION_EULER_ANGLES);
@@ -990,7 +973,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::RELATIVE_ORIENTATION_QUATERNION);
@@ -1005,7 +987,6 @@ TEST_F(PlatformSensorAndProviderLinuxTest,
InitializeSupportedSensor(
SensorType::ACCELEROMETER, kAccelerometerFrequencyValue,
kAccelerometerOffsetValue, kAccelerometerScalingValue, sensor_value);
- InitializeMockUdevMethods(sensors_dir_.GetPath());
SetServiceStart();
auto sensor = CreateSensor(SensorType::RELATIVE_ORIENTATION_QUATERNION);
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
index 1f951322af7..63e745911e9 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.cc
@@ -8,7 +8,7 @@
#include <vector>
#include "base/bind.h"
-#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_refptr.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
@@ -60,6 +60,8 @@ void PlatformSensorProviderLinux::CreateSensorInternal(
mojom::SensorType type,
SensorReadingSharedBuffer* reading_buffer,
CreateSensorCallback callback) {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
if (!sensor_nodes_enumerated_) {
if (!sensor_nodes_enumeration_started_) {
// Unretained() is safe because the deletion of |sensor_device_manager_|
@@ -84,20 +86,8 @@ void PlatformSensorProviderLinux::CreateSensorInternal(
return;
}
- SensorDeviceFound(type, reading_buffer, std::move(callback), sensor_device);
-}
-
-void PlatformSensorProviderLinux::SensorDeviceFound(
- mojom::SensorType type,
- SensorReadingSharedBuffer* reading_buffer,
- PlatformSensorProviderBase::CreateSensorCallback callback,
- const SensorInfoLinux* sensor_device) {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- DCHECK(sensor_device);
-
- scoped_refptr<PlatformSensorLinux> sensor =
- new PlatformSensorLinux(type, reading_buffer, this, sensor_device);
- std::move(callback).Run(sensor);
+ std::move(callback).Run(base::MakeRefCounted<PlatformSensorLinux>(
+ type, reading_buffer, this, sensor_device));
}
void PlatformSensorProviderLinux::FreeResources() {
@@ -113,12 +103,6 @@ SensorInfoLinux* PlatformSensorProviderLinux::GetSensorDevice(
return sensor->second.get();
}
-void PlatformSensorProviderLinux::GetAllSensorDevices() {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- // TODO(maksims): implement this method once we have discovery API.
- NOTIMPLEMENTED();
-}
-
void PlatformSensorProviderLinux::SetSensorDeviceManagerForTesting(
std::unique_ptr<SensorDeviceManager> sensor_device_manager) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
index 4a564385269..820003f1235 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider_linux.h
@@ -42,21 +42,12 @@ class PlatformSensorProviderLinux : public PlatformSensorProvider,
using SensorDeviceMap =
std::unordered_map<mojom::SensorType, std::unique_ptr<SensorInfoLinux>>;
- void SensorDeviceFound(
- mojom::SensorType type,
- SensorReadingSharedBuffer* reading_buffer,
- PlatformSensorProviderBase::CreateSensorCallback callback,
- const SensorInfoLinux* sensor_device);
-
// Returns SensorInfoLinux structure of a requested type.
// If a request cannot be processed immediately, returns nullptr and
// all the requests stored in |requests_map_| are processed after
// enumeration is ready.
SensorInfoLinux* GetSensorDevice(mojom::SensorType type);
- // Returns all found iio devices. Currently not implemented.
- void GetAllSensorDevices();
-
// Processed stored requests in |request_map_|.
void ProcessStoredRequests();
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.cc b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.cc
index fa980f8fddf..622d85f02ae 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.cc
@@ -299,20 +299,6 @@ void PlatformSensorReaderWinrtBase<
}
}
-template <wchar_t const* runtime_class_id,
- class ISensorWinrtStatics,
- class ISensorWinrtClass,
- class ISensorReadingChangedHandler,
- class ISensorReadingChangedEventArgs>
-PlatformSensorReaderWinrtBase<
- runtime_class_id,
- ISensorWinrtStatics,
- ISensorWinrtClass,
- ISensorReadingChangedHandler,
- ISensorReadingChangedEventArgs>::~PlatformSensorReaderWinrtBase() {
- StopSensor();
-}
-
// static
std::unique_ptr<PlatformSensorReaderWinBase>
PlatformSensorReaderWinrtLightSensor::Create() {
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
index cae0f6504be..0abc1c18628 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_winrt.h
@@ -74,7 +74,7 @@ class PlatformSensorReaderWinrtBase : public PlatformSensorReaderWinBase {
protected:
PlatformSensorReaderWinrtBase();
- virtual ~PlatformSensorReaderWinrtBase();
+ virtual ~PlatformSensorReaderWinrtBase() { StopSensor(); }
// Derived classes should implement this function to handle sensor specific
// parsing of the sensor reading.
diff --git a/chromium/services/device/geolocation/BUILD.gn b/chromium/services/device/geolocation/BUILD.gn
index 45e6296d458..bc366b81794 100644
--- a/chromium/services/device/geolocation/BUILD.gn
+++ b/chromium/services/device/geolocation/BUILD.gn
@@ -70,8 +70,8 @@ source_set("geolocation") {
deps = [
"//base",
- "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/system",
"//net",
"//ui/gfx",
]
diff --git a/chromium/services/device/geolocation/geolocation_context.cc b/chromium/services/device/geolocation/geolocation_context.cc
index 379b7651ea6..a41139ad815 100644
--- a/chromium/services/device/geolocation/geolocation_context.cc
+++ b/chromium/services/device/geolocation/geolocation_context.cc
@@ -24,7 +24,8 @@ void GeolocationContext::Create(
}
void GeolocationContext::BindGeolocation(
- mojo::PendingReceiver<mojom::Geolocation> receiver) {
+ mojo::PendingReceiver<mojom::Geolocation> receiver,
+ const GURL& requesting_origin) {
GeolocationImpl* impl = new GeolocationImpl(std::move(receiver), this);
impls_.push_back(base::WrapUnique<GeolocationImpl>(impl));
if (geoposition_override_)
diff --git a/chromium/services/device/geolocation/geolocation_context.h b/chromium/services/device/geolocation/geolocation_context.h
index d5863794b0f..b7c65a67a68 100644
--- a/chromium/services/device/geolocation/geolocation_context.h
+++ b/chromium/services/device/geolocation/geolocation_context.h
@@ -30,8 +30,8 @@ class GeolocationContext : public mojom::GeolocationContext {
static void Create(mojo::PendingReceiver<mojom::GeolocationContext> receiver);
// mojom::GeolocationContext implementation:
- void BindGeolocation(
- mojo::PendingReceiver<mojom::Geolocation> receiver) override;
+ void BindGeolocation(mojo::PendingReceiver<mojom::Geolocation> receiver,
+ const GURL& requesting_origin) override;
void SetOverride(mojom::GeopositionPtr geoposition) override;
void ClearOverride() override;
diff --git a/chromium/services/device/geolocation/geolocation_service_unittest.cc b/chromium/services/device/geolocation/geolocation_service_unittest.cc
index 52ebfee8e3a..70547aab16b 100644
--- a/chromium/services/device/geolocation/geolocation_service_unittest.cc
+++ b/chromium/services/device/geolocation/geolocation_service_unittest.cc
@@ -54,7 +54,7 @@ class GeolocationServiceUnitTest : public DeviceServiceTestBase {
device_service()->BindGeolocationContext(
geolocation_context_.BindNewPipeAndPassReceiver());
geolocation_context_->BindGeolocation(
- geolocation_.BindNewPipeAndPassReceiver());
+ geolocation_.BindNewPipeAndPassReceiver(), GURL::EmptyGURL());
}
void TearDown() override {
diff --git a/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc b/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc
index 258ce53af1a..d6e7b4ddc15 100644
--- a/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc
+++ b/chromium/services/device/geolocation/public_ip_address_geolocator_unittest.cc
@@ -9,9 +9,9 @@
#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/test/task_environment.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
+#include "mojo/public/cpp/system/functions.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "services/network/public/cpp/weak_wrapper_shared_url_loader_factory.h"
#include "services/network/test/test_network_connection_tracker.h"
@@ -42,7 +42,7 @@ class PublicIpAddressGeolocatorTest : public testing::Test {
protected:
void SetUp() override {
// Intercept Mojo bad-message errors.
- mojo::core::SetDefaultProcessErrorCallback(
+ mojo::SetDefaultProcessErrorHandler(
base::BindRepeating(&PublicIpAddressGeolocatorTest::OnMojoBadMessage,
base::Unretained(this)));
@@ -57,8 +57,7 @@ class PublicIpAddressGeolocatorTest : public testing::Test {
void TearDown() override {
// Stop intercepting Mojo bad-message errors.
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
// Deal with mojo bad message.
diff --git a/chromium/services/device/geolocation/wifi_data_provider_chromeos.cc b/chromium/services/device/geolocation/wifi_data_provider_chromeos.cc
index 6698a7f6588..37bc1d54eae 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_chromeos.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_chromeos.cc
@@ -9,6 +9,7 @@
#include <stdint.h>
#include "base/bind.h"
+#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "chromeos/network/geolocation_handler.h"
#include "chromeos/network/network_handler.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_common.h b/chromium/services/device/geolocation/wifi_data_provider_common.h
index 19a168eb4c6..2590e0a83ae 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_common.h
+++ b/chromium/services/device/geolocation/wifi_data_provider_common.h
@@ -10,7 +10,6 @@
#include <memory>
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_linux.cc b/chromium/services/device/geolocation/wifi_data_provider_linux.cc
index 549df44c578..ffb0cb08820 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_linux.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_linux.cc
@@ -16,6 +16,7 @@
#include <utility>
#include <vector>
+#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_linux_unittest.cc b/chromium/services/device/geolocation/wifi_data_provider_linux_unittest.cc
index af08db71f86..0552077b043 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_linux_unittest.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_linux_unittest.cc
@@ -8,6 +8,7 @@
#include <memory>
+#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_mac.mm b/chromium/services/device/geolocation/wifi_data_provider_mac.mm
index 49cd5870f26..5764adf247c 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_mac.mm
+++ b/chromium/services/device/geolocation/wifi_data_provider_mac.mm
@@ -7,6 +7,7 @@
#import <CoreWLAN/CoreWLAN.h>
#import <Foundation/Foundation.h>
+#include "base/logging.h"
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
diff --git a/chromium/services/device/geolocation/wifi_data_provider_win.cc b/chromium/services/device/geolocation/wifi_data_provider_win.cc
index 0dd3a5f8875..e383a590996 100644
--- a/chromium/services/device/geolocation/wifi_data_provider_win.cc
+++ b/chromium/services/device/geolocation/wifi_data_provider_win.cc
@@ -8,6 +8,7 @@
#include <winioctl.h>
#include <wlanapi.h>
+#include "base/logging.h"
#include "base/memory/free_deleter.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
diff --git a/chromium/services/device/hid/hid_service.h b/chromium/services/device/hid/hid_service.h
index 1db1f5fbe51..49a49dd7ae9 100644
--- a/chromium/services/device/hid/hid_service.h
+++ b/chromium/services/device/hid/hid_service.h
@@ -11,7 +11,7 @@
#include <vector>
#include "base/bind_helpers.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/services/device/hid/hid_service_linux.cc b/chromium/services/device/hid/hid_service_linux.cc
index 55c636faf1e..28bf7f8641f 100644
--- a/chromium/services/device/hid/hid_service_linux.cc
+++ b/chromium/services/device/hid/hid_service_linux.cc
@@ -5,6 +5,7 @@
#include "services/device/hid/hid_service_linux.h"
#include <fcntl.h>
+#include <linux/input.h>
#include <stdint.h>
#include <limits>
@@ -24,6 +25,7 @@
#include "base/sequenced_task_runner.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
+#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
@@ -42,11 +44,132 @@ namespace device {
namespace {
-const char kHidrawSubsystem[] = "hidraw";
+const char kDevtypeUsbDevice[] = "usb_device";
+const char kSubsystemBluetooth[] = "bluetooth";
+const char kSubsystemHid[] = "hid";
+const char kSubsystemHidraw[] = "hidraw";
+const char kSubsystemUsb[] = "usb";
const char kHIDID[] = "HID_ID";
const char kHIDName[] = "HID_NAME";
const char kHIDUnique[] = "HID_UNIQ";
const char kSysfsReportDescriptorKey[] = "report_descriptor";
+const char kKernelHciPrefix[] = "hci";
+
+// Walks up the sysfs device tree starting at |device| and returns the first
+// ancestor in the "hid" subsystem. Returns nullptr on failure.
+udev_device* FindFirstHidAncestor(udev_device* device) {
+ udev_device* ancestor = device;
+ do {
+ const char* subsystem = udev_device_get_subsystem(ancestor);
+ if (!subsystem)
+ return nullptr;
+ if (strcmp(subsystem, kSubsystemHid) == 0)
+ return ancestor;
+ } while ((ancestor = udev_device_get_parent(ancestor)));
+ return nullptr;
+}
+
+// Walks up the sysfs device tree starting at |device| and returns the first
+// ancestor not in the "hid" or "hidraw" subsystems. Returns nullptr on failure.
+udev_device* FindFirstNonHidAncestor(udev_device* device) {
+ udev_device* ancestor = device;
+ do {
+ const char* subsystem = udev_device_get_subsystem(ancestor);
+ if (!subsystem)
+ return nullptr;
+ if (strcmp(subsystem, kSubsystemHid) != 0 &&
+ strcmp(subsystem, kSubsystemHidraw) != 0) {
+ return ancestor;
+ }
+ } while ((ancestor = udev_device_get_parent(ancestor)));
+ return nullptr;
+}
+
+// Returns the sysfs path for a USB device |usb_device|, or nullptr if the sysfs
+// path could not be retrieved. |usb_device| must be a device in the "usb"
+// subsystem.
+//
+// Some USB devices expose multiple interfaces. If |usb_device| refers to a
+// single USB interface, walk up the device tree to find the ancestor that
+// represents the physical device.
+const char* GetUsbDeviceSyspath(udev_device* usb_device) {
+ do {
+ const char* subsystem = udev_device_get_subsystem(usb_device);
+ if (!subsystem || strcmp(subsystem, kSubsystemUsb) != 0)
+ return nullptr;
+
+ const char* devtype = udev_device_get_devtype(usb_device);
+ if (!devtype)
+ return nullptr;
+
+ // Use the syspath of the first ancestor with devtype "usb_device".
+ if (strcmp(devtype, kDevtypeUsbDevice) == 0)
+ return udev_device_get_syspath(usb_device);
+ } while ((usb_device = udev_device_get_parent(usb_device)));
+ return nullptr;
+}
+
+// Returns the sysfs path for a Bluetooth Classic device |bt_device|, or nullptr
+// if the sysfs path could not be retrieved. |bt_device| must be a device in the
+// "bluetooth" subsystem.
+const char* GetBluetoothDeviceSyspath(udev_device* bt_device) {
+ do {
+ const char* subsystem = udev_device_get_subsystem(bt_device);
+ if (!subsystem || strcmp(subsystem, kSubsystemBluetooth) != 0)
+ return nullptr;
+
+ // Look for a sysname like "hci0:123".
+ const char* sysfs_name = udev_device_get_sysname(bt_device);
+ if (!sysfs_name)
+ return nullptr;
+
+ std::vector<std::string> parts = base::SplitString(
+ sysfs_name, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ if (parts.size() == 2 && base::StartsWith(parts[0], kKernelHciPrefix,
+ base::CompareCase::SENSITIVE)) {
+ return udev_device_get_syspath(bt_device);
+ }
+ } while ((bt_device = udev_device_get_parent(bt_device)));
+ return nullptr;
+}
+
+// Returns the physical device ID for a device |hidraw_device|. On Linux, the
+// physical device ID is the sysfs path to the device node that represents the
+// physical device if it is available. When the physical device node is not
+// available, the sysfs path of the HID interface is returned instead. Returns
+// nullptr on failure.
+const char* GetPhysicalDeviceId(udev_device* hidraw_device) {
+ const char* subsystem = udev_device_get_subsystem(hidraw_device);
+ if (!subsystem || strcmp(subsystem, kSubsystemHidraw) != 0)
+ return nullptr;
+
+ udev_device* hid_ancestor = FindFirstHidAncestor(hidraw_device);
+ if (!hid_ancestor)
+ return nullptr;
+ const char* hid_sysfs_path = udev_device_get_syspath(hid_ancestor);
+
+ udev_device* ancestor = FindFirstNonHidAncestor(hid_ancestor);
+ if (!ancestor)
+ return hid_sysfs_path;
+
+ const char* ancestor_subsystem = udev_device_get_subsystem(ancestor);
+ if (!ancestor_subsystem)
+ return hid_sysfs_path;
+
+ if (strcmp(ancestor_subsystem, kSubsystemUsb) == 0) {
+ const char* usb_sysfs_path = GetUsbDeviceSyspath(ancestor);
+ if (usb_sysfs_path)
+ return usb_sysfs_path;
+ }
+
+ if (strcmp(ancestor_subsystem, kSubsystemBluetooth) == 0) {
+ const char* bt_sysfs_path = GetBluetoothDeviceSyspath(ancestor);
+ if (bt_sysfs_path)
+ return bt_sysfs_path;
+ }
+
+ return hid_sysfs_path;
+}
} // namespace
@@ -82,7 +205,8 @@ class HidServiceLinux::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
void Start() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- watcher_ = UdevWatcher::StartWatching(this);
+ watcher_ = UdevWatcher::StartWatching(
+ this, {UdevWatcher::Filter(kSubsystemHidraw, "")});
watcher_->EnumerateExistingDevices();
task_runner_->PostTask(
FROM_HERE,
@@ -101,9 +225,11 @@ class HidServiceLinux::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
return;
HidPlatformDeviceId platform_device_id = device_path;
+#if DCHECK_IS_ON()
const char* subsystem = udev_device_get_subsystem(device.get());
- if (!subsystem || strcmp(subsystem, kHidrawSubsystem) != 0)
- return;
+ DCHECK(subsystem);
+ DCHECK_EQ(base::StringPiece(subsystem), kSubsystemHidraw);
+#endif
const char* str_property = udev_device_get_devnode(device.get());
if (!str_property)
@@ -155,14 +281,21 @@ class HidServiceLinux::BlockingTaskRunnerHelper : public UdevWatcher::Observer {
if (!base::ReadFileToString(report_descriptor_path, &report_descriptor_str))
return;
- scoped_refptr<HidDeviceInfo> device_info(
- new HidDeviceInfo(platform_device_id, /*physical_device_id=*/"",
- vendor_id, product_id, product_name, serial_number,
- // TODO(reillyg): Detect Bluetooth. crbug.com/443335
- mojom::HidBusType::kHIDBusTypeUSB,
- std::vector<uint8_t>(report_descriptor_str.begin(),
- report_descriptor_str.end()),
- device_node));
+ const char* physical_device_id = GetPhysicalDeviceId(device.get());
+ if (!physical_device_id) {
+ HID_LOG(EVENT) << "GetPhysicalDeviceId failed for '" << device_path
+ << "'";
+ return;
+ }
+
+ auto device_info = base::MakeRefCounted<HidDeviceInfo>(
+ platform_device_id, physical_device_id, vendor_id, product_id,
+ product_name, serial_number,
+ // TODO(reillyg): Detect Bluetooth. crbug.com/443335
+ mojom::HidBusType::kHIDBusTypeUSB,
+ std::vector<uint8_t>(report_descriptor_str.begin(),
+ report_descriptor_str.end()),
+ device_node);
task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/services/device/hid/hid_service_mac.cc b/chromium/services/device/hid/hid_service_mac.cc
index f65c8afda57..5ef38b1e0ba 100644
--- a/chromium/services/device/hid/hid_service_mac.cc
+++ b/chromium/services/device/hid/hid_service_mac.cc
@@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/mac/foundation_util.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/thread_pool.h"
@@ -78,8 +79,11 @@ scoped_refptr<HidDeviceInfo> CreateDeviceInfo(
HID_LOG(DEBUG) << "Device report descriptor not available.";
}
+ int32_t location_id = GetIntProperty(service, CFSTR(kIOHIDLocationIDKey));
+ std::string physical_device_id = base::NumberToString(location_id);
+
return new HidDeviceInfo(
- entry_id, /*physical_device_id=*/"",
+ entry_id, physical_device_id,
GetIntProperty(service, CFSTR(kIOHIDVendorIDKey)),
GetIntProperty(service, CFSTR(kIOHIDProductIDKey)),
GetStringProperty(service, CFSTR(kIOHIDProductKey)),
diff --git a/chromium/services/device/hid/hid_service_win.cc b/chromium/services/device/hid/hid_service_win.cc
index b9a5e7a3ec6..80fff2d39a8 100644
--- a/chromium/services/device/hid/hid_service_win.cc
+++ b/chromium/services/device/hid/hid_service_win.cc
@@ -4,15 +4,16 @@
#include "services/device/hid/hid_service_win.h"
-#include <memory>
-
#define INITGUID
#include <dbt.h>
+#include <devpkey.h>
#include <setupapi.h>
#include <stddef.h>
+#include <wdmguid.h>
#include <winioctl.h>
+#include <memory>
#include <utility>
#include "base/bind.h"
@@ -22,15 +23,112 @@
#include "base/memory/free_deleter.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_util.h"
-#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/task/thread_pool.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "base/win/scoped_devinfo.h"
+#include "base/win/win_util.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/hid/hid_connection_win.h"
#include "services/device/hid/hid_device_info.h"
namespace device {
+namespace {
+
+// Looks up the value of a GUID-type device property specified by |property| for
+// the device described by |device_info_data|. On success, returns true and sets
+// |property_buffer| to the property value. Returns false if the property is not
+// present or has a different type.
+bool GetDeviceGuidProperty(HDEVINFO device_info_set,
+ SP_DEVINFO_DATA& device_info_data,
+ const DEVPROPKEY& property,
+ GUID* property_buffer) {
+ DEVPROPTYPE property_type;
+ if (!SetupDiGetDeviceProperty(
+ device_info_set, &device_info_data, &property, &property_type,
+ reinterpret_cast<PBYTE>(property_buffer), sizeof(*property_buffer),
+ /*RequiredSize=*/nullptr, /*Flags=*/0) ||
+ property_type != DEVPROP_TYPE_GUID) {
+ return false;
+ }
+ return true;
+}
+
+// Looks up information about the device described by |device_interface_data|
+// in |device_info_set|. On success, returns true and sets |device_info_data|
+// and |device_path|. Returns false if an error occurred.
+bool GetDeviceInfoAndPathFromInterface(
+ HDEVINFO device_info_set,
+ SP_DEVICE_INTERFACE_DATA& device_interface_data,
+ SP_DEVINFO_DATA* device_info_data,
+ base::string16* device_path) {
+ // Get the required buffer size. When called with
+ // DeviceInterfaceDetailData == nullptr and DeviceInterfaceDetailSize == 0,
+ // SetupDiGetDeviceInterfaceDetail returns the required buffer size at
+ // RequiredSize and fails with GetLastError() == ERROR_INSUFFICIENT_BUFFER.
+ DWORD required_size;
+ if (SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data,
+ /*DeviceInterfaceDetailData=*/nullptr,
+ /*DeviceInterfaceDetailSize=*/0,
+ &required_size,
+ /*DeviceInfoData=*/nullptr) ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
+ return false;
+ }
+
+ std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
+ device_interface_detail_data(
+ static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size)));
+ device_interface_detail_data->cbSize = sizeof(*device_interface_detail_data);
+
+ // Call the function again with the correct buffer size to get the detailed
+ // data for this device.
+ if (!SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data,
+ device_interface_detail_data.get(),
+ required_size, /*RequiredSize=*/nullptr,
+ device_info_data)) {
+ return false;
+ }
+
+ // Windows uses case-insensitive paths and may return paths that differ only
+ // by case. Canonicalize the device path by converting to lowercase.
+ base::string16 path =
+ base::string16(device_interface_detail_data->DevicePath);
+ DCHECK(base::IsStringASCII(path));
+ *device_path = base::ToLowerASCII(path);
+ return true;
+}
+
+// Returns a device info set containing only the device described by
+// |device_path|, or an invalid ScopedDevInfo if there was an error while
+// creating the device set. The device info is returned in |device_info_data|.
+base::win::ScopedDevInfo GetDeviceInfoFromPath(
+ const base::string16& device_path,
+ SP_DEVINFO_DATA* device_info_data) {
+ base::win::ScopedDevInfo device_info_set(SetupDiGetClassDevs(
+ &GUID_DEVINTERFACE_HID, /*Enumerator=*/nullptr,
+ /*hwndParent=*/0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
+ if (!device_info_set.is_valid())
+ return base::win::ScopedDevInfo();
+
+ SP_DEVICE_INTERFACE_DATA device_interface_data;
+ device_interface_data.cbSize = sizeof(device_interface_data);
+ if (!SetupDiOpenDeviceInterface(device_info_set.get(), device_path.c_str(),
+ /*OpenFlags=*/0, &device_interface_data)) {
+ return base::win::ScopedDevInfo();
+ }
+
+ base::string16 intf_device_path;
+ GetDeviceInfoAndPathFromInterface(device_info_set.get(),
+ device_interface_data, device_info_data,
+ &intf_device_path);
+ DCHECK_EQ(intf_device_path, device_path);
+ return device_info_set;
+}
+
+} // namespace
+
HidServiceWin::HidServiceWin()
: task_runner_(base::SequencedTaskRunnerHandle::Get()),
blocking_task_runner_(
@@ -81,41 +179,37 @@ base::WeakPtr<HidService> HidServiceWin::GetWeakPtr() {
void HidServiceWin::EnumerateBlocking(
base::WeakPtr<HidServiceWin> service,
scoped_refptr<base::SequencedTaskRunner> task_runner) {
- HDEVINFO device_info_set =
- SetupDiGetClassDevs(&GUID_DEVINTERFACE_HID, NULL, NULL,
- DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
+ base::win::ScopedDevInfo dev_info(SetupDiGetClassDevs(
+ &GUID_DEVINTERFACE_HID, /*Enumerator=*/nullptr,
+ /*hwndParent=*/nullptr, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE));
- if (device_info_set != INVALID_HANDLE_VALUE) {
- SP_DEVICE_INTERFACE_DATA device_interface_data;
- device_interface_data.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
+ if (dev_info.is_valid()) {
+ SP_DEVICE_INTERFACE_DATA device_interface_data = {0};
+ device_interface_data.cbSize = sizeof(device_interface_data);
for (int device_index = 0; SetupDiEnumDeviceInterfaces(
- device_info_set, NULL, &GUID_DEVINTERFACE_HID, device_index,
- &device_interface_data);
+ dev_info.get(), /*DeviceInfoData=*/nullptr, &GUID_DEVINTERFACE_HID,
+ device_index, &device_interface_data);
++device_index) {
- DWORD required_size = 0;
-
- // Determime the required size of detail struct.
- SetupDiGetDeviceInterfaceDetail(device_info_set, &device_interface_data,
- NULL, 0, &required_size, NULL);
+ SP_DEVINFO_DATA dev_info_data = {0};
+ dev_info_data.cbSize = sizeof(dev_info_data);
+ base::string16 device_path;
+ if (!GetDeviceInfoAndPathFromInterface(dev_info.get(),
+ device_interface_data,
+ &dev_info_data, &device_path)) {
+ continue;
+ }
- std::unique_ptr<SP_DEVICE_INTERFACE_DETAIL_DATA, base::FreeDeleter>
- device_interface_detail_data(
- static_cast<SP_DEVICE_INTERFACE_DETAIL_DATA*>(malloc(required_size)));
- device_interface_detail_data->cbSize =
- sizeof(SP_DEVICE_INTERFACE_DETAIL_DATA);
-
- // Get the detailed data for this device.
- BOOL res = SetupDiGetDeviceInterfaceDetail(
- device_info_set, &device_interface_data,
- device_interface_detail_data.get(), required_size, NULL, NULL);
- if (!res) {
+ // Get the container ID for the physical device.
+ GUID container_id;
+ if (!GetDeviceGuidProperty(dev_info.get(), dev_info_data,
+ DEVPKEY_Device_ContainerId, &container_id)) {
continue;
}
+ std::string physical_device_id =
+ base::UTF16ToUTF8(base::win::String16FromGUID(container_id));
- base::string16 device_path(device_interface_detail_data->DevicePath);
- DCHECK(base::IsStringASCII(device_path));
- AddDeviceBlocking(service, task_runner, base::ToLowerASCII(device_path));
+ AddDeviceBlocking(service, task_runner, device_path, physical_device_id);
}
}
@@ -170,14 +264,15 @@ void HidServiceWin::CollectInfoFromValueCaps(
void HidServiceWin::AddDeviceBlocking(
base::WeakPtr<HidServiceWin> service,
scoped_refptr<base::SequencedTaskRunner> task_runner,
- const base::string16& device_path) {
+ const base::string16& device_path,
+ const std::string& physical_device_id) {
base::win::ScopedHandle device_handle(OpenDevice(device_path));
if (!device_handle.IsValid()) {
return;
}
HIDD_ATTRIBUTES attrib = {0};
- attrib.Size = sizeof(HIDD_ATTRIBUTES);
+ attrib.Size = sizeof(attrib);
if (!HidD_GetAttributes(device_handle.Get(), &attrib)) {
HID_LOG(EVENT) << "Failed to get device attributes.";
return;
@@ -237,24 +332,24 @@ void HidServiceWin::AddDeviceBlocking(
// 1023 characters plus NULL terminator is more than enough for a USB string
// descriptor which is limited to 126 characters.
- wchar_t buffer[1024];
+ base::char16 buffer[1024];
std::string product_name;
if (HidD_GetProductString(device_handle.Get(), &buffer[0], sizeof(buffer))) {
// NULL termination guaranteed by the API.
- product_name = base::SysWideToUTF8(buffer);
+ product_name = base::UTF16ToUTF8(buffer);
}
std::string serial_number;
if (HidD_GetSerialNumberString(device_handle.Get(), &buffer[0],
sizeof(buffer))) {
// NULL termination guaranteed by the API.
- serial_number = base::SysWideToUTF8(buffer);
+ serial_number = base::UTF16ToUTF8(buffer);
}
// This populates the HidDeviceInfo instance without a raw report descriptor.
// The descriptor is unavailable on Windows because HID devices are exposed to
// user-space as individual top-level collections.
scoped_refptr<HidDeviceInfo> device_info(new HidDeviceInfo(
- device_path, /*physical_device_id=*/"", attrib.VendorID, attrib.ProductID,
+ device_path, physical_device_id, attrib.VendorID, attrib.ProductID,
product_name, serial_number,
// TODO(reillyg): Detect Bluetooth. crbug.com/443335
mojom::HidBusType::kHIDBusTypeUSB, std::move(collection_info),
@@ -267,10 +362,24 @@ void HidServiceWin::AddDeviceBlocking(
void HidServiceWin::OnDeviceAdded(const GUID& class_guid,
const base::string16& device_path) {
+ SP_DEVINFO_DATA device_info_data = {0};
+ device_info_data.cbSize = sizeof(device_info_data);
+ auto device_info_set = GetDeviceInfoFromPath(device_path, &device_info_data);
+ if (!device_info_set.is_valid())
+ return;
+
+ GUID container_id;
+ if (!GetDeviceGuidProperty(device_info_set.get(), device_info_data,
+ DEVPKEY_Device_ContainerId, &container_id)) {
+ return;
+ }
+ std::string physical_device_id =
+ base::UTF16ToUTF8(base::win::String16FromGUID(container_id));
+
blocking_task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(&HidServiceWin::AddDeviceBlocking,
- weak_factory_.GetWeakPtr(), task_runner_, device_path));
+ FROM_HERE, base::BindOnce(&HidServiceWin::AddDeviceBlocking,
+ weak_factory_.GetWeakPtr(), task_runner_,
+ device_path, physical_device_id));
}
void HidServiceWin::OnDeviceRemoved(const GUID& class_guid,
diff --git a/chromium/services/device/hid/hid_service_win.h b/chromium/services/device/hid/hid_service_win.h
index 4965888e989..ac6745f3aaf 100644
--- a/chromium/services/device/hid/hid_service_win.h
+++ b/chromium/services/device/hid/hid_service_win.h
@@ -59,7 +59,8 @@ class HidServiceWin : public HidService, public DeviceMonitorWin::Observer {
static void AddDeviceBlocking(
base::WeakPtr<HidServiceWin> service,
scoped_refptr<base::SequencedTaskRunner> task_runner,
- const base::string16& device_path);
+ const base::string16& device_path,
+ const std::string& physical_device_id);
// DeviceMonitorWin::Observer implementation:
void OnDeviceAdded(const GUID& class_guid,
diff --git a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
index 67991e5272c..5fcd34093f2 100644
--- a/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
+++ b/chromium/services/device/media_transfer_protocol/mtp_device_manager.h
@@ -13,7 +13,6 @@
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/queue.h"
-#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/sequenced_task_runner.h"
#include "base/threading/thread_checker.h"
diff --git a/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NfcBlocklistTest.java b/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NfcBlocklistTest.java
index a94863557f0..be7b36f3e0a 100644
--- a/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NfcBlocklistTest.java
+++ b/chromium/services/device/nfc/android/junit/src/org/chromium/device/nfc/NfcBlocklistTest.java
@@ -18,7 +18,7 @@ import org.chromium.base.test.util.Feature;
* Unit tests for the {@link NfcBlocklist} class.
*/
@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@Config(sdk = 21, manifest = Config.NONE)
public class NfcBlocklistTest {
// Static historical bytes
private static final byte[] YUBIKEY_NEO_HISTORICAL_BYTES = new byte[] {
@@ -87,4 +87,4 @@ public class NfcBlocklistTest {
assertFalse(areHistoricalBytesBlocked(new byte[] {}));
assertFalse(areHistoricalBytesBlocked(new byte[] {0x01, 0x02, 0x03}));
}
-} \ No newline at end of file
+}
diff --git a/chromium/services/device/public/cpp/device_feature_list.cc b/chromium/services/device/public/cpp/device_feature_list.cc
index 04d1858ae6a..28284fc701c 100644
--- a/chromium/services/device/public/cpp/device_feature_list.cc
+++ b/chromium/services/device/public/cpp/device_feature_list.cc
@@ -4,6 +4,7 @@
#include "base/android/jni_string.h"
#include "base/feature_list.h"
+#include "base/notreached.h"
#include "base/stl_util.h"
#include "services/device/device_service_jni_headers/DeviceFeatureList_jni.h"
#include "services/device/public/cpp/device_features.h"
diff --git a/chromium/services/device/public/cpp/generic_sensor/platform_sensor_configuration.h b/chromium/services/device/public/cpp/generic_sensor/platform_sensor_configuration.h
index 93e8507e136..e75d20d6273 100644
--- a/chromium/services/device/public/cpp/generic_sensor/platform_sensor_configuration.h
+++ b/chromium/services/device/public/cpp/generic_sensor/platform_sensor_configuration.h
@@ -5,7 +5,6 @@
#ifndef SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_PLATFORM_SENSOR_CONFIGURATION_H_
#define SERVICES_DEVICE_PUBLIC_CPP_GENERIC_SENSOR_PLATFORM_SENSOR_CONFIGURATION_H_
-#include "base/logging.h"
namespace device {
diff --git a/chromium/services/device/public/cpp/hid/fake_hid_manager.cc b/chromium/services/device/public/cpp/hid/fake_hid_manager.cc
index ca3c5c63465..eae9dede08c 100644
--- a/chromium/services/device/public/cpp/hid/fake_hid_manager.cc
+++ b/chromium/services/device/public/cpp/hid/fake_hid_manager.cc
@@ -92,7 +92,7 @@ void FakeHidConnection::SendFeatureReport(uint8_t report_id,
}
// Implementation of FakeHidManager.
-FakeHidManager::FakeHidManager() {}
+FakeHidManager::FakeHidManager() = default;
FakeHidManager::~FakeHidManager() = default;
void FakeHidManager::Bind(mojo::PendingReceiver<mojom::HidManager> receiver) {
@@ -105,6 +105,9 @@ void FakeHidManager::GetDevicesAndSetClient(
GetDevicesCallback callback) {
GetDevices(std::move(callback));
+ if (!client.is_valid())
+ return;
+
clients_.Add(std::move(client));
}
@@ -201,4 +204,9 @@ void FakeHidManager::RemoveDevice(const std::string& guid) {
}
}
+void FakeHidManager::SimulateConnectionError() {
+ clients_.Clear();
+ receivers_.Clear();
+}
+
} // namespace device
diff --git a/chromium/services/device/public/cpp/hid/fake_hid_manager.h b/chromium/services/device/public/cpp/hid/fake_hid_manager.h
index e4319ee221a..7c7f0c02774 100644
--- a/chromium/services/device/public/cpp/hid/fake_hid_manager.h
+++ b/chromium/services/device/public/cpp/hid/fake_hid_manager.h
@@ -20,6 +20,8 @@ namespace device {
class FakeHidConnection : public mojom::HidConnection {
public:
explicit FakeHidConnection(mojom::HidDeviceInfoPtr device);
+ FakeHidConnection(FakeHidConnection&) = delete;
+ FakeHidConnection& operator=(FakeHidConnection&) = delete;
~FakeHidConnection() override;
// mojom::HidConnection implementation:
@@ -41,6 +43,8 @@ class FakeHidConnection : public mojom::HidConnection {
class FakeHidManager : public mojom::HidManager {
public:
FakeHidManager();
+ FakeHidManager(FakeHidManager&) = delete;
+ FakeHidManager& operator=(FakeHidManager&) = delete;
~FakeHidManager() override;
void Bind(mojo::PendingReceiver<mojom::HidManager> receiver);
@@ -74,6 +78,7 @@ class FakeHidManager : public mojom::HidManager {
uint16_t usage);
void AddDevice(mojom::HidDeviceInfoPtr device);
void RemoveDevice(const std::string& guid);
+ void SimulateConnectionError();
private:
std::map<std::string, mojom::HidDeviceInfoPtr> devices_;
diff --git a/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.cc b/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.cc
index fd406fe6d47..c40fd7d74bd 100644
--- a/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.cc
+++ b/chromium/services/device/public/cpp/hid/hid_report_descriptor_item.cc
@@ -26,8 +26,8 @@ HidReportDescriptorItem::HidReportDescriptorItem(
size_t size,
HidReportDescriptorItem* previous)
: previous_(previous),
- next_(NULL),
- parent_(NULL),
+ next_(nullptr),
+ parent_(nullptr),
shortData_(0),
payload_size_(0) {
Header* header = (Header*)&bytes[0];
diff --git a/chromium/services/device/public/mojom/BUILD.gn b/chromium/services/device/public/mojom/BUILD.gn
index 6a3a2ae2b6c..221576f2369 100644
--- a/chromium/services/device/public/mojom/BUILD.gn
+++ b/chromium/services/device/public/mojom/BUILD.gn
@@ -37,6 +37,7 @@ mojom("mojom") {
"//mojo/public/mojom/base",
"//services/network/public/mojom",
"//services/network/public/mojom:mutable_network_traffic_annotation_interface",
+ "//url/mojom:url_mojom_gurl",
]
if (is_chromeos) {
diff --git a/chromium/services/device/public/mojom/geolocation_context.mojom b/chromium/services/device/public/mojom/geolocation_context.mojom
index 2123c45c4ac..1917b339b9f 100644
--- a/chromium/services/device/public/mojom/geolocation_context.mojom
+++ b/chromium/services/device/public/mojom/geolocation_context.mojom
@@ -6,13 +6,18 @@ module device.mojom;
import "services/device/public/mojom/geolocation.mojom";
import "services/device/public/mojom/geoposition.mojom";
+import "url/mojom/url.mojom";
// GeolocationContext provides methods to bind Geolocation instance and to
// set/clear overrides of geoposition that will apply to all Geolocation
// instances created by this context.
interface GeolocationContext {
// Creates a Geolocation instance that is bound to the |request|.
- BindGeolocation(pending_receiver<Geolocation> receiver);
+ // The |origin| is the origin of the top-level frame which the |request| from,
+ // it is only used for |InstalledWebappGeolocationContext| to separate request
+ // from different Trusted Web Activity client apps.
+ BindGeolocation(pending_receiver<Geolocation> receiver,
+ url.mojom.Url origin);
// Enables geolocation override. This method can be used to trigger possible
// location-specific behavior in GeolocationImpl created by this
diff --git a/chromium/services/device/public/mojom/nfc_provider.mojom b/chromium/services/device/public/mojom/nfc_provider.mojom
index ae2e89241a5..b4638000cea 100644
--- a/chromium/services/device/public/mojom/nfc_provider.mojom
+++ b/chromium/services/device/public/mojom/nfc_provider.mojom
@@ -10,7 +10,7 @@ interface NFCProvider {
// Gets an NFC that is associated with |host_id|. |host_id|
// is used to obtain the Activity that this NFC instance should use on
// Android (see NFCDelegate.java).
- GetNFCForHost(int32 host_id, NFC& nfc);
+ GetNFCForHost(int32 host_id, pending_receiver<NFC> receiver);
// Suspends all pending NFC operations. Could be used when web page
// visibility is lost.
diff --git a/chromium/services/device/public/mojom/serial.mojom b/chromium/services/device/public/mojom/serial.mojom
index b4a089120b0..b24628c54ee 100644
--- a/chromium/services/device/public/mojom/serial.mojom
+++ b/chromium/services/device/public/mojom/serial.mojom
@@ -9,7 +9,19 @@ import "mojo/public/mojom/base/unguessable_token.mojom";
struct SerialPortInfo {
mojo_base.mojom.UnguessableToken token;
+
+ // This platform-specific identifier, if present, can be used to identify the
+ // device across restarts of the application and operating system.
+ string? persistent_id;
+
mojo_base.mojom.FilePath path;
+
+ // On macOS a serial device may have two paths, one for the call-out device
+ // and one for the dial-in device. The call-out device is preferred. If
+ // there is also an associated dial-in device its path is provided here. If
+ // the dial-in device is the only option its path will be in |path|.
+ [EnableIf=is_mac] mojo_base.mojom.FilePath? alternate_path;
+
uint16 vendor_id;
bool has_vendor_id = false;
uint16 product_id;
@@ -100,9 +112,11 @@ interface SerialPortManager {
GetDevices() => (array<SerialPortInfo> devices);
// Creates a SerialPort instance attached to the port represented by |token|.
- // When the pipe passed in |port_receiver| is closed the optional pipe passed
- // in |watcher| will also be closed.
+ // If |use_alternate_path| is specified then the |alternate_path| for the
+ // port will be used instead. When the pipe passed in |port_receiver| is
+ // closed the optional pipe passed in |watcher| will also be closed.
GetPort(mojo_base.mojom.UnguessableToken token,
+ bool use_alternate_path,
pending_receiver<SerialPort> port_receiver,
pending_remote<SerialPortConnectionWatcher>? watcher);
};
@@ -120,19 +134,17 @@ interface SerialPortManagerClient {
interface SerialPort {
// Initiates an Open of the device then returns result.
Open(SerialConnectionOptions options,
- handle<data_pipe_consumer> in_stream,
- handle<data_pipe_producer> out_stream,
pending_remote<SerialPortClient> client) => (bool success);
- // Try to clear existing send error and reconnect the data pipe for send.
- // This is supposed to be called after SerialPortClient#OnSendError is
- // notified.
- ClearSendError(handle<data_pipe_consumer> consumer);
+ // Start writing data from |consumer| to the port. This should be called after
+ // Open() or to restart data flow after when SerialPortClient#OnSendError is
+ // called on |client| to indicate an error.
+ StartWriting(handle<data_pipe_consumer> consumer);
- // Try to clear existing read error and reconnect the data pipe for read.
- // This is supposed to be called after SerialPortClient#OnReadError is
- // notified.
- ClearReadError(handle<data_pipe_producer> producer);
+ // Start reading data from the port into |producer|. This should be called
+ // after Open() or to restart data flow when SerialPortClient#OnReadError is
+ // called on |client| to indicate an error.
+ StartReading(handle<data_pipe_producer> producer);
// Flushes input and output buffers.
Flush() => (bool success);
diff --git a/chromium/services/device/public/mojom/usb_manager.mojom b/chromium/services/device/public/mojom/usb_manager.mojom
index a1ec731a19a..62a9bc61806 100644
--- a/chromium/services/device/public/mojom/usb_manager.mojom
+++ b/chromium/services/device/public/mojom/usb_manager.mojom
@@ -37,9 +37,11 @@ interface UsbDeviceManager {
CheckAccess(string guid) => (bool success);
// Attempt to open a USB device using permission_broker and return
- // a file descriptor.
+ // a file descriptor. Allow access only to interfaces specified in
+ // |allowed_interfaces_mask|.
[EnableIf=is_chromeos]
- OpenFileDescriptor(string guid) => (mojo_base.mojom.File? fd);
+ OpenFileDescriptor(string guid, uint32 allowed_interfaces_mask)
+ => (mojo_base.mojom.File? fd);
// Sets the client for this DeviceManager service. The service will notify its
// client of device events such as connection and disconnection.
diff --git a/chromium/services/device/serial/serial_device_enumerator.cc b/chromium/services/device/serial/serial_device_enumerator.cc
index 781df170927..057efc7654a 100644
--- a/chromium/services/device/serial/serial_device_enumerator.cc
+++ b/chromium/services/device/serial/serial_device_enumerator.cc
@@ -58,13 +58,19 @@ void SerialDeviceEnumerator::RemoveObserver(Observer* observer) {
}
base::Optional<base::FilePath> SerialDeviceEnumerator::GetPathFromToken(
- const base::UnguessableToken& token) {
+ const base::UnguessableToken& token,
+ bool use_alternate_path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto it = ports_.find(token);
if (it == ports_.end())
return base::nullopt;
+#if defined(OS_MACOSX)
+ if (use_alternate_path)
+ return it->second->alternate_path;
+#endif
+
return it->second->path;
}
diff --git a/chromium/services/device/serial/serial_device_enumerator.h b/chromium/services/device/serial/serial_device_enumerator.h
index 5a0ef07c154..fe852ede549 100644
--- a/chromium/services/device/serial/serial_device_enumerator.h
+++ b/chromium/services/device/serial/serial_device_enumerator.h
@@ -41,8 +41,9 @@ class SerialDeviceEnumerator {
void AddObserver(Observer* observer);
void RemoveObserver(Observer* observer);
- virtual base::Optional<base::FilePath> GetPathFromToken(
- const base::UnguessableToken& token);
+ base::Optional<base::FilePath> GetPathFromToken(
+ const base::UnguessableToken& token,
+ bool use_alternate_path);
protected:
// These helper methods take care of managing |ports_| and notifying
diff --git a/chromium/services/device/serial/serial_device_enumerator_linux.cc b/chromium/services/device/serial/serial_device_enumerator_linux.cc
index 5553deb0528..a90aa6afded 100644
--- a/chromium/services/device/serial/serial_device_enumerator_linux.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_linux.cc
@@ -11,32 +11,84 @@
#include <vector>
#include "base/check_op.h"
+#include "base/files/file_util.h"
#include "base/strings/string_number_conversions.h"
+#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/threading/scoped_blocking_call.h"
+#include "device/udev_linux/udev.h"
namespace device {
namespace {
-const char kSerialSubsystem[] = "tty";
+constexpr char kSubsystemTty[] = "tty";
+
+// Holds information about a TTY driver for serial devices. Each driver creates
+// device nodes with a given major number and in a range of minor numbers.
+struct SerialDriverInfo {
+ int major;
+ int minor_start;
+ int minor_end; // Inclusive.
+};
+
+std::vector<SerialDriverInfo> ReadSerialDriverInfo() {
+ std::string tty_drivers;
+ if (!base::ReadFileToString(base::FilePath("/proc/tty/drivers"),
+ &tty_drivers)) {
+ return {};
+ }
-const char kHostPathKey[] = "DEVNAME";
-const char kHostBusKey[] = "ID_BUS";
-const char kMajorKey[] = "MAJOR";
-const char kVendorIDKey[] = "ID_VENDOR_ID";
-const char kProductIDKey[] = "ID_MODEL_ID";
-const char kProductNameKey[] = "ID_MODEL";
+ // Each line has information on a single TTY driver.
+ std::vector<SerialDriverInfo> serial_drivers;
+ for (const auto& line :
+ base::SplitStringPiece(tty_drivers, "\n", base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
+ std::vector<base::StringPiece> fields = base::SplitStringPiece(
+ line, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ // The format of each line is:
+ //
+ // driver name<SPACE>name<SPACE>major<SPACE>minor range<SPACE>type
+ //
+ // We only care about drivers that provide the "serial" type. The rest are
+ // things like pseudoterminals.
+ if (fields.size() < 5 || fields[4] != "serial")
+ continue;
+
+ SerialDriverInfo info;
+ if (!base::StringToInt(fields[2], &info.major))
+ continue;
+
+ std::vector<base::StringPiece> minor_range = base::SplitStringPiece(
+ fields[3], "-", base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ if (minor_range.size() == 1) {
+ if (!base::StringToInt(minor_range[0], &info.minor_start))
+ continue;
+ info.minor_end = info.minor_start;
+ } else if (minor_range.size() == 2) {
+ if (!base::StringToInt(minor_range[0], &info.minor_start) ||
+ !base::StringToInt(minor_range[1], &info.minor_end)) {
+ continue;
+ }
+ } else {
+ continue;
+ }
+
+ serial_drivers.push_back(info);
+ }
-// The major number for an RFCOMM TTY device.
-const char kRfcommMajor[] = "216";
+ return serial_drivers;
+}
} // namespace
SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux() {
DETACH_FROM_SEQUENCE(sequence_checker_);
- watcher_ = UdevWatcher::StartWatching(this);
+ watcher_ = UdevWatcher::StartWatching(
+ this, {UdevWatcher::Filter(kSubsystemTty, "")});
watcher_->EnumerateExistingDevices();
}
@@ -49,34 +101,32 @@ void SerialDeviceEnumeratorLinux::OnDeviceAdded(ScopedUdevDevicePtr device) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
+#if DCHECK_IS_ON()
const char* subsystem = udev_device_get_subsystem(device.get());
- if (!subsystem || strcmp(subsystem, kSerialSubsystem) != 0)
- return;
+ DCHECK(subsystem);
+ DCHECK_EQ(base::StringPiece(subsystem), kSubsystemTty);
+#endif
const char* syspath_str = udev_device_get_syspath(device.get());
if (!syspath_str)
return;
std::string syspath(syspath_str);
- // Platform serial ports.
- if (base::StartsWith(syspath, "/sys/devices/platform/",
- base::CompareCase::SENSITIVE)) {
- CreatePort(std::move(device), syspath);
- return;
- }
+ const char* major_str = udev_device_get_property_value(device.get(), "MAJOR");
+ const char* minor_str = udev_device_get_property_value(device.get(), "MINOR");
- // USB serial ports and others that have a proper bus identifier.
- const char* bus = udev_device_get_property_value(device.get(), kHostBusKey);
- if (bus) {
- CreatePort(std::move(device), syspath);
+ int major, minor;
+ if (!major_str || !minor_str || !base::StringToInt(major_str, &major) ||
+ !base::StringToInt(minor_str, &minor)) {
return;
}
- // Bluetooth ports are virtual TTYs but have an identifiable major number.
- const char* major = udev_device_get_property_value(device.get(), kMajorKey);
- if (major && base::StringPiece(major) == kRfcommMajor) {
- CreatePort(std::move(device), syspath);
- return;
+ for (const auto& driver : ReadSerialDriverInfo()) {
+ if (major == driver.major && minor >= driver.minor_start &&
+ minor <= driver.minor_end) {
+ CreatePort(std::move(device), syspath);
+ return;
+ }
}
}
@@ -102,7 +152,7 @@ void SerialDeviceEnumeratorLinux::OnDeviceRemoved(ScopedUdevDevicePtr device) {
void SerialDeviceEnumeratorLinux::CreatePort(ScopedUdevDevicePtr device,
const std::string& syspath) {
- const char* path = udev_device_get_property_value(device.get(), kHostPathKey);
+ const char* path = udev_device_get_property_value(device.get(), "DEVNAME");
if (!path)
return;
@@ -112,11 +162,13 @@ void SerialDeviceEnumeratorLinux::CreatePort(ScopedUdevDevicePtr device,
info->token = token;
const char* vendor_id =
- udev_device_get_property_value(device.get(), kVendorIDKey);
+ udev_device_get_property_value(device.get(), "ID_VENDOR_ID");
const char* product_id =
- udev_device_get_property_value(device.get(), kProductIDKey);
- const char* product_name =
- udev_device_get_property_value(device.get(), kProductNameKey);
+ udev_device_get_property_value(device.get(), "ID_PRODUCT_ID");
+ const char* product_name_enc =
+ udev_device_get_property_value(device.get(), "ID_MODEL_ENC");
+ const char* serial_number =
+ udev_device_get_property_value(device.get(), "ID_SERIAL_SHORT");
uint32_t int_value;
if (vendor_id && base::HexStringToUInt(vendor_id, &int_value)) {
@@ -127,8 +179,13 @@ void SerialDeviceEnumeratorLinux::CreatePort(ScopedUdevDevicePtr device,
info->product_id = int_value;
info->has_product_id = true;
}
- if (product_name)
- info->display_name.emplace(product_name);
+ if (product_name_enc)
+ info->display_name = device::UdevDecodeString(product_name_enc);
+
+ if (info->has_vendor_id && info->has_product_id && serial_number) {
+ info->persistent_id = base::StringPrintf("%04X-%04X-%s", info->vendor_id,
+ info->product_id, serial_number);
+ }
paths_.insert(std::make_pair(syspath, token));
AddPort(std::move(info));
diff --git a/chromium/services/device/serial/serial_device_enumerator_mac.cc b/chromium/services/device/serial/serial_device_enumerator_mac.cc
index 8d950297f60..3685b4bc42e 100644
--- a/chromium/services/device/serial/serial_device_enumerator_mac.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_mac.cc
@@ -69,37 +69,28 @@ CFNumberRef GetCFNumberProperty(io_service_t service, const CFStringRef key) {
return NULL;
}
-// Searches the specified service for a string property with the specified key,
-// sets value to that property's value, and returns whether the operation was
-// successful.
-bool GetStringProperty(io_service_t service,
- const CFStringRef key,
- std::string* value) {
+// Searches the specified service for a string property with the specified key.
+base::Optional<std::string> GetStringProperty(io_service_t service,
+ const CFStringRef key) {
CFStringRef propValue = GetCFStringProperty(service, key);
- if (propValue) {
- *value = base::SysCFStringRefToUTF8(propValue);
- return true;
- }
+ if (propValue)
+ return base::SysCFStringRefToUTF8(propValue);
- return false;
+ return base::nullopt;
}
// Searches the specified service for a uint16_t property with the specified
-// key, sets value to that property's value, and returns whether the operation
-// was successful.
-bool GetUInt16Property(io_service_t service,
- const CFStringRef key,
- uint16_t* value) {
+// key.
+base::Optional<uint16_t> GetUInt16Property(io_service_t service,
+ const CFStringRef key) {
CFNumberRef propValue = GetCFNumberProperty(service, key);
if (propValue) {
int intValue;
- if (CFNumberGetValue(propValue, kCFNumberIntType, &intValue)) {
- *value = static_cast<uint16_t>(intValue);
- return true;
- }
+ if (CFNumberGetValue(propValue, kCFNumberIntType, &intValue))
+ return static_cast<uint16_t>(intValue);
}
- return false;
+ return base::nullopt;
}
} // namespace
@@ -165,51 +156,55 @@ void SerialDeviceEnumeratorMac::AddDevices() {
if (result != kIOReturnSuccess)
continue;
- auto callout_info = mojom::SerialPortInfo::New();
- uint16_t vendorId;
- if (GetUInt16Property(device.get(), CFSTR(kUSBVendorID), &vendorId)) {
- callout_info->has_vendor_id = true;
- callout_info->vendor_id = vendorId;
+ auto info = mojom::SerialPortInfo::New();
+ base::Optional<uint16_t> vendor_id =
+ GetUInt16Property(device.get(), CFSTR(kUSBVendorID));
+ if (vendor_id) {
+ info->has_vendor_id = true;
+ info->vendor_id = *vendor_id;
}
- uint16_t productId;
- if (GetUInt16Property(device.get(), CFSTR(kUSBProductID), &productId)) {
- callout_info->has_product_id = true;
- callout_info->product_id = productId;
+ base::Optional<uint16_t> product_id =
+ GetUInt16Property(device.get(), CFSTR(kUSBProductID));
+ if (product_id) {
+ info->has_product_id = true;
+ info->product_id = *product_id;
}
- std::string display_name;
- if (GetStringProperty(device.get(), CFSTR(kUSBProductString),
- &display_name)) {
- callout_info->display_name = std::move(display_name);
+ info->display_name =
+ GetStringProperty(device.get(), CFSTR(kUSBProductString));
+
+ base::Optional<std::string> serial_number =
+ GetStringProperty(device.get(), CFSTR(kUSBSerialNumberString));
+ if (vendor_id && product_id && serial_number) {
+ info->persistent_id = base::StringPrintf(
+ "%04X-%04X-%s", *vendor_id, *product_id, serial_number->c_str());
}
- // Each serial device has two "paths" in /dev/ associated with it: a
- // "dialin" path starting with "tty" and a "callout" path starting with
- // "cu". Each of these is considered a different device from Chrome's
- // standpoint, but both should share the device's USB properties.
- std::string dialin_device;
- if (GetStringProperty(device.get(), CFSTR(kIODialinDeviceKey),
- &dialin_device)) {
- auto token = base::UnguessableToken::Create();
- mojom::SerialPortInfoPtr dialin_info = callout_info.Clone();
- dialin_info->path = base::FilePath(dialin_device);
- dialin_info->token = token;
-
- entries_[entry_id].first = token;
- AddPort(std::move(dialin_info));
+ // Each serial device has two paths associated with it: a "dialin" path
+ // starting with "tty" and a "callout" path starting with "cu". The
+ // call-out device is typically preferred but requesting the dial-in device
+ // is supported for the legacy Chrome Apps API.
+ base::Optional<std::string> dialin_device =
+ GetStringProperty(device.get(), CFSTR(kIODialinDeviceKey));
+ base::Optional<std::string> callout_device =
+ GetStringProperty(device.get(), CFSTR(kIOCalloutDeviceKey));
+
+ if (callout_device) {
+ info->path = base::FilePath(*callout_device);
+ if (dialin_device)
+ info->alternate_path = base::FilePath(*dialin_device);
+ } else if (dialin_device) {
+ info->path = base::FilePath(*dialin_device);
+ } else {
+ continue;
}
- std::string callout_device;
- if (GetStringProperty(device.get(), CFSTR(kIOCalloutDeviceKey),
- &callout_device)) {
- auto token = base::UnguessableToken::Create();
- callout_info->path = base::FilePath(callout_device);
- callout_info->token = token;
+ auto token = base::UnguessableToken::Create();
+ info->token = token;
- entries_[entry_id].second = token;
- AddPort(std::move(callout_info));
- }
+ entries_.insert({entry_id, token});
+ AddPort(std::move(info));
}
}
@@ -227,14 +222,10 @@ void SerialDeviceEnumeratorMac::RemoveDevices() {
if (it == entries_.end())
continue;
- std::pair<base::UnguessableToken, base::UnguessableToken> tokens =
- it->second;
+ base::UnguessableToken token = it->second;
entries_.erase(it);
- if (tokens.first)
- RemovePort(tokens.first);
- if (tokens.second)
- RemovePort(tokens.second);
+ RemovePort(token);
}
}
diff --git a/chromium/services/device/serial/serial_device_enumerator_mac.h b/chromium/services/device/serial/serial_device_enumerator_mac.h
index 79b6e55b17c..5ba21837d53 100644
--- a/chromium/services/device/serial/serial_device_enumerator_mac.h
+++ b/chromium/services/device/serial/serial_device_enumerator_mac.h
@@ -33,10 +33,9 @@ class SerialDeviceEnumeratorMac : public SerialDeviceEnumerator {
void AddDevices();
void RemoveDevices();
- // Each IORegistry entry potentially creates two serial ports for the dialin
- // and callout device nodes.
- std::map<uint64_t, std::pair<base::UnguessableToken, base::UnguessableToken>>
- entries_;
+ // Map from IORegistry entry IDs to the token used to refer to the device
+ // internally.
+ std::map<uint64_t, base::UnguessableToken> entries_;
base::mac::ScopedIONotificationPortRef notify_port_;
base::mac::ScopedIOObject<io_iterator_t> devices_added_iterator_;
diff --git a/chromium/services/device/serial/serial_device_enumerator_win.cc b/chromium/services/device/serial/serial_device_enumerator_win.cc
index cecf66c047d..931173b8f55 100644
--- a/chromium/services/device/serial/serial_device_enumerator_win.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_win.cc
@@ -11,6 +11,9 @@
#include <setupapi.h>
#include <stdint.h>
+#define INITGUID
+#include <devpkey.h>
+
#include <algorithm>
#include <memory>
#include <string>
@@ -26,45 +29,40 @@
#include "base/strings/utf_string_conversions.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/win/registry.h"
+#include "base/win/scoped_devinfo.h"
#include "third_party/re2/src/re2/re2.h"
namespace device {
namespace {
-struct DevInfoScopedTraits {
- static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
- static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
-};
+base::Optional<std::string> GetProperty(HDEVINFO dev_info,
+ SP_DEVINFO_DATA* dev_info_data,
+ const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
-using ScopedDevInfo = base::ScopedGeneric<HDEVINFO, DevInfoScopedTraits>;
-
-// Searches the specified device info for a property with the specified key,
-// assigns the result to value, and returns whether the operation was
-// successful.
-bool GetProperty(HDEVINFO dev_info,
- SP_DEVINFO_DATA* dev_info_data,
- const int key,
- std::string* value) {
- // We don't know how much space the property's value will take up, so we call
- // the property retrieval function once to fetch the size of the required
- // value buffer, then again once we've allocated a sufficiently large buffer.
- DWORD buffer_size = 0;
- SetupDiGetDeviceRegistryProperty(dev_info, dev_info_data, key, nullptr,
- nullptr, buffer_size, &buffer_size);
- if (GetLastError() != ERROR_INSUFFICIENT_BUFFER)
- return false;
+ DEVPROPTYPE property_type;
+ DWORD required_size;
+ if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
+ &property_type, /*PropertyBuffer=*/nullptr,
+ /*PropertyBufferSize=*/0, &required_size,
+ /*Flags=*/0) ||
+ GetLastError() != ERROR_INSUFFICIENT_BUFFER ||
+ property_type != DEVPROP_TYPE_STRING) {
+ return base::nullopt;
+ }
base::string16 buffer;
- if (!SetupDiGetDeviceRegistryProperty(
- dev_info, dev_info_data, key, nullptr,
- reinterpret_cast<PBYTE>(base::WriteInto(&buffer, buffer_size)),
- buffer_size, nullptr)) {
- return false;
+ if (!SetupDiGetDeviceProperty(
+ dev_info, dev_info_data, &property, &property_type,
+ reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
+ required_size, /*RequiredSize=*/nullptr, /*Flags=*/0)) {
+ return base::nullopt;
}
- *value = base::UTF16ToUTF8(buffer);
- return true;
+ return base::UTF16ToUTF8(buffer);
}
base::FilePath FixUpPortName(base::StringPiece port_name) {
@@ -84,19 +82,19 @@ bool GetDisplayName(const std::string friendly_name,
display_name);
}
-// Searches for the vendor ID in the device's hardware ID, assigns its value to
+// Searches for the vendor ID in the device's instance ID, assigns its value to
// vendor_id, and returns whether the operation was successful.
-bool GetVendorID(const std::string hardware_id, uint32_t* vendor_id) {
+bool GetVendorID(const std::string& instance_id, uint32_t* vendor_id) {
std::string vendor_id_str;
- return RE2::PartialMatch(hardware_id, "VID_([0-9a-fA-F]+)", &vendor_id_str) &&
+ return RE2::PartialMatch(instance_id, "VID_([0-9a-fA-F]+)", &vendor_id_str) &&
base::HexStringToUInt(vendor_id_str, vendor_id);
}
-// Searches for the product ID in the device's product ID, assigns its value to
+// Searches for the product ID in the device's instance ID, assigns its value to
// product_id, and returns whether the operation was successful.
-bool GetProductID(const std::string hardware_id, uint32_t* product_id) {
+bool GetProductID(const std::string& instance_id, uint32_t* product_id) {
std::string product_id_str;
- return RE2::PartialMatch(hardware_id, "PID_([0-9a-fA-F]+)",
+ return RE2::PartialMatch(instance_id, "PID_([0-9a-fA-F]+)",
&product_id_str) &&
base::HexStringToUInt(product_id_str, product_id);
}
@@ -179,7 +177,8 @@ base::Optional<base::FilePath> SerialDeviceEnumeratorWin::GetPath(
}
void SerialDeviceEnumeratorWin::OnPathAdded(const base::string16& device_path) {
- ScopedDevInfo dev_info(SetupDiCreateDeviceInfoList(nullptr, nullptr));
+ base::win::ScopedDevInfo dev_info(
+ SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid())
return;
@@ -198,7 +197,8 @@ void SerialDeviceEnumeratorWin::OnPathAdded(const base::string16& device_path) {
void SerialDeviceEnumeratorWin::OnPathRemoved(
const base::string16& device_path) {
- ScopedDevInfo dev_info(SetupDiCreateDeviceInfoList(nullptr, nullptr));
+ base::win::ScopedDevInfo dev_info(
+ SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid())
return;
@@ -212,16 +212,15 @@ void SerialDeviceEnumeratorWin::OnPathRemoved(
if (!SetupDiEnumDeviceInfo(dev_info.get(), 0, &dev_info_data))
return;
- std::string friendly_name;
- // SPDRP_FRIENDLYNAME looks like "USB_SERIAL_PORT (COM3)".
+ // The friendly name looks like "USB_SERIAL_PORT (COM3)".
// In Windows, the COM port is the path used to uniquely identify the
// serial device. If the COM can't be found, ignore the device.
- if (!GetProperty(dev_info.get(), &dev_info_data, SPDRP_FRIENDLYNAME,
- &friendly_name)) {
+ base::Optional<std::string> friendly_name =
+ GetProperty(dev_info.get(), &dev_info_data, DEVPKEY_Device_FriendlyName);
+ if (!friendly_name)
return;
- }
- base::Optional<base::FilePath> path = GetPath(friendly_name);
+ base::Optional<base::FilePath> path = GetPath(*friendly_name);
if (!path)
return;
@@ -239,7 +238,7 @@ void SerialDeviceEnumeratorWin::DoInitialEnumeration() {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
// Make a device interface query to find all serial devices.
- ScopedDevInfo dev_info(
+ base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&GUID_DEVINTERFACE_COMPORT, nullptr, 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid())
@@ -255,40 +254,43 @@ void SerialDeviceEnumeratorWin::DoInitialEnumeration() {
void SerialDeviceEnumeratorWin::EnumeratePort(HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data) {
- std::string friendly_name;
- // SPDRP_FRIENDLYNAME looks like "USB_SERIAL_PORT (COM3)".
+ // The friendly name looks like "USB_SERIAL_PORT (COM3)".
// In Windows, the COM port is the path used to uniquely identify the
// serial device. If the COM can't be found, ignore the device.
- if (!GetProperty(dev_info, dev_info_data, SPDRP_FRIENDLYNAME,
- &friendly_name)) {
+ base::Optional<std::string> friendly_name =
+ GetProperty(dev_info, dev_info_data, DEVPKEY_Device_FriendlyName);
+ if (!friendly_name)
return;
- }
- base::Optional<base::FilePath> path = GetPath(friendly_name);
+ base::Optional<base::FilePath> path = GetPath(*friendly_name);
if (!path)
return;
- auto info = mojom::SerialPortInfo::New();
- info->path = *path;
+ base::Optional<std::string> instance_id =
+ GetProperty(dev_info, dev_info_data, DEVPKEY_Device_InstanceId);
+ if (!instance_id)
+ return;
+
base::UnguessableToken token = base::UnguessableToken::Create();
+ auto info = mojom::SerialPortInfo::New();
info->token = token;
+ info->path = *path;
+ info->persistent_id = instance_id;
+ // TODO(https://crbug.com/1015074): Read the real USB strings here.
std::string display_name;
- if (GetDisplayName(friendly_name, &display_name))
+ if (GetDisplayName(*friendly_name, &display_name))
info->display_name = std::move(display_name);
- std::string hardware_id;
- // SPDRP_HARDWAREID looks like "FTDIBUS\COMPORT&VID_0403&PID_6001".
- if (GetProperty(dev_info, dev_info_data, SPDRP_HARDWAREID, &hardware_id)) {
- uint32_t vendor_id, product_id;
- if (GetVendorID(hardware_id, &vendor_id)) {
- info->has_vendor_id = true;
- info->vendor_id = vendor_id;
- }
- if (GetProductID(hardware_id, &product_id)) {
- info->has_product_id = true;
- info->product_id = product_id;
- }
+ // The instance ID looks like "FTDIBUS\VID_0403+PID_6001+A703X87GA\0000".
+ uint32_t vendor_id, product_id;
+ if (GetVendorID(*instance_id, &vendor_id)) {
+ info->has_vendor_id = true;
+ info->vendor_id = vendor_id;
+ }
+ if (GetProductID(*instance_id, &product_id)) {
+ info->has_product_id = true;
+ info->product_id = product_id;
}
paths_.insert(std::make_pair(*path, token));
diff --git a/chromium/services/device/serial/serial_io_handler_posix.cc b/chromium/services/device/serial/serial_io_handler_posix.cc
index 452d81538fd..7f2a2c421b3 100644
--- a/chromium/services/device/serial/serial_io_handler_posix.cc
+++ b/chromium/services/device/serial/serial_io_handler_posix.cc
@@ -126,7 +126,11 @@ scoped_refptr<SerialIoHandler> SerialIoHandler::Create(
void SerialIoHandlerPosix::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_read_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
+ return;
+ }
// Try to read immediately. This is needed because on some platforms
// (e.g., OSX) there may not be a notification from the message loop
@@ -138,7 +142,11 @@ void SerialIoHandlerPosix::ReadImpl() {
void SerialIoHandlerPosix::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_write_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ return;
+ }
EnsureWatchingWrites();
}
diff --git a/chromium/services/device/serial/serial_io_handler_win.cc b/chromium/services/device/serial/serial_io_handler_win.cc
index 92d05b2cb16..12d91e68ea9 100644
--- a/chromium/services/device/serial/serial_io_handler_win.cc
+++ b/chromium/services/device/serial/serial_io_handler_win.cc
@@ -266,7 +266,11 @@ bool SerialIoHandlerWin::PostOpen() {
void SerialIoHandlerWin::ReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_read_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueReadCompleted(0, mojom::SerialReceiveError::DISCONNECTED);
+ return;
+ }
if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) {
VPLOG(1) << "Failed to set serial event flags";
@@ -285,7 +289,11 @@ void SerialIoHandlerWin::ReadImpl() {
void SerialIoHandlerWin::WriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(pending_write_buffer());
- DCHECK(file().IsValid());
+
+ if (!file().IsValid()) {
+ QueueWriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ return;
+ }
BOOL ok = ::WriteFile(file().GetPlatformFile(), pending_write_buffer(),
pending_write_buffer_len(), NULL,
@@ -319,7 +327,7 @@ bool SerialIoHandlerWin::ConfigurePortImpl() {
// Set up some sane default options that are not configurable.
config.fBinary = TRUE;
config.fParity = TRUE;
- config.fAbortOnError = TRUE;
+ config.fAbortOnError = FALSE;
config.fOutxDsrFlow = FALSE;
config.fDtrControl = DTR_CONTROL_ENABLE;
config.fDsrSensitivity = FALSE;
@@ -371,9 +379,13 @@ void SerialIoHandlerWin::OnIOCompleted(
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (context == comm_context_.get()) {
DWORD errors;
- COMSTAT status;
- if (!ClearCommError(file().GetPlatformFile(), &errors, &status) ||
- errors != 0) {
+ if (!ClearCommError(file().GetPlatformFile(), &errors, nullptr)) {
+ VPLOG(1) << "Failed to clear communication error";
+ ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
+ return;
+ }
+
+ if (errors != 0) {
if (errors & CE_BREAK) {
ReadCompleted(0, mojom::SerialReceiveError::BREAK);
} else if (errors & CE_FRAME) {
@@ -385,7 +397,8 @@ void SerialIoHandlerWin::OnIOCompleted(
} else if (errors & CE_RXPARITY) {
ReadCompleted(0, mojom::SerialReceiveError::PARITY_ERROR);
} else {
- ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
+ NOTIMPLEMENTED() << "Unexpected communication error: " << std::hex
+ << errors;
}
return;
}
@@ -393,6 +406,8 @@ void SerialIoHandlerWin::OnIOCompleted(
if (read_canceled()) {
ReadCompleted(bytes_transferred, read_cancel_reason());
} else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
+ VLOG(1) << "Waiting for communcations event failed: "
+ << logging::SystemErrorCodeToString(error);
ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
} else if (pending_read_buffer()) {
BOOL ok = ::ReadFile(file().GetPlatformFile(), pending_read_buffer(),
@@ -406,19 +421,20 @@ void SerialIoHandlerWin::OnIOCompleted(
} else if (context == read_context_.get()) {
if (read_canceled()) {
ReadCompleted(bytes_transferred, read_cancel_reason());
- } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
- ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
+ } else if (error == ERROR_SUCCESS || error == ERROR_OPERATION_ABORTED) {
+ ReadCompleted(bytes_transferred, mojom::SerialReceiveError::NONE);
} else {
- ReadCompleted(bytes_transferred,
- error == ERROR_SUCCESS
- ? mojom::SerialReceiveError::NONE
- : mojom::SerialReceiveError::SYSTEM_ERROR);
+ VLOG(1) << "Read failed: " << logging::SystemErrorCodeToString(error);
+ ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
}
} else if (context == write_context_.get()) {
DCHECK(pending_write_buffer());
if (write_canceled()) {
WriteCompleted(0, write_cancel_reason());
- } else if (error != ERROR_SUCCESS && error != ERROR_OPERATION_ABORTED) {
+ } else if (error == ERROR_SUCCESS || error == ERROR_OPERATION_ABORTED) {
+ WriteCompleted(bytes_transferred, mojom::SerialSendError::NONE);
+ } else {
+ VLOG(1) << "Write failed: " << logging::SystemErrorCodeToString(error);
WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
if (error == ERROR_GEN_FAILURE && IsReadPending()) {
// For devices using drivers such as FTDI, CP2xxx, when device is
@@ -432,11 +448,6 @@ void SerialIoHandlerWin::OnIOCompleted(
// disconnection.
CancelRead(mojom::SerialReceiveError::SYSTEM_ERROR);
}
- } else {
- WriteCompleted(bytes_transferred,
- error == ERROR_SUCCESS
- ? mojom::SerialSendError::NONE
- : mojom::SerialSendError::SYSTEM_ERROR);
}
} else {
NOTREACHED() << "Invalid IOContext";
diff --git a/chromium/services/device/serial/serial_port_impl.cc b/chromium/services/device/serial/serial_port_impl.cc
index 26c90886ed1..efef354e9d4 100644
--- a/chromium/services/device/serial/serial_port_impl.cc
+++ b/chromium/services/device/serial/serial_port_impl.cc
@@ -52,30 +52,22 @@ SerialPortImpl::~SerialPortImpl() {
}
void SerialPortImpl::Open(mojom::SerialConnectionOptionsPtr options,
- mojo::ScopedDataPipeConsumerHandle in_stream,
- mojo::ScopedDataPipeProducerHandle out_stream,
mojo::PendingRemote<mojom::SerialPortClient> client,
OpenCallback callback) {
- DCHECK(in_stream);
- DCHECK(out_stream);
- in_stream_ = std::move(in_stream);
- out_stream_ = std::move(out_stream);
if (client)
client_.Bind(std::move(client));
- io_handler_->Open(*options, base::BindOnce(&SerialPortImpl::OnOpenCompleted,
- weak_factory_.GetWeakPtr(),
- std::move(callback)));
+
+ io_handler_->Open(*options, std::move(callback));
}
-void SerialPortImpl::ClearSendError(
- mojo::ScopedDataPipeConsumerHandle consumer) {
- // Make sure |io_handler_| is still open and the |in_stream_| has been
- // closed.
- if (!io_handler_ || in_stream_) {
+void SerialPortImpl::StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) {
+ if (in_stream_) {
+ mojo::ReportBadMessage("Data pipe consumer still open.");
return;
}
+
in_stream_watcher_.Cancel();
- in_stream_.swap(consumer);
+ in_stream_ = std::move(consumer);
in_stream_watcher_.Watch(
in_stream_.get(),
MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@@ -85,15 +77,14 @@ void SerialPortImpl::ClearSendError(
in_stream_watcher_.ArmOrNotify();
}
-void SerialPortImpl::ClearReadError(
- mojo::ScopedDataPipeProducerHandle producer) {
- // Make sure |io_handler_| is still open and the |out_stream_| has been
- // closed.
- if (!io_handler_ || out_stream_) {
+void SerialPortImpl::StartReading(mojo::ScopedDataPipeProducerHandle producer) {
+ if (out_stream_) {
+ mojo::ReportBadMessage("Data pipe producer still open.");
return;
}
+
out_stream_watcher_.Cancel();
- out_stream_.swap(producer);
+ out_stream_ = std::move(producer);
out_stream_watcher_.Watch(
out_stream_.get(),
MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
@@ -132,27 +123,6 @@ void SerialPortImpl::Close(CloseCallback callback) {
io_handler_->Close(std::move(callback));
}
-void SerialPortImpl::OnOpenCompleted(OpenCallback callback, bool success) {
- if (success) {
- in_stream_watcher_.Watch(
- in_stream_.get(),
- MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
- base::BindRepeating(&SerialPortImpl::WriteToPort,
- weak_factory_.GetWeakPtr()));
- in_stream_watcher_.ArmOrNotify();
-
- out_stream_watcher_.Watch(
- out_stream_.get(),
- MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
- MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
- base::BindRepeating(&SerialPortImpl::ReadFromPortAndWriteOut,
- weak_factory_.GetWeakPtr()));
- out_stream_watcher_.ArmOrNotify();
- }
- std::move(callback).Run(success);
-}
-
void SerialPortImpl::WriteToPort(MojoResult result,
const mojo::HandleSignalsState& state) {
const void* buffer;
diff --git a/chromium/services/device/serial/serial_port_impl.h b/chromium/services/device/serial/serial_port_impl.h
index bf5ac94571e..2ba5d31d45c 100644
--- a/chromium/services/device/serial/serial_port_impl.h
+++ b/chromium/services/device/serial/serial_port_impl.h
@@ -49,12 +49,10 @@ class SerialPortImpl : public mojom::SerialPort {
// mojom::SerialPort methods:
void Open(mojom::SerialConnectionOptionsPtr options,
- mojo::ScopedDataPipeConsumerHandle in_stream,
- mojo::ScopedDataPipeProducerHandle out_stream,
mojo::PendingRemote<mojom::SerialPortClient> client,
OpenCallback callback) override;
- void ClearSendError(mojo::ScopedDataPipeConsumerHandle consumer) override;
- void ClearReadError(mojo::ScopedDataPipeProducerHandle producer) override;
+ void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override;
+ void StartReading(mojo::ScopedDataPipeProducerHandle producer) override;
void Flush(FlushCallback callback) override;
void GetControlSignals(GetControlSignalsCallback callback) override;
void SetControlSignals(mojom::SerialHostControlSignalsPtr signals,
@@ -64,7 +62,6 @@ class SerialPortImpl : public mojom::SerialPort {
void GetPortInfo(GetPortInfoCallback callback) override;
void Close(CloseCallback callback) override;
- void OnOpenCompleted(OpenCallback callback, bool success);
void WriteToPort(MojoResult result, const mojo::HandleSignalsState& state);
void OnWriteToPortCompleted(uint32_t bytes_expected,
uint32_t bytes_sent,
diff --git a/chromium/services/device/serial/serial_port_impl_unittest.cc b/chromium/services/device/serial/serial_port_impl_unittest.cc
index 3618b88e916..93c7f0aa317 100644
--- a/chromium/services/device/serial/serial_port_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_impl_unittest.cc
@@ -21,9 +21,65 @@ class SerialPortImplTest : public DeviceServiceTestBase {
~SerialPortImplTest() override = default;
protected:
+ void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
+ mojo::ScopedDataPipeConsumerHandle* consumer) {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(MojoCreateDataPipeOptions);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = 1;
+ options.capacity_num_bytes = 64;
+
+ MojoResult result = mojo::CreateDataPipe(&options, producer, consumer);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+ }
+
+ mojo::ScopedDataPipeConsumerHandle StartReading(
+ mojom::SerialPort* serial_port) {
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+ serial_port->StartReading(std::move(producer));
+ return consumer;
+ }
+
+ mojo::ScopedDataPipeProducerHandle StartWriting(
+ mojom::SerialPort* serial_port) {
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+ serial_port->StartWriting(std::move(consumer));
+ return producer;
+ }
+
DISALLOW_COPY_AND_ASSIGN(SerialPortImplTest);
};
+TEST_F(SerialPortImplTest, StartIoBeforeOpen) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher =
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<mojom::SerialPortConnectionWatcher>(),
+ watcher_remote.InitWithNewPipeAndPassReceiver());
+ SerialPortImpl::Create(
+ base::FilePath(FILE_PATH_LITERAL("/dev/fakeserialmojo")),
+ serial_port.BindNewPipeAndPassReceiver(), std::move(watcher_remote),
+ task_environment_.GetMainThreadTaskRunner());
+
+ mojo::ScopedDataPipeConsumerHandle consumer = StartReading(serial_port.get());
+ mojo::ScopedDataPipeProducerHandle producer = StartWriting(serial_port.get());
+
+ // Write some data so that StartWriting() will cause a call to Write().
+ static const char kBuffer[] = "test";
+ uint32_t bytes_written = base::size(kBuffer);
+ MojoResult result =
+ producer->WriteData(&kBuffer, &bytes_written, MOJO_WRITE_DATA_FLAG_NONE);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+ DCHECK_EQ(bytes_written, base::size(kBuffer));
+
+ base::RunLoop().RunUntilIdle();
+}
+
TEST_F(SerialPortImplTest, WatcherClosedWhenPortClosed) {
mojo::Remote<mojom::SerialPort> serial_port;
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher;
diff --git a/chromium/services/device/serial/serial_port_manager_impl.cc b/chromium/services/device/serial/serial_port_manager_impl.cc
index d519b7eb546..b893f4e2e2a 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl.cc
@@ -50,13 +50,15 @@ void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
void SerialPortManagerImpl::GetPort(
const base::UnguessableToken& token,
+ bool use_alternate_path,
mojo::PendingReceiver<mojom::SerialPort> receiver,
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) {
if (!enumerator_) {
enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
observed_enumerator_.Add(enumerator_.get());
}
- base::Optional<base::FilePath> path = enumerator_->GetPathFromToken(token);
+ base::Optional<base::FilePath> path =
+ enumerator_->GetPathFromToken(token, use_alternate_path);
if (path) {
io_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/services/device/serial/serial_port_manager_impl.h b/chromium/services/device/serial/serial_port_manager_impl.h
index 9d162a241c3..546e9a25fcb 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.h
+++ b/chromium/services/device/serial/serial_port_manager_impl.h
@@ -46,6 +46,7 @@ class SerialPortManagerImpl : public mojom::SerialPortManager,
void GetDevices(GetDevicesCallback callback) override;
void GetPort(
const base::UnguessableToken& token,
+ bool use_alternate_path,
mojo::PendingReceiver<mojom::SerialPort> receiver,
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) override;
diff --git a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
index 8fe414196d8..3b5b4da545f 100644
--- a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
@@ -98,6 +98,7 @@ TEST_F(SerialPortManagerImplTest, SimpleConnectTest) {
for (auto& device : results) {
mojo::Remote<mojom::SerialPort> serial_port;
port_manager->GetPort(device->token,
+ /*use_alternate_path=*/false,
serial_port.BindNewPipeAndPassReceiver(),
/*watcher=*/mojo::NullRemote());
// Send a message on the pipe and wait for the response to make sure
@@ -189,6 +190,7 @@ TEST_F(SerialPortManagerImplTest, GetPort) {
mojo::Remote<mojom::SerialPort> serial_port;
port_manager->GetPort(results[0]->token,
+ /*use_alternate_path=*/false,
serial_port.BindNewPipeAndPassReceiver(),
/*watcher=*/mojo::NullRemote());
// Send a message on the pipe and wait for the response to make sure
diff --git a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
index 65ca480d017..c03a0d554c6 100644
--- a/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
+++ b/chromium/services/device/time_zone_monitor/time_zone_monitor_linux.cc
@@ -87,7 +87,7 @@ class TimeZoneMonitorLinuxImpl
void StopWatching() {
DCHECK(main_task_runner_->RunsTasksInCurrentSequence());
- owner_ = NULL;
+ owner_ = nullptr;
file_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&TimeZoneMonitorLinuxImpl::StopWatchingOnFileThread,
diff --git a/chromium/services/device/usb/mojo/device_manager_impl.cc b/chromium/services/device/usb/mojo/device_manager_impl.cc
index 2c7b79af77c..8c3aa4ee25b 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl.cc
+++ b/chromium/services/device/usb/mojo/device_manager_impl.cc
@@ -123,6 +123,7 @@ void DeviceManagerImpl::CheckAccess(const std::string& guid,
void DeviceManagerImpl::OpenFileDescriptor(
const std::string& guid,
+ uint32_t drop_privileges_mask,
OpenFileDescriptorCallback callback) {
scoped_refptr<UsbDevice> device = usb_service_->GetDevice(guid);
if (!device) {
@@ -133,8 +134,8 @@ void DeviceManagerImpl::OpenFileDescriptor(
base::AdaptCallbackForRepeating(std::move(callback));
auto devpath =
static_cast<device::UsbDeviceLinux*>(device.get())->device_path();
- chromeos::PermissionBrokerClient::Get()->OpenPath(
- devpath,
+ chromeos::PermissionBrokerClient::Get()->OpenPathWithDroppedPrivileges(
+ devpath, drop_privileges_mask,
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptor,
weak_factory_.GetWeakPtr(), copyable_callback),
base::BindOnce(&DeviceManagerImpl::OnOpenFileDescriptorError,
diff --git a/chromium/services/device/usb/mojo/device_manager_impl.h b/chromium/services/device/usb/mojo/device_manager_impl.h
index 5684eab03cf..a048b379dff 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl.h
+++ b/chromium/services/device/usb/mojo/device_manager_impl.h
@@ -70,6 +70,7 @@ class DeviceManagerImpl : public mojom::UsbDeviceManager,
CheckAccessCallback callback) override;
void OpenFileDescriptor(const std::string& guid,
+ uint32_t drop_privileges_mask,
OpenFileDescriptorCallback callback) override;
void OnOpenFileDescriptor(OpenFileDescriptorCallback callback,
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.cc b/chromium/services/device/usb/usb_device_handle_usbfs.cc
index 90e2be66708..68eb5658725 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.cc
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.cc
@@ -17,6 +17,7 @@
#include "base/files/file_descriptor_watcher_posix.h"
#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"
+#include "base/numerics/checked_math.h"
#include "base/posix/eintr_wrapper.h"
#include "base/sequence_checker.h"
#include "base/stl_util.h"
@@ -169,7 +170,7 @@ class UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper {
DISALLOW_COPY_AND_ASSIGN(BlockingTaskRunnerHelper);
};
-struct UsbDeviceHandleUsbfs::Transfer {
+struct UsbDeviceHandleUsbfs::Transfer final {
Transfer() = delete;
Transfer(scoped_refptr<base::RefCountedBytes> buffer,
TransferCallback callback);
@@ -291,8 +292,12 @@ void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::SetInterface(
USB_PLOG(DEBUG) << "Failed to set interface " << interface_number
<< " to alternate setting " << alternate_setting;
}
- task_runner_->PostTask(FROM_HERE,
- base::BindOnce(std::move(callback), rc == 0));
+ task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ &UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete,
+ device_handle_, interface_number, alternate_setting, rc == 0,
+ std::move(callback)));
}
void UsbDeviceHandleUsbfs::BlockingTaskRunnerHelper::ResetDevice(
@@ -386,9 +391,9 @@ UsbDeviceHandleUsbfs::Transfer::Transfer(
scoped_refptr<base::RefCountedBytes> buffer,
IsochronousTransferCallback callback)
: buffer(buffer), isoc_callback(std::move(callback)) {
- memset(
- &urb, 0,
- sizeof(urb) + sizeof(usbdevfs_iso_packet_desc) * urb.number_of_packets);
+ // This buffer size calculation is checked in operator new().
+ memset(&urb, 0,
+ sizeof(urb) + sizeof(urb.iso_frame_desc[0]) * urb.number_of_packets);
urb.usercontext = this;
urb.buffer = buffer->front();
}
@@ -396,10 +401,15 @@ UsbDeviceHandleUsbfs::Transfer::Transfer(
UsbDeviceHandleUsbfs::Transfer::~Transfer() = default;
void* UsbDeviceHandleUsbfs::Transfer::operator new(
- std::size_t size,
+ size_t size,
size_t number_of_iso_packets) {
- void* p = ::operator new(size + sizeof(usbdevfs_iso_packet_desc) *
- number_of_iso_packets);
+ // The checked math should pass as long as Mojo message size limits are being
+ // enforced.
+ size_t total_size =
+ base::CheckAdd(size, base::CheckMul(sizeof(urb.iso_frame_desc[0]),
+ number_of_iso_packets))
+ .ValueOrDie();
+ void* p = ::operator new(total_size);
Transfer* transfer = static_cast<Transfer*>(p);
transfer->urb.number_of_packets = number_of_iso_packets;
return p;
@@ -763,6 +773,19 @@ void UsbDeviceHandleUsbfs::SetConfigurationComplete(int configuration_value,
std::move(callback).Run(success);
}
+void UsbDeviceHandleUsbfs::SetAlternateInterfaceSettingComplete(
+ int interface_number,
+ int alternate_setting,
+ bool success,
+ ResultCallback callback) {
+ DCHECK(sequence_checker_.CalledOnValidSequence());
+ if (success && device_) {
+ interfaces_[interface_number].alternate_setting = alternate_setting;
+ RefreshEndpointInfo();
+ }
+ std::move(callback).Run(success);
+}
+
void UsbDeviceHandleUsbfs::ReleaseInterfaceComplete(int interface_number,
ResultCallback callback) {
DCHECK(sequence_checker_.CalledOnValidSequence());
diff --git a/chromium/services/device/usb/usb_device_handle_usbfs.h b/chromium/services/device/usb/usb_device_handle_usbfs.h
index 33a09d00542..949ddd05327 100644
--- a/chromium/services/device/usb/usb_device_handle_usbfs.h
+++ b/chromium/services/device/usb/usb_device_handle_usbfs.h
@@ -103,6 +103,10 @@ class UsbDeviceHandleUsbfs : public UsbDeviceHandle {
void SetConfigurationComplete(int configuration_value,
bool success,
ResultCallback callback);
+ void SetAlternateInterfaceSettingComplete(int interface_number,
+ int alternate_setting,
+ bool success,
+ ResultCallback callback);
void ReleaseInterfaceComplete(int interface_number, ResultCallback callback);
void IsochronousTransferInternal(uint8_t endpoint_address,
scoped_refptr<base::RefCountedBytes> buffer,
diff --git a/chromium/services/device/usb/usb_device_handle_win.cc b/chromium/services/device/usb/usb_device_handle_win.cc
index 2cac1b0cc6d..e9364245b16 100644
--- a/chromium/services/device/usb/usb_device_handle_win.cc
+++ b/chromium/services/device/usb/usb_device_handle_win.cc
@@ -26,6 +26,7 @@
#include "base/stl_util.h"
#include "base/strings/string16.h"
#include "base/task/post_task.h"
+#include "base/task/thread_pool.h"
#include "base/threading/scoped_blocking_call.h"
#include "base/threading/sequenced_task_runner_handle.h"
#include "base/win/object_watcher.h"
@@ -335,8 +336,8 @@ void UsbDeviceHandleWin::SetInterfaceAlternateSetting(int interface_number,
// Use a strong reference to |this| rather than a weak pointer to prevent
// |interface.handle| from being freed because |this| was destroyed.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&SetCurrentAlternateSettingBlocking,
interface.handle.Get(), alternate_setting),
base::BindOnce(&UsbDeviceHandleWin::OnSetAlternateInterfaceSetting, this,
@@ -388,8 +389,8 @@ void UsbDeviceHandleWin::ClearHalt(mojom::UsbTransferDirection direction,
// Use a strong reference to |this| rather than a weak pointer to prevent
// |interface.handle| from being freed because |this| was destroyed.
- base::PostTaskAndReplyWithResult(
- FROM_HERE, {base::ThreadPool(), base::MayBlock()},
+ base::ThreadPool::PostTaskAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
base::BindOnce(&ResetPipeBlocking, interface.handle.Get(),
endpoint_address),
base::BindOnce(&UsbDeviceHandleWin::OnClearHalt, this,
@@ -1017,13 +1018,22 @@ void UsbDeviceHandleWin::GotDescriptorFromNodeConnection(
if (win32_result != ERROR_SUCCESS) {
SetLastError(win32_result);
USB_PLOG(ERROR) << "Failed to read descriptor from node connection";
- std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR, nullptr, 0);
+ std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR,
+ /*buffer=*/nullptr, /*length=*/0);
+ return;
+ }
+
+ if (bytes_transferred < sizeof(USB_DESCRIPTOR_REQUEST)) {
+ USB_LOG(ERROR) << "Descriptor response too short (" << bytes_transferred
+ << " < " << sizeof(USB_DESCRIPTOR_REQUEST) << ")";
+ std::move(callback).Run(UsbTransferStatus::TRANSFER_ERROR,
+ /*buffer=*/nullptr, /*length=*/0);
return;
}
- DCHECK_GE(bytes_transferred, sizeof(USB_DESCRIPTOR_REQUEST));
bytes_transferred -= sizeof(USB_DESCRIPTOR_REQUEST);
- DCHECK_LE(bytes_transferred, original_buffer->size());
+ bytes_transferred = std::min(bytes_transferred, original_buffer->size());
+
memcpy(original_buffer->front(),
request_buffer->front() + sizeof(USB_DESCRIPTOR_REQUEST),
bytes_transferred);
diff --git a/chromium/services/device/usb/usb_service.h b/chromium/services/device/usb/usb_service.h
index 97a44f0ccea..3e9df5c05ab 100644
--- a/chromium/services/device/usb/usb_service.h
+++ b/chromium/services/device/usb/usb_service.h
@@ -12,7 +12,7 @@
#include <vector>
#include "base/bind_helpers.h"
-#include "base/logging.h"
+#include "base/check.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/observer_list.h"
diff --git a/chromium/services/device/usb/usb_service_linux.cc b/chromium/services/device/usb/usb_service_linux.cc
index d5cef63fe30..7e7eb833b76 100644
--- a/chromium/services/device/usb/usb_service_linux.cc
+++ b/chromium/services/device/usb/usb_service_linux.cc
@@ -34,6 +34,8 @@ namespace device {
namespace {
+constexpr char kSubsystemUsb[] = "usb";
+
// Standard USB requests and descriptor types:
const uint16_t kUsbVersion2_1 = 0x0210;
@@ -109,7 +111,8 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::Start() {
// Initializing udev for device enumeration and monitoring may fail. In that
// case this service will continue to exist but no devices will be found.
- watcher_ = UdevWatcher::StartWatching(this);
+ watcher_ = UdevWatcher::StartWatching(
+ this, {UdevWatcher::Filter(kSubsystemUsb, "")});
if (watcher_)
watcher_->EnumerateExistingDevices();
@@ -123,9 +126,12 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
+
+#if DCHECK_IS_ON()
const char* subsystem = udev_device_get_subsystem(device.get());
- if (!subsystem || strcmp(subsystem, "usb") != 0)
- return;
+ DCHECK(subsystem);
+ DCHECK_EQ(base::StringPiece(subsystem), kSubsystemUsb);
+#endif
const char* value = udev_device_get_devnode(device.get());
if (!value)
diff --git a/chromium/services/device/usb/usb_service_win.cc b/chromium/services/device/usb/usb_service_win.cc
index 6acaf445f91..4e8989f6d3d 100644
--- a/chromium/services/device/usb/usb_service_win.cc
+++ b/chromium/services/device/usb/usb_service_win.cc
@@ -24,8 +24,11 @@
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/threading/scoped_blocking_call.h"
+#include "base/threading/scoped_thread_priority.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/registry.h"
+#include "base/win/scoped_devinfo.h"
#include "base/win/scoped_handle.h"
#include "components/device_event_log/device_event_log.h"
#include "services/device/usb/usb_descriptors.h"
@@ -37,16 +40,13 @@ namespace device {
namespace {
-struct DevInfoScopedTraits {
- static HDEVINFO InvalidValue() { return INVALID_HANDLE_VALUE; }
- static void Free(HDEVINFO h) { SetupDiDestroyDeviceInfoList(h); }
-};
-
-using ScopedDevInfo = base::ScopedGeneric<HDEVINFO, DevInfoScopedTraits>;
-
base::Optional<uint32_t> GetDeviceUint32Property(HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
uint32_t buffer;
if (!SetupDiGetDeviceProperty(
@@ -63,6 +63,10 @@ base::Optional<base::string16> GetDeviceStringProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
DWORD required_size;
if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
@@ -87,6 +91,10 @@ base::Optional<std::vector<base::string16>> GetDeviceStringListProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
+ // SetupDiGetDeviceProperty() makes an RPC which may block.
+ base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
+ base::BlockingType::MAY_BLOCK);
+
DEVPROPTYPE property_type;
DWORD required_size;
if (SetupDiGetDeviceProperty(dev_info, dev_info_data, &property,
@@ -236,7 +244,7 @@ bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
base::string16 GetDevicePath(const base::string16& instance_id,
const GUID& device_interface_guid) {
- ScopedDevInfo dev_info(
+ base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&device_interface_guid, instance_id.c_str(), 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
@@ -287,7 +295,8 @@ int GetInterfaceNumber(const base::string16& instance_id) {
UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
UsbDeviceWin::FunctionInfo info;
- ScopedDevInfo dev_info(SetupDiCreateDeviceInfoList(nullptr, nullptr));
+ base::win::ScopedDevInfo dev_info(
+ SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid()) {
USB_PLOG(ERROR) << "SetupDiCreateDeviceInfoList";
return info;
@@ -310,6 +319,10 @@ UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
if (!base::EqualsCaseInsensitiveASCII(info.driver, L"winusb"))
return info;
+ // Boost priority while potentially loading Advapi32.dll on a background
+ // thread for the registry functions used below.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
// There is no standard device interface GUID for USB functions and so we
// must discover the set of GUIDs that have been set in the registry by
// the INF file or Microsoft OS Compatibility descriptors before
@@ -332,6 +345,10 @@ UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
}
for (const auto& guid_string : device_interface_guids) {
+ // Boost priority while potentially loading Ole32.dll on a background
+ // thread for CLSIDFromString().
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
GUID guid;
if (FAILED(CLSIDFromString(guid_string.c_str(), &guid))) {
USB_LOG(ERROR) << "Failed to parse device interface GUID: "
@@ -357,7 +374,11 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
~BlockingTaskRunnerHelper() {}
void EnumerateDevices() {
- ScopedDevInfo dev_info(
+ // Boost priority while potentially loading SetupAPI.dll for the following
+ // functions on a background thread.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
+ base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&GUID_DEVINTERFACE_USB_DEVICE, nullptr, 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
@@ -384,7 +405,11 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
}
void OnDeviceAdded(const GUID& guid, const base::string16& device_path) {
- ScopedDevInfo dev_info(SetupDiGetClassDevs(
+ // Boost priority while potentially loading SetupAPI.dll and Ole32.dll on a
+ // background thread for the following functions.
+ SCOPED_MAY_LOAD_LIBRARY_AT_BACKGROUND_PRIORITY();
+
+ base::win::ScopedDevInfo dev_info(SetupDiGetClassDevs(
&guid, nullptr, 0, DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
USB_PLOG(ERROR) << "Failed to set up device enumeration";
@@ -407,6 +432,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
}
}
+ private:
void EnumerateDevice(HDEVINFO dev_info,
SP_DEVICE_INTERFACE_DATA* device_interface_data,
const base::Optional<base::string16>& opt_device_path) {
@@ -499,7 +525,6 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
std::move(parent_path), interface_number, info));
}
- private:
std::unordered_map<base::string16, base::string16> hub_paths_;
// Calls back to |service_| must be posted to |service_task_runner_|, which
diff --git a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
index a60e9f21e26..9365bd609d5 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
+++ b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
@@ -47,7 +47,6 @@ source_set("power_save_blocker") {
"//ui/gfx",
]
if (use_x11) {
- configs += [ "//build/config/linux:xscrnsaver" ]
deps += [ "//ui/gfx/x" ]
}
} else if (is_mac) {
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
index ea4ffee26e5..6b28c96b7dc 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc
@@ -26,9 +26,9 @@
#include "ui/gfx/switches.h"
#if defined(USE_X11)
-#include <X11/extensions/scrnsaver.h>
-
-#include "ui/gfx/x/x11_types.h" // nogncheck
+#include "ui/gfx/x/connection.h" // nogncheck
+#include "ui/gfx/x/screensaver.h" // nogncheck
+#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
namespace device {
@@ -138,18 +138,16 @@ bool X11ScreenSaverAvailable() {
// X Screen Saver isn't accessible in headless mode.
if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kHeadless))
return false;
- XDisplay* display = gfx::GetXDisplay();
- int dummy;
- int major;
- int minor;
-
- if (!XScreenSaverQueryExtension(display, &dummy, &dummy))
- return false;
+ auto* connection = x11::Connection::Get();
- if (!XScreenSaverQueryVersion(display, &major, &minor))
- return false;
+ auto version = connection->screensaver()
+ .QueryVersion({x11::ScreenSaver::major_version,
+ x11::ScreenSaver::minor_version})
+ .Sync();
- return major > 1 || (major == 1 && minor >= 1);
+ return version && (version->server_major_version > 1 ||
+ (version->server_major_version == 1 &&
+ version->server_minor_version >= 1));
}
// Wrapper for XScreenSaverSuspend. Checks whether the X11 Screen Saver
@@ -159,8 +157,8 @@ void X11ScreenSaverSuspendSet(bool suspend) {
if (!X11ScreenSaverAvailable())
return;
- XDisplay* display = gfx::GetXDisplay();
- XScreenSaverSuspend(display, suspend);
+ auto* connection = x11::Connection::Get();
+ connection->screensaver().Suspend({suspend});
}
#endif
diff --git a/chromium/services/image_annotation/annotator.cc b/chromium/services/image_annotation/annotator.cc
index 53de4424f67..4c8b943a70e 100644
--- a/chromium/services/image_annotation/annotator.cc
+++ b/chromium/services/image_annotation/annotator.cc
@@ -737,8 +737,11 @@ void Annotator::ProcessResults(
// |request_infos_|, and this method should only execute once per request
// key.
const auto request_info_it = request_infos_.find(request_key);
- if (request_info_it == request_infos_.end())
+ if (request_info_it == request_infos_.end()) {
+ LOG(ERROR) << "Could not find request key in request_infos_: "
+ << request_key.first << "," << request_key.second;
continue;
+ }
const auto image_result = result_lookup != results.end()
? result_lookup->second.Clone()
diff --git a/chromium/services/image_annotation/annotator.h b/chromium/services/image_annotation/annotator.h
index 572ba326fc3..56ddf90fc34 100644
--- a/chromium/services/image_annotation/annotator.h
+++ b/chromium/services/image_annotation/annotator.h
@@ -107,6 +107,7 @@ class Annotator : public mojom::Annotator {
FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, ComputePreferredLanguage);
FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, FetchServerLanguages);
FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, ServerLanguagesMustContainEnglish);
+ FRIEND_TEST_ALL_PREFIXES(AnnotatorTest, LanguageFallback);
// The relevant info for a request from a client feature for a single image.
struct ClientRequestInfo {
diff --git a/chromium/services/image_annotation/annotator_unittest.cc b/chromium/services/image_annotation/annotator_unittest.cc
index 7803095dd5d..40e6b6cc239 100644
--- a/chromium/services/image_annotation/annotator_unittest.cc
+++ b/chromium/services/image_annotation/annotator_unittest.cc
@@ -2173,6 +2173,107 @@ TEST(AnnotatorTest, DescLanguage) {
mojom::AnnotationType::kOcr, 1.0, "2")));
}
+// Test that annotation works properly when we need to fall back on a
+// different language because the page language isn't available.
+TEST(AnnotatorTest, LanguageFallback) {
+ base::test::TaskEnvironment test_task_env(
+ base::test::TaskEnvironment::TimeSource::MOCK_TIME);
+ TestServerURLLoaderFactory test_url_factory(
+ "https://ia-pa.googleapis.com/v1/");
+ data_decoder::test::InProcessDataDecoder in_process_data_decoder;
+ base::HistogramTester histogram_tester;
+
+ Annotator annotator(GURL(kTestServerUrl), GURL(""),
+ std::string() /* api_key */, kThrottle,
+ 1 /* batch_size */, 1.0 /* min_ocr_confidence */,
+ test_url_factory.AsSharedURLLoaderFactory(),
+ std::make_unique<TestAnnotatorClient>());
+ annotator.server_languages_ = {"en", "it", "fr"};
+
+ TestImageProcessor processor;
+ base::Optional<mojom::AnnotateImageError> error;
+ std::vector<mojom::Annotation> annotations;
+
+ // Send a request in an unsupported language.
+ annotator.AnnotateImage(kImage1Url, "hu", processor.GetPendingRemote(),
+ base::BindOnce(&ReportResult, &error, &annotations));
+ test_task_env.RunUntilIdle();
+
+ // Send back image data.
+ std::move(processor.callbacks()[0]).Run({1, 2, 3}, kDescDim, kDescDim);
+ processor.callbacks().pop_back();
+ test_task_env.RunUntilIdle();
+
+ // Fast-forward time so that server sends batch.
+ EXPECT_THAT(test_url_factory.requests(), IsEmpty());
+ test_task_env.FastForwardBy(base::TimeDelta::FromSeconds(1));
+
+ // A single HTTP request for all images should have been sent.
+ test_url_factory.ExpectRequestAndSimulateResponse(
+ "annotation", {} /* expected_headers */, ReformatJson(R"(
+ {
+ "imageRequests": [
+ {
+ "imageId": "https://www.example.com/image1.jpg en",
+ "imageBytes": "AQID",
+ "engineParameters": [
+ {"ocrParameters": {}},
+ {
+ "descriptionParameters": {
+ "preferredLanguages": ["en"]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ )"),
+ R"(
+ {
+ "results": [
+ {
+ "imageId": "https://www.example.com/image1.jpg en",
+ "engineResults": [
+ {
+ "status": {},
+ "ocrEngine": {
+ "ocrRegions": [{
+ "words": [{
+ "detectedText": "1",
+ "confidenceScore": 1.0
+ }]
+ }]
+ }
+ },
+ {
+ "status": {},
+ "descriptionEngine": {
+ "descriptionList": {
+ "descriptions": [{
+ "type": "CAPTION",
+ "text": "Result in fallback language.",
+ "score": 1.0
+ }]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ )",
+ net::HTTP_OK);
+ test_task_env.RunUntilIdle();
+
+ // Annotator should have called each callback with its corresponding results.
+ ASSERT_EQ(error, base::nullopt);
+ EXPECT_THAT(
+ annotations,
+ UnorderedElementsAre(AnnotatorEq(mojom::AnnotationType::kOcr, 1.0, "1"),
+ AnnotatorEq(mojom::AnnotationType::kCaption, 1.0,
+ "Result in fallback language.")));
+}
+
// Test that the specified API key is sent, but only to Google-associated server
// domains.
TEST(AnnotatorTest, ApiKey) {
diff --git a/chromium/services/metrics/public/cpp/ukm_source.cc b/chromium/services/metrics/public/cpp/ukm_source.cc
index 408d0ad9a2e..b83454bd115 100644
--- a/chromium/services/metrics/public/cpp/ukm_source.cc
+++ b/chromium/services/metrics/public/cpp/ukm_source.cc
@@ -9,6 +9,7 @@
#include "base/atomicops.h"
#include "base/check_op.h"
#include "base/hash/hash.h"
+#include "base/notreached.h"
#include "third_party/metrics_proto/ukm/source.pb.h"
namespace ukm {
@@ -35,6 +36,28 @@ std::string GetShortenedURL(const GURL& url) {
return url.spec();
}
+// Translates ukm::SourceIdType to the equivalent Source proto enum value.
+SourceType ToProtobufSourceType(SourceIdType source_id_type) {
+ switch (source_id_type) {
+ case SourceIdType::DEFAULT:
+ return SourceType::DEFAULT;
+ case SourceIdType::NAVIGATION_ID:
+ return SourceType::NAVIGATION_ID;
+ case SourceIdType::APP_ID:
+ return SourceType::APP_ID;
+ case SourceIdType::HISTORY_ID:
+ return SourceType::HISTORY_ID;
+ case SourceIdType::WEBAPK_ID:
+ return SourceType::WEBAPK_ID;
+ case SourceIdType::PAYMENT_APP_ID:
+ return SourceType::PAYMENT_APP_ID;
+ case SourceIdType::DESKTOP_WEB_APP_ID:
+ return SourceType::DESKTOP_WEB_APP_ID;
+ default:
+ NOTREACHED();
+ return SourceType::DEFAULT;
+ }
+}
} // namespace
// static
@@ -70,6 +93,7 @@ UkmSource::NavigationData UkmSource::NavigationData::CopyWithSanitizedUrls(
UkmSource::UkmSource(ukm::SourceId id, const GURL& url)
: id_(id),
+ type_(GetSourceIdType(id_)),
custom_tab_state_(g_custom_tab_state),
creation_time_(base::TimeTicks::Now()) {
navigation_data_.urls = {url};
@@ -78,10 +102,11 @@ UkmSource::UkmSource(ukm::SourceId id, const GURL& url)
UkmSource::UkmSource(ukm::SourceId id, const NavigationData& navigation_data)
: id_(id),
+ type_(GetSourceIdType(id_)),
navigation_data_(navigation_data),
custom_tab_state_(g_custom_tab_state),
creation_time_(base::TimeTicks::Now()) {
- DCHECK(GetSourceIdType(id_) == SourceIdType::NAVIGATION_ID);
+ DCHECK(type_ == SourceIdType::NAVIGATION_ID);
DCHECK(!navigation_data.urls.empty());
DCHECK(!navigation_data.urls.back().is_empty());
}
@@ -98,10 +123,12 @@ void UkmSource::UpdateUrl(const GURL& new_url) {
void UkmSource::PopulateProto(Source* proto_source) const {
DCHECK(!proto_source->has_id());
+ DCHECK(!proto_source->has_type());
DCHECK(!proto_source->has_url());
DCHECK(!proto_source->has_initial_url());
proto_source->set_id(id_);
+ proto_source->set_type(ToProtobufSourceType(type_));
for (const auto& url : urls()) {
proto_source->add_urls()->set_url(GetShortenedURL(url));
}
diff --git a/chromium/services/metrics/public/cpp/ukm_source.h b/chromium/services/metrics/public/cpp/ukm_source.h
index ec138b0888b..fd65515dfeb 100644
--- a/chromium/services/metrics/public/cpp/ukm_source.h
+++ b/chromium/services/metrics/public/cpp/ukm_source.h
@@ -113,6 +113,7 @@ class METRICS_EXPORT UkmSource {
private:
const ukm::SourceId id_;
+ const ukm::SourceIdType type_;
NavigationData navigation_data_;
diff --git a/chromium/services/metrics/public/cpp/ukm_source_id_unittest.cc b/chromium/services/metrics/public/cpp/ukm_source_id_unittest.cc
index eff8fda5293..6c976a3e248 100644
--- a/chromium/services/metrics/public/cpp/ukm_source_id_unittest.cc
+++ b/chromium/services/metrics/public/cpp/ukm_source_id_unittest.cc
@@ -15,7 +15,7 @@ TEST(UkmSourceIdTest, AssignSourceIds) {
for (size_t i = 0; i < numIds; i++) {
ids[i] = AssignNewSourceId();
EXPECT_NE(kInvalidSourceId, ids[i]);
- EXPECT_EQ(SourceIdType::UKM, GetSourceIdType(ids[i]));
+ EXPECT_EQ(SourceIdType::DEFAULT, GetSourceIdType(ids[i]));
for (size_t j = 0; j < i; j++) {
EXPECT_NE(ids[j], ids[i]);
}
@@ -37,9 +37,9 @@ TEST(UkmSourceIdTest, ConvertToNavigationType) {
}
TEST(UkmSourceIdTest, GetSourceIdType) {
- // Check that the newly assigned id is defaulted to "UKM" type.
+ // Check that the newly assigned id has the default type.
const SourceId new_id = AssignNewSourceId();
- EXPECT_EQ(SourceIdType::UKM, GetSourceIdType(new_id));
+ EXPECT_EQ(SourceIdType::DEFAULT, GetSourceIdType(new_id));
const int64_t num_types = static_cast<int64_t>(SourceIdType::kMaxValue);
for (int64_t type_index = 0; type_index <= num_types; type_index++) {
diff --git a/chromium/services/network/BUILD.gn b/chromium/services/network/BUILD.gn
index 5c963f42c7f..1a4135ea4b7 100644
--- a/chromium/services/network/BUILD.gn
+++ b/chromium/services/network/BUILD.gn
@@ -36,8 +36,6 @@ jumbo_component("network_service") {
"data_pipe_element_reader.h",
"dns_config_change_manager.cc",
"dns_config_change_manager.h",
- "empty_url_loader_client.cc",
- "empty_url_loader_client.h",
"host_resolver.cc",
"host_resolver.h",
"host_resolver_mdns_listener.cc",
@@ -231,12 +229,12 @@ jumbo_component("network_service") {
"//components/os_crypt",
"//components/prefs",
"//jingle:fake_ssl_socket",
- "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//net",
"//net:extras",
"//services/network/public/cpp",
+ "//services/network/public/cpp:crash_keys",
"//services/network/public/cpp/cert_verifier:cert_verifier_creation",
"//services/network/public/cpp/cert_verifier:mojo_cert_verifier",
"//services/network/public/mojom",
@@ -380,7 +378,6 @@ source_set("tests") {
"//components/variations:test_support",
"//crypto:test_support",
"//jingle:fake_ssl_socket",
- "//mojo/core/embedder",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
"//net",
@@ -417,6 +414,8 @@ jumbo_source_set("test_support") {
sources = [
"mojo_socket_test_util.cc",
"mojo_socket_test_util.h",
+ "test/fake_test_cert_verifier_params_factory.cc",
+ "test/fake_test_cert_verifier_params_factory.h",
"test/test_cookie_manager.cc",
"test/test_cookie_manager.h",
"test/test_data_pipe_getter.cc",
diff --git a/chromium/services/network/README.md b/chromium/services/network/README.md
index 58b776b4775..d9f0ca04baf 100644
--- a/chromium/services/network/README.md
+++ b/chromium/services/network/README.md
@@ -12,7 +12,7 @@ Some design goals
not have hooks here. The only exception is when it's impossible for these
features to function without some hooks in the network service. In that
case, we add the minimal code required. Some examples included traffic
- shaping for devtools and CORB blocking.
+ shaping for devtools, CORB blocking, and CORS.
* every PostTask, thread hop and process hop (IPC) should be counted carefully
as they introduce delays which could harm this performance critical code.
* `NetworkContext` and `NetworkService` are trusted interfaces that aren't
@@ -24,6 +24,77 @@ See https://bugs.chromium.org/p/chromium/issues/detail?id=598073
See the design doc
https://docs.google.com/document/d/1wAHLw9h7gGuqJNCgG1mP1BmLtCGfZ2pys-PdZQ1vg7M/edit?pref=2&pli=1#
+# Related docs
+
+* [URLLoader](url_loader.md)
+
+# Where does the network service run?
+
+> Note: For more background about this section, see also [Multi-process
+Architecture](https://www.chromium.org/developers/design-documents/multi-process-architecture)
+for an overview of the processes in Chromium.
+
+The network service is designed as a [Mojo service](/docs/mojo_and_services.md)
+that in general doesn't need to be aware of which thread/process it runs on.
+The browser process launches the network service and decides whether to run it
+inside the browser process (*in-process*) or in a dedicated utility process
+(*out-of-process*).
+
+The out-of-process configuration is preferred for isolation and stability, and
+is the default on most platforms. The in-process configuration is the default on
+Android because of some unresolved issues; see https://crbug.com/1049008. It
+can also be useful for debugging; for example, it's used in Chromium's
+[`--single-process`](https://www.chromium.org/developers/design-documents/process-models)
+mode.
+
+*In the out-of-process case*: The network service runs on the [IO
+thread](/docs/threading_and_tasks.md) of the utility process (see this
+[comment][1] in `content/utility/services.cc` for why). The utility process
+houses only the network service, so there is nothing running on its main thread.
+
+[1]: https://source.chromium.org/chromium/chromium/src/+/master:content/utility/services.cc;l=197-198;drc=9b85cd82c52e13ed685dd74c726d91067bbd34d5
+
+*In the in-process case*: The network service runs on its own dedicated thread
+in the browser process. Exception: on Chrome OS, it currently runs on the IO
+thread; see https://crbug.com/1086738.
+
+# How does the network service start?
+
+*In the out-of-process case*: The browser creates the utility process and asks
+it to launch the network service. For the browser-side code, see
+`GetNetworkService()` in `content/browser/network_service_instance_impl.cc`.
+For the utility process code, see `GetIOThreadServiceFactory` in
+content/utility/services.cc. This calls `RunNetworkService()` which creates the
+`network::NetworkService` instance. For more background about Chromium's
+services architecture, see [Mojo and Services](/docs/mojo_and_services.md).
+
+*In the in-process case*: The browser process starts the network service. See
+`CreateInProcessNetworkService()` in
+`content/browser/network_service_instance_impl.cc`, which posts a task to create
+the `network::NetworkService` instance.
+
+# What happens if the network service crashes?
+
+*In the out-of-process case*: If the network service crashes, it gets restarted
+in a new utility process. The goal is for the failure to be mostly recoverable.
+It is important to note that any URLLoaderFactories bound to the Network Service
+before it crashes become disconnected, and will no longer continue to work.
+Therefore it is useful to establish reconnection logic if it is detected that
+the URLLoaderFactory is no longer connected.
+
+For example, a navigation request's URLLoaderFactory comes from
+`StoragePartitionImpl::GetURLLoaderFactoryForBrowserProcessInternal` in the
+browser process. This method has logic to detect if the URLLoaderFactory it
+would normally return is disconnected. In that case, it creates a new one which
+is used for all future navigation requests. Since most URLLoaderFactory users
+use factories that are not created out-of-band, and are provided by some
+service, reconnection logic is often implemented for free, and is usually not
+something to worry about.
+
+*In the in-process case*: If the network service crashes in this case, of
+course, the entire browser crashes. This is one reason for the goal to always
+run it out-of-process.
+
# Buildbot
The [Network Service
@@ -41,13 +112,9 @@ Its steps are:
Chrome on Android runs with the network service in-process by default
(https://crbug.com/1049008). However, `browser_tests` are not well-supported
on Android (https://crbug.com/611756), so we run them on this Linux bot.
- Furthermore, there is a flag and group policy to run the network service
- in-process on Desktop, but there are efforts to remove this
- (https://crbug.com/1036230).
* **`network_service_in_process_content_browsertests`**: Same as above but for
`content_browsertests`. We might consider removing this from the bot, since
- the Android bots run `content_browsertests` which should give enough coverage,
- but maybe we can remove the Desktop flag and group policy first.
+ the Android bots run `content_browsertests` which should give enough coverage.
* **`network_service_web_request_proxy_browser_tests`**: Runs `browser_tests`
while forcing the "network request proxying" code path that is taken when the
browser has an extension installed that uses the
diff --git a/chromium/services/network/cert_verifier_with_trust_anchors.cc b/chromium/services/network/cert_verifier_with_trust_anchors.cc
index 80081f16797..32b648d6028 100644
--- a/chromium/services/network/cert_verifier_with_trust_anchors.cc
+++ b/chromium/services/network/cert_verifier_with_trust_anchors.cc
@@ -7,7 +7,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/logging.h"
+#include "base/check_op.h"
#include "net/base/net_errors.h"
#include "net/cert/caching_cert_verifier.h"
#include "net/cert/cert_verifier.h"
@@ -38,13 +38,17 @@ void CompleteAndSignalAnchorUse(
std::move(completion_callback).Run(error);
}
-net::CertVerifier::Config ExtendTrustAnchors(
+net::CertVerifier::Config ExtendTrustAnchorsAndTempCerts(
const net::CertVerifier::Config& config,
- const net::CertificateList& trust_anchors) {
+ const net::CertificateList& trust_anchors,
+ const net::CertificateList& untrusted_authorities) {
net::CertVerifier::Config new_config = config;
new_config.additional_trust_anchors.insert(
new_config.additional_trust_anchors.begin(), trust_anchors.begin(),
trust_anchors.end());
+ new_config.additional_untrusted_authorities.insert(
+ new_config.additional_untrusted_authorities.begin(),
+ untrusted_authorities.begin(), untrusted_authorities.end());
return new_config;
}
@@ -64,18 +68,23 @@ void CertVerifierWithTrustAnchors::InitializeOnIOThread(
std::unique_ptr<net::CertVerifier> delegate) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
delegate_ = std::move(delegate);
- delegate_->SetConfig(ExtendTrustAnchors(orig_config_, trust_anchors_));
+ delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
+ orig_config_, trust_anchors_, untrusted_authorities_));
}
-void CertVerifierWithTrustAnchors::SetTrustAnchors(
- const net::CertificateList& trust_anchors) {
+void CertVerifierWithTrustAnchors::SetAdditionalCerts(
+ const net::CertificateList& trust_anchors,
+ const net::CertificateList& untrusted_authorities) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- if (trust_anchors == trust_anchors_)
+ if (std::tie(trust_anchors, untrusted_authorities) ==
+ std::tie(trust_anchors_, untrusted_authorities_))
return;
trust_anchors_ = trust_anchors;
+ untrusted_authorities_ = untrusted_authorities;
if (!delegate_)
return;
- delegate_->SetConfig(ExtendTrustAnchors(orig_config_, trust_anchors_));
+ delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
+ orig_config_, trust_anchors_, untrusted_authorities_));
}
int CertVerifierWithTrustAnchors::Verify(
@@ -100,7 +109,8 @@ int CertVerifierWithTrustAnchors::Verify(
void CertVerifierWithTrustAnchors::SetConfig(const Config& config) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
orig_config_ = config;
- delegate_->SetConfig(ExtendTrustAnchors(orig_config_, trust_anchors_));
+ delegate_->SetConfig(ExtendTrustAnchorsAndTempCerts(
+ orig_config_, trust_anchors_, untrusted_authorities_));
}
} // namespace network
diff --git a/chromium/services/network/cert_verifier_with_trust_anchors.h b/chromium/services/network/cert_verifier_with_trust_anchors.h
index 271eed95ead..6e0c02a1f4f 100644
--- a/chromium/services/network/cert_verifier_with_trust_anchors.h
+++ b/chromium/services/network/cert_verifier_with_trust_anchors.h
@@ -42,8 +42,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CertVerifierWithTrustAnchors
// this method.
void InitializeOnIOThread(std::unique_ptr<net::CertVerifier> delegate);
- // Sets the additional trust anchors.
- void SetTrustAnchors(const net::CertificateList& trust_anchors);
+ // Sets the additional trust anchors and untrusted authorities to be
+ // considered as intermediates.
+ void SetAdditionalCerts(const net::CertificateList& trust_anchors,
+ const net::CertificateList& untrusted_authorities);
// CertVerifier:
int Verify(const RequestParams& params,
@@ -56,6 +58,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CertVerifierWithTrustAnchors
private:
net::CertVerifier::Config orig_config_;
net::CertificateList trust_anchors_;
+ net::CertificateList untrusted_authorities_;
base::RepeatingClosure anchor_used_callback_;
std::unique_ptr<CertVerifier> delegate_;
THREAD_CHECKER(thread_checker_);
diff --git a/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc b/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc
index 7ec5f95ab8c..26acf6497ff 100644
--- a/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc
+++ b/chromium/services/network/cert_verifier_with_trust_anchors_unittest.cc
@@ -227,7 +227,8 @@ TEST_F(CertVerifierWithTrustAnchorsTest, VerifyUsingAdditionalTrustAnchor) {
ASSERT_FALSE(test_ca_x509cert_list.empty());
// Verify() again with the additional trust anchors.
- cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
+ cert_verifier_->SetAdditionalCerts(test_ca_x509cert_list,
+ net::CertificateList());
{
net::CertVerifyResult verify_result;
net::TestCompletionCallback callback;
@@ -242,7 +243,8 @@ TEST_F(CertVerifierWithTrustAnchorsTest, VerifyUsingAdditionalTrustAnchor) {
EXPECT_TRUE(WasTrustAnchorUsedAndReset());
// Verify() again with the additional trust anchors will hit the cache.
- cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
+ cert_verifier_->SetAdditionalCerts(test_ca_x509cert_list,
+ net::CertificateList());
{
net::CertVerifyResult verify_result;
net::TestCompletionCallback callback;
@@ -254,7 +256,8 @@ TEST_F(CertVerifierWithTrustAnchorsTest, VerifyUsingAdditionalTrustAnchor) {
EXPECT_TRUE(WasTrustAnchorUsedAndReset());
// Verifying after removing the trust anchors should now fail.
- cert_verifier_->SetTrustAnchors(net::CertificateList());
+ cert_verifier_->SetAdditionalCerts(net::CertificateList(),
+ net::CertificateList());
{
net::CertVerifyResult verify_result;
net::TestCompletionCallback callback;
@@ -296,7 +299,8 @@ TEST_F(CertVerifierWithTrustAnchorsTest,
ASSERT_FALSE(test_ca_x509cert_list.empty());
// Verify() again with the additional trust anchors.
- cert_verifier_->SetTrustAnchors(test_ca_x509cert_list);
+ cert_verifier_->SetAdditionalCerts(test_ca_x509cert_list,
+ net::CertificateList());
{
net::CertVerifyResult verify_result;
net::TestCompletionCallback callback;
diff --git a/chromium/services/network/chunked_data_pipe_upload_data_stream.cc b/chromium/services/network/chunked_data_pipe_upload_data_stream.cc
index e5c53e606e2..305bfa2ef3c 100644
--- a/chromium/services/network/chunked_data_pipe_upload_data_stream.cc
+++ b/chromium/services/network/chunked_data_pipe_upload_data_stream.cc
@@ -33,6 +33,10 @@ ChunkedDataPipeUploadDataStream::ChunkedDataPipeUploadDataStream(
ChunkedDataPipeUploadDataStream::~ChunkedDataPipeUploadDataStream() {}
+bool ChunkedDataPipeUploadDataStream::AllowHTTP1() const {
+ return resource_request_body_->AllowHTTP1ForStreamingUpload();
+}
+
int ChunkedDataPipeUploadDataStream::InitInternal(
const net::NetLogWithSource& net_log) {
// If there was an error either passed to the ReadCallback or as a result of
diff --git a/chromium/services/network/chunked_data_pipe_upload_data_stream.h b/chromium/services/network/chunked_data_pipe_upload_data_stream.h
index 45f7c2b5aa4..10590039c39 100644
--- a/chromium/services/network/chunked_data_pipe_upload_data_stream.h
+++ b/chromium/services/network/chunked_data_pipe_upload_data_stream.h
@@ -43,6 +43,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ChunkedDataPipeUploadDataStream
~ChunkedDataPipeUploadDataStream() override;
+ bool AllowHTTP1() const override;
+
private:
// net::UploadDataStream implementation.
int InitInternal(const net::NetLogWithSource& net_log) override;
diff --git a/chromium/services/network/cookie_manager_unittest.cc b/chromium/services/network/cookie_manager_unittest.cc
index 9f7bad7172d..b66d553eb79 100644
--- a/chromium/services/network/cookie_manager_unittest.cc
+++ b/chromium/services/network/cookie_manager_unittest.cc
@@ -18,6 +18,7 @@
#include "base/test/task_environment.h"
#include "base/time/time.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_monster.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_store_test_callbacks.h"
@@ -109,25 +110,26 @@ class SynchronousCookieManager {
url, options,
base::BindLambdaForTesting(
[&run_loop, &cookies_out](
- const net::CookieStatusList& cookies,
- const net::CookieStatusList& excluded_cookies) {
- cookies_out = net::cookie_util::StripStatuses(cookies);
+ const net::CookieAccessResultList& cookies,
+ const net::CookieAccessResultList& excluded_cookies) {
+ cookies_out = net::cookie_util::StripAccessResults(cookies);
run_loop.Quit();
}));
run_loop.Run();
return cookies_out;
}
- net::CookieStatusList GetExcludedCookieList(const GURL& url,
- net::CookieOptions options) {
+ net::CookieAccessResultList GetExcludedCookieList(
+ const GURL& url,
+ net::CookieOptions options) {
base::RunLoop run_loop;
- net::CookieStatusList cookies_out;
+ net::CookieAccessResultList cookies_out;
cookie_service_->GetCookieList(
url, options,
base::BindLambdaForTesting(
[&run_loop, &cookies_out](
- const net::CookieStatusList& cookies,
- const net::CookieStatusList& excluded_cookies) {
+ const net::CookieAccessResultList& cookies,
+ const net::CookieAccessResultList& excluded_cookies) {
cookies_out = excluded_cookies;
run_loop.Quit();
}));
@@ -139,8 +141,8 @@ class SynchronousCookieManager {
std::string source_scheme,
bool modify_http_only) {
base::RunLoop run_loop;
- net::CanonicalCookie::CookieInclusionStatus result_out(
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+ net::CookieInclusionStatus result_out(
+ net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
net::CookieOptions options;
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
@@ -150,8 +152,7 @@ class SynchronousCookieManager {
cookie, net::cookie_util::SimulatedCookieSource(cookie, source_scheme),
options,
base::BindLambdaForTesting(
- [&run_loop,
- &result_out](net::CanonicalCookie::CookieInclusionStatus result) {
+ [&run_loop, &result_out](net::CookieInclusionStatus result) {
result_out = result;
run_loop.Quit();
}));
@@ -160,7 +161,7 @@ class SynchronousCookieManager {
return result_out.IsInclude();
}
- net::CanonicalCookie::CookieInclusionStatus SetCanonicalCookieWithStatus(
+ net::CookieInclusionStatus SetCanonicalCookieWithStatus(
const net::CanonicalCookie& cookie,
std::string source_scheme,
bool modify_http_only) {
@@ -170,14 +171,13 @@ class SynchronousCookieManager {
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
if (modify_http_only)
options.set_include_httponly();
- net::CanonicalCookie::CookieInclusionStatus result_out(
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+ net::CookieInclusionStatus result_out(
+ net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
cookie_service_->SetCanonicalCookie(
cookie, net::cookie_util::SimulatedCookieSource(cookie, source_scheme),
options,
base::BindLambdaForTesting(
- [&run_loop,
- &result_out](net::CanonicalCookie::CookieInclusionStatus result) {
+ [&run_loop, &result_out](net::CookieInclusionStatus result) {
result_out = result;
run_loop.Quit();
}));
@@ -262,8 +262,7 @@ class CookieManagerTest : public testing::Test {
bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
std::string source_scheme,
bool can_modify_httponly) {
- net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
- callback;
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
net::CookieOptions options;
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
@@ -273,9 +272,9 @@ class CookieManagerTest : public testing::Test {
cookie_monster_->SetCanonicalCookieAsync(
std::make_unique<net::CanonicalCookie>(cookie),
net::cookie_util::SimulatedCookieSource(cookie, source_scheme), options,
- base::BindOnce(&net::ResultSavingCookieCallback<
- net::CanonicalCookie::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback)));
callback.WaitUntilDone();
return callback.result().IsInclude();
}
@@ -589,7 +588,7 @@ TEST_F(CookieManagerTest, GetCookieList) {
net::CookieOptions excluded_options = options;
excluded_options.set_return_excluded_cookies();
- net::CookieStatusList excluded_cookies =
+ net::CookieAccessResultList excluded_cookies =
service_wrapper()->GetExcludedCookieList(
GURL("https://foo_host.com/with/path"), excluded_options);
@@ -597,8 +596,9 @@ TEST_F(CookieManagerTest, GetCookieList) {
EXPECT_EQ("HttpOnly", excluded_cookies[0].cookie.Name());
EXPECT_EQ("F", excluded_cookies[0].cookie.Value());
- EXPECT_TRUE(excluded_cookies[0].status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
+ EXPECT_TRUE(excluded_cookies[0]
+ .access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
}
TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
@@ -634,7 +634,7 @@ TEST_F(CookieManagerTest, GetCookieListHttpOnly) {
options.set_return_excluded_cookies();
- net::CookieStatusList excluded_cookies =
+ net::CookieAccessResultList excluded_cookies =
service_wrapper()->GetExcludedCookieList(
GURL("https://foo_host.com/with/path"), options);
ASSERT_EQ(1u, excluded_cookies.size());
@@ -690,7 +690,7 @@ TEST_F(CookieManagerTest, GetCookieListSameSite) {
options.set_return_excluded_cookies();
- net::CookieStatusList excluded_cookies =
+ net::CookieAccessResultList excluded_cookies =
service_wrapper()->GetExcludedCookieList(
GURL("https://foo_host.com/with/path"), options);
ASSERT_EQ(2u, excluded_cookies.size());
@@ -842,8 +842,7 @@ TEST_F(CookieManagerTest, ConfirmSecureSetFails) {
net::COOKIE_PRIORITY_MEDIUM),
"http", false)
.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_SECURE_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -861,8 +860,7 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlySetFails) {
net::COOKIE_PRIORITY_MEDIUM),
"http", false)
.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_HTTP_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -888,8 +886,7 @@ TEST_F(CookieManagerTest, ConfirmSecureOverwriteFails) {
net::COOKIE_PRIORITY_MEDIUM),
"http", false)
.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_OVERWRITE_SECURE}));
+ {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE}));
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -918,8 +915,7 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlyOverwriteFails) {
net::COOKIE_PRIORITY_MEDIUM),
"https", false)
.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_OVERWRITE_HTTP_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY}));
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
diff --git a/chromium/services/network/cookie_settings.cc b/chromium/services/network/cookie_settings.cc
index 099a4518415..5122960ccdd 100644
--- a/chromium/services/network/cookie_settings.cc
+++ b/chromium/services/network/cookie_settings.cc
@@ -184,16 +184,25 @@ void CookieSettings::GetCookieSettingInternal(
// We'll only utilize the SAA grant if our value is set to
// CONTENT_SETTING_ALLOW as other values would indicate the user
// rejected a prompt to allow access.
- if (storage_access_setting == CONTENT_SETTING_ALLOW)
+ if (storage_access_setting == CONTENT_SETTING_ALLOW) {
block = false;
+ FireStorageAccessHistogram(net::cookie_util::StorageAccessResult::
+ ACCESS_ALLOWED_STORAGE_ACCESS_GRANT);
+ }
break;
}
}
+ } else {
+ FireStorageAccessHistogram(
+ net::cookie_util::StorageAccessResult::ACCESS_ALLOWED);
}
- if (block)
+ if (block) {
*cookie_setting = CONTENT_SETTING_BLOCK;
+ FireStorageAccessHistogram(
+ net::cookie_util::StorageAccessResult::ACCESS_BLOCKED);
+ }
}
bool CookieSettings::HasSessionOnlyOrigins() const {
diff --git a/chromium/services/network/cookie_settings_unittest.cc b/chromium/services/network/cookie_settings_unittest.cc
index 04bdf94e067..4e902b52288 100644
--- a/chromium/services/network/cookie_settings_unittest.cc
+++ b/chromium/services/network/cookie_settings_unittest.cc
@@ -4,6 +4,7 @@
#include "services/network/cookie_settings.h"
+#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "net/base/features.h"
@@ -15,6 +16,9 @@
namespace network {
namespace {
+constexpr char kAllowedRequestsHistogram[] =
+ "API.StorageAccess.AllowedRequests";
+
constexpr char kDomainURL[] = "http://example.com";
constexpr char kURL[] = "http://foo.com";
constexpr char kOtherURL[] = "http://other.com";
@@ -90,6 +94,9 @@ TEST_F(CookieSettingsTest, GetCookieSettingGetsFirstSetting) {
}
TEST_F(CookieSettingsTest, GetCookieSettingDontBlockThirdParty) {
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0);
+
CookieSettings settings;
settings.set_content_settings(
{CreateSetting("*", "*", CONTENT_SETTING_ALLOW)});
@@ -97,6 +104,11 @@ TEST_F(CookieSettingsTest, GetCookieSettingDontBlockThirdParty) {
ContentSetting setting;
settings.GetCookieSetting(GURL(kURL), GURL(kOtherURL), nullptr, &setting);
EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::ACCESS_ALLOWED),
+ 1);
}
TEST_F(CookieSettingsTest, GetCookieSettingBlockThirdParty) {
@@ -126,6 +138,9 @@ TEST_F(CookieSettingsTest, GetCookieSettingSAAUnblocks) {
GURL url = GURL(kOtherURL);
GURL third_url = GURL(kDomainURL);
+ base::HistogramTester histogram_tester;
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 0);
+
CookieSettings settings;
settings.set_content_settings(
{CreateSetting("*", "*", CONTENT_SETTING_ALLOW)});
@@ -140,11 +155,27 @@ TEST_F(CookieSettingsTest, GetCookieSettingSAAUnblocks) {
ContentSetting setting;
settings.GetCookieSetting(url, top_level_url, nullptr, &setting);
EXPECT_EQ(setting, CONTENT_SETTING_ALLOW);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::
+ ACCESS_ALLOWED_STORAGE_ACCESS_GRANT),
+ 1);
// Invalid pair the |top_level_url| granting access to |url| is now
// being loaded under |url| as the top level url.
settings.GetCookieSetting(top_level_url, url, nullptr, &setting);
EXPECT_EQ(setting, CONTENT_SETTING_BLOCK);
+ histogram_tester.ExpectTotalCount(kAllowedRequestsHistogram, 2);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::
+ ACCESS_ALLOWED_STORAGE_ACCESS_GRANT),
+ 1);
+ histogram_tester.ExpectBucketCount(
+ kAllowedRequestsHistogram,
+ static_cast<int>(net::cookie_util::StorageAccessResult::ACCESS_BLOCKED),
+ 1);
// Invalid pairs where a |third_url| is used.
settings.GetCookieSetting(url, third_url, nullptr, &setting);
diff --git a/chromium/services/network/cors/cors_url_loader.cc b/chromium/services/network/cors/cors_url_loader.cc
index 30bb273eae1..2e7f769c7a3 100644
--- a/chromium/services/network/cors/cors_url_loader.cc
+++ b/chromium/services/network/cors/cors_url_loader.cc
@@ -11,6 +11,7 @@
#include "base/stl_util.h"
#include "base/strings/string_split.h"
#include "net/base/load_flags.h"
+#include "net/http/http_status_code.h"
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/cors/preflight_controller.h"
#include "services/network/public/cpp/cors/cors.h"
@@ -102,7 +103,8 @@ CorsURLLoader::CorsURLLoader(
const OriginAccessList* factory_bound_origin_access_list,
PreflightController* preflight_controller,
const base::flat_set<std::string>* allowed_exempt_headers,
- bool allow_any_cors_exempt_header)
+ bool allow_any_cors_exempt_header,
+ const net::IsolationInfo& isolation_info)
: receiver_(this, std::move(loader_receiver)),
process_id_(process_id),
routing_id_(routing_id),
@@ -118,7 +120,8 @@ CorsURLLoader::CorsURLLoader(
preflight_controller_(preflight_controller),
allowed_exempt_headers_(allowed_exempt_headers),
skip_cors_enabled_scheme_check_(skip_cors_enabled_scheme_check),
- allow_any_cors_exempt_header_(allow_any_cors_exempt_header) {
+ allow_any_cors_exempt_header_(allow_any_cors_exempt_header),
+ isolation_info_(isolation_info) {
if (ignore_isolated_world_origin)
request_.isolated_world_origin = base::nullopt;
@@ -215,6 +218,13 @@ void CorsURLLoader::FollowRedirect(
request_.method = redirect_info_.new_method;
request_.referrer = GURL(redirect_info_.new_referrer);
request_.referrer_policy = redirect_info_.new_referrer_policy;
+ request_.site_for_cookies = redirect_info_.new_site_for_cookies;
+
+ if (request_.trusted_params) {
+ request_.trusted_params->isolation_info =
+ request_.trusted_params->isolation_info.CreateForRedirect(
+ url::Origin::Create(request_.url));
+ }
// The request method can be changed to "GET". In this case we need to
// reset the request body manually.
@@ -358,10 +368,13 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
return;
}
- // TODO(yhirano): Implement the following (Note: this is needed when upload
- // streaming is implemented):
// If |actualResponse|’s status is not 303, |request|’s body is non-null, and
// |request|’s body’s source is null, then return a network error.
+ if (redirect_info.status_code != net::HTTP_SEE_OTHER &&
+ network::URLLoader::HasFetchStreamingUploadBody(&request_)) {
+ HandleComplete(URLLoaderCompletionStatus(net::ERR_INVALID_ARGUMENT));
+ return;
+ }
// If |actualResponse|’s location URL’s origin is not same origin with
// |request|’s current url’s origin and |request|’s origin is not same origin
@@ -515,7 +528,7 @@ void CorsURLLoader::StartRequest() {
PreflightController::WithTrustedHeaderClient(
options_ & mojom::kURLLoadOptionUseHeaderClient),
tainted_, net::NetworkTrafficAnnotationTag(traffic_annotation_),
- network_loader_factory_, process_id_);
+ network_loader_factory_, process_id_, isolation_info_);
}
void CorsURLLoader::StartNetworkRequest(
@@ -532,10 +545,12 @@ void CorsURLLoader::StartNetworkRequest(
// network::URLLoader doesn't understand |kSameOrigin|.
// TODO(crbug.com/943939): Fix this.
auto original_credentials_mode = request_.credentials_mode;
- request_.credentials_mode =
- CalculateCredentialsFlag(original_credentials_mode, response_tainting_)
- ? mojom::CredentialsMode::kInclude
- : mojom::CredentialsMode::kOmit;
+ if (original_credentials_mode == mojom::CredentialsMode::kSameOrigin) {
+ request_.credentials_mode =
+ CalculateCredentialsFlag(original_credentials_mode, response_tainting_)
+ ? mojom::CredentialsMode::kInclude
+ : mojom::CredentialsMode::kOmit;
+ }
// Binding |this| as an unretained pointer is safe because
// |network_client_receiver_| shares this object's lifetime.
diff --git a/chromium/services/network/cors/cors_url_loader.h b/chromium/services/network/cors/cors_url_loader.h
index d3d5059e7de..98de4924bdc 100644
--- a/chromium/services/network/cors/cors_url_loader.h
+++ b/chromium/services/network/cors/cors_url_loader.h
@@ -54,7 +54,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
const OriginAccessList* factory_bound_origin_access_list,
PreflightController* preflight_controller,
const base::flat_set<std::string>* allowed_exempt_headers,
- bool allow_any_cors_exempt_header);
+ bool allow_any_cors_exempt_header,
+ const net::IsolationInfo& isolation_info);
~CorsURLLoader() override;
@@ -192,6 +193,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoader
const bool allow_any_cors_exempt_header_;
+ net::IsolationInfo isolation_info_;
+
// Used to run asynchronous class instance bound callbacks safely.
base::WeakPtrFactory<CorsURLLoader> weak_factory_{this};
diff --git a/chromium/services/network/cors/cors_url_loader_factory.cc b/chromium/services/network/cors/cors_url_loader_factory.cc
index 26dfa0b5df2..9c73e446778 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory.cc
@@ -23,8 +23,10 @@
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
+#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/request_mode.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/trust_token_operation_authorization.h"
#include "services/network/public/mojom/fetch_api.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/url_loader.h"
@@ -35,6 +37,58 @@ namespace network {
namespace cors {
+namespace {
+
+// Verifies state that should hold for Trust Tokens parameters provided by a
+// functioning renderer:
+// - Trust Tokens should be enabled
+// - the request should come from a trustworthy context
+// - if the request is for redemption or signing, it should be from a context
+// where these operations are permitted (as specified by
+// URLLoaderFactoryParams::trust_token_redemption_policy).
+bool VerifyTrustTokenParamsIntegrityIfPresent(
+ const ResourceRequest& url_request,
+ const NetworkContext* context,
+ mojom::TrustTokenRedemptionPolicy trust_token_redemption_policy) {
+ if (!url_request.trust_token_params)
+ return true;
+
+ if (!context->trust_token_store()) {
+ // Got a request with Trust Tokens parameters with Trust tokens
+ // disabled.
+ //
+ // Here and below, we use concise error messages to make them easier to
+ // search search.
+ mojo::ReportBadMessage(
+ "TrustTokenParamsIntegrity: TrustTokensRequestWithTrustTokensDisabled");
+ return false;
+ }
+
+ if (url_request.request_initiator &&
+ !IsOriginPotentiallyTrustworthy(*url_request.request_initiator)) {
+ // Got a request with Trust Tokens parameters from an insecure context,
+ // but Trust Tokens operations may only be executed from secure
+ // contexts.
+ mojo::ReportBadMessage("TrustTokenParamsIntegrity: NotFromSecureContext");
+ return false;
+ }
+
+ if (trust_token_redemption_policy ==
+ mojom::TrustTokenRedemptionPolicy::kForbid &&
+ DoesTrustTokenOperationRequireFeaturePolicy(
+ url_request.trust_token_params->type)) {
+ // Got a request configured for Trust Tokens redemption or signing from
+ // a context in which this operation is prohibited.
+ mojo::ReportBadMessage(
+ "TrustTokenParamsIntegrity: MissingRequiredFeaturePolicy");
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace
+
class CorsURLLoaderFactory::FactoryOverride final {
public:
class ExposedNetworkLoaderFactory final : public mojom::URLLoaderFactory {
@@ -114,10 +168,14 @@ CorsURLLoaderFactory::CorsURLLoaderFactory(
process_id_(params->process_id),
request_initiator_site_lock_(params->request_initiator_site_lock),
ignore_isolated_world_origin_(params->ignore_isolated_world_origin),
+ trust_token_redemption_policy_(params->trust_token_redemption_policy),
+ isolation_info_(params->isolation_info),
origin_access_list_(origin_access_list) {
DCHECK(context_);
DCHECK(origin_access_list_);
DCHECK_NE(mojom::kInvalidProcessId, process_id_);
+ DCHECK_EQ(net::IsolationInfo::RedirectMode::kUpdateNothing,
+ params->isolation_info.redirect_mode());
if (params->automatically_assign_isolation_info) {
DCHECK(params->isolation_info.IsEmpty());
// Only the browser process is currently permitted to use automatically
@@ -202,7 +260,7 @@ void CorsURLLoaderFactory::CreateLoaderAndStart(
origin_access_list_, factory_bound_origin_access_list_.get(),
context_->cors_preflight_controller(),
context_->cors_exempt_header_list(),
- GetAllowAnyCorsExemptHeaderForBrowser());
+ GetAllowAnyCorsExemptHeaderForBrowser(), isolation_info_);
auto* raw_loader = loader.get();
OnLoaderCreated(std::move(loader));
raw_loader->Start();
@@ -347,7 +405,15 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
case InitiatorLockCompatibility::kIncorrectLock:
// Requests from the renderer need to always specify a correct initiator.
NOTREACHED();
- // TODO(lukasza): https://crbug.com/920634: Return false below.
+ if (base::FeatureList::IsEnabled(
+ features::kRequestInitiatorSiteLockEnfocement)) {
+ url::debug::ScopedOriginCrashKey initiator_lock_crash_key(
+ debug::GetRequestInitiatorSiteLockCrashKey(),
+ base::OptionalOrNullptr(request_initiator_site_lock_));
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: lock VS initiator mismatch");
+ return false;
+ }
break;
}
@@ -395,6 +461,13 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
}
}
+ if (!VerifyTrustTokenParamsIntegrityIfPresent(
+ request, context_, trust_token_redemption_policy_)) {
+ // VerifyTrustTokenParamsIntegrityIfPresent will report an appropriate bad
+ // message.
+ return false;
+ }
+
// TODO(yhirano): If the request mode is "no-cors", the redirect mode should
// be "follow".
return true;
diff --git a/chromium/services/network/cors/cors_url_loader_factory.h b/chromium/services/network/cors/cors_url_loader_factory.h
index ca9f7940484..1dfdeac49f8 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.h
+++ b/chromium/services/network/cors/cors_url_loader_factory.h
@@ -107,6 +107,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
const int32_t process_id_ = mojom::kInvalidProcessId;
const base::Optional<url::Origin> request_initiator_site_lock_;
const bool ignore_isolated_world_origin_;
+ const mojom::TrustTokenRedemptionPolicy trust_token_redemption_policy_;
+ net::IsolationInfo isolation_info_;
// Relative order of |network_loader_factory_| and |loaders_| matters -
// URLLoaderFactory needs to live longer than URLLoaders created using the
diff --git a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
index a31fd61f6f2..20e261e4a92 100644
--- a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
@@ -21,6 +21,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -54,6 +55,10 @@ class CorsURLLoaderFactoryTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
auto context_params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
context_params->initial_proxy_config =
diff --git a/chromium/services/network/cors/cors_url_loader_unittest.cc b/chromium/services/network/cors/cors_url_loader_unittest.cc
index 09b1097cddb..3d64f7ef8c1 100644
--- a/chromium/services/network/cors/cors_url_loader_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_unittest.cc
@@ -9,6 +9,7 @@
#include <utility>
#include <vector>
+#include "base/bind_helpers.h"
#include "base/check.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -20,8 +21,8 @@
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/message.h"
+#include "mojo/public/cpp/system/functions.h"
#include "net/base/load_flags.h"
#include "net/http/http_request_headers.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
@@ -39,6 +40,7 @@
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "services/network/url_loader.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -162,6 +164,12 @@ class CorsURLLoaderTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
+ // Use a fixed proxy config, to avoid dependencies on local network
+ // configuration.
context_params->initial_proxy_config =
net::ProxyConfigWithAnnotation::CreateDirect();
context_params->cors_exempt_header_list.push_back(kTestCorsExemptHeader);
@@ -325,13 +333,15 @@ class CorsURLLoaderTest : public testing::Test {
base::StringPiece method,
const GURL& url,
base::StringPiece referrer = base::StringPiece(),
- ReferrerPolicy referrer_policy = net::URLRequest::NO_REFERRER) {
+ ReferrerPolicy referrer_policy = net::URLRequest::NO_REFERRER,
+ net::SiteForCookies site_for_cookies = net::SiteForCookies()) {
net::RedirectInfo redirect_info;
redirect_info.status_code = status_code;
redirect_info.new_method = method.as_string();
redirect_info.new_url = url;
redirect_info.new_referrer = referrer.as_string();
redirect_info.new_referrer_policy = referrer_policy;
+ redirect_info.new_site_for_cookies = site_for_cookies;
return redirect_info;
}
@@ -431,13 +441,12 @@ class BadMessageTestHelper {
public:
BadMessageTestHelper()
: dummy_message_(0, 0, 0, 0, nullptr), context_(&dummy_message_) {
- mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
+ mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
&BadMessageTestHelper::OnBadMessage, base::Unretained(this)));
}
~BadMessageTestHelper() {
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
const std::vector<std::string>& bad_message_reports() const {
@@ -1154,9 +1163,11 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
RunUntilCreateLoaderAndStartCalled();
EXPECT_EQ(1, num_created_loaders());
- EXPECT_EQ(GetRequest().url, url);
- EXPECT_EQ(GetRequest().method, "POST");
- EXPECT_EQ(GetRequest().referrer, url);
+ EXPECT_EQ(url, GetRequest().url);
+ EXPECT_EQ("POST", GetRequest().method);
+ EXPECT_EQ(url, GetRequest().referrer);
+ EXPECT_EQ(net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+ GetRequest().referrer_policy);
NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(
303, "GET", new_url, "https://other.example.com",
@@ -1173,9 +1184,86 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
RunUntilCreateLoaderAndStartCalled();
EXPECT_EQ(2, num_created_loaders());
- EXPECT_EQ(GetRequest().url, new_url);
- EXPECT_EQ(GetRequest().referrer, GURL("https://other.example.com"));
- EXPECT_EQ(GetRequest().method, "GET");
+ EXPECT_EQ(new_url, GetRequest().url);
+ EXPECT_EQ("GET", GetRequest().method);
+ EXPECT_EQ(GURL("https://other.example.com"), GetRequest().referrer);
+ EXPECT_EQ(net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+ GetRequest().referrer_policy);
+
+ NotifyLoaderClientOnReceiveResponse(
+ {{"Access-Control-Allow-Origin", "https://example.com"}});
+ NotifyLoaderClientOnComplete(net::OK);
+ RunUntilComplete();
+
+ EXPECT_FALSE(client().has_received_redirect());
+ EXPECT_TRUE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_completion());
+ EXPECT_EQ(net::OK, client().completion_status().error_code);
+}
+
+// Makes sure that if an intercepted redirect updates the IsolationInfo and the
+// SiteForCookies values, the CorsURLLoader respects those changes. The former
+// only happens for frames, and the latter for subframes, but should make
+// assumptions about whether these need to be updated in CorsURLLoader.
+TEST_F(CorsURLLoaderTest,
+ InterceptedRedirectChangesIsolationInfoAndSiteForCookies) {
+ auto params = network::mojom::URLLoaderFactoryParams::New();
+ ResetFactory(base::nullopt, kRendererProcessId, true /* is_trusted */,
+ params->ignore_isolated_world_origin,
+ false /* skip_cors_enabled_scheme_check */);
+
+ const GURL url("https://example.com/foo.png");
+ const url::Origin url_origin = url::Origin::Create(url);
+ const net::SiteForCookies url_site_for_cookies =
+ net::SiteForCookies::FromOrigin(url_origin);
+
+ const GURL new_url("https://other.example.com/foo.png");
+ const url::Origin new_url_origin = url::Origin::Create(new_url);
+ const net::SiteForCookies new_url_site_for_cookies =
+ net::SiteForCookies::FromOrigin(new_url_origin);
+
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kCors;
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
+ request.url = url;
+ request.request_initiator = url_origin;
+ request.site_for_cookies = url_site_for_cookies;
+ request.update_first_party_url_on_redirect = true;
+ request.trusted_params = ResourceRequest::TrustedParams();
+ request.trusted_params->isolation_info = net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateTopFrame,
+ url_origin /* top_frame_origin */, url_origin /* frame_origin */,
+ url_site_for_cookies);
+ CreateLoaderAndStart(request);
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(1, num_created_loaders());
+ EXPECT_EQ(url, GetRequest().url);
+
+ NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(
+ 303, "GET", new_url, "" /* referrer */, net::URLRequest::NO_REFERRER,
+ new_url_site_for_cookies));
+ RunUntilRedirectReceived();
+
+ EXPECT_TRUE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_completion());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_redirect());
+
+ ClearHasReceivedRedirect();
+ FollowRedirect();
+ RunUntilCreateLoaderAndStartCalled();
+
+ EXPECT_EQ(2, num_created_loaders());
+ EXPECT_EQ(new_url, GetRequest().url);
+ EXPECT_EQ("GET", GetRequest().method);
+ EXPECT_TRUE(
+ GetRequest().site_for_cookies.IsEquivalent(new_url_site_for_cookies));
+ EXPECT_TRUE(GetRequest().trusted_params->isolation_info.IsEqualForTesting(
+ net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateTopFrame,
+ new_url_origin /* top_frame_origin */,
+ new_url_origin /* frame_origin */, new_url_site_for_cookies)));
NotifyLoaderClientOnReceiveResponse(
{{"Access-Control-Allow-Origin", "https://example.com"}});
diff --git a/chromium/services/network/cors/preflight_controller.cc b/chromium/services/network/cors/preflight_controller.cc
index 24f48caf747..84bc1ec35d0 100644
--- a/chromium/services/network/cors/preflight_controller.cc
+++ b/chromium/services/network/cors/preflight_controller.cc
@@ -200,12 +200,14 @@ class PreflightController::PreflightLoader final {
WithTrustedHeaderClient with_trusted_header_client,
bool tainted,
const net::NetworkTrafficAnnotationTag& annotation_tag,
- int32_t process_id)
+ int32_t process_id,
+ const net::NetworkIsolationKey& network_isolation_key)
: controller_(controller),
completion_callback_(std::move(completion_callback)),
original_request_(request),
tainted_(tainted),
- process_id_(process_id) {
+ process_id_(process_id),
+ network_isolation_key_(network_isolation_key) {
auto* network_service_client = MaybeGetNetworkServiceClientForDevTools();
if (network_service_client)
devtools_request_id_ = base::UnguessableToken::Create();
@@ -296,7 +298,8 @@ class PreflightController::PreflightLoader final {
if (!(original_request_.load_flags & net::LOAD_DISABLE_CACHE) &&
!detected_error_status) {
controller_->AppendToCache(*original_request_.request_initiator,
- original_request_.url, std::move(result));
+ original_request_.url, network_isolation_key_,
+ std::move(result));
}
std::move(completion_callback_)
@@ -357,6 +360,7 @@ class PreflightController::PreflightLoader final {
const bool tainted_;
const int32_t process_id_;
base::Optional<base::UnguessableToken> devtools_request_id_;
+ const net::NetworkIsolationKey network_isolation_key_;
DISALLOW_COPY_AND_ASSIGN(PreflightLoader);
};
@@ -397,21 +401,28 @@ void PreflightController::PerformPreflightCheck(
bool tainted,
const net::NetworkTrafficAnnotationTag& annotation_tag,
mojom::URLLoaderFactory* loader_factory,
- int32_t process_id) {
+ int32_t process_id,
+ const net::IsolationInfo& isolation_info) {
DCHECK(request.request_initiator);
+ const net::NetworkIsolationKey& network_isolation_key =
+ !isolation_info.IsEmpty()
+ ? isolation_info.network_isolation_key()
+ : request.trusted_params.has_value()
+ ? request.trusted_params->isolation_info.network_isolation_key()
+ : net::NetworkIsolationKey();
if (!RetrieveCacheFlags(request.load_flags) && !request.is_external_request &&
cache_.CheckIfRequestCanSkipPreflight(
- request.request_initiator.value(), request.url,
- net::NetworkIsolationKey::Todo(), request.credentials_mode,
- request.method, request.headers, request.is_revalidating)) {
+ request.request_initiator.value(), request.url, network_isolation_key,
+ request.credentials_mode, request.method, request.headers,
+ request.is_revalidating)) {
std::move(callback).Run(net::OK, base::nullopt);
return;
}
auto emplaced_pair = loaders_.emplace(std::make_unique<PreflightLoader>(
this, std::move(callback), request, with_trusted_header_client, tainted,
- annotation_tag, process_id));
+ annotation_tag, process_id, network_isolation_key));
(*emplaced_pair.first)->Request(loader_factory);
}
@@ -424,9 +435,9 @@ void PreflightController::RemoveLoader(PreflightLoader* loader) {
void PreflightController::AppendToCache(
const url::Origin& origin,
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
std::unique_ptr<PreflightResult> result) {
- cache_.AppendEntry(origin, url, net::NetworkIsolationKey::Todo(),
- std::move(result));
+ cache_.AppendEntry(origin, url, network_isolation_key, std::move(result));
}
} // namespace cors
diff --git a/chromium/services/network/cors/preflight_controller.h b/chromium/services/network/cors/preflight_controller.h
index 737bfcabfb7..437840d7049 100644
--- a/chromium/services/network/cors/preflight_controller.h
+++ b/chromium/services/network/cors/preflight_controller.h
@@ -67,7 +67,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
bool tainted,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
mojom::URLLoaderFactory* loader_factory,
- int32_t process_id);
+ int32_t process_id,
+ const net::IsolationInfo& isolation_info);
const base::flat_set<std::string>& extra_safelisted_header_names() const {
return extra_safelisted_header_names_;
@@ -84,6 +85,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
void RemoveLoader(PreflightLoader* loader);
void AppendToCache(const url::Origin& origin,
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
std::unique_ptr<PreflightResult> result);
NetworkService* network_service() { return network_service_; }
diff --git a/chromium/services/network/cors/preflight_controller_unittest.cc b/chromium/services/network/cors/preflight_controller_unittest.cc
index 3e6f9595364..c252df4121a 100644
--- a/chromium/services/network/cors/preflight_controller_unittest.cc
+++ b/chromium/services/network/cors/preflight_controller_unittest.cc
@@ -21,8 +21,10 @@
#include "services/network/cors/cors_url_loader_factory.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_service_client.h"
#include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -236,12 +238,14 @@ TEST(PreflightControllerOptionsTest, CheckOptions) {
preflight_controller.PerformPreflightCheck(
base::BindOnce([](int, base::Optional<CorsErrorStatus>) {}), request,
WithTrustedHeaderClient(false), false /* tainted */,
- TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, 0 /* process_id */);
+ TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, 0 /* process_id */,
+ net::IsolationInfo());
preflight_controller.PerformPreflightCheck(
base::BindOnce([](int, base::Optional<CorsErrorStatus>) {}), request,
WithTrustedHeaderClient(true), false /* tainted */,
- TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, 0 /* process_id */);
+ TRAFFIC_ANNOTATION_FOR_TESTS, &url_loader_factory, 0 /* process_id */,
+ net::IsolationInfo());
ASSERT_EQ(2, url_loader_factory.NumPending());
EXPECT_EQ(mojom::kURLLoadOptionAsCorsPreflight,
@@ -288,7 +292,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
int32_t process_id,
int32_t routing_id,
const std::string& devtools_request_id,
- const net::CookieStatusList& cookies_with_status,
+ const net::CookieAccessResultList& cookies_with_access_result,
std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override {
on_raw_request_called_ = true;
}
@@ -341,15 +345,21 @@ class PreflightControllerTest : public testing::Test {
PreflightControllerTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
test_initiator_origin_(
- url::Origin::Create(GURL("http://example.com/"))) {
+ url::Origin::Create(GURL("http://example.com/"))),
+ access_control_allow_origin_(test_initiator_origin_) {
CorsURLLoaderFactory::SetAllowExternalPreflightsForTesting(true);
mojo::Remote<mojom::NetworkService> network_service_remote;
network_service_ = NetworkService::Create(
network_service_remote.BindNewPipeAndPassReceiver());
+ auto context_params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_service_remote->CreateNetworkContext(
network_context_remote_.BindNewPipeAndPassReceiver(),
- mojom::NetworkContextParams::New());
+ std::move(context_params));
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
@@ -373,8 +383,10 @@ class PreflightControllerTest : public testing::Test {
GURL GetURL(const std::string& path) { return test_server_.GetURL(path); }
- void PerformPreflightCheck(const ResourceRequest& request,
- bool tainted = false) {
+ void PerformPreflightCheck(
+ const ResourceRequest& request,
+ bool tainted = false,
+ net::IsolationInfo isolation_info = net::IsolationInfo()) {
DCHECK(preflight_controller_);
run_loop_ = std::make_unique<base::RunLoop>();
preflight_controller_->PerformPreflightCheck(
@@ -382,13 +394,20 @@ class PreflightControllerTest : public testing::Test {
base::Unretained(this)),
request, WithTrustedHeaderClient(false), tainted,
TRAFFIC_ANNOTATION_FOR_TESTS, url_loader_factory_remote_.get(),
- 0 /* process_id */);
+ 0 /* process_id */, isolation_info);
run_loop_->Run();
}
+ void SetAccessControlAllowOrigin(const url::Origin origin) {
+ access_control_allow_origin_ = origin;
+ }
+
const url::Origin& test_initiator_origin() const {
return test_initiator_origin_;
}
+ const url::Origin& access_control_allow_origin() const {
+ return access_control_allow_origin_;
+ }
int net_error() const { return net_error_; }
base::Optional<CorsErrorStatus> status() { return status_; }
base::Optional<CorsErrorStatus> success() { return base::nullopt; }
@@ -397,6 +416,8 @@ class PreflightControllerTest : public testing::Test {
private:
void SetUp() override {
+ SetAccessControlAllowOrigin(test_initiator_origin_);
+
preflight_controller_ = std::make_unique<PreflightController>(
std::vector<std::string>(), network_service_.get());
@@ -423,7 +444,7 @@ class PreflightControllerTest : public testing::Test {
const url::Origin origin =
net::test_server::ShouldHandle(request, "/tainted")
? url::Origin()
- : test_initiator_origin();
+ : access_control_allow_origin();
response->AddCustomHeader(header_names::kAccessControlAllowOrigin,
origin.Serialize());
response->AddCustomHeader(header_names::kAccessControlAllowMethods,
@@ -438,6 +459,7 @@ class PreflightControllerTest : public testing::Test {
base::test::TaskEnvironment task_environment_;
const url::Origin test_initiator_origin_;
+ url::Origin access_control_allow_origin_;
std::unique_ptr<base::RunLoop> run_loop_;
std::unique_ptr<NetworkService> network_service_;
@@ -503,6 +525,69 @@ TEST_F(PreflightControllerTest, CheckValidRequest) {
EXPECT_EQ(4u, access_count());
}
+TEST_F(PreflightControllerTest, CheckRequestNetworkIsolationKey) {
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kCors;
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
+ request.url = GetURL("/allow");
+ const url::Origin& origin = test_initiator_origin();
+ request.request_initiator = origin;
+ ResourceRequest::TrustedParams trusted_params;
+ trusted_params.isolation_info = net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin,
+ net::SiteForCookies());
+ request.trusted_params = {trusted_params};
+
+ PerformPreflightCheck(request);
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(1u, access_count());
+
+ PerformPreflightCheck(request);
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(1u, access_count()); // Should be from the preflight cache.
+
+ url::Origin second_origin = url::Origin::Create(GURL("https://example.com/"));
+ request.request_initiator = second_origin;
+ SetAccessControlAllowOrigin(second_origin);
+ request.trusted_params->isolation_info = net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateNothing, origin, second_origin,
+ net::SiteForCookies());
+ PerformPreflightCheck(request);
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(2u, access_count());
+}
+
+TEST_F(PreflightControllerTest, CheckFactoryNetworkIsolationKey) {
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kCors;
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
+ request.url = GetURL("/allow");
+ const url::Origin& origin = test_initiator_origin();
+ request.request_initiator = origin;
+
+ const net::IsolationInfo isolation_info = net::IsolationInfo::Create(
+ net::IsolationInfo::RedirectMode::kUpdateNothing, origin, origin,
+ net::SiteForCookies());
+
+ PerformPreflightCheck(request, false, isolation_info);
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(1u, access_count());
+
+ PerformPreflightCheck(request, false, isolation_info);
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(1u, access_count()); // Should be from the preflight cache.
+
+ PerformPreflightCheck(request, false, net::IsolationInfo());
+ EXPECT_EQ(net::OK, net_error());
+ ASSERT_FALSE(status());
+ EXPECT_EQ(2u, access_count()); // Should not be from the preflight cache.
+}
+
TEST_F(PreflightControllerTest, CheckTaintedRequest) {
ResourceRequest request;
request.mode = mojom::RequestMode::kCors;
diff --git a/chromium/services/network/crl_set_distributor.cc b/chromium/services/network/crl_set_distributor.cc
index 82753f97e24..21914560b65 100644
--- a/chromium/services/network/crl_set_distributor.cc
+++ b/chromium/services/network/crl_set_distributor.cc
@@ -8,10 +8,12 @@
#include "base/bind.h"
#include "base/containers/span.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/strings/string_piece.h"
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
+#include "services/network/public/cpp/features.h"
namespace network {
@@ -21,8 +23,13 @@ namespace {
// CRLSet.
scoped_refptr<net::CRLSet> ParseCRLSet(std::string crl_set) {
scoped_refptr<net::CRLSet> result;
- if (!net::CRLSet::Parse(crl_set, &result))
- return nullptr;
+ if (base::FeatureList::IsEnabled(network::features::kCertVerifierService)) {
+ if (!net::CRLSet::ParseAndStoreUnparsedData(std::move(crl_set), &result))
+ return nullptr;
+ } else {
+ if (!net::CRLSet::Parse(std::move(crl_set), &result))
+ return nullptr;
+ }
return result;
}
diff --git a/chromium/services/network/expect_ct_reporter.cc b/chromium/services/network/expect_ct_reporter.cc
index cf7ab32f2c5..31123b7be52 100644
--- a/chromium/services/network/expect_ct_reporter.cc
+++ b/chromium/services/network/expect_ct_reporter.cc
@@ -20,6 +20,7 @@
#include "base/time/time.h"
#include "base/time/time_to_iso8601.h"
#include "base/values.h"
+#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/cert/ct_serialization.h"
#include "net/http/http_request_headers.h"
@@ -158,7 +159,8 @@ void ExpectCTReporter::OnExpectCTFailed(
const net::X509Certificate* validated_certificate_chain,
const net::X509Certificate* served_certificate_chain,
const net::SignedCertificateTimestampAndStatusList&
- signed_certificate_timestamps) {
+ signed_certificate_timestamps,
+ const net::NetworkIsolationKey& network_isolation_key) {
if (report_uri.is_empty())
return;
@@ -193,7 +195,7 @@ void ExpectCTReporter::OnExpectCTFailed(
UMA_HISTOGRAM_BOOLEAN("SSL.ExpectCTReportSendingAttempt", true);
- SendPreflight(report_uri, serialized_report);
+ SendPreflight(report_uri, serialized_report, network_isolation_key);
}
void ExpectCTReporter::OnResponseStarted(net::URLRequest* request,
@@ -228,6 +230,8 @@ void ExpectCTReporter::OnResponseStarted(net::URLRequest* request,
return;
}
+ // TODO(https://crbug.com/993805): Pass in preflight->network_isolation_key,
+ // once reporting API accepts NetworkIsolationKeys.
report_sender_->Send(preflight->report_uri,
"application/expect-ct-report+json; charset=utf-8",
preflight->serialized_report, success_callback_,
@@ -247,21 +251,27 @@ void ExpectCTReporter::OnReadCompleted(net::URLRequest* request,
ExpectCTReporter::PreflightInProgress::PreflightInProgress(
std::unique_ptr<net::URLRequest> request,
const std::string& serialized_report,
- const GURL& report_uri)
+ const GURL& report_uri,
+ const net::NetworkIsolationKey& network_isolation_key)
: request(std::move(request)),
serialized_report(serialized_report),
- report_uri(report_uri) {}
+ report_uri(report_uri),
+ network_isolation_key(network_isolation_key) {}
ExpectCTReporter::PreflightInProgress::~PreflightInProgress() {}
-void ExpectCTReporter::SendPreflight(const GURL& report_uri,
- const std::string& serialized_report) {
+void ExpectCTReporter::SendPreflight(
+ const GURL& report_uri,
+ const std::string& serialized_report,
+ const net::NetworkIsolationKey& network_isolation_key) {
std::unique_ptr<net::URLRequest> url_request =
request_context_->CreateRequest(report_uri, net::DEFAULT_PRIORITY, this,
kExpectCTReporterTrafficAnnotation);
url_request->SetLoadFlags(net::LOAD_BYPASS_CACHE | net::LOAD_DISABLE_CACHE);
url_request->set_allow_credentials(false);
url_request->set_method(net::HttpRequestHeaders::kOptionsMethod);
+ url_request->set_isolation_info(net::IsolationInfo::CreatePartial(
+ net::IsolationInfo::RedirectMode::kUpdateNothing, network_isolation_key));
net::HttpRequestHeaders extra_headers;
extra_headers.SetHeader("Origin", "null");
@@ -272,7 +282,8 @@ void ExpectCTReporter::SendPreflight(const GURL& report_uri,
net::URLRequest* raw_request = url_request.get();
inflight_preflights_[raw_request] = std::make_unique<PreflightInProgress>(
- std::move(url_request), serialized_report, report_uri);
+ std::move(url_request), serialized_report, report_uri,
+ network_isolation_key);
raw_request->Start();
}
diff --git a/chromium/services/network/expect_ct_reporter.h b/chromium/services/network/expect_ct_reporter.h
index 141b3702fd9..559229601f2 100644
--- a/chromium/services/network/expect_ct_reporter.h
+++ b/chromium/services/network/expect_ct_reporter.h
@@ -10,6 +10,7 @@
#include "base/component_export.h"
#include "base/macros.h"
+#include "net/base/network_isolation_key.h"
#include "net/http/transport_security_state.h"
#include "net/url_request/url_request.h"
@@ -42,13 +43,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ExpectCTReporter
~ExpectCTReporter() override;
// net::TransportSecurityState::ExpectCTReporter:
- void OnExpectCTFailed(const net::HostPortPair& host_port_pair,
- const GURL& report_uri,
- base::Time expiration,
- const net::X509Certificate* validated_certificate_chain,
- const net::X509Certificate* served_certificate_chain,
- const net::SignedCertificateTimestampAndStatusList&
- signed_certificate_timestamps) override;
+ void OnExpectCTFailed(
+ const net::HostPortPair& host_port_pair,
+ const GURL& report_uri,
+ base::Time expiration,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::X509Certificate* served_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps,
+ const net::NetworkIsolationKey& network_isolation_key) override;
// net::URLRequest::Delegate:
void OnResponseStarted(net::URLRequest* request, int net_error) override;
@@ -61,19 +64,24 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ExpectCTReporter
struct PreflightInProgress {
PreflightInProgress(std::unique_ptr<net::URLRequest> request,
const std::string& serialized_report,
- const GURL& report_uri);
+ const GURL& report_uri,
+ const net::NetworkIsolationKey& network_isolation_key);
~PreflightInProgress();
+
// The preflight request.
const std::unique_ptr<net::URLRequest> request;
// |serialized_report| should be sent to |report_uri| if the preflight
// succeeds.
const std::string serialized_report;
const GURL report_uri;
+ const net::NetworkIsolationKey network_isolation_key;
};
FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, FeatureDisabled);
FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, EmptyReportURI);
FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, SendReport);
+ FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest,
+ PreflightUsesNetworkIsolationKey);
FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest, PreflightContainsWhitespace);
FRIEND_TEST_ALL_PREFIXES(ExpectCTReporterTest,
BadCorsPreflightResponseOrigin);
@@ -87,7 +95,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ExpectCTReporter
// preflight result is checked in OnResponseStarted(), and an actual report is
// sent with |report_sender_| if the preflight succeeds.
void SendPreflight(const GURL& report_uri,
- const std::string& serialized_report);
+ const std::string& serialized_report,
+ const net::NetworkIsolationKey& network_isolation_key);
// When a report fails to send, this method records an UMA histogram and calls
// |failure_callback_|.
diff --git a/chromium/services/network/expect_ct_reporter_unittest.cc b/chromium/services/network/expect_ct_reporter_unittest.cc
index 452e8a9b765..08449291e7c 100644
--- a/chromium/services/network/expect_ct_reporter_unittest.cc
+++ b/chromium/services/network/expect_ct_reporter_unittest.cc
@@ -12,10 +12,12 @@
#include "base/command_line.h"
#include "base/json/json_reader.h"
#include "base/run_loop.h"
+#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/values.h"
+#include "net/base/network_isolation_key.h"
#include "net/cert/ct_serialization.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/test/cert_test_util.h"
@@ -270,8 +272,15 @@ void CheckExpectCTReport(const std::string& serialized_report,
// be run whenever a net::URLRequest is destroyed.
class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl {
public:
- TestExpectCTNetworkDelegate()
- : url_request_destroyed_callback_(base::NullCallback()) {}
+ TestExpectCTNetworkDelegate() = default;
+
+ using OnBeforeURLRequestCallback =
+ base::RepeatingCallback<void(net::URLRequest* request)>;
+
+ void set_on_before_url_request_callback(
+ const OnBeforeURLRequestCallback& on_before_url_request_callback) {
+ on_before_url_request_callback_ = on_before_url_request_callback;
+ }
void set_url_request_destroyed_callback(
const base::RepeatingClosure& callback) {
@@ -279,11 +288,20 @@ class TestExpectCTNetworkDelegate : public net::NetworkDelegateImpl {
}
// net::NetworkDelegateImpl:
+ int OnBeforeURLRequest(net::URLRequest* request,
+ net::CompletionOnceCallback callback,
+ GURL* new_url) override {
+ if (on_before_url_request_callback_)
+ on_before_url_request_callback_.Run(request);
+ return net::OK;
+ }
void OnURLRequestDestroyed(net::URLRequest* request) override {
- url_request_destroyed_callback_.Run();
+ if (url_request_destroyed_callback_)
+ url_request_destroyed_callback_.Run();
}
private:
+ OnBeforeURLRequestCallback on_before_url_request_callback_;
base::RepeatingClosure url_request_destroyed_callback_;
DISALLOW_COPY_AND_ASSIGN(TestExpectCTNetworkDelegate);
@@ -298,7 +316,8 @@ class ExpectCTReporterWaitTest : public ::testing::Test {
void SetUp() override {
// Initializes URLRequestContext after the thread is set up.
- context_.reset(new net::TestURLRequestContext(true));
+ context_.reset(
+ new net::TestURLRequestContext(true /* delay_initialization */));
context_->set_network_delegate(&network_delegate_);
context_->Init();
net::URLRequestFailedJob::AddUrlHandler();
@@ -321,7 +340,8 @@ class ExpectCTReporterWaitTest : public ::testing::Test {
run_loop.QuitClosure());
reporter->OnExpectCTFailed(
host_port, report_uri, expiration, ssl_info.cert.get(),
- ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
+ ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
+ net::NetworkIsolationKey());
run_loop.Run();
}
@@ -423,7 +443,8 @@ class ExpectCTReporterTest : public ::testing::Test {
reporter->OnExpectCTFailed(
host_port, fail_report_uri, base::Time(), ssl_info.cert.get(),
- ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
+ ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
+ net::NetworkIsolationKey());
bad_cors_run_loop.Run();
// The CORS preflight response may not even have been received yet, so
// these expectations are mostly aspirational.
@@ -437,7 +458,8 @@ class ExpectCTReporterTest : public ::testing::Test {
// be 2.
reporter->OnExpectCTFailed(
host_port, successful_report_uri, base::Time(), ssl_info.cert.get(),
- ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
+ ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
+ net::NetworkIsolationKey());
sender->WaitForReport(successful_report_uri);
EXPECT_EQ(successful_report_uri, sender->latest_report_uri());
EXPECT_EQ(1, sender->sent_report_count());
@@ -482,7 +504,8 @@ TEST_F(ExpectCTReporterTest, FeatureDisabled) {
reporter.OnExpectCTFailed(
host_port, report_uri, base::Time(), ssl_info.cert.get(),
- ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
+ ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
+ net::NetworkIsolationKey());
EXPECT_TRUE(sender->latest_report_uri().is_empty());
EXPECT_TRUE(sender->latest_serialized_report().empty());
@@ -499,7 +522,8 @@ TEST_F(ExpectCTReporterTest, FeatureDisabled) {
scoped_feature_list.InitAndEnableFeature(features::kExpectCTReporting);
reporter.OnExpectCTFailed(
host_port, report_uri, base::Time(), ssl_info.cert.get(),
- ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps);
+ ssl_info.unverified_cert.get(), ssl_info.signed_certificate_timestamps,
+ net::NetworkIsolationKey());
sender->WaitForReport(report_uri);
EXPECT_EQ(report_uri, sender->latest_report_uri());
EXPECT_EQ(1, sender->sent_report_count());
@@ -521,7 +545,8 @@ TEST_F(ExpectCTReporterTest, EmptyReportURI) {
reporter.OnExpectCTFailed(net::HostPortPair(), GURL(), base::Time(), nullptr,
nullptr,
- net::SignedCertificateTimestampAndStatusList());
+ net::SignedCertificateTimestampAndStatusList(),
+ net::NetworkIsolationKey());
EXPECT_TRUE(sender->latest_report_uri().is_empty());
EXPECT_TRUE(sender->latest_serialized_report().empty());
@@ -662,10 +687,10 @@ TEST_F(ExpectCTReporterTest, SendReport) {
const GURL report_uri = test_server().GetURL(report_path);
// Check that the report is sent and contains the correct information.
- reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
- expiration, ssl_info.cert.get(),
- ssl_info.unverified_cert.get(),
- ssl_info.signed_certificate_timestamps);
+ reporter.OnExpectCTFailed(
+ net::HostPortPair::FromURL(report_uri), report_uri, expiration,
+ ssl_info.cert.get(), ssl_info.unverified_cert.get(),
+ ssl_info.signed_certificate_timestamps, net::NetworkIsolationKey());
// A CORS preflight request should be sent before the actual report.
cors_run_loop.Run();
@@ -725,15 +750,72 @@ TEST_F(ExpectCTReporterTest, SendReportSuccessCallback) {
const GURL report_uri = test_server().GetURL("/report");
- reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
- expiration, ssl_info.cert.get(),
- ssl_info.unverified_cert.get(),
- ssl_info.signed_certificate_timestamps);
+ reporter.OnExpectCTFailed(
+ net::HostPortPair::FromURL(report_uri), report_uri, expiration,
+ ssl_info.cert.get(), ssl_info.unverified_cert.get(),
+ ssl_info.signed_certificate_timestamps, net::NetworkIsolationKey());
// Wait to check that the success callback is run.
run_loop.Run();
}
+// Test that report preflight requests use the correct NetworkIsolationKey.
+TEST_F(ExpectCTReporterTest, PreflightUsesNetworkIsolationKey) {
+ net::NetworkIsolationKey network_isolation_key =
+ net::NetworkIsolationKey::CreateTransient();
+
+ const std::string report_path = "/report";
+ std::map<std::string, std::string> cors_headers = kGoodCorsHeaders;
+ base::RunLoop cors_run_loop;
+ test_server().RegisterRequestHandler(
+ base::BindRepeating(&HandleReportPreflightForPath, report_path,
+ cors_headers, cors_run_loop.QuitClosure()));
+ ASSERT_TRUE(test_server().Start());
+
+ TestCertificateReportSender* sender = new TestCertificateReportSender();
+
+ TestExpectCTNetworkDelegate network_delegate;
+ net::TestURLRequestContext context(true /* delay_initialization*/);
+ context.set_network_delegate(&network_delegate);
+ context.Init();
+
+ ExpectCTReporter reporter(&context, base::NullCallback(),
+ base::NullCallback());
+ reporter.report_sender_.reset(sender);
+ EXPECT_TRUE(sender->latest_report_uri().is_empty());
+ EXPECT_TRUE(sender->latest_serialized_report().empty());
+
+ net::SSLInfo ssl_info;
+ ssl_info.cert =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+ ssl_info.unverified_cert = net::ImportCertFromFile(
+ net::GetTestCertsDirectory(), "localhost_cert.pem");
+
+ base::RunLoop before_url_request_run_loop;
+ network_delegate.set_on_before_url_request_callback(
+ base::BindLambdaForTesting([&](net::URLRequest* request) {
+ EXPECT_EQ(network_isolation_key,
+ request->isolation_info().network_isolation_key());
+ before_url_request_run_loop.Quit();
+ }));
+
+ const GURL report_uri = test_server().GetURL(report_path);
+ reporter.OnExpectCTFailed(
+ net::HostPortPair::FromURL(report_uri), report_uri, base::Time::Now(),
+ ssl_info.cert.get(), ssl_info.unverified_cert.get(),
+ ssl_info.signed_certificate_timestamps, network_isolation_key);
+
+ // Make sure the OnBeforeURLRequestCallback is hit.
+ before_url_request_run_loop.Run();
+
+ // A CORS preflight request should be sent before the actual report.
+ cors_run_loop.Run();
+ sender->WaitForReport(report_uri);
+
+ EXPECT_EQ(report_uri, sender->latest_report_uri());
+ EXPECT_FALSE(sender->latest_serialized_report().empty());
+}
+
// Test that report preflight responses can contain whitespace.
TEST_F(ExpectCTReporterTest, PreflightContainsWhitespace) {
const std::string report_path = "/report";
@@ -760,10 +842,10 @@ TEST_F(ExpectCTReporterTest, PreflightContainsWhitespace) {
net::GetTestCertsDirectory(), "localhost_cert.pem");
const GURL report_uri = test_server().GetURL(report_path);
- reporter.OnExpectCTFailed(net::HostPortPair::FromURL(report_uri), report_uri,
- base::Time::Now(), ssl_info.cert.get(),
- ssl_info.unverified_cert.get(),
- ssl_info.signed_certificate_timestamps);
+ reporter.OnExpectCTFailed(
+ net::HostPortPair::FromURL(report_uri), report_uri, base::Time::Now(),
+ ssl_info.cert.get(), ssl_info.unverified_cert.get(),
+ ssl_info.signed_certificate_timestamps, net::NetworkIsolationKey());
// A CORS preflight request should be sent before the actual report.
cors_run_loop.Run();
diff --git a/chromium/services/network/http_cache_data_counter_unittest.cc b/chromium/services/network/http_cache_data_counter_unittest.cc
index e5c6bf5422c..ea7d6c5d1a3 100644
--- a/chromium/services/network/http_cache_data_counter_unittest.cc
+++ b/chromium/services/network/http_cache_data_counter_unittest.cc
@@ -30,6 +30,7 @@
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@@ -54,6 +55,10 @@ constexpr CacheTestEntry kCacheEntries[] = {
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
diff --git a/chromium/services/network/http_cache_data_remover_unittest.cc b/chromium/services/network/http_cache_data_remover_unittest.cc
index 1952008d076..899b438fe02 100644
--- a/chromium/services/network/http_cache_data_remover_unittest.cc
+++ b/chromium/services/network/http_cache_data_remover_unittest.cc
@@ -29,6 +29,7 @@
#include "net/url_request/url_request_context_builder.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@@ -61,6 +62,10 @@ constexpr CacheTestEntry kCacheEntries[] = {
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
diff --git a/chromium/services/network/ignore_errors_cert_verifier.cc b/chromium/services/network/ignore_errors_cert_verifier.cc
index e3b9c7a8eb8..2038664a563 100644
--- a/chromium/services/network/ignore_errors_cert_verifier.cc
+++ b/chromium/services/network/ignore_errors_cert_verifier.cc
@@ -20,6 +20,7 @@
#include "net/cert/x509_certificate.h"
#include "net/cert/x509_util.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/cpp/spki_hash_set.h"
using ::net::CertVerifier;
using ::net::HashValue;
@@ -42,31 +43,13 @@ std::unique_ptr<CertVerifier> IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
switches::kIgnoreCertificateErrorsSPKIList),
",", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
return std::make_unique<IgnoreErrorsCertVerifier>(
- std::move(verifier), IgnoreErrorsCertVerifier::MakeWhitelist(spki_list));
-}
-
-// static
-IgnoreErrorsCertVerifier::SPKIHashSet IgnoreErrorsCertVerifier::MakeWhitelist(
- const std::vector<std::string>& fingerprints) {
- IgnoreErrorsCertVerifier::SPKIHashSet whitelist;
- for (const std::string& fingerprint : fingerprints) {
- HashValue hash;
- if (!hash.FromString("sha256/" + fingerprint)) {
- LOG(ERROR) << "Invalid SPKI: " << fingerprint;
- continue;
- }
- SHA256HashValue sha256;
- DCHECK_EQ(hash.size(), sizeof(sha256));
- memcpy(&sha256, hash.data(), sizeof(sha256));
- whitelist.insert(sha256);
- }
- return whitelist;
+ std::move(verifier), CreateSPKIHashSet(spki_list));
}
IgnoreErrorsCertVerifier::IgnoreErrorsCertVerifier(
std::unique_ptr<CertVerifier> verifier,
- IgnoreErrorsCertVerifier::SPKIHashSet whitelist)
- : verifier_(std::move(verifier)), whitelist_(std::move(whitelist)) {}
+ SPKIHashSet allowlist)
+ : verifier_(std::move(verifier)), allowlist_(std::move(allowlist)) {}
IgnoreErrorsCertVerifier::~IgnoreErrorsCertVerifier() {}
@@ -95,17 +78,17 @@ int IgnoreErrorsCertVerifier::Verify(const RequestParams& params,
}
}
- // Intersect SPKI hashes from the chain with the whitelist.
- auto whitelist_begin = whitelist_.begin();
- auto whitelist_end = whitelist_.end();
+ // Intersect SPKI hashes from the chain with the allowlist.
+ auto allowlist_begin = allowlist_.begin();
+ auto allowlist_end = allowlist_.end();
auto fingerprints_begin = spki_fingerprints.begin();
auto fingerprints_end = spki_fingerprints.end();
bool ignore_errors = false;
- while (whitelist_begin != whitelist_end &&
+ while (allowlist_begin != allowlist_end &&
fingerprints_begin != fingerprints_end) {
- if (*whitelist_begin < *fingerprints_begin) {
- ++whitelist_begin;
- } else if (*fingerprints_begin < *whitelist_begin) {
+ if (*allowlist_begin < *fingerprints_begin) {
+ ++allowlist_begin;
+ } else if (*fingerprints_begin < *allowlist_begin) {
++fingerprints_begin;
} else {
ignore_errors = true;
@@ -136,8 +119,9 @@ void IgnoreErrorsCertVerifier::SetConfig(const Config& config) {
verifier_->SetConfig(config);
}
-void IgnoreErrorsCertVerifier::set_whitelist(const SPKIHashSet& whitelist) {
- whitelist_ = whitelist;
+void IgnoreErrorsCertVerifier::SetAllowlistForTesting(
+ const SPKIHashSet& allowlist) {
+ allowlist_ = allowlist;
}
} // namespace network
diff --git a/chromium/services/network/ignore_errors_cert_verifier.h b/chromium/services/network/ignore_errors_cert_verifier.h
index f122a0e9ce8..a2ab2338d19 100644
--- a/chromium/services/network/ignore_errors_cert_verifier.h
+++ b/chromium/services/network/ignore_errors_cert_verifier.h
@@ -14,27 +14,21 @@
#include "base/containers/flat_set.h"
#include "net/base/completion_once_callback.h"
#include "net/cert/cert_verifier.h"
-
-namespace net {
-struct SHA256HashValue;
-} // namespace net
+#include "services/network/public/cpp/spki_hash_set.h"
namespace network {
// IgnoreErrorsCertVerifier wraps another CertVerifier in order to ignore
-// verification errors from certificate chains that match a whitelist of SPKI
+// verification errors from certificate chains that match a allowlist of SPKI
// fingerprints.
class COMPONENT_EXPORT(NETWORK_SERVICE) IgnoreErrorsCertVerifier
: public net::CertVerifier {
public:
- // SPKIHashSet is a set of SHA-256 SPKI fingerprints (RFC 7469, Section 2.4).
- using SPKIHashSet = base::flat_set<net::SHA256HashValue>;
-
// If the |user_data_dir_switch| is passed in as a valid pointer but
// --user-data-dir flag is missing, or --ignore-certificate-errors-spki-list
// flag is missing then MaybeWrapCertVerifier returns the supplied verifier.
// Otherwise it returns an IgnoreErrorsCertVerifier wrapping the supplied
- // verifier using the whitelist from the
+ // verifier using the allowlist from the
// --ignore-certificate-errors-spki-list flag.
//
// As the --user-data-dir flag is embedder defined, the flag to check for
@@ -44,19 +38,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) IgnoreErrorsCertVerifier
const char* user_data_dir_switch,
std::unique_ptr<net::CertVerifier> verifier);
- // MakeWhitelist converts a vector of Base64-encoded SHA-256 SPKI fingerprints
- // into an SPKIHashSet. Invalid fingerprints are logged and skipped.
- static SPKIHashSet MakeWhitelist(
- const std::vector<std::string>& fingerprints);
-
IgnoreErrorsCertVerifier(std::unique_ptr<net::CertVerifier> verifier,
- SPKIHashSet whitelist);
+ SPKIHashSet allowlist);
~IgnoreErrorsCertVerifier() override;
// Verify skips certificate verification and returns OK if any of the
// certificates from the chain in |params| match one of the SPKI fingerprints
- // from the whitelist. Otherwise, it invokes Verify on the wrapped verifier
+ // from the allowlist. Otherwise, it invokes Verify on the wrapped verifier
// and returns the result.
int Verify(const RequestParams& params,
net::CertVerifyResult* verify_result,
@@ -67,10 +56,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) IgnoreErrorsCertVerifier
private:
friend class IgnoreErrorsCertVerifierTest;
- void set_whitelist(const SPKIHashSet& whitelist); // Testing only.
+
+ void SetAllowlistForTesting(const SPKIHashSet& whitelist);
std::unique_ptr<net::CertVerifier> verifier_;
- SPKIHashSet whitelist_;
+ SPKIHashSet allowlist_;
DISALLOW_COPY_AND_ASSIGN(IgnoreErrorsCertVerifier);
};
diff --git a/chromium/services/network/ignore_errors_cert_verifier_unittest.cc b/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
index afd4c3d0128..699018a6069 100644
--- a/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
+++ b/chromium/services/network/ignore_errors_cert_verifier_unittest.cc
@@ -22,6 +22,7 @@
#include "net/test/gtest_util.h"
#include "net/test/test_data_directory.h"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/public/cpp/spki_hash_set.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -45,7 +46,7 @@ namespace network {
static const char kTestUserDataDirSwitch[] = "test-user-data-dir";
-static std::vector<std::string> MakeWhitelist() {
+static std::vector<std::string> MakeAllowlist() {
base::FilePath certs_dir = net::GetTestCertsDirectory();
net::CertificateList certs = net::CreateCertificateListFromFile(
certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO);
@@ -68,14 +69,12 @@ class IgnoreErrorsCertVerifierTest : public ::testing::Test {
public:
IgnoreErrorsCertVerifierTest()
: mock_verifier_(new MockCertVerifier()),
- verifier_(base::WrapUnique(mock_verifier_),
- IgnoreErrorsCertVerifier::SPKIHashSet()) {}
+ verifier_(base::WrapUnique(mock_verifier_), SPKIHashSet()) {}
~IgnoreErrorsCertVerifierTest() override {}
protected:
void SetUp() override {
- verifier_.set_whitelist(
- IgnoreErrorsCertVerifier::MakeWhitelist(MakeWhitelist()));
+ verifier_.SetAllowlistForTesting(CreateSPKIHashSet(MakeAllowlist()));
}
// The wrapped CertVerifier. Defaults to returning ERR_CERT_INVALID. Owned by
@@ -84,7 +83,7 @@ class IgnoreErrorsCertVerifierTest : public ::testing::Test {
IgnoreErrorsCertVerifier verifier_;
};
-static void GetNonWhitelistedTestCert(scoped_refptr<X509Certificate>* out) {
+static void GetNonAllowlistedTestCert(scoped_refptr<X509Certificate>* out) {
base::FilePath certs_dir = net::GetTestCertsDirectory();
scoped_refptr<X509Certificate> test_cert(
net::ImportCertFromFile(certs_dir, "ok_cert.pem"));
@@ -99,7 +98,7 @@ static CertVerifier::RequestParams MakeRequestParams(
/*sct_list=*/std::string());
}
-static void GetWhitelistedTestCert(scoped_refptr<X509Certificate>* out) {
+static void GetAllowlistedTestCert(scoped_refptr<X509Certificate>* out) {
base::FilePath certs_dir = net::GetTestCertsDirectory();
*out = net::CreateCertificateChainFromFile(
certs_dir, "x509_verify_results.chain.pem", X509Certificate::FORMAT_AUTO);
@@ -111,7 +110,7 @@ TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertOk) {
mock_verifier_->set_default_result(OK);
scoped_refptr<X509Certificate> test_cert;
- ASSERT_NO_FATAL_FAILURE(GetNonWhitelistedTestCert(&test_cert));
+ ASSERT_NO_FATAL_FAILURE(GetNonAllowlistedTestCert(&test_cert));
CertVerifyResult verify_result;
TestCompletionCallback callback;
std::unique_ptr<CertVerifier::Request> request;
@@ -124,7 +123,7 @@ TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertOk) {
TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertError) {
scoped_refptr<X509Certificate> test_cert;
- ASSERT_NO_FATAL_FAILURE(GetNonWhitelistedTestCert(&test_cert));
+ ASSERT_NO_FATAL_FAILURE(GetNonAllowlistedTestCert(&test_cert));
CertVerifyResult verify_result;
TestCompletionCallback callback;
std::unique_ptr<CertVerifier::Request> request;
@@ -137,7 +136,7 @@ TEST_F(IgnoreErrorsCertVerifierTest, TestNoMatchCertError) {
TEST_F(IgnoreErrorsCertVerifierTest, TestMatch) {
scoped_refptr<X509Certificate> test_cert;
- ASSERT_NO_FATAL_FAILURE(GetWhitelistedTestCert(&test_cert));
+ ASSERT_NO_FATAL_FAILURE(GetAllowlistedTestCert(&test_cert));
CertVerifyResult verify_result;
TestCompletionCallback callback;
std::unique_ptr<CertVerifier::Request> request;
@@ -157,7 +156,7 @@ class IgnoreCertificateErrorsSPKIListFlagTest
command_line.AppendSwitchASCII(kTestUserDataDirSwitch, "/foo/bar/baz");
}
command_line.AppendSwitchASCII(switches::kIgnoreCertificateErrorsSPKIList,
- base::JoinString(MakeWhitelist(), ","));
+ base::JoinString(MakeAllowlist(), ","));
auto mock_verifier = std::make_unique<MockCertVerifier>();
mock_verifier->set_default_result(ERR_CERT_INVALID);
@@ -174,7 +173,7 @@ class IgnoreCertificateErrorsSPKIListFlagTest
// are present, certificate verification is bypassed.
TEST_P(IgnoreCertificateErrorsSPKIListFlagTest, TestUserDataDirSwitchRequired) {
scoped_refptr<X509Certificate> test_cert;
- ASSERT_NO_FATAL_FAILURE(GetWhitelistedTestCert(&test_cert));
+ ASSERT_NO_FATAL_FAILURE(GetAllowlistedTestCert(&test_cert));
CertVerifyResult verify_result;
TestCompletionCallback callback;
std::unique_ptr<CertVerifier::Request> request;
diff --git a/chromium/services/network/legacy_tls_config_distributor.h b/chromium/services/network/legacy_tls_config_distributor.h
index aa8cba2f156..1b05570061c 100644
--- a/chromium/services/network/legacy_tls_config_distributor.h
+++ b/chromium/services/network/legacy_tls_config_distributor.h
@@ -11,6 +11,7 @@
#include <memory>
#include <string>
+#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/containers/span.h"
#include "base/macros.h"
diff --git a/chromium/services/network/net_log_exporter.cc b/chromium/services/network/net_log_exporter.cc
index e09b9c6cef0..717076e1fe1 100644
--- a/chromium/services/network/net_log_exporter.cc
+++ b/chromium/services/network/net_log_exporter.cc
@@ -181,7 +181,9 @@ void NetLogExporter::StartWithScratchDir(
state_ = STATE_RUNNING;
- std::unique_ptr<base::DictionaryValue> constants = net::GetNetConstants();
+ std::unique_ptr<base::DictionaryValue> constants =
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(net::GetNetConstants()));
if (extra_constants)
constants->MergeDictionary(extra_constants);
diff --git a/chromium/services/network/network_context.cc b/chromium/services/network/network_context.cc
index 2c3f75ea4ad..3bb208bad23 100644
--- a/chromium/services/network/network_context.cc
+++ b/chromium/services/network/network_context.cc
@@ -39,6 +39,7 @@
#include "components/prefs/pref_service.h"
#include "components/prefs/pref_service_factory.h"
#include "crypto/sha2.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/network_delegate.h"
@@ -53,7 +54,6 @@
#include "net/dns/host_cache.h"
#include "net/dns/mapped_host_resolver.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
-#include "net/http/failing_http_transaction_factory.h"
#include "net/http/http_auth.h"
#include "net/http/http_auth_handler_factory.h"
#include "net/http/http_auth_preferences.h"
@@ -86,11 +86,14 @@
#include "services/network/proxy_lookup_request.h"
#include "services/network/proxy_resolving_socket_factory_mojo.h"
#include "services/network/public/cpp/cert_verifier/cert_verifier_creation.h"
+#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/parsed_headers.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/quic_transport.h"
#include "services/network/resolve_host_request.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
@@ -126,7 +129,6 @@
#if defined(OS_CHROMEOS)
#include "services/network/cert_verifier_with_trust_anchors.h"
-#include "services/network/nss_temp_certs_cache_chromeos.h"
#endif // defined(OS_CHROMEOS)
#if !defined(OS_IOS)
@@ -345,7 +347,15 @@ NetworkContext::NetworkContext(
cors_preflight_controller_(
params_->cors_extra_safelisted_request_header_names,
network_service) {
- url_request_context_owner_ = MakeURLRequestContext();
+ mojo::PendingRemote<mojom::URLLoaderFactory>
+ url_loader_factory_for_cert_net_fetcher;
+ mojo::PendingReceiver<mojom::URLLoaderFactory>
+ url_loader_factory_for_cert_net_fetcher_receiver =
+ url_loader_factory_for_cert_net_fetcher
+ .InitWithNewPipeAndPassReceiver();
+
+ url_request_context_owner_ =
+ MakeURLRequestContext(std::move(url_loader_factory_for_cert_net_fetcher));
url_request_context_ = url_request_context_owner_.url_request_context.get();
network_service_->RegisterNetworkContext(this);
@@ -383,6 +393,9 @@ NetworkContext::NetworkContext(
if (params_->cookie_manager)
GetCookieManager(std::move(params_->cookie_manager));
#endif
+
+ CreateURLLoaderFactoryForCertNetFetcher(
+ std::move(url_loader_factory_for_cert_net_fetcher_receiver));
}
NetworkContext::NetworkContext(
@@ -463,15 +476,12 @@ NetworkContext::~NetworkContext() {
}
}
+// static
void NetworkContext::SetCertVerifierForTesting(
net::CertVerifier* cert_verifier) {
g_cert_verifier_for_testing = cert_verifier;
}
-bool NetworkContext::IsPrimaryNetworkContext() const {
- return params_ && params_->primary_network_context;
-}
-
void NetworkContext::CreateURLLoaderFactory(
mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
mojom::URLLoaderFactoryParamsPtr params,
@@ -481,6 +491,18 @@ void NetworkContext::CreateURLLoaderFactory(
std::move(receiver), &cors_origin_access_list_));
}
+void NetworkContext::CreateURLLoaderFactoryForCertNetFetcher(
+ mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver) {
+ // TODO(crbug.com/1087790): investigate changing these params.
+ auto url_loader_factory_params = mojom::URLLoaderFactoryParams::New();
+ url_loader_factory_params->is_trusted = true;
+ url_loader_factory_params->process_id = mojom::kBrowserProcessId;
+ url_loader_factory_params->automatically_assign_isolation_info = true;
+ url_loader_factory_params->is_corb_enabled = false;
+ CreateURLLoaderFactory(std::move(factory_receiver),
+ std::move(url_loader_factory_params));
+}
+
void NetworkContext::ActivateDohProbes() {
DCHECK(url_request_context_->host_resolver());
@@ -946,19 +968,18 @@ void NetworkContext::SetEnableReferrers(bool enable_referrers) {
void NetworkContext::UpdateAdditionalCertificates(
mojom::AdditionalCertificatesPtr additional_certificates) {
if (!cert_verifier_with_trust_anchors_) {
- CHECK(g_cert_verifier_for_testing ||
- params_->cert_verifier_creation_params->username_hash.empty());
+ CHECK(g_cert_verifier_for_testing);
return;
}
if (!additional_certificates) {
- nss_temp_certs_cache_.reset();
- cert_verifier_with_trust_anchors_->SetTrustAnchors(net::CertificateList());
+ cert_verifier_with_trust_anchors_->SetAdditionalCerts(
+ net::CertificateList(), net::CertificateList());
return;
}
- nss_temp_certs_cache_ = std::make_unique<network::NSSTempCertsCacheChromeOS>(
+
+ cert_verifier_with_trust_anchors_->SetAdditionalCerts(
+ additional_certificates->trust_anchors,
additional_certificates->all_certificates);
- cert_verifier_with_trust_anchors_->SetTrustAnchors(
- additional_certificates->trust_anchors);
}
#endif // defined(OS_CHROMEOS)
@@ -972,11 +993,13 @@ void NetworkContext::SetCTPolicy(mojom::CTPolicyPtr ct_policy) {
ct_policy->excluded_spkis, ct_policy->excluded_legacy_spkis);
}
-void NetworkContext::AddExpectCT(const std::string& domain,
- base::Time expiry,
- bool enforce,
- const GURL& report_uri,
- AddExpectCTCallback callback) {
+void NetworkContext::AddExpectCT(
+ const std::string& domain,
+ base::Time expiry,
+ bool enforce,
+ const GURL& report_uri,
+ const net::NetworkIsolationKey& network_isolation_key,
+ AddExpectCTCallback callback) {
net::TransportSecurityState* transport_security_state =
url_request_context()->transport_security_state();
if (!transport_security_state) {
@@ -984,7 +1007,8 @@ void NetworkContext::AddExpectCT(const std::string& domain,
return;
}
- transport_security_state->AddExpectCT(domain, expiry, enforce, report_uri);
+ transport_security_state->AddExpectCT(domain, expiry, enforce, report_uri,
+ network_isolation_key);
std::move(callback).Run(true);
}
@@ -1010,7 +1034,11 @@ void NetworkContext::SetExpectCTTestReport(
net::SignedCertificateTimestampAndStatusList dummy_sct_list;
expect_ct_reporter_->OnExpectCTFailed(
net::HostPortPair("expect-ct-report.test", 443), report_uri,
- base::Time::Now(), dummy_cert.get(), dummy_cert.get(), dummy_sct_list);
+ base::Time::Now(), dummy_cert.get(), dummy_cert.get(), dummy_sct_list,
+ // No need for a shared NetworkIsolationKey here, as this is test-only
+ // code and none
+ // of the tests that call it care about the NetworkIsolationKey.
+ net::NetworkIsolationKey::CreateTransient());
}
void NetworkContext::LazyCreateExpectCTReporter(
@@ -1042,8 +1070,10 @@ void NetworkContext::OnSetExpectCTTestReportFailure() {
outstanding_set_expect_ct_callbacks_.pop();
}
-void NetworkContext::GetExpectCTState(const std::string& domain,
- GetExpectCTStateCallback callback) {
+void NetworkContext::GetExpectCTState(
+ const std::string& domain,
+ const net::NetworkIsolationKey& network_isolation_key,
+ GetExpectCTStateCallback callback) {
base::DictionaryValue result;
if (base::IsStringASCII(domain)) {
net::TransportSecurityState* transport_security_state =
@@ -1051,7 +1081,7 @@ void NetworkContext::GetExpectCTState(const std::string& domain,
if (transport_security_state) {
net::TransportSecurityState::ExpectCTState dynamic_expect_ct_state;
bool found = transport_security_state->GetDynamicExpectCTState(
- domain, &dynamic_expect_ct_state);
+ domain, network_isolation_key, &dynamic_expect_ct_state);
// TODO(estark): query static Expect-CT state as well.
if (found) {
@@ -1192,10 +1222,12 @@ void NetworkContext::CreateQuicTransport(
const GURL& url,
const url::Origin& origin,
const net::NetworkIsolationKey& key,
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints,
mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
pending_handshake_client) {
- quic_transports_.insert(std::make_unique<QuicTransport>(
- url, origin, key, this, std::move(pending_handshake_client)));
+ quic_transports_.insert(
+ std::make_unique<QuicTransport>(url, origin, key, fingerprints, this,
+ std::move(pending_handshake_client)));
}
void NetworkContext::CreateNetLogExporter(
@@ -1384,7 +1416,7 @@ void NetworkContext::GetHSTSState(const std::string& domain,
net::TransportSecurityState::STSState dynamic_sts_state;
net::TransportSecurityState::PKPState dynamic_pkp_state;
bool found_sts_dynamic = transport_security_state->GetDynamicSTSState(
- domain, &dynamic_sts_state, nullptr);
+ domain, &dynamic_sts_state);
bool found_pkp_dynamic = transport_security_state->GetDynamicPKPState(
domain, &dynamic_pkp_state);
@@ -1510,14 +1542,15 @@ void NetworkContext::PreconnectSockets(
}
void NetworkContext::CreateP2PSocketManager(
+ const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> client,
mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
trusted_socket_manager,
mojo::PendingReceiver<mojom::P2PSocketManager> socket_manager_receiver) {
std::unique_ptr<P2PSocketManager> socket_manager =
std::make_unique<P2PSocketManager>(
- std::move(client), std::move(trusted_socket_manager),
- std::move(socket_manager_receiver),
+ network_isolation_key, std::move(client),
+ std::move(trusted_socket_manager), std::move(socket_manager_receiver),
base::BindRepeating(&NetworkContext::DestroySocketManager,
base::Unretained(this)),
url_request_context_);
@@ -1674,26 +1707,56 @@ void NetworkContext::OnHttpAuthDynamicParamsChanged(
#endif
}
-URLRequestContextOwner NetworkContext::MakeURLRequestContext() {
+URLRequestContextOwner NetworkContext::MakeURLRequestContext(
+ mojo::PendingRemote<mojom::URLLoaderFactory>
+ url_loader_factory_for_cert_net_fetcher) {
URLRequestContextBuilderMojo builder;
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
+ DCHECK(
+ g_cert_verifier_for_testing ||
+ !base::FeatureList::IsEnabled(network::features::kCertVerifierService) ||
+ (params_->cert_verifier_params &&
+ params_->cert_verifier_params->is_remote_params()))
+ << "If cert verification service is on, the creator of the "
+ "NetworkContext should pass CertVerifierServiceRemoteParams.";
+
std::unique_ptr<net::CertVerifier> cert_verifier;
if (g_cert_verifier_for_testing) {
cert_verifier = std::make_unique<WrappedTestingCertVerifier>();
} else {
- mojom::CertVerifierCreationParams* creation_params = nullptr;
- if (params_->cert_verifier_creation_params)
- creation_params = params_->cert_verifier_creation_params.get();
+ if (params_->cert_verifier_params &&
+ params_->cert_verifier_params->is_remote_params()) {
+ // base::Unretained() is safe below because |this| will own
+ // |cert_verifier|.
+ // TODO(https://crbug.com/1085233): this cert verifier should deal with
+ // disconnections if the CertVerifierService is run outside of the browser
+ // process.
+ cert_verifier = std::make_unique<cert_verifier::MojoCertVerifier>(
+ std::move(params_->cert_verifier_params->get_remote_params()
+ ->cert_verifier_service),
+ std::move(url_loader_factory_for_cert_net_fetcher),
+ base::BindRepeating(
+ &NetworkContext::CreateURLLoaderFactoryForCertNetFetcher,
+ base::Unretained(this)));
+ } else {
+ mojom::CertVerifierCreationParams* creation_params = nullptr;
+ if (params_->cert_verifier_params &&
+ params_->cert_verifier_params->is_creation_params()) {
+ creation_params =
+ params_->cert_verifier_params->get_creation_params().get();
+ }
- if (IsUsingCertNetFetcher())
- cert_net_fetcher_ = base::MakeRefCounted<net::CertNetFetcherURLRequest>();
+ if (IsUsingCertNetFetcher())
+ cert_net_fetcher_ =
+ base::MakeRefCounted<net::CertNetFetcherURLRequest>();
- cert_verifier = CreateCertVerifier(creation_params, cert_net_fetcher_);
+ cert_verifier = CreateCertVerifier(creation_params, cert_net_fetcher_);
+ }
- // Wrap the cert verifier in caching and coalescing layers to avoid extra
- // verifications.
+ // Whether the cert verifier is remote or in-process, we should wrap it in
+ // caching and coalescing layers to avoid extra verifications and IPCs.
cert_verifier = std::make_unique<net::CachingCertVerifier>(
std::make_unique<net::CoalescingCertVerifier>(
std::move(cert_verifier)));
@@ -2223,6 +2286,9 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id,
pending_cert_verify->result->cert_status &= ~net::CERT_STATUS_IS_EV;
}
+ // TODO(https://crbug.com/1087091): Update
+ // NetworkContext::VerifyCertForSignedExchange() to take a
+ // NetworkIsolationKey, and pass it in here.
net::TransportSecurityState::CTRequirementsStatus ct_requirement_status =
url_request_context_->transport_security_state()->CheckCTRequirements(
net::HostPortPair::FromURL(pending_cert_verify->url),
@@ -2230,7 +2296,8 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id,
pending_cert_verify->result->public_key_hashes, verified_cert,
pending_cert_verify->certificate.get(), ct_verify_result.scts,
net::TransportSecurityState::ENABLE_EXPECT_CT_REPORTS,
- ct_verify_result.policy_compliance);
+ ct_verify_result.policy_compliance,
+ net::NetworkIsolationKey::Todo());
switch (ct_requirement_status) {
case net::TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
diff --git a/chromium/services/network/network_context.h b/chromium/services/network/network_context.h
index 932ca19462c..eced38ff04f 100644
--- a/chromium/services/network/network_context.h
+++ b/chromium/services/network/network_context.h
@@ -93,7 +93,6 @@ class NetworkService;
class NetworkServiceNetworkDelegate;
class NetworkServiceProxyDelegate;
class MdnsResponderManager;
-class NSSTempCertsCacheChromeOS;
class P2PSocketManager;
class ProxyLookupRequest;
class QuicTransport;
@@ -138,13 +137,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
// Sets a global CertVerifier to use when initializing all profiles.
static void SetCertVerifierForTesting(net::CertVerifier* cert_verifier);
- // Whether the NetworkContext should be used for certain URL fetches of
- // global scope (validating certs on some platforms, DNS over HTTPS).
- // May only be set to true the first NetworkContext created using the
- // NetworkService. Destroying the NetworkContext with this set to true
- // will destroy all other NetworkContexts.
- bool IsPrimaryNetworkContext() const;
-
net::URLRequestContext* url_request_context() { return url_request_context_; }
NetworkService* network_service() { return network_service_; }
@@ -179,6 +171,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
mojom::URLLoaderFactoryParamsPtr params,
scoped_refptr<ResourceSchedulerClient> resource_scheduler_client);
+ // Creates a URLLoaderFactory with params specific to the
+ // CertVerifierService. A URLLoaderFactory created by this function will be
+ // used by a CertNetFetcherURLLoader to perform AIA and OCSP fetching.
+ // These URLLoaderFactories should only ever be used by the
+ // CertVerifierService, and should never be passed to a renderer.
+ void CreateURLLoaderFactoryForCertNetFetcher(
+ mojo::PendingReceiver<mojom::URLLoaderFactory> factory_receiver);
+
// Enables DoH probes to be sent using this context whenever the DNS
// configuration contains DoH servers.
void ActivateDohProbes();
@@ -251,10 +251,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
base::Time expiry,
bool enforce,
const GURL& report_uri,
+ const net::NetworkIsolationKey& network_isolation_key,
AddExpectCTCallback callback) override;
void SetExpectCTTestReport(const GURL& report_uri,
SetExpectCTTestReportCallback callback) override;
void GetExpectCTState(const std::string& domain,
+ const net::NetworkIsolationKey& network_isolation_key,
GetExpectCTStateCallback callback) override;
#endif // BUILDFLAG(IS_CT_SUPPORTED)
void CreateUDPSocket(
@@ -305,6 +307,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const GURL& url,
const url::Origin& origin,
const net::NetworkIsolationKey& network_isolation_key,
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints,
mojo::PendingRemote<mojom::QuicTransportHandshakeClient> handshake_client)
override;
void CreateNetLogExporter(
@@ -359,6 +362,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
bool allow_credentials,
const net::NetworkIsolationKey& network_isolation_key) override;
void CreateP2PSocketManager(
+ const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient> client,
mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
trusted_socket_manager,
@@ -486,9 +490,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
PendingTrustTokenStore* trust_token_store() {
return trust_token_store_.get();
}
+ const PendingTrustTokenStore* trust_token_store() const {
+ return trust_token_store_.get();
+ }
private:
- URLRequestContextOwner MakeURLRequestContext();
+ URLRequestContextOwner MakeURLRequestContext(
+ mojo::PendingRemote<mojom::URLLoaderFactory>
+ url_loader_factory_for_cert_net_fetcher);
// Invoked when the HTTP cache was cleared. Invokes |callback|.
void OnHttpCacheCleared(ClearHttpCacheCallback callback,
@@ -642,13 +651,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
#if defined(OS_CHROMEOS)
CertVerifierWithTrustAnchors* cert_verifier_with_trust_anchors_ = nullptr;
- // Additional certificates made available to NSS cert validation as temporary
- // certificates.
- std::unique_ptr<network::NSSTempCertsCacheChromeOS> nss_temp_certs_cache_;
#endif
// CertNetFetcher used by the context's CertVerifier. May be nullptr if
- // CertNetFetcher is not used by the current platform.
+ // CertNetFetcher is not used by the current platform, or if the actual
+ // net::CertVerifier is instantiated outside of the network service.
scoped_refptr<net::CertNetFetcherURLRequest> cert_net_fetcher_;
// Created on-demand. Null if unused.
diff --git a/chromium/services/network/network_context_unittest.cc b/chromium/services/network/network_context_unittest.cc
index e23b961a115..22955e89804 100644
--- a/chromium/services/network/network_context_unittest.cc
+++ b/chromium/services/network/network_context_unittest.cc
@@ -13,6 +13,7 @@
#include "base/barrier_closure.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/files/file.h"
@@ -28,6 +29,7 @@
#include "base/stl_util.h"
#include "base/strings/strcat.h"
#include "base/strings/string_split.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/waitable_event.h"
#include "base/test/bind_test_util.h"
@@ -47,9 +49,9 @@
#include "components/network_session_configurator/common/network_switches.h"
#include "components/prefs/testing_pref_service.h"
#include "crypto/sha2.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "mojo/public/cpp/system/data_pipe_utils.h"
+#include "mojo/public/cpp/system/functions.h"
#include "net/base/cache_type.h"
#include "net/base/features.h"
#include "net/base/hash_value.h"
@@ -65,6 +67,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
@@ -116,6 +119,8 @@
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/proxy_config.mojom.h"
+#include "services/network/public/mojom/url_loader.mojom-shared.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_url_loader_client.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
@@ -376,6 +381,19 @@ class TestProxyLookupClient : public mojom::ProxyLookupClient {
DISALLOW_COPY_AND_ASSIGN(TestProxyLookupClient);
};
+class MockP2PTrustedSocketManagerClient
+ : public mojom::P2PTrustedSocketManagerClient {
+ public:
+ MockP2PTrustedSocketManagerClient() = default;
+ ~MockP2PTrustedSocketManagerClient() override = default;
+
+ // mojom::P2PTrustedSocketManagerClient:
+ void InvalidSocketPortRangeRequested() override {}
+ void DumpPacket(const std::vector<uint8_t>& packet_header,
+ uint64_t packet_length,
+ bool incoming) override {}
+};
+
class NetworkContextTest : public testing::Test {
public:
explicit NetworkContextTest(
@@ -390,6 +408,11 @@ class NetworkContextTest : public testing::Test {
std::unique_ptr<NetworkContext> CreateContextWithParams(
mojom::NetworkContextParamsPtr context_params) {
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ DCHECK(!context_params->cert_verifier_params);
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_context_remote_.reset();
return std::make_unique<NetworkContext>(
network_service_.get(),
@@ -1070,11 +1093,11 @@ TEST_F(NetworkContextTest, TransportSecurityStatePersisted) {
net::TransportSecurityState::STSState sts_state;
net::TransportSecurityState* state =
network_context->url_request_context()->transport_security_state();
- EXPECT_FALSE(state->GetDynamicSTSState(kDomain, &sts_state, nullptr));
+ EXPECT_FALSE(state->GetDynamicSTSState(kDomain, &sts_state));
state->AddHSTS(kDomain,
base::Time::Now() + base::TimeDelta::FromSecondsD(1000),
false /* include subdomains */);
- EXPECT_TRUE(state->GetDynamicSTSState(kDomain, &sts_state, nullptr));
+ EXPECT_TRUE(state->GetDynamicSTSState(kDomain, &sts_state));
ASSERT_EQ(kDomain, sts_state.domain);
// Destroy the network context, and wait for all tasks to write state to
@@ -1095,7 +1118,7 @@ TEST_F(NetworkContextTest, TransportSecurityStatePersisted) {
// Wait for the entry to load.
task_environment_.RunUntilIdle();
state = network_context->url_request_context()->transport_security_state();
- ASSERT_EQ(on_disk, state->GetDynamicSTSState(kDomain, &sts_state, nullptr));
+ ASSERT_EQ(on_disk, state->GetDynamicSTSState(kDomain, &sts_state));
if (on_disk)
EXPECT_EQ(kDomain, sts_state.domain);
}
@@ -1253,6 +1276,85 @@ TEST_F(NetworkContextTest, HostResolutionFailure) {
client.completion_status().resolve_error_info.error);
}
+// Test the P2PSocketManager::GetHostAddress() works and uses the correct
+// NetworkIsolationKey.
+TEST_F(NetworkContextTest, P2PHostResolution) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ net::features::kSplitHostCacheByNetworkIsolationKey);
+
+ const char kHostname[] = "foo.test.";
+ net::IPAddress ip_address;
+ ASSERT_TRUE(ip_address.AssignFromIPLiteral("1.2.3.4"));
+ net::NetworkIsolationKey network_isolation_key =
+ net::NetworkIsolationKey::CreateTransient();
+ net::MockCachingHostResolver host_resolver;
+ std::unique_ptr<net::TestURLRequestContext> url_request_context =
+ std::make_unique<net::TestURLRequestContext>(
+ true /* delay_initialization */);
+ url_request_context->set_host_resolver(&host_resolver);
+ host_resolver.rules()->AddRule(kHostname, ip_address.ToString());
+ url_request_context->Init();
+
+ network_context_remote_.reset();
+ std::unique_ptr<NetworkContext> network_context =
+ std::make_unique<NetworkContext>(
+ network_service_.get(),
+ network_context_remote_.BindNewPipeAndPassReceiver(),
+ url_request_context.get(),
+ std::vector<std::string>() /* cors_exempt_header_list */);
+
+ MockP2PTrustedSocketManagerClient client;
+ mojo::Receiver<network::mojom::P2PTrustedSocketManagerClient> receiver(
+ &client);
+
+ mojo::Remote<mojom::P2PTrustedSocketManager> trusted_socket_manager;
+ mojo::Remote<mojom::P2PSocketManager> socket_manager;
+ network_context_remote_->CreateP2PSocketManager(
+ network_isolation_key, receiver.BindNewPipeAndPassRemote(),
+ trusted_socket_manager.BindNewPipeAndPassReceiver(),
+ socket_manager.BindNewPipeAndPassReceiver());
+
+ base::RunLoop run_loop;
+ std::vector<net::IPAddress> results;
+ socket_manager->GetHostAddress(
+ kHostname, false /* enable_mdns */,
+ base::BindLambdaForTesting(
+ [&](const std::vector<net::IPAddress>& addresses) {
+ EXPECT_EQ(std::vector<net::IPAddress>{ip_address}, addresses);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+
+ // Check that the URL in kHostname is in the HostCache, with
+ // |network_isolation_key|.
+ const net::HostPortPair kHostPortPair = net::HostPortPair(kHostname, 0);
+ net::HostResolver::ResolveHostParameters params;
+ params.source = net::HostResolverSource::LOCAL_ONLY;
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request1 =
+ host_resolver.CreateRequest(kHostPortPair, network_isolation_key,
+ net::NetLogWithSource(), params);
+ net::TestCompletionCallback callback1;
+ int result = request1->Start(callback1.callback());
+ EXPECT_EQ(net::OK, callback1.GetResult(result));
+
+ // Check that the hostname is not in the DNS cache for other possible NIKs.
+ const url::Origin kDestinationOrigin =
+ url::Origin::Create(GURL(base::StringPrintf("https://%s", kHostname)));
+ const net::NetworkIsolationKey kOtherNiks[] = {
+ net::NetworkIsolationKey(),
+ net::NetworkIsolationKey(kDestinationOrigin /* top_frame_origin */,
+ kDestinationOrigin /* frame_origin */)};
+ for (const auto& other_nik : kOtherNiks) {
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request2 =
+ host_resolver.CreateRequest(kHostPortPair, other_nik,
+ net::NetLogWithSource(), params);
+ net::TestCompletionCallback callback2;
+ int result = request2->Start(callback2.callback());
+ EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, callback2.GetResult(result));
+ }
+}
+
// Test that valid referrers are allowed, while invalid ones result in errors.
TEST_F(NetworkContextTest, Referrers) {
const GURL kReferrer = GURL("http://referrer/");
@@ -2162,16 +2264,17 @@ TEST_F(NetworkContextTest, ClearEmptyNetworkErrorLoggingWithNoService) {
void SetCookieCallback(base::RunLoop* run_loop,
bool* result_out,
- net::CanonicalCookie::CookieInclusionStatus result) {
+ net::CookieInclusionStatus result) {
*result_out = result.IsInclude();
run_loop->Quit();
}
-void GetCookieListCallback(base::RunLoop* run_loop,
- net::CookieList* result_out,
- const net::CookieStatusList& result,
- const net::CookieStatusList& excluded_cookies) {
- *result_out = net::cookie_util::StripStatuses(result);
+void GetCookieListCallback(
+ base::RunLoop* run_loop,
+ net::CookieList* result_out,
+ const net::CookieAccessResultList& result,
+ const net::CookieAccessResultList& excluded_cookies) {
+ *result_out = net::cookie_util::StripAccessResults(result);
run_loop->Quit();
}
@@ -3539,7 +3642,6 @@ TEST_F(NetworkContextTest, CreateHostResolverWithConfigOverrides) {
TEST_F(NetworkContextTest, ActivateDohProbes) {
auto resolver = std::make_unique<net::MockHostResolver>();
mojom::NetworkContextParamsPtr params = CreateContextParams();
- params->primary_network_context = true;
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(std::move(params));
network_context->url_request_context()->set_host_resolver(resolver.get());
@@ -3678,7 +3780,6 @@ TEST_F(NetworkContextTest, CanSetCookieFalseIfCookiesBlocked) {
base::Time(), base::Time(), base::Time(), false,
false, net::CookieSameSite::LAX_MODE,
net::COOKIE_PRIORITY_LOW);
-
EXPECT_TRUE(
network_context->url_request_context()->network_delegate()->CanSetCookie(
*request, cookie, nullptr, true));
@@ -3716,11 +3817,11 @@ TEST_F(NetworkContextTest, CanGetCookiesFalseIfCookiesBlocked) {
EXPECT_TRUE(
network_context->url_request_context()->network_delegate()->CanGetCookies(
- *request, {}, true));
+ *request, true));
SetDefaultContentSetting(CONTENT_SETTING_BLOCK, network_context.get());
EXPECT_FALSE(
network_context->url_request_context()->network_delegate()->CanGetCookies(
- *request, {}, true));
+ *request, true));
}
TEST_F(NetworkContextTest, CanGetCookiesTrueIfCookiesAllowed) {
@@ -3734,7 +3835,7 @@ TEST_F(NetworkContextTest, CanGetCookiesTrueIfCookiesAllowed) {
SetDefaultContentSetting(CONTENT_SETTING_ALLOW, network_context.get());
EXPECT_TRUE(
network_context->url_request_context()->network_delegate()->CanGetCookies(
- *request, {}, true));
+ *request, true));
}
// Gets notified by the EmbeddedTestServer on incoming connections being
@@ -4298,6 +4399,10 @@ TEST_F(NetworkContextTest, FactoryParams_DisableSecureDns) {
#if BUILDFLAG(IS_CT_SUPPORTED)
TEST_F(NetworkContextTest, ExpectCT) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ net::features::kPartitionExpectCTStateByNetworkIsolationKey);
+
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(CreateContextParams());
@@ -4307,12 +4412,15 @@ TEST_F(NetworkContextTest, ExpectCT) {
const bool enforce = true;
const GURL report_uri = GURL("https://example.com/foo/bar");
+ net::NetworkIsolationKey network_isolation_key =
+ net::NetworkIsolationKey::CreateTransient();
+
// Assert we start with no data for the test host.
{
base::Value state;
base::RunLoop run_loop;
network_context->GetExpectCTState(
- kTestDomain,
+ kTestDomain, network_isolation_key,
base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_TRUE(state.is_dict());
@@ -4328,7 +4436,7 @@ TEST_F(NetworkContextTest, ExpectCT) {
base::RunLoop run_loop;
bool result = false;
network_context->AddExpectCT(
- kTestDomain, expiry, enforce, report_uri,
+ kTestDomain, expiry, enforce, report_uri, network_isolation_key,
base::BindOnce(&StoreBool, &result, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_TRUE(result);
@@ -4339,7 +4447,7 @@ TEST_F(NetworkContextTest, ExpectCT) {
base::Value state;
base::RunLoop run_loop;
network_context->GetExpectCTState(
- kTestDomain,
+ kTestDomain, network_isolation_key,
base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_TRUE(state.is_dict());
@@ -4365,6 +4473,22 @@ TEST_F(NetworkContextTest, ExpectCT) {
EXPECT_EQ(report_uri, value->GetString());
}
+ // Using a different NetworkIsolationKey should return no result.
+ {
+ base::Value state;
+ base::RunLoop run_loop;
+ network_context->GetExpectCTState(
+ kTestDomain, net::NetworkIsolationKey::CreateTransient(),
+ base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
+ run_loop.Run();
+ EXPECT_TRUE(state.is_dict());
+
+ const base::Value* result =
+ state.FindKeyOfType("result", base::Value::Type::BOOLEAN);
+ ASSERT_TRUE(result != nullptr);
+ EXPECT_FALSE(result->GetBool());
+ }
+
// Delete host data.
{
bool result;
@@ -4381,7 +4505,7 @@ TEST_F(NetworkContextTest, ExpectCT) {
base::Value state;
base::RunLoop run_loop;
network_context->GetExpectCTState(
- kTestDomain,
+ kTestDomain, network_isolation_key,
base::BindOnce(&StoreValue, &state, run_loop.QuitClosure()));
run_loop.Run();
EXPECT_TRUE(state.is_dict());
@@ -6144,87 +6268,6 @@ TEST_F(NetworkContextTest, FactoriesDeletedWhenBindingsCleared) {
EXPECT_EQ(network_context->num_url_loader_factories_for_testing(), 0u);
}
-#if BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
-TEST_F(NetworkContextTest, UseCertVerifierBuiltin) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::test_server::RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
-
- // This just happens to be the only histogram that directly records which
- // verifier was used.
- const char kBuiltinVerifierHistogram[] =
- "Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
-
- for (bool builtin_verifier_enabled : {false, true}) {
- SCOPED_TRACE(builtin_verifier_enabled);
-
- mojom::NetworkContextParamsPtr params = CreateContextParams();
- auto creation_params = mojom::CertVerifierCreationParams::New();
- creation_params->use_builtin_cert_verifier =
- builtin_verifier_enabled
- ? mojom::CertVerifierCreationParams::CertVerifierImpl::kBuiltin
- : mojom::CertVerifierCreationParams::CertVerifierImpl::kSystem;
- params->cert_verifier_creation_params = std::move(creation_params);
- std::unique_ptr<NetworkContext> network_context =
- CreateContextWithParams(std::move(params));
-
- ResourceRequest request;
- request.url = test_server.GetURL("/nocontent");
- base::HistogramTester histogram_tester;
- std::unique_ptr<TestURLLoaderClient> client =
- FetchRequest(request, network_context.get());
- EXPECT_EQ(net::OK, client->completion_status().error_code);
- histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
- builtin_verifier_enabled ? 1 : 0);
- }
-}
-
-class NetworkContextCertVerifierBuiltinFeatureFlagTest
- : public NetworkContextTest,
- public testing::WithParamInterface<bool> {
- public:
- NetworkContextCertVerifierBuiltinFeatureFlagTest() {
- scoped_feature_list_.InitWithFeatureState(
- net::features::kCertVerifierBuiltinFeature,
- /*enabled=*/GetParam());
- }
-
- private:
- base::test::ScopedFeatureList scoped_feature_list_;
-};
-
-TEST_P(NetworkContextCertVerifierBuiltinFeatureFlagTest,
- DefaultNetworkContextParamsUsesCorrectVerifier) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::test_server::RegisterDefaultHandlers(&test_server);
- ASSERT_TRUE(test_server.Start());
-
- // This just happens to be the only histogram that directly records which
- // verifier was used.
- const char kBuiltinVerifierHistogram[] =
- "Net.CertVerifier.NameNormalizationPrivateRoots.Builtin";
-
- // Test creating a NetworkContextParams without specifying a value for
- // use_builtin_cert_verifier. Should use whatever the default cert verifier
- // implementation is according to the feature flag.
- std::unique_ptr<NetworkContext> network_context =
- CreateContextWithParams(CreateContextParams());
-
- ResourceRequest request;
- request.url = test_server.GetURL("/nocontent");
- base::HistogramTester histogram_tester;
- std::unique_ptr<TestURLLoaderClient> client =
- FetchRequest(request, network_context.get());
- EXPECT_EQ(net::OK, client->completion_status().error_code);
- histogram_tester.ExpectTotalCount(kBuiltinVerifierHistogram,
- GetParam() ? 1 : 0);
-}
-
-INSTANTIATE_TEST_SUITE_P(All,
- NetworkContextCertVerifierBuiltinFeatureFlagTest,
- ::testing::Bool());
-#endif // BUILDFLAG(BUILTIN_CERT_VERIFIER_FEATURE_SUPPORTED)
-
static ResourceRequest CreateResourceRequest(const char* method,
const GURL& url) {
ResourceRequest request;
@@ -6535,15 +6578,14 @@ TEST_F(NetworkContextTest, DisableTrustTokens) {
class NetworkContextExpectBadMessageTest : public NetworkContextTest {
public:
NetworkContextExpectBadMessageTest() {
- mojo::core::SetDefaultProcessErrorCallback(
+ mojo::SetDefaultProcessErrorHandler(
base::BindLambdaForTesting([&](const std::string&) {
EXPECT_FALSE(got_bad_message_);
got_bad_message_ = true;
}));
}
~NetworkContextExpectBadMessageTest() override {
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
protected:
@@ -6603,30 +6645,86 @@ TEST_F(NetworkContextExpectBadMessageTest,
AssertBadMessage();
}
-TEST_F(NetworkContextTest,
- AttemptsTrustTokenBearingRequestWhenTrustTokensIsEnabled) {
+TEST_F(NetworkContextExpectBadMessageTest,
+ FailsTrustTokenRedemptionWhenForbidden) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
std::unique_ptr<NetworkContext> network_context =
CreateContextWithParams(mojom::NetworkContextParams::New());
- // Allow the store time to initialize asynchronously.
+ // Allow |network_context|'s Trust Tokens store time to initialize
+ // asynchronously, if necessary.
task_environment_.RunUntilIdle();
+ ASSERT_TRUE(network_context->trust_token_store());
+
ResourceRequest my_request;
my_request.trust_token_params =
OptionalTrustTokenParams(mojom::TrustTokenParams::New());
+ my_request.trust_token_params->type =
+ mojom::TrustTokenOperationType::kRedemption;
auto factory_params = mojom::URLLoaderFactoryParams::New();
- factory_params->top_frame_origin =
- url::Origin::Create(GURL("https://topframe.com/"));
+ factory_params->trust_token_redemption_policy =
+ mojom::TrustTokenRedemptionPolicy::kForbid;
+ std::unique_ptr<TestURLLoaderClient> client =
+ FetchRequest(my_request, network_context.get(), mojom::kURLLoadOptionNone,
+ mojom::kBrowserProcessId, std::move(factory_params));
- // Since the request doesn't have a destination URL suitable for use as a
- // Trust Tokens issuer, it should fail.
+ AssertBadMessage();
+}
+
+TEST_F(NetworkContextExpectBadMessageTest,
+ FailsTrustTokenSigningWhenForbidden) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
+
+ std::unique_ptr<NetworkContext> network_context =
+ CreateContextWithParams(mojom::NetworkContextParams::New());
+
+ // Allow |network_context|'s Trust Tokens store time to initialize
+ // asynchronously, if necessary.
+ task_environment_.RunUntilIdle();
+
+ ASSERT_TRUE(network_context->trust_token_store());
+
+ ResourceRequest my_request;
+ my_request.trust_token_params =
+ OptionalTrustTokenParams(mojom::TrustTokenParams::New());
+ my_request.trust_token_params->type =
+ mojom::TrustTokenOperationType::kSigning;
+
+ auto factory_params = mojom::URLLoaderFactoryParams::New();
+ factory_params->trust_token_redemption_policy =
+ mojom::TrustTokenRedemptionPolicy::kForbid;
std::unique_ptr<TestURLLoaderClient> client =
FetchRequest(my_request, network_context.get(), mojom::kURLLoadOptionNone,
mojom::kBrowserProcessId, std::move(factory_params));
+
+ AssertBadMessage();
+}
+
+TEST_F(NetworkContextTest,
+ AttemptsTrustTokenBearingRequestWhenTrustTokensIsEnabled) {
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
+
+ std::unique_ptr<NetworkContext> network_context =
+ CreateContextWithParams(mojom::NetworkContextParams::New());
+
+ // Allow the store time to initialize asynchronously.
+ task_environment_.RunUntilIdle();
+
+ ResourceRequest my_request;
+ my_request.trust_token_params =
+ OptionalTrustTokenParams(mojom::TrustTokenParams::New());
+
+ // Since the request doesn't have a destination URL suitable for use as a
+ // Trust Tokens issuer, it should fail.
+ std::unique_ptr<TestURLLoaderClient> client = FetchRequest(
+ my_request, network_context.get(), mojom::kURLLoadOptionNone,
+ mojom::kBrowserProcessId, mojom::URLLoaderFactoryParams::New());
EXPECT_EQ(client->completion_status().error_code,
net::ERR_TRUST_TOKEN_OPERATION_FAILED);
EXPECT_EQ(client->completion_status().trust_token_operation_status,
@@ -6654,13 +6752,9 @@ TEST_F(NetworkContextTest,
my_request.trust_token_params =
OptionalTrustTokenParams(mojom::TrustTokenParams::New());
- auto factory_params = mojom::URLLoaderFactoryParams::New();
- factory_params->top_frame_origin =
- url::Origin::Create(GURL("https://topframe.com/"));
-
- std::unique_ptr<TestURLLoaderClient> client =
- FetchRequest(my_request, network_context.get(), mojom::kURLLoadOptionNone,
- mojom::kBrowserProcessId, std::move(factory_params));
+ std::unique_ptr<TestURLLoaderClient> client = FetchRequest(
+ my_request, network_context.get(), mojom::kURLLoadOptionNone,
+ mojom::kBrowserProcessId, mojom::URLLoaderFactoryParams::New());
EXPECT_EQ(client->completion_status().error_code,
net::ERR_TRUST_TOKEN_OPERATION_FAILED);
EXPECT_EQ(client->completion_status().trust_token_operation_status,
diff --git a/chromium/services/network/network_service.cc b/chromium/services/network/network_service.cc
index b289d86c03b..75b0c7e2e97 100644
--- a/chromium/services/network/network_service.cc
+++ b/chromium/services/network/network_service.cc
@@ -26,8 +26,8 @@
#include "build/chromecast_buildflags.h"
#include "components/network_session_configurator/common/network_features.h"
#include "components/os_crypt/os_crypt.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/scoped_message_error_crash_key.h"
+#include "mojo/public/cpp/system/functions.h"
#include "net/base/logging_network_change_observer.h"
#include "net/base/network_change_notifier.h"
#include "net/base/network_change_notifier_posix.h"
@@ -56,6 +56,7 @@
#include "services/network/net_log_proxy_sink.h"
#include "services/network/network_context.h"
#include "services/network/network_usage_accumulator.h"
+#include "services/network/public/cpp/crash_keys.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
#include "services/network/public/cpp/load_info_util.h"
@@ -184,10 +185,38 @@ void HandleBadMessage(const std::string& error) {
LOG(WARNING) << "Mojo error in NetworkService:" << error;
mojo::debug::ScopedMessageErrorCrashKey crash_key_value(error);
base::debug::DumpWithoutCrashing();
+ network::debug::ClearDeserializationCrashKeyString();
}
} // namespace
+DataPipeUseTracker::DataPipeUseTracker(NetworkService* network_service,
+ DataPipeUser user)
+ : network_service_(network_service), user_(user) {}
+
+DataPipeUseTracker::DataPipeUseTracker(DataPipeUseTracker&& that)
+ : DataPipeUseTracker(that.network_service_, that.user_) {
+ this->state_ = that.state_;
+ that.state_ = State::kReset;
+}
+
+DataPipeUseTracker::~DataPipeUseTracker() {
+ Reset();
+}
+
+void DataPipeUseTracker::Activate() {
+ DCHECK_EQ(state_, State::kInit);
+ network_service_->OnDataPipeCreated(user_);
+ state_ = State::kActivated;
+}
+
+void DataPipeUseTracker::Reset() {
+ if (state_ == State::kActivated) {
+ network_service_->OnDataPipeDropped(user_);
+ }
+ state_ = State::kReset;
+}
+
// static
const base::TimeDelta NetworkService::kInitialDohProbeTimeout =
base::TimeDelta::FromSeconds(5);
@@ -249,16 +278,17 @@ NetworkService::NetworkService(
// |registry_| is nullptr when an in-process NetworkService is
// created directly, like in most unit tests.
- if (registry_) {
- mojo::core::SetDefaultProcessErrorCallback(
- base::BindRepeating(&HandleBadMessage));
- }
+ if (registry_)
+ mojo::SetDefaultProcessErrorHandler(base::BindRepeating(&HandleBadMessage));
if (receiver.is_valid())
Bind(std::move(receiver));
if (!delay_initialization_until_set_client)
Initialize(mojom::NetworkServiceParams::New());
+
+ metrics_trigger_timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(20),
+ this, &NetworkService::ReportMetrics);
}
void NetworkService::Initialize(mojom::NetworkServiceParamsPtr params,
@@ -375,11 +405,6 @@ std::unique_ptr<NetworkService> NetworkService::CreateForTesting() {
}
void NetworkService::RegisterNetworkContext(NetworkContext* network_context) {
- // If IsPrimaryNetworkContext() is true, there must be no other
- // NetworkContexts created yet.
- DCHECK(!network_context->IsPrimaryNetworkContext() ||
- network_contexts_.empty());
-
DCHECK_EQ(0u, network_contexts_.count(network_context));
network_contexts_.insert(network_context);
if (quic_disabled_)
@@ -399,11 +424,6 @@ void NetworkService::RegisterNetworkContext(NetworkContext* network_context) {
}
void NetworkService::DeregisterNetworkContext(NetworkContext* network_context) {
- // If the NetworkContext is the primary network context, all other
- // NetworkContexts must already have been destroyed.
- DCHECK(!network_context->IsPrimaryNetworkContext() ||
- network_contexts_.size() == 1);
-
DCHECK_EQ(1u, network_contexts_.count(network_context));
network_contexts_.erase(network_context);
}
@@ -442,7 +462,9 @@ void NetworkService::StartNetLog(base::File file,
net::NetLogCaptureMode capture_mode,
base::Value client_constants) {
DCHECK(client_constants.is_dict());
- std::unique_ptr<base::DictionaryValue> constants = net::GetNetConstants();
+ std::unique_ptr<base::DictionaryValue> constants =
+ base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(net::GetNetConstants()));
constants->MergeDictionary(&client_constants);
file_net_log_observer_ = net::FileNetLogObserver::CreateUnboundedPreExisting(
@@ -467,10 +489,6 @@ void NetworkService::SetSSLKeyLogFile(base::File file) {
void NetworkService::CreateNetworkContext(
mojo::PendingReceiver<mojom::NetworkContext> receiver,
mojom::NetworkContextParamsPtr params) {
- // Only the first created NetworkContext can have |primary_next_context| set
- // to true.
- DCHECK(!params->primary_network_context || network_contexts_.empty());
-
owned_network_contexts_.emplace(std::make_unique<NetworkContext>(
this, std::move(receiver), std::move(params),
base::BindOnce(&NetworkService::OnNetworkContextConnectionClosed,
@@ -504,6 +522,14 @@ void NetworkService::ConfigureStubHostResolver(
overrides.disabled_upgrade_providers =
SplitString(features::kDnsOverHttpsUpgradeDisabledProvidersParam.Get(),
",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+
+ // Because SECURE mode does not allow any fallback, allow multiple retries as
+ // a quick hack to increase the timeout for these requests.
+ // TODO(crbug.com/1105138): Rethink the timeout logic to be less aggressive in
+ // cases where there is no fallback, without needing to make so many retries.
+ if (secure_dns_mode == net::DnsConfig::SecureDnsMode::SECURE)
+ overrides.doh_attempts = 3;
+
host_resolver_manager_->SetDnsConfigOverrides(overrides);
}
@@ -768,28 +794,29 @@ void NetworkService::OnBeforeURLRequest() {
MaybeStartUpdateLoadInfoTimer();
}
-void NetworkService::DestroyNetworkContexts() {
- // Delete NetworkContexts. If there's a primary NetworkContext, it must be
- // deleted after all other NetworkContexts, to avoid use-after-frees.
- for (auto it = owned_network_contexts_.begin();
- it != owned_network_contexts_.end();) {
- const auto last = it;
- ++it;
- if (!(*last)->IsPrimaryNetworkContext())
- owned_network_contexts_.erase(last);
- }
+void NetworkService::OnDataPipeCreated(DataPipeUser user) {
+ auto& entry = data_pipe_use_[user];
+ ++entry.current;
+ entry.max = std::max(entry.max, entry.current);
+}
+
+void NetworkService::OnDataPipeDropped(DataPipeUser user) {
+ auto& entry = data_pipe_use_[user];
+ DCHECK_GT(entry.current, 0);
+ --entry.current;
+ entry.min = std::min(entry.min, entry.current);
+}
+
+void NetworkService::StopMetricsTimerForTesting() {
+ metrics_trigger_timer_.Stop();
+}
- DCHECK_LE(owned_network_contexts_.size(), 1u);
+void NetworkService::DestroyNetworkContexts() {
owned_network_contexts_.clear();
}
void NetworkService::OnNetworkContextConnectionClosed(
NetworkContext* network_context) {
- if (network_context->IsPrimaryNetworkContext()) {
- DestroyNetworkContexts();
- return;
- }
-
auto it = owned_network_contexts_.find(network_context);
DCHECK(it != owned_network_contexts_.end());
owned_network_contexts_.erase(it);
@@ -881,6 +908,23 @@ void NetworkService::AckUpdateLoadInfo() {
MaybeStartUpdateLoadInfoTimer();
}
+void NetworkService::ReportMetrics() {
+ UMA_HISTOGRAM_COUNTS_10000("Net.DataPipeUseForUrlLoader.Min",
+ data_pipe_use_[DataPipeUser::kUrlLoader].min);
+ UMA_HISTOGRAM_COUNTS_10000("Net.DataPipeUseForUrlLoader.Max",
+ data_pipe_use_[DataPipeUser::kUrlLoader].max);
+ UMA_HISTOGRAM_COUNTS_10000("Net.DataPipeUseForWebSocket.Min",
+ data_pipe_use_[DataPipeUser::kWebSocket].min);
+ UMA_HISTOGRAM_COUNTS_10000("Net.DataPipeUseForWebSocket.Max",
+ data_pipe_use_[DataPipeUser::kWebSocket].max);
+
+ for (auto& pair : data_pipe_use_) {
+ DataPipeUsage& entry = pair.second;
+ entry.max = entry.current;
+ entry.min = entry.current;
+ }
+}
+
void NetworkService::Bind(
mojo::PendingReceiver<mojom::NetworkService> receiver) {
DCHECK(!receiver_.is_bound());
diff --git a/chromium/services/network/network_service.h b/chromium/services/network/network_service.h
index c98aa7f5d93..50120d006a0 100644
--- a/chromium/services/network/network_service.h
+++ b/chromium/services/network/network_service.h
@@ -13,6 +13,7 @@
#include <vector>
#include "base/component_export.h"
+#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/containers/span.h"
#include "base/containers/unique_ptr_adapters.h"
@@ -59,8 +60,43 @@ class HttpAuthCacheCopier;
class LegacyTLSConfigDistributor;
class NetLogProxySink;
class NetworkContext;
+class NetworkService;
class NetworkUsageAccumulator;
+// DataPipeUseTracker tracks the mojo data pipe usage in the network
+// service.
+class COMPONENT_EXPORT(NETWORK_SERVICE) DataPipeUseTracker final {
+ public:
+ enum DataPipeUser {
+ kUrlLoader = 0,
+ kWebSocket = 1,
+ };
+ // |network_service| must outlive |this|.
+ DataPipeUseTracker(NetworkService* network_service, DataPipeUser user);
+ DataPipeUseTracker(DataPipeUseTracker&&);
+ ~DataPipeUseTracker();
+ DataPipeUseTracker(const DataPipeUseTracker&) = delete;
+ DataPipeUseTracker& operator=(const DataPipeUseTracker&) = delete;
+
+ // Call this when the associated data pipe is created.
+ void Activate();
+ // Call this when (one end of) the associated data pipe is dropped.
+ void Reset();
+
+ private:
+ enum State {
+ kInit,
+ kActivated,
+ kReset,
+ };
+ NetworkService* const network_service_;
+ const DataPipeUser user_;
+
+ State state_ = State::kInit;
+};
+
+using DataPipeUser = DataPipeUseTracker::DataPipeUser;
+
class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
: public mojom::NetworkService {
public:
@@ -247,6 +283,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
return trust_token_key_commitments_.get();
}
+ void OnDataPipeCreated(DataPipeUser user);
+ void OnDataPipeDropped(DataPipeUser user);
+ void StopMetricsTimerForTesting();
+
static NetworkService* GetNetworkServiceForTesting();
private:
@@ -271,6 +311,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
// Starts timer call UpdateLoadInfo() again, if needed.
void AckUpdateLoadInfo();
+ void ReportMetrics();
+
bool initialized_ = false;
net::NetLog* net_log_;
@@ -351,7 +393,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
// acknowledged.
bool waiting_on_load_state_ack_ = false;
- // A timer that periodically calls ReportMetrics every hour.
+ // A timer that periodically calls ReportMetrics every 20 minutes.
base::RepeatingTimer metrics_trigger_timer_;
// Whether new NetworkContexts will be configured to partition their
@@ -370,6 +412,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
// requests should have their initiator origin within the set stored here).
std::map<int, std::set<url::Origin>> plugin_origins_;
+ struct DataPipeUsage final {
+ int current = 0;
+ int max = 0;
+ int min = 0;
+ };
+ base::flat_map<DataPipeUser, DataPipeUsage> data_pipe_use_;
+
DISALLOW_COPY_AND_ASSIGN(NetworkService);
};
diff --git a/chromium/services/network/network_service_network_delegate.cc b/chromium/services/network/network_service_network_delegate.cc
index c0e1a2e9bf3..abf4451b269 100644
--- a/chromium/services/network/network_service_network_delegate.cc
+++ b/chromium/services/network/network_service_network_delegate.cc
@@ -11,6 +11,7 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "components/domain_reliability/monitor.h"
+#include "net/base/features.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
@@ -20,7 +21,6 @@
#include "services/network/network_service.h"
#include "services/network/network_service_proxy_delegate.h"
#include "services/network/pending_callback_chain.h"
-#include "services/network/public/cpp/features.h"
#include "services/network/url_loader.h"
#include "url/gurl.h"
@@ -61,7 +61,7 @@ void NetworkServiceNetworkDelegate::MaybeTruncateReferrer(
}
if (base::FeatureList::IsEnabled(
- features::kCapReferrerToOriginOnCrossOrigin)) {
+ net::features::kCapReferrerToOriginOnCrossOrigin)) {
url::Origin destination_origin = url::Origin::Create(effective_url);
url::Origin source_origin = url::Origin::Create(GURL(request->referrer()));
if (!destination_origin.IsSameOriginWith(source_origin))
@@ -186,7 +186,6 @@ void NetworkServiceNetworkDelegate::OnPACScriptError(
bool NetworkServiceNetworkDelegate::OnCanGetCookies(
const net::URLRequest& request,
- const net::CookieList& cookie_list,
bool allowed_from_caller) {
bool allowed =
allowed_from_caller &&
diff --git a/chromium/services/network/network_service_network_delegate.h b/chromium/services/network/network_service_network_delegate.h
index 31dd7812921..0926327d2a0 100644
--- a/chromium/services/network/network_service_network_delegate.h
+++ b/chromium/services/network/network_service_network_delegate.h
@@ -56,7 +56,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkServiceNetworkDelegate
int net_error) override;
void OnPACScriptError(int line_number, const base::string16& error) override;
bool OnCanGetCookies(const net::URLRequest& request,
- const net::CookieList& cookie_list,
bool allowed_from_caller) override;
bool OnCanSetCookie(const net::URLRequest& request,
const net::CanonicalCookie& cookie,
diff --git a/chromium/services/network/network_service_unittest.cc b/chromium/services/network/network_service_unittest.cc
index 8c3719a41ff..bb38b299fcb 100644
--- a/chromium/services/network/network_service_unittest.cc
+++ b/chromium/services/network/network_service_unittest.cc
@@ -56,6 +56,7 @@
#include "services/network/public/mojom/network_change_manager.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/network_service.mojom.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_context_client.h"
#include "services/network/test/test_network_service_client.h"
#include "services/network/test/test_url_loader_client.h"
@@ -83,6 +84,10 @@ GURL AddQuery(const GURL& url,
mojom::NetworkContextParamsPtr CreateContextParams() {
mojom::NetworkContextParamsPtr params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
params->initial_proxy_config = net::ProxyConfigWithAnnotation::CreateDirect();
@@ -616,31 +621,6 @@ TEST_F(NetworkServiceTest, DisableDohUpgradeProviders) {
TEST_F(NetworkServiceTest, DohProbe) {
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
- mojo::Remote<mojom::NetworkContext> network_context;
- service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
- std::move(context_params));
-
- net::DnsConfig config;
- config.nameservers.push_back(net::IPEndPoint());
- config.dns_over_https_servers.emplace_back("example.com",
- true /* use_post */);
- auto dns_client = std::make_unique<net::MockDnsClient>(
- std::move(config), net::MockDnsClientRuleList());
- dns_client->set_ignore_system_config_changes(true);
- net::MockDnsClient* dns_client_ptr = dns_client.get();
- service()->host_resolver_manager()->SetDnsClientForTesting(
- std::move(dns_client));
-
- EXPECT_FALSE(dns_client_ptr->factory()->doh_probes_running());
-
- task_environment()->FastForwardBy(NetworkService::kInitialDohProbeTimeout);
- EXPECT_TRUE(dns_client_ptr->factory()->doh_probes_running());
-}
-
-TEST_F(NetworkServiceTest, DohProbe_NoPrimaryContext) {
- mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = false;
mojo::Remote<mojom::NetworkContext> network_context;
service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -663,8 +643,8 @@ TEST_F(NetworkServiceTest, DohProbe_NoPrimaryContext) {
}
TEST_F(NetworkServiceTest, DohProbe_MultipleContexts) {
+ service()->StopMetricsTimerForTesting();
mojom::NetworkContextParamsPtr context_params1 = CreateContextParams();
- context_params1->primary_network_context = true;
mojo::Remote<mojom::NetworkContext> network_context1;
service()->CreateNetworkContext(network_context1.BindNewPipeAndPassReceiver(),
std::move(context_params1));
@@ -684,7 +664,6 @@ TEST_F(NetworkServiceTest, DohProbe_MultipleContexts) {
ASSERT_TRUE(dns_client_ptr->factory()->doh_probes_running());
mojom::NetworkContextParamsPtr context_params2 = CreateContextParams();
- context_params2->primary_network_context = false;
mojo::Remote<mojom::NetworkContext> network_context2;
service()->CreateNetworkContext(network_context2.BindNewPipeAndPassReceiver(),
std::move(context_params2));
@@ -714,7 +693,6 @@ TEST_F(NetworkServiceTest, DohProbe_ContextAddedBeforeTimeout) {
EXPECT_FALSE(dns_client_ptr->factory()->doh_probes_running());
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
mojo::Remote<mojom::NetworkContext> network_context;
service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -726,6 +704,7 @@ TEST_F(NetworkServiceTest, DohProbe_ContextAddedBeforeTimeout) {
}
TEST_F(NetworkServiceTest, DohProbe_ContextAddedAfterTimeout) {
+ service()->StopMetricsTimerForTesting();
net::DnsConfig config;
config.nameservers.push_back(net::IPEndPoint());
config.dns_over_https_servers.emplace_back("example.com",
@@ -743,7 +722,6 @@ TEST_F(NetworkServiceTest, DohProbe_ContextAddedAfterTimeout) {
EXPECT_FALSE(dns_client_ptr->factory()->doh_probes_running());
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
mojo::Remote<mojom::NetworkContext> network_context;
service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -752,8 +730,8 @@ TEST_F(NetworkServiceTest, DohProbe_ContextAddedAfterTimeout) {
}
TEST_F(NetworkServiceTest, DohProbe_ContextRemovedBeforeTimeout) {
+ service()->StopMetricsTimerForTesting();
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
mojo::Remote<mojom::NetworkContext> network_context;
service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -780,8 +758,8 @@ TEST_F(NetworkServiceTest, DohProbe_ContextRemovedBeforeTimeout) {
}
TEST_F(NetworkServiceTest, DohProbe_ContextRemovedAfterTimeout) {
+ service()->StopMetricsTimerForTesting();
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
mojo::Remote<mojom::NetworkContext> network_context;
service()->CreateNetworkContext(network_context.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -931,6 +909,10 @@ class NetworkServiceTestWithService : public testing::Test {
void CreateNetworkContext() {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
network_service_->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));
@@ -1257,292 +1239,6 @@ TEST_F(NetworkServiceTestWithService, SetsTrustTokenKeyCommitments) {
EXPECT_TRUE(result.Equals(expectation));
}
-// CRLSets are not supported on iOS and Android system verifiers.
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
-
-// Verifies CRLSets take effect if configured on the service.
-TEST_F(NetworkServiceTestWithService, CRLSetIsApplied) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
- test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
- ASSERT_TRUE(test_server.Start());
-
- CreateNetworkContext();
-
- uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
- mojom::kURLLoadOptionSendSSLInfoForCertificateError;
- // Make sure the test server loads fine with no CRLSet.
- LoadURL(test_server.GetURL("/echo"), options);
- ASSERT_EQ(net::OK, client()->completion_status().error_code);
-
- // Send a CRLSet that blocks the leaf cert.
- std::string crl_set_bytes;
- EXPECT_TRUE(base::ReadFileToString(
- net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
- &crl_set_bytes));
-
- {
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Flush all connections in the context, to force a new connection. A new
- // verification should be attempted, due to the configuration having
- // changed, thus forcing the CRLSet to be checked.
- {
- base::RunLoop run_loop;
- context()->CloseAllConnections(run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Make sure the connection fails, due to the certificate being revoked.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-}
-
-// Verifies CRLSets configured before creating a new network context are
-// applied to that network context.
-TEST_F(NetworkServiceTestWithService, CRLSetIsPassedToNewContexts) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
- test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
- ASSERT_TRUE(test_server.Start());
-
- // Send a CRLSet that blocks the leaf cert, even while no NetworkContexts
- // exist.
- std::string crl_set_bytes;
- EXPECT_TRUE(base::ReadFileToString(
- net::GetTestCertsDirectory().AppendASCII("crlset_by_leaf_spki.raw"),
- &crl_set_bytes));
-
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
-
- // Configure a new NetworkContext.
- CreateNetworkContext();
-
- uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
- mojom::kURLLoadOptionSendSSLInfoForCertificateError;
- // Make sure the connection fails, due to the certificate being revoked.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-}
-
-// Verifies newer CRLSets (by sequence number) are applied.
-TEST_F(NetworkServiceTestWithService, CRLSetIsUpdatedIfNewer) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
- test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
- ASSERT_TRUE(test_server.Start());
-
- // Send a CRLSet that only allows the root cert if it matches a known SPKI
- // hash (that matches the test server chain)
- std::string crl_set_bytes;
- ASSERT_TRUE(base::ReadFileToString(
- net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
- &crl_set_bytes));
-
- {
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- CreateNetworkContext();
-
- uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
- mojom::kURLLoadOptionSendSSLInfoForCertificateError;
- // Make sure the connection loads, due to the root being permitted.
- LoadURL(test_server.GetURL("/echo"), options);
- ASSERT_EQ(net::OK, client()->completion_status().error_code);
-
- // Send a new CRLSet that removes trust in the root.
- ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
- "crlset_by_root_subject_no_spki.raw"),
- &crl_set_bytes));
-
- {
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Flush all connections in the context, to force a new connection. A new
- // verification should be attempted, due to the configuration having
- // changed, thus forcing the CRLSet to be checked.
- {
- base::RunLoop run_loop;
- context()->CloseAllConnections(run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Make sure the connection fails, due to the certificate being revoked.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-}
-
-// Verifies that attempting to send an older CRLSet (by sequence number)
-// does not apply to existing or new contexts.
-TEST_F(NetworkServiceTestWithService, CRLSetDoesNotDowngrade) {
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK);
- test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
- ASSERT_TRUE(test_server.Start());
-
- // Send a CRLSet that blocks the root certificate by subject name.
- std::string crl_set_bytes;
- ASSERT_TRUE(base::ReadFileToString(net::GetTestCertsDirectory().AppendASCII(
- "crlset_by_root_subject_no_spki.raw"),
- &crl_set_bytes));
-
- {
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- CreateNetworkContext();
-
- uint32_t options = mojom::kURLLoadOptionSendSSLInfoWithResponse |
- mojom::kURLLoadOptionSendSSLInfoForCertificateError;
- // Make sure the connection fails, due to the certificate being revoked.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-
- // Attempt to configure an older CRLSet that allowed trust in the root.
- ASSERT_TRUE(base::ReadFileToString(
- net::GetTestCertsDirectory().AppendASCII("crlset_by_root_subject.raw"),
- &crl_set_bytes));
-
- {
- base::RunLoop run_loop;
- service()->UpdateCRLSet(base::as_bytes(base::make_span(crl_set_bytes)),
- run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Flush all connections in the context, to force a new connection. A new
- // verification should be attempted, due to the configuration having
- // changed, thus forcing the CRLSet to be checked.
- {
- base::RunLoop run_loop;
- context()->CloseAllConnections(run_loop.QuitClosure());
- run_loop.Run();
- }
-
- // Make sure the connection still fails, due to the newer CRLSet still
- // applying.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-
- // Create a new NetworkContext and ensure the latest CRLSet is still
- // applied.
- network_context_.reset();
- CreateNetworkContext();
-
- // The newer CRLSet that blocks the connection should still apply, even to
- // new NetworkContexts.
- LoadURL(test_server.GetURL("/echo"), options);
- EXPECT_EQ(net::ERR_INSECURE_RESPONSE,
- client()->completion_status().error_code);
- ASSERT_TRUE(client()->completion_status().ssl_info.has_value());
- EXPECT_TRUE(client()->completion_status().ssl_info->cert_status &
- net::CERT_STATUS_REVOKED);
-}
-
-#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
-
-// TODO(crbug.com/860189): AIA tests fail on iOS
-#if defined(OS_IOS)
-#define MAYBE_AIAFetching DISABLED_AIAFetching
-#else
-#define MAYBE_AIAFetching AIAFetching
-#endif
-// Test |primary_network_context|, which is required by AIA fetching, among
-// other things.
-TEST_F(NetworkServiceTestWithService, MAYBE_AIAFetching) {
- mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
-
- network_service_->CreateNetworkContext(
- network_context_.BindNewPipeAndPassReceiver(), std::move(context_params));
-
- net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
- net::EmbeddedTestServer::ServerCertificateConfig cert_config;
- cert_config.intermediate = net::EmbeddedTestServer::IntermediateType::kByAIA;
- test_server.SetSSLConfig(cert_config);
- test_server.AddDefaultHandlers(base::FilePath(kServicesTestData));
- ASSERT_TRUE(test_server.Start());
-
- LoadURL(test_server.GetURL("/echo"),
- mojom::kURLLoadOptionSendSSLInfoWithResponse);
- EXPECT_EQ(net::OK, client()->completion_status().error_code);
- ASSERT_TRUE(client()->response_head());
- EXPECT_EQ(
- 0u, client()->response_head()->cert_status & net::CERT_STATUS_ALL_ERRORS);
- ASSERT_TRUE(client()->ssl_info());
- ASSERT_TRUE(client()->ssl_info()->cert);
- EXPECT_EQ(2u, client()->ssl_info()->cert->intermediate_buffers().size());
- ASSERT_TRUE(client()->ssl_info()->unverified_cert);
- EXPECT_EQ(
- 0u, client()->ssl_info()->unverified_cert->intermediate_buffers().size());
-}
-
-// Check that destroying a NetworkContext with |primary_network_context| set
-// destroys all other NetworkContexts.
-TEST_F(NetworkServiceTestWithService,
- DestroyingPrimaryNetworkContextDestroysOtherContexts) {
- mojom::NetworkContextParamsPtr context_params = CreateContextParams();
- context_params->primary_network_context = true;
- mojo::Remote<mojom::NetworkContext> cert_validating_network_context;
- network_service_->CreateNetworkContext(
- cert_validating_network_context.BindNewPipeAndPassReceiver(),
- std::move(context_params));
-
- base::RunLoop run_loop;
- mojo::Remote<mojom::NetworkContext> network_context;
- network_service_->CreateNetworkContext(
- network_context.BindNewPipeAndPassReceiver(), CreateContextParams());
- network_context.set_disconnect_handler(run_loop.QuitClosure());
-
- // Wait until the new NetworkContext has been created, so it's not created
- // after the primary NetworkContext is destroyed.
- network_service_.FlushForTesting();
-
- // Destroying |cert_validating_network_context| should result in destroying
- // |network_context| as well.
- cert_validating_network_context.reset();
- run_loop.Run();
- EXPECT_FALSE(network_context.is_connected());
-}
-
TEST_F(NetworkServiceTestWithService, GetDnsConfigChangeManager) {
mojo::Remote<mojom::DnsConfigChangeManager> remote;
ASSERT_FALSE(remote.is_bound());
@@ -1699,6 +1395,10 @@ class NetworkServiceNetworkDelegateTest : public NetworkServiceTest {
void CreateNetworkContext() {
mojom::NetworkContextParamsPtr context_params =
mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
service()->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));
diff --git a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
index ab2c413192a..37a759cdda9 100644
--- a/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
+++ b/chromium/services/network/origin_policy/origin_policy_manager_unittest.cc
@@ -12,6 +12,7 @@
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/origin_policy.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -30,6 +31,10 @@ class OriginPolicyManagerTest : public testing::Test {
network_service_ = NetworkService::CreateForTesting();
auto context_params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
// Use a fixed proxy config, to avoid dependencies on local network
// configuration.
context_params->initial_proxy_config =
diff --git a/chromium/services/network/p2p/socket.h b/chromium/services/network/p2p/socket.h
index 3904fb6414a..63a42ac6b29 100644
--- a/chromium/services/network/p2p/socket.h
+++ b/chromium/services/network/p2p/socket.h
@@ -26,6 +26,7 @@
namespace net {
class NetLog;
+class NetworkIsolationKey;
}
namespace network {
@@ -79,10 +80,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocket : public mojom::P2PSocket {
// in the valid range.
// If |local_address.port()| is nonzero and not in the valid range,
// initialization will fail.
+ // |network_isolation_key| specifies the network stack cache shard to used.
virtual void Init(const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) = 0;
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) = 0;
mojo::PendingRemote<mojom::P2PSocketClient> ReleaseClientForTesting();
mojo::PendingReceiver<mojom::P2PSocket> ReleaseReceiverForTesting();
diff --git a/chromium/services/network/p2p/socket_manager.cc b/chromium/services/network/p2p/socket_manager.cc
index 56dc77eddb7..8b149110739 100644
--- a/chromium/services/network/p2p/socket_manager.cc
+++ b/chromium/services/network/p2p/socket_manager.cc
@@ -15,6 +15,7 @@
#include "net/base/address_list.h"
#include "net/base/net_errors.h"
#include "net/base/network_interfaces.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/sys_addrinfo.h"
#include "net/dns/host_resolver.h"
#include "net/log/net_log_source.h"
@@ -79,7 +80,9 @@ class P2PSocketManager::DnsRequest {
DnsRequest(net::HostResolver* host_resolver, bool enable_mdns)
: resolver_(host_resolver), enable_mdns_(enable_mdns) {}
- void Resolve(const std::string& host_name, DoneCallback done_callback) {
+ void Resolve(const std::string& host_name,
+ const net::NetworkIsolationKey& network_isolation_key,
+ DoneCallback done_callback) {
DCHECK(!done_callback.is_null());
host_name_ = host_name;
@@ -107,8 +110,8 @@ class P2PSocketManager::DnsRequest {
parameters.source = net::HostResolverSource::MULTICAST_DNS;
#endif // ENABLE_MDNS
}
- request_ =
- resolver_->CreateRequest(host, net::NetLogWithSource(), parameters);
+ request_ = resolver_->CreateRequest(host, network_isolation_key,
+ net::NetLogWithSource(), parameters);
int result = request_->Start(base::BindOnce(
&P2PSocketManager::DnsRequest::OnDone, base::Unretained(this)));
@@ -144,6 +147,7 @@ class P2PSocketManager::DnsRequest {
};
P2PSocketManager::P2PSocketManager(
+ const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient>
trusted_socket_manager_client,
mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
@@ -153,6 +157,7 @@ P2PSocketManager::P2PSocketManager(
net::URLRequestContext* url_request_context)
: delete_callback_(std::move(delete_callback)),
url_request_context_(url_request_context),
+ network_isolation_key_(network_isolation_key),
network_list_task_runner_(base::ThreadPool::CreateSequencedTaskRunner(
{base::MayBlock(), base::TaskPriority::USER_VISIBLE})),
trusted_socket_manager_client_(std::move(trusted_socket_manager_client)),
@@ -286,7 +291,7 @@ void P2PSocketManager::GetHostAddress(
DnsRequest* request_ptr = request.get();
dns_requests_.insert(std::move(request));
request_ptr->Resolve(
- host_name,
+ host_name, network_isolation_key_,
base::BindOnce(&P2PSocketManager::OnAddressResolved,
base::Unretained(this), request_ptr, std::move(callback)));
}
@@ -327,7 +332,7 @@ void P2PSocketManager::CreateSocket(
// Init() may call SocketManager::DestroySocket(), so it must be called after
// adding the socket to |sockets_|.
socket_ptr->Init(local_address, port_range.min_port, port_range.max_port,
- remote_address);
+ remote_address, network_isolation_key_);
}
void P2PSocketManager::StartRtpDump(bool incoming, bool outgoing) {
diff --git a/chromium/services/network/p2p/socket_manager.h b/chromium/services/network/p2p/socket_manager.h
index f6e793fa556..79f6546cf68 100644
--- a/chromium/services/network/p2p/socket_manager.h
+++ b/chromium/services/network/p2p/socket_manager.h
@@ -26,6 +26,7 @@
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
#include "net/base/network_change_notifier.h"
+#include "net/base/network_isolation_key.h"
#include "services/network/p2p/socket.h"
#include "services/network/p2p/socket_throttler.h"
#include "services/network/public/cpp/p2p_socket_type.h"
@@ -58,6 +59,7 @@ class P2PSocketManager
// P2PSocketManager. The P2PSocketManager must be destroyed before the
// |url_request_context|.
P2PSocketManager(
+ const net::NetworkIsolationKey& network_isolation_key,
mojo::PendingRemote<mojom::P2PTrustedSocketManagerClient>
trusted_socket_manager_client,
mojo::PendingReceiver<mojom::P2PTrustedSocketManager>
@@ -121,6 +123,7 @@ class P2PSocketManager
DeleteCallback delete_callback_;
net::URLRequestContext* url_request_context_;
+ const net::NetworkIsolationKey network_isolation_key_;
std::unique_ptr<ProxyResolvingClientSocketFactory>
proxy_resolving_socket_factory_;
diff --git a/chromium/services/network/p2p/socket_tcp.cc b/chromium/services/network/p2p/socket_tcp.cc
index 385433b53d8..9d7d9fd7495 100644
--- a/chromium/services/network/p2p/socket_tcp.cc
+++ b/chromium/services/network/p2p/socket_tcp.cc
@@ -14,6 +14,7 @@
#include "jingle/glue/fake_ssl_client_socket.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/socket/client_socket_factory.h"
#include "net/socket/client_socket_handle.h"
#include "net/socket/ssl_client_socket.h"
@@ -78,10 +79,12 @@ void P2PSocketTcpBase::InitAccepted(const net::IPEndPoint& remote_address,
DoRead();
}
-void P2PSocketTcpBase::Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
+void P2PSocketTcpBase::Init(
+ const net::IPEndPoint& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) {
DCHECK(!socket_);
remote_address_ = remote_address;
@@ -105,7 +108,7 @@ void P2PSocketTcpBase::Init(const net::IPEndPoint& local_address,
// a problem on multi-homed host.
socket_ = proxy_resolving_socket_factory_->CreateSocket(
- GURL("https://" + dest_host_port_pair.ToString()),
+ GURL("https://" + dest_host_port_pair.ToString()), network_isolation_key,
IsTlsClientSocket(type_));
if (IsPseudoTlsClientSocket(type_)) {
diff --git a/chromium/services/network/p2p/socket_tcp.h b/chromium/services/network/p2p/socket_tcp.h
index e4640f181d7..b086186a6aa 100644
--- a/chromium/services/network/p2p/socket_tcp.h
+++ b/chromium/services/network/p2p/socket_tcp.h
@@ -48,7 +48,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketTcpBase : public P2PSocket {
void Init(const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) override;
// mojom::P2PSocket implementation:
void Send(const std::vector<int8_t>& data,
diff --git a/chromium/services/network/p2p/socket_tcp_server.cc b/chromium/services/network/p2p/socket_tcp_server.cc
index d2bdc4fcd2b..f9dafef98aa 100644
--- a/chromium/services/network/p2p/socket_tcp_server.cc
+++ b/chromium/services/network/p2p/socket_tcp_server.cc
@@ -37,10 +37,12 @@ P2PSocketTcpServer::P2PSocketTcpServer(
P2PSocketTcpServer::~P2PSocketTcpServer() = default;
// TODO(guidou): Add support for port range.
-void P2PSocketTcpServer::Init(const net::IPEndPoint& local_address,
- uint16_t min_port,
- uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
+void P2PSocketTcpServer::Init(
+ const net::IPEndPoint& local_address,
+ uint16_t min_port,
+ uint16_t max_port,
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) {
int result = socket_->Listen(local_address, kListenBacklog);
if (result < 0) {
LOG(ERROR) << "Listen() failed: " << result;
diff --git a/chromium/services/network/p2p/socket_tcp_server.h b/chromium/services/network/p2p/socket_tcp_server.h
index b496ba2574e..527110ea7d7 100644
--- a/chromium/services/network/p2p/socket_tcp_server.h
+++ b/chromium/services/network/p2p/socket_tcp_server.h
@@ -39,7 +39,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketTcpServer : public P2PSocket {
void Init(const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) override;
// mojom::P2PSocket implementation:
void Send(const std::vector<int8_t>& data,
diff --git a/chromium/services/network/p2p/socket_tcp_server_unittest.cc b/chromium/services/network/p2p/socket_tcp_server_unittest.cc
index 87876968539..0c0ec2f4c5d 100644
--- a/chromium/services/network/p2p/socket_tcp_server_unittest.cc
+++ b/chromium/services/network/p2p/socket_tcp_server_unittest.cc
@@ -12,6 +12,7 @@
#include "base/run_loop.h"
#include "base/test/task_environment.h"
#include "net/base/completion_once_callback.h"
+#include "net/base/network_isolation_key.h"
#include "services/network/p2p/socket_tcp.h"
#include "services/network/p2p/socket_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
@@ -105,7 +106,8 @@ class P2PSocketTcpServerTest : public testing::Test {
P2PHostAndIPEndPoint dest;
dest.ip_address = ParseAddress(kTestIpAddress1, kTestPort1);
- p2p_socket_->Init(ParseAddress(kTestLocalIpAddress, 0), 0, 0, dest);
+ p2p_socket_->Init(ParseAddress(kTestLocalIpAddress, 0), 0, 0, dest,
+ net::NetworkIsolationKey());
EXPECT_TRUE(socket_->listening());
base::RunLoop().RunUntilIdle();
}
diff --git a/chromium/services/network/p2p/socket_tcp_unittest.cc b/chromium/services/network/p2p/socket_tcp_unittest.cc
index 1150cf293b8..dd1f75cb2a2 100644
--- a/chromium/services/network/p2p/socket_tcp_unittest.cc
+++ b/chromium/services/network/p2p/socket_tcp_unittest.cc
@@ -9,12 +9,17 @@
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/strings/stringprintf.h"
#include "base/sys_byteorder.h"
#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "jingle/glue/fake_ssl_client_socket.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "net/base/features.h"
+#include "net/base/network_isolation_key.h"
+#include "net/dns/mock_host_resolver.h"
#include "net/socket/socket_test_util.h"
#include "net/socket/stream_socket.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -522,13 +527,104 @@ TEST(P2PSocketTcpWithPseudoTlsTest, Basic) {
&factory);
P2PHostAndIPEndPoint dest;
dest.ip_address = server_addr;
- host.Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0), 0, 0, dest);
+ host.Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0), 0, 0, dest,
+ net::NetworkIsolationKey());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(data_provider.AllReadDataConsumed());
EXPECT_TRUE(data_provider.AllWriteDataConsumed());
}
+// Test the case where P2PHostAndIPEndPoint::hostname is populated. Make sure
+// there's a DNS lookup using the right hostname and NetworkIsolationKey.
+TEST(P2PSocketTcpWithPseudoTlsTest, Hostname) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitAndEnableFeature(
+ net::features::kSplitHostCacheByNetworkIsolationKey);
+
+ const char kHostname[] = "foo.test";
+ base::test::TaskEnvironment task_environment(
+ base::test::TaskEnvironment::MainThreadType::IO);
+
+ mojo::PendingRemote<mojom::P2PSocketClient> socket_client;
+ mojo::PendingRemote<mojom::P2PSocket> socket;
+ auto socket_receiver = socket.InitWithNewPipeAndPassReceiver();
+
+ FakeSocketClient fake_client2(std::move(socket),
+ socket_client.InitWithNewPipeAndPassReceiver());
+ EXPECT_CALL(fake_client2, SocketCreated(_, _)).Times(1);
+
+ net::TestURLRequestContext context(true);
+ net::MockClientSocketFactory mock_socket_factory;
+ context.set_client_socket_factory(&mock_socket_factory);
+ net::MockCachingHostResolver host_resolver;
+ host_resolver.rules()->AddRule(kHostname, "1.2.3.4");
+ context.set_host_resolver(&host_resolver);
+ context.Init();
+ ProxyResolvingClientSocketFactory factory(&context);
+
+ base::StringPiece ssl_client_hello =
+ jingle_glue::FakeSSLClientSocket::GetSslClientHello();
+ base::StringPiece ssl_server_hello =
+ jingle_glue::FakeSSLClientSocket::GetSslServerHello();
+ net::MockRead reads[] = {
+ net::MockRead(net::ASYNC, ssl_server_hello.data(),
+ ssl_server_hello.size()),
+ net::MockRead(net::SYNCHRONOUS, net::ERR_IO_PENDING)};
+ net::MockWrite writes[] = {net::MockWrite(
+ net::SYNCHRONOUS, ssl_client_hello.data(), ssl_client_hello.size())};
+ net::StaticSocketDataProvider data_provider(reads, writes);
+ net::IPEndPoint server_addr(net::IPAddress::IPv4Localhost(), 1234);
+ data_provider.set_connect_data(
+ net::MockConnect(net::SYNCHRONOUS, net::OK, server_addr));
+ mock_socket_factory.AddSocketDataProvider(&data_provider);
+
+ FakeP2PSocketDelegate socket_delegate;
+ P2PSocketTcp host(&socket_delegate, std::move(socket_client),
+ std::move(socket_receiver), P2P_SOCKET_SSLTCP_CLIENT,
+ &factory);
+ P2PHostAndIPEndPoint dest;
+ dest.ip_address = server_addr;
+ dest.hostname = kHostname;
+ net::NetworkIsolationKey network_isolation_key =
+ net::NetworkIsolationKey::CreateTransient();
+ host.Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0), 0, 0, dest,
+ network_isolation_key);
+
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(data_provider.AllReadDataConsumed());
+ EXPECT_TRUE(data_provider.AllWriteDataConsumed());
+
+ // Check that the URL in kHostname is in the HostCache, with
+ // |network_isolation_key|.
+ const net::HostPortPair kHostPortPair = net::HostPortPair(kHostname, 0);
+ net::HostResolver::ResolveHostParameters params;
+ params.source = net::HostResolverSource::LOCAL_ONLY;
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request1 =
+ context.host_resolver()->CreateRequest(kHostPortPair,
+ network_isolation_key,
+ net::NetLogWithSource(), params);
+ net::TestCompletionCallback callback1;
+ int result = request1->Start(callback1.callback());
+ EXPECT_EQ(net::OK, callback1.GetResult(result));
+
+ // Check that the hostname is not in the DNS cache for other possible NIKs.
+ const url::Origin kDestinationOrigin =
+ url::Origin::Create(GURL(base::StringPrintf("https://%s", kHostname)));
+ const net::NetworkIsolationKey kOtherNiks[] = {
+ net::NetworkIsolationKey(),
+ net::NetworkIsolationKey(kDestinationOrigin /* top_frame_origin */,
+ kDestinationOrigin /* frame_origin */)};
+ for (const auto& other_nik : kOtherNiks) {
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request2 =
+ context.host_resolver()->CreateRequest(kHostPortPair, other_nik,
+ net::NetLogWithSource(), params);
+ net::TestCompletionCallback callback2;
+ int result = request2->Start(callback2.callback());
+ EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, callback2.GetResult(result));
+ }
+}
+
class P2PSocketTcpWithTlsTest
: public testing::TestWithParam<std::tuple<net::IoMode, P2PSocketType>> {};
@@ -585,7 +681,8 @@ TEST_P(P2PSocketTcpWithTlsTest, Basic) {
}
P2PHostAndIPEndPoint dest;
dest.ip_address = server_addr;
- host->Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0), 0, 0, dest);
+ host->Init(net::IPEndPoint(net::IPAddress::IPv4Localhost(), 0), 0, 0, dest,
+ net::NetworkIsolationKey());
base::RunLoop().RunUntilIdle();
EXPECT_TRUE(data_provider.AllReadDataConsumed());
diff --git a/chromium/services/network/p2p/socket_udp.cc b/chromium/services/network/p2p/socket_udp.cc
index b6d6392873d..bf042cfd6de 100644
--- a/chromium/services/network/p2p/socket_udp.cc
+++ b/chromium/services/network/p2p/socket_udp.cc
@@ -129,7 +129,8 @@ P2PSocketUdp::~P2PSocketUdp() = default;
void P2PSocketUdp::Init(const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) {
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) {
DCHECK(!socket_);
DCHECK((min_port == 0 && max_port == 0) || min_port > 0);
DCHECK_LE(min_port, max_port);
diff --git a/chromium/services/network/p2p/socket_udp.h b/chromium/services/network/p2p/socket_udp.h
index 7ffa5e5fead..e2e4f540845 100644
--- a/chromium/services/network/p2p/socket_udp.h
+++ b/chromium/services/network/p2p/socket_udp.h
@@ -58,7 +58,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) P2PSocketUdp : public P2PSocket {
void Init(const net::IPEndPoint& local_address,
uint16_t min_port,
uint16_t max_port,
- const P2PHostAndIPEndPoint& remote_address) override;
+ const P2PHostAndIPEndPoint& remote_address,
+ const net::NetworkIsolationKey& network_isolation_key) override;
// mojom::P2PSocket implementation:
void Send(const std::vector<int8_t>& data,
diff --git a/chromium/services/network/p2p/socket_udp_unittest.cc b/chromium/services/network/p2p/socket_udp_unittest.cc
index 624a3b05dac..48d9379dcf8 100644
--- a/chromium/services/network/p2p/socket_udp_unittest.cc
+++ b/chromium/services/network/p2p/socket_udp_unittest.cc
@@ -21,6 +21,7 @@
#include "net/base/io_buffer.h"
#include "net/base/ip_endpoint.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/log/net_log_with_source.h"
#include "net/socket/datagram_server_socket.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
@@ -233,7 +234,8 @@ class P2PSocketUdpTest : public testing::Test {
socket_impl_->Init(
local_address_, 0, 0,
P2PHostAndIPEndPoint(std::string(),
- ParseAddress(kTestIpAddress1, kTestPort1)));
+ ParseAddress(kTestIpAddress1, kTestPort1)),
+ net::NetworkIsolationKey());
socket_ = GetSocketFromHost(socket_impl_.get());
dest1_ = ParseAddress(kTestIpAddress1, kTestPort1);
@@ -577,7 +579,8 @@ TEST_F(P2PSocketUdpTest, PortRangeImplicitPort) {
socket_impl->Init(
local_address, min_port, max_port,
P2PHostAndIPEndPoint(std::string(),
- ParseAddress(kTestIpAddress1, kTestPort1)));
+ ParseAddress(kTestIpAddress1, kTestPort1)),
+ net::NetworkIsolationKey());
FakeDatagramServerSocket* socket = GetSocketFromHost(socket_impl.get());
net::IPEndPoint bound_address;
@@ -601,7 +604,8 @@ TEST_F(P2PSocketUdpTest, PortRangeImplicitPort) {
socket_impl_ptr->Init(
local_address, min_port, max_port,
P2PHostAndIPEndPoint(std::string(),
- ParseAddress(kTestIpAddress1, kTestPort1)));
+ ParseAddress(kTestIpAddress1, kTestPort1)),
+ net::NetworkIsolationKey());
base::RunLoop().RunUntilIdle();
@@ -638,7 +642,8 @@ TEST_F(P2PSocketUdpTest, PortRangeExplictValidPort) {
socket_host->Init(
local_address, min_port, max_port,
P2PHostAndIPEndPoint(std::string(),
- ParseAddress(kTestIpAddress1, kTestPort1)));
+ ParseAddress(kTestIpAddress1, kTestPort1)),
+ net::NetworkIsolationKey());
FakeDatagramServerSocket* fake_socket = GetSocketFromHost(socket_host.get());
net::IPEndPoint bound_address;
@@ -679,7 +684,8 @@ TEST_F(P2PSocketUdpTest, PortRangeExplictInvalidPort) {
socket_impl_ptr->Init(
local_address, min_port, max_port,
P2PHostAndIPEndPoint(std::string(),
- ParseAddress(kTestIpAddress1, kTestPort1)));
+ ParseAddress(kTestIpAddress1, kTestPort1)),
+ net::NetworkIsolationKey());
base::RunLoop().RunUntilIdle();
diff --git a/chromium/services/network/proxy_resolving_client_socket.cc b/chromium/services/network/proxy_resolving_client_socket.cc
index fc6008039ba..c1fe895100c 100644
--- a/chromium/services/network/proxy_resolving_client_socket.cc
+++ b/chromium/services/network/proxy_resolving_client_socket.cc
@@ -38,10 +38,12 @@ ProxyResolvingClientSocket::ProxyResolvingClientSocket(
net::HttpNetworkSession* network_session,
const net::CommonConnectJobParams* common_connect_job_params,
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
bool use_tls)
: network_session_(network_session),
common_connect_job_params_(common_connect_job_params),
url_(url),
+ network_isolation_key_(network_isolation_key),
use_tls_(use_tls),
net_log_(net::NetLogWithSource::Make(network_session_->net_log(),
net::NetLogSourceType::SOCKET)),
@@ -245,8 +247,8 @@ int ProxyResolvingClientSocket::DoProxyResolve() {
//
// TODO(https://crbug.com/1023439): Pass along a NetworkIsolationKey.
return network_session_->proxy_resolution_service()->ResolveProxy(
- url_, net::HttpRequestHeaders::kPostMethod,
- net::NetworkIsolationKey::Todo(), &proxy_info_,
+ url_, net::HttpRequestHeaders::kPostMethod, network_isolation_key_,
+ &proxy_info_,
base::BindOnce(&ProxyResolvingClientSocket::OnIOComplete,
base::Unretained(this)),
&proxy_resolve_request_, net_log_);
@@ -299,7 +301,7 @@ int ProxyResolvingClientSocket::DoInitConnection() {
use_tls_, net::HostPortPair::FromURL(url_), proxy_info_.proxy_server(),
proxy_annotation_tag, &ssl_config, &ssl_config, true /* force_tunnel */,
net::PRIVACY_MODE_DISABLED, net::OnHostResolutionCallback(),
- net::MAXIMUM_PRIORITY, net::SocketTag(), net::NetworkIsolationKey(),
+ net::MAXIMUM_PRIORITY, net::SocketTag(), network_isolation_key_,
false /* disable_secure_dns */, common_connect_job_params_, this);
return connect_job_->Connect();
}
diff --git a/chromium/services/network/proxy_resolving_client_socket.h b/chromium/services/network/proxy_resolving_client_socket.h
index 07271b53c2b..6ce2a2bd215 100644
--- a/chromium/services/network/proxy_resolving_client_socket.h
+++ b/chromium/services/network/proxy_resolving_client_socket.h
@@ -17,6 +17,7 @@
#include "base/memory/weak_ptr.h"
#include "net/base/host_port_pair.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolution_service.h"
@@ -31,6 +32,7 @@ struct CommonConnectJobParams;
class HttpAuthController;
class HttpResponseInfo;
class HttpNetworkSession;
+class NetworkIsolationKey;
class ProxyResolutionRequest;
} // namespace net
@@ -55,6 +57,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
net::HttpNetworkSession* network_session,
const net::CommonConnectJobParams* common_connect_job_params,
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
bool use_tls);
~ProxyResolvingClientSocket() override;
@@ -132,6 +135,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocket
std::unique_ptr<net::ProxyResolutionRequest> proxy_resolve_request_;
net::ProxyInfo proxy_info_;
const GURL url_;
+ const net::NetworkIsolationKey network_isolation_key_;
const bool use_tls_;
net::NetLogWithSource net_log_;
diff --git a/chromium/services/network/proxy_resolving_client_socket_factory.cc b/chromium/services/network/proxy_resolving_client_socket_factory.cc
index 0d00e6db3cc..47d01a340d3 100644
--- a/chromium/services/network/proxy_resolving_client_socket_factory.cc
+++ b/chromium/services/network/proxy_resolving_client_socket_factory.cc
@@ -76,6 +76,7 @@ ProxyResolvingClientSocketFactory::~ProxyResolvingClientSocketFactory() {}
std::unique_ptr<ProxyResolvingClientSocket>
ProxyResolvingClientSocketFactory::CreateSocket(
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
bool use_tls) {
// |request_context|'s HttpAuthCache might have updates. For example, a user
// might have since entered proxy credentials. Clear the http auth of
@@ -96,7 +97,8 @@ ProxyResolvingClientSocketFactory::CreateSocket(
->http_auth_cache();
network_session_->http_auth_cache()->CopyProxyEntriesFrom(*other_auth_cache);
return std::make_unique<ProxyResolvingClientSocket>(
- network_session_.get(), common_connect_job_params_.get(), url, use_tls);
+ network_session_.get(), common_connect_job_params_.get(), url,
+ network_isolation_key, use_tls);
}
} // namespace network
diff --git a/chromium/services/network/proxy_resolving_client_socket_factory.h b/chromium/services/network/proxy_resolving_client_socket_factory.h
index 9192d57ea15..01410d980d9 100644
--- a/chromium/services/network/proxy_resolving_client_socket_factory.h
+++ b/chromium/services/network/proxy_resolving_client_socket_factory.h
@@ -16,6 +16,7 @@
namespace net {
struct CommonConnectJobParams;
class HttpNetworkSession;
+class NetworkIsolationKey;
class URLRequestContext;
} // namespace net
@@ -37,11 +38,20 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingClientSocketFactory {
// doesn't need to explicitly sanitize the url, any sensitive data (like
// embedded usernames and passwords), and local data (i.e. reference fragment)
// will be sanitized by net::ProxyService::ResolveProxyHelper() before the url
- // is disclosed to the proxy. If |use_tls|, TLS connect will be used in
- // addition to TCP connect. The URLRequestContext's SSL configurations will be
- // respected when establishing a TLS connection.
- std::unique_ptr<ProxyResolvingClientSocket> CreateSocket(const GURL& url,
- bool use_tls);
+ // is disclosed to the proxy.
+ //
+ // |network_isolation_key| indicates the network shard to use for storing
+ // shared network state (DNS cache entries, shared H2/QUIC proxy connections,
+ // etc). Proxy connections will only be shared with other
+ // ProxyResolvingClientSockets, not with standards HTTP/HTTPS requests.
+ //
+ // If |use_tls| is true, TLS connect will be used in addition to TCP connect.
+ // The URLRequestContext's SSL configurations will be respected when
+ // establishing a TLS connection.
+ std::unique_ptr<ProxyResolvingClientSocket> CreateSocket(
+ const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
+ bool use_tls);
const net::HttpNetworkSession* network_session() const {
return network_session_.get();
diff --git a/chromium/services/network/proxy_resolving_client_socket_unittest.cc b/chromium/services/network/proxy_resolving_client_socket_unittest.cc
index 84a404f336a..c9941339291 100644
--- a/chromium/services/network/proxy_resolving_client_socket_unittest.cc
+++ b/chromium/services/network/proxy_resolving_client_socket_unittest.cc
@@ -13,17 +13,21 @@
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "net/base/features.h"
#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/http/http_proxy_connect_job.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/proxy_resolution/mock_proxy_resolver.h"
#include "net/proxy_resolution/proxy_config_service_fixed.h"
#include "net/proxy_resolution/proxy_config_with_annotation.h"
#include "net/socket/client_socket_pool_manager.h"
#include "net/socket/socket_test_util.h"
+#include "net/spdy/spdy_test_util_common.h"
#include "net/test/gtest_util.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_test_util.h"
@@ -44,7 +48,7 @@ class TestURLRequestContextWithProxy : public net::TestURLRequestContext {
net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
pac_result, TRAFFIC_ANNOTATION_FOR_TESTS));
// net::MockHostResolver maps all hosts to localhost.
- auto host_resolver = std::make_unique<net::MockHostResolver>();
+ auto host_resolver = std::make_unique<net::MockCachingHostResolver>();
context_storage_.set_host_resolver(std::move(host_resolver));
set_client_socket_factory(client_socket_factory);
Init();
@@ -61,7 +65,14 @@ class ProxyResolvingClientSocketTest
ProxyResolvingClientSocketTest()
: context_with_proxy_("PROXY bad:99; PROXY maybe:80; DIRECT",
&mock_client_socket_factory_),
- use_tls_(GetParam()) {}
+ use_tls_(GetParam()) {
+ feature_list_.InitWithFeatures(
+ // enabled_features
+ {net::features::kPartitionConnectionsByNetworkIsolationKey,
+ net::features::kSplitHostCacheByNetworkIsolationKey},
+ // disabled_features
+ {});
+ }
~ProxyResolvingClientSocketTest() override {}
@@ -72,6 +83,7 @@ class ProxyResolvingClientSocketTest
}
base::test::TaskEnvironment task_environment_;
+ base::test::ScopedFeatureList feature_list_;
TestURLRequestContextWithProxy context_with_proxy_;
net::MockClientSocketFactory mock_client_socket_factory_;
const bool use_tls_;
@@ -81,6 +93,183 @@ INSTANTIATE_TEST_SUITE_P(All,
ProxyResolvingClientSocketTest,
::testing::Bool());
+// Checks the correct NetworkIsolationKey is used for host resolution in the
+// case no proxy is in use.
+TEST_P(ProxyResolvingClientSocketTest, NetworkIsolationKeyDirect) {
+ // This deliberately uses a different origin than the one being connected to.
+ url::Origin kNetworkIsolationKeyOrigin =
+ url::Origin::Create(GURL("https://foopy.test"));
+ net::NetworkIsolationKey kNetworkIsolationKey(
+ kNetworkIsolationKeyOrigin /* top_frame_origin */,
+ kNetworkIsolationKeyOrigin /* frame_origin */);
+
+ TestURLRequestContextWithProxy url_request_context(
+ "DIRECT", &mock_client_socket_factory_);
+ const GURL kDestination("https://dest.test/");
+ net::StaticSocketDataProvider socket_data;
+ mock_client_socket_factory_.AddSocketDataProvider(&socket_data);
+ net::SSLSocketDataProvider ssl_data(net::ASYNC, net::OK);
+ mock_client_socket_factory_.AddSSLSocketDataProvider(&ssl_data);
+
+ ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
+ &url_request_context);
+ std::unique_ptr<ProxyResolvingClientSocket> socket =
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, kNetworkIsolationKey, use_tls_);
+ net::TestCompletionCallback callback;
+ int status = socket->Connect(callback.callback());
+ EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
+
+ // Check that the URL in kDestination is in the HostCache, with
+ // kNetworkIsolationInfo.
+ const net::HostPortPair kDestinationHostPortPair =
+ net::HostPortPair::FromURL(kDestination);
+ net::HostResolver::ResolveHostParameters params;
+ params.source = net::HostResolverSource::LOCAL_ONLY;
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request1 =
+ url_request_context.host_resolver()->CreateRequest(
+ kDestinationHostPortPair, kNetworkIsolationKey,
+ net::NetLogWithSource(), params);
+ net::TestCompletionCallback callback2;
+ int result = request1->Start(callback2.callback());
+ EXPECT_EQ(net::OK, callback2.GetResult(result));
+
+ // Check that the hostname is not in the DNS cache for other possible NIKs.
+ const url::Origin kDestinationOrigin = url::Origin::Create(kDestination);
+ const net::NetworkIsolationKey kOtherNiks[] = {
+ net::NetworkIsolationKey(),
+ net::NetworkIsolationKey(kDestinationOrigin /* top_frame_origin */,
+ kDestinationOrigin /* frame_origin */)};
+ for (const auto& other_nik : kOtherNiks) {
+ std::unique_ptr<net::HostResolver::ResolveHostRequest> request2 =
+ url_request_context.host_resolver()->CreateRequest(
+ kDestinationHostPortPair, other_nik, net::NetLogWithSource(),
+ params);
+ net::TestCompletionCallback callback3;
+ int result = request2->Start(callback3.callback());
+ EXPECT_EQ(net::ERR_NAME_NOT_RESOLVED, callback3.GetResult(result));
+ }
+}
+
+// Checks the correct NetworkIsolationKey is used for host resolution in the
+// case an H2 proxy is in use. In the non-H2 proxy case, the NetworkIsolationKey
+// makes little difference, but in the H2 case, it affects which requests use
+// the same session. Unlike other tests, this test creates a
+// ProxyResolvingClientSocket instead of using the factory class, because it
+// uses SpdySessionDependencies to create a NetworkSession configured to test
+// H2.
+TEST_P(ProxyResolvingClientSocketTest, NetworkIsolationKeyWithH2Proxy) {
+ // Don't bother running this test in the SSL case - it's complicated enough
+ // without it, and testing HTTPS on top of H2 provides minimal value, since
+ // SSL is mocked out anyways and there are other tests that cover it on top of
+ // HTTP/1.x tunnels.
+ if (GetParam() == true)
+ return;
+ net::SpdySessionDependencies session_deps;
+ session_deps.proxy_resolution_service =
+ net::ConfiguredProxyResolutionService::CreateFixedFromPacResult(
+ "HTTPS proxy.test:80", TRAFFIC_ANNOTATION_FOR_TESTS);
+ std::unique_ptr<net::HttpNetworkSession> http_network_session =
+ net::SpdySessionDependencies::SpdyCreateSession(&session_deps);
+
+ net::NetworkIsolationKey kNetworkIsolationKey1 =
+ net::NetworkIsolationKey::CreateTransient();
+ net::NetworkIsolationKey kNetworkIsolationKey2 =
+ net::NetworkIsolationKey::CreateTransient();
+
+ const GURL kDestination1("https://dest1.test/");
+ const GURL kDestination2("https://dest2.test/");
+ const GURL kDestination3("https://dest3.test/");
+
+ // A tunnel to kDestination1 and kDestination3 is requested using
+ // kNetworkIsolationKey1, so they should use the same H2 session, and a tunnel
+ // to kDestination2 is requested using kNetworkIsolationKey2, which should use
+ // a different session.
+ net::SpdyTestUtil spdy_util1;
+ spdy::SpdySerializedFrame connect_dest1(spdy_util1.ConstructSpdyConnect(
+ nullptr, 0, 1, net::HttpProxyConnectJob::kH2QuicTunnelPriority,
+ net::HostPortPair::FromURL(kDestination1)));
+ spdy::SpdySerializedFrame connect_dest1_resp(
+ spdy_util1.ConstructSpdyGetReply(nullptr, 0, 1));
+ spdy::SpdySerializedFrame connect_dest3(spdy_util1.ConstructSpdyConnect(
+ nullptr, 0, 3, net::HttpProxyConnectJob::kH2QuicTunnelPriority,
+ net::HostPortPair::FromURL(kDestination3)));
+ spdy::SpdySerializedFrame connect_dest3_resp(
+ spdy_util1.ConstructSpdyGetReply(nullptr, 0, 3));
+
+ net::MockWrite spdy_writes[] = {
+ net::CreateMockWrite(connect_dest1, 0),
+ net::CreateMockWrite(connect_dest3, 2),
+ };
+
+ net::MockRead spdy_reads[] = {
+ net::CreateMockRead(connect_dest1_resp, 1, net::ASYNC),
+ net::CreateMockRead(connect_dest3_resp, 3, net::ASYNC),
+ net::MockRead(net::SYNCHRONOUS, 0, 4),
+ };
+
+ net::SequencedSocketData socket_data(spdy_reads, spdy_writes);
+ session_deps.socket_factory->AddSocketDataProvider(&socket_data);
+ net::SSLSocketDataProvider ssl_data(net::ASYNC, net::OK);
+ ssl_data.next_proto = net::kProtoHTTP2;
+ session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_data);
+
+ net::SpdyTestUtil spdy_util2;
+ spdy::SpdySerializedFrame connect_dest2(spdy_util2.ConstructSpdyConnect(
+ nullptr, 0, 1, net::HttpProxyConnectJob::kH2QuicTunnelPriority,
+ net::HostPortPair::FromURL(kDestination2)));
+ spdy::SpdySerializedFrame connect_dest2_resp(
+ spdy_util2.ConstructSpdyGetReply(nullptr, 0, 1));
+
+ net::MockWrite spdy_writes2[] = {
+ net::CreateMockWrite(connect_dest2, 0),
+ };
+
+ net::MockRead spdy_reads2[] = {
+ net::CreateMockRead(connect_dest2_resp, 1, net::ASYNC),
+ net::MockRead(net::SYNCHRONOUS, 0, 2),
+ };
+
+ net::SequencedSocketData socket_data2(spdy_reads2, spdy_writes2);
+ session_deps.socket_factory->AddSocketDataProvider(&socket_data2);
+ net::SSLSocketDataProvider ssl_data2(net::ASYNC, net::OK);
+ ssl_data2.next_proto = net::kProtoHTTP2;
+ session_deps.socket_factory->AddSSLSocketDataProvider(&ssl_data2);
+
+ // Connect to kDestination1 using kNetworkIsolationKey1. It should use a new
+ // H2 session.
+ net::CommonConnectJobParams common_connect_job_params =
+ http_network_session->CreateCommonConnectJobParams();
+ ProxyResolvingClientSocket socket1(
+ http_network_session.get(), &common_connect_job_params, kDestination1,
+ kNetworkIsolationKey1, false /* use_tls */);
+ net::TestCompletionCallback callback1;
+ int result = socket1.Connect(callback1.callback());
+ EXPECT_THAT(callback1.GetResult(result), net::test::IsOk());
+
+ // Connect to kDestination2 using kNetworkIsolationKey2. It should use a new
+ // H2 session.
+ ProxyResolvingClientSocket socket2(
+ http_network_session.get(), &common_connect_job_params, kDestination2,
+ kNetworkIsolationKey2, false /* use_tls */);
+ net::TestCompletionCallback callback2;
+ result = socket2.Connect(callback2.callback());
+ EXPECT_THAT(callback2.GetResult(result), net::test::IsOk());
+ EXPECT_TRUE(socket_data2.AllWriteDataConsumed());
+ EXPECT_TRUE(socket_data2.AllReadDataConsumed());
+
+ // Connect to kDestination3 using kNetworkIsolationKey1. It should reuse the
+ // first H2 session.
+ ProxyResolvingClientSocket socket3(
+ http_network_session.get(), &common_connect_job_params, kDestination3,
+ kNetworkIsolationKey1, false /* use_tls */);
+ net::TestCompletionCallback callback3;
+ result = socket3.Connect(callback3.callback());
+ EXPECT_THAT(callback3.GetResult(result), net::test::IsOk());
+ EXPECT_TRUE(socket_data.AllWriteDataConsumed());
+ EXPECT_TRUE(socket_data.AllReadDataConsumed());
+}
+
// Tests that the global socket pool limit
// (ClientSocketPoolManager::max_sockets_per_group) doesn't apply to this
// type of sockets.
@@ -112,7 +301,8 @@ TEST_P(ProxyResolvingClientSocketTest, SocketLimitNotApply) {
std::vector<std::unique_ptr<ProxyResolvingClientSocket>> sockets;
for (int i = 0; i < kNumSockets; ++i) {
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
@@ -153,7 +343,8 @@ TEST_P(ProxyResolvingClientSocketTest, ConnectError) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -203,7 +394,8 @@ TEST_P(ProxyResolvingClientSocketTest, ConnectToProxy) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -238,7 +430,8 @@ TEST_P(ProxyResolvingClientSocketTest, SocketDestroyedBeforeConnectComplete) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -305,7 +498,8 @@ TEST_P(ProxyResolvingClientSocketTest, ReadWriteErrors) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -369,7 +563,8 @@ TEST_P(ProxyResolvingClientSocketTest, ReportsBadProxies) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -405,7 +600,8 @@ TEST_P(ProxyResolvingClientSocketTest, ResetSocketAfterTunnelAuth) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_THAT(callback.GetResult(status),
@@ -483,7 +679,8 @@ TEST_P(ProxyResolvingClientSocketTest, MultiroundAuth) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
@@ -540,7 +737,8 @@ TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Lookup) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
@@ -598,7 +796,8 @@ TEST_P(ProxyResolvingClientSocketTest, FactoryUsesLatestHTTPAuthCache) {
mock_client_socket_factory_.AddSSLSocketDataProvider(&ssl_socket);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_THAT(callback.GetResult(status), net::test::IsOk());
@@ -638,7 +837,8 @@ TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_Preemptive) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
@@ -666,7 +866,8 @@ TEST_P(ProxyResolvingClientSocketTest, ReusesHTTPAuthCache_NoCredentials) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
@@ -698,7 +899,8 @@ TEST_P(ProxyResolvingClientSocketTest, URLSanitized) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(url, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ url, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
@@ -742,7 +944,8 @@ TEST_P(ProxyResolvingClientSocketTest,
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(url, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ url, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
EXPECT_EQ(net::ERR_IO_PENDING, socket->Connect(callback.callback()));
socket.reset();
@@ -776,7 +979,8 @@ TEST_P(ProxyResolvingClientSocketTest, NoSupportedProxies) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
context.get());
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
status = callback.GetResult(status);
@@ -868,7 +1072,8 @@ TEST_P(ReconsiderProxyAfterErrorTest, ReconsiderProxyAfterError) {
ProxyResolvingClientSocketFactory proxy_resolving_socket_factory(
&context_with_proxy_);
std::unique_ptr<ProxyResolvingClientSocket> socket =
- proxy_resolving_socket_factory.CreateSocket(kDestination, use_tls_);
+ proxy_resolving_socket_factory.CreateSocket(
+ kDestination, net::NetworkIsolationKey(), use_tls_);
net::TestCompletionCallback callback;
int status = socket->Connect(callback.callback());
EXPECT_EQ(net::ERR_IO_PENDING, status);
diff --git a/chromium/services/network/proxy_resolving_socket_factory_mojo.cc b/chromium/services/network/proxy_resolving_socket_factory_mojo.cc
index 2d673a7115d..059a4886374 100644
--- a/chromium/services/network/proxy_resolving_socket_factory_mojo.cc
+++ b/chromium/services/network/proxy_resolving_socket_factory_mojo.cc
@@ -25,13 +25,14 @@ ProxyResolvingSocketFactoryMojo::~ProxyResolvingSocketFactoryMojo() {}
void ProxyResolvingSocketFactoryMojo::CreateProxyResolvingSocket(
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
mojom::ProxyResolvingSocketOptionsPtr options,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingReceiver<mojom::ProxyResolvingSocket> receiver,
mojo::PendingRemote<mojom::SocketObserver> observer,
CreateProxyResolvingSocketCallback callback) {
- std::unique_ptr<net::StreamSocket> net_socket =
- factory_impl_.CreateSocket(url, options && options->use_tls);
+ std::unique_ptr<net::StreamSocket> net_socket = factory_impl_.CreateSocket(
+ url, network_isolation_key, options && options->use_tls);
if (options && options->fake_tls_handshake) {
DCHECK(!options->use_tls);
net_socket = std::make_unique<jingle_glue::FakeSSLClientSocket>(
diff --git a/chromium/services/network/proxy_resolving_socket_factory_mojo.h b/chromium/services/network/proxy_resolving_socket_factory_mojo.h
index b32c0824cb1..f7c8d5b3db5 100644
--- a/chromium/services/network/proxy_resolving_socket_factory_mojo.h
+++ b/chromium/services/network/proxy_resolving_socket_factory_mojo.h
@@ -19,6 +19,7 @@
#include "services/network/tls_socket_factory.h"
namespace net {
+class NetworkIsolationKey;
class URLRequestContext;
} // namespace net
@@ -33,6 +34,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ProxyResolvingSocketFactoryMojo
// mojom::ProxyResolvingSocketFactory implementation.
void CreateProxyResolvingSocket(
const GURL& url,
+ const net::NetworkIsolationKey& network_isolation_key,
mojom::ProxyResolvingSocketOptionsPtr options,
const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingReceiver<mojom::ProxyResolvingSocket> receiver,
diff --git a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
index 1a2b199963a..f840843a062 100644
--- a/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
+++ b/chromium/services/network/proxy_resolving_socket_mojo_unittest.cc
@@ -18,6 +18,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_utils.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/proxy_resolution/configured_proxy_resolution_service.h"
@@ -122,7 +123,7 @@ class ProxyResolvingSocketTestBase {
options->use_tls = use_tls_;
options->fake_tls_handshake = fake_tls_handshake_;
factory_remote_->CreateProxyResolvingSocket(
- url, std::move(options),
+ url, net::NetworkIsolationKey(), std::move(options),
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
std::move(receiver), std::move(socket_observer),
base::BindLambdaForTesting(
@@ -401,7 +402,7 @@ TEST_F(ProxyResolvingSocketMojoTest, SocketDestroyedBeforeConnectCompletes) {
base::RunLoop run_loop;
int net_error = net::OK;
factory()->CreateProxyResolvingSocket(
- kDestination, nullptr,
+ kDestination, net::NetworkIsolationKey(), nullptr,
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
socket.InitWithNewPipeAndPassReceiver(),
mojo::NullRemote() /* observer */,
diff --git a/chromium/services/network/public/cpp/BUILD.gn b/chromium/services/network/public/cpp/BUILD.gn
index 6d0de4d137f..8447695610e 100644
--- a/chromium/services/network/public/cpp/BUILD.gn
+++ b/chromium/services/network/public/cpp/BUILD.gn
@@ -13,6 +13,15 @@ buildflag_header("buildflags") {
flags = [ "IS_CT_SUPPORTED=$is_ct_supported" ]
}
+jumbo_component("crash_keys") {
+ sources = [
+ "crash_keys.cc",
+ "crash_keys.h",
+ ]
+ deps = [ "//base" ]
+ defines = [ "IS_NETWORK_CPP_CRASH_KEYS_IMPL" ]
+}
+
jumbo_component("cpp") {
output_name = "network_cpp"
@@ -49,6 +58,8 @@ jumbo_component("cpp") {
"cross_thread_pending_shared_url_loader_factory.h",
"data_pipe_to_source_stream.cc",
"data_pipe_to_source_stream.h",
+ "empty_url_loader_client.cc",
+ "empty_url_loader_client.h",
"features.cc",
"features.h",
"header_util.cc",
@@ -67,6 +78,8 @@ jumbo_component("cpp") {
"network_quality_tracker.h",
"network_switches.cc",
"network_switches.h",
+ "origin_isolation_parser.cc",
+ "origin_isolation_parser.h",
"parsed_headers.cc",
"parsed_headers.h",
"request_destination.cc",
@@ -82,6 +95,9 @@ jumbo_component("cpp") {
"simple_url_loader_stream_consumer.h",
"source_stream_to_data_pipe.cc",
"source_stream_to_data_pipe.h",
+ "spki_hash_set.cc",
+ "spki_hash_set.h",
+ "trust_token_operation_authorization.h",
"weak_wrapper_shared_url_loader_factory.cc",
"weak_wrapper_shared_url_loader_factory.h",
"web_sandbox_flags.cc",
@@ -151,6 +167,7 @@ component("cookies_mojom_support") {
"site_for_cookies_mojom_traits.h",
]
deps = [
+ ":crash_keys",
"//net",
"//services/network/public/mojom:cookies_mojom_shared",
]
@@ -202,10 +219,13 @@ jumbo_component("cpp_base") {
"proxy_config_mojom_traits.h",
"proxy_config_with_annotation_mojom_traits.cc",
"proxy_config_with_annotation_mojom_traits.h",
+ "quic_transport_error_mojom_traits.cc",
+ "quic_transport_error_mojom_traits.h",
"resource_request.cc",
"resource_request.h",
"resource_request_body.cc",
"resource_request_body.h",
+ "trust_token_parameterization.h",
"url_loader_completion_status.cc",
"url_loader_completion_status.h",
"url_request_mojom_traits.cc",
@@ -225,6 +245,7 @@ jumbo_component("cpp_base") {
public_deps = [
":cookies_mojom_support",
+ ":crash_keys",
":ip_address_mojom_support",
"//services/network/public/mojom:data_pipe_interfaces",
"//services/network/public/mojom:mutable_network_traffic_annotation_interface",
@@ -258,6 +279,7 @@ source_set("tests") {
"content_security_policy/content_security_policy_unittest.cc",
"content_security_policy/csp_context_unittest.cc",
"content_security_policy/csp_source_list_unittest.cc",
+ "content_security_policy/csp_source_unittest.cc",
"cookie_manager_mojom_traits_unittest.cc",
"cors/cors_unittest.cc",
"cors/origin_access_entry_unittest.cc",
@@ -285,6 +307,7 @@ source_set("tests") {
"network_mojom_traits_unittest.cc",
"network_quality_tracker_unittest.cc",
"optional_trust_token_params_unittest.cc",
+ "origin_isolation_parser_unittest.cc",
"proxy_config_mojom_traits_unittest.cc",
"simple_url_loader_unittest.cc",
"site_for_cookies_mojom_traits_unittest.cc",
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
index c7ff782ff6e..8c82aad1bd6 100644
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.cc
@@ -34,8 +34,12 @@ bool StructTraits<cert_verifier::mojom::CertVerifierConfigDataView,
net::CertVerifier::Config* config) {
mojo_base::BigBuffer crl_set_buffer;
std::vector<scoped_refptr<net::X509Certificate>> additional_trust_anchors;
+ std::vector<scoped_refptr<net::X509Certificate>>
+ additional_untrusted_authorities;
if (!data.ReadCrlSet(&crl_set_buffer) ||
- !data.ReadAdditionalTrustAnchors(&additional_trust_anchors))
+ !data.ReadAdditionalTrustAnchors(&additional_trust_anchors) ||
+ !data.ReadAdditionalUntrustedAuthorities(
+ &additional_untrusted_authorities))
return false;
scoped_refptr<net::CRLSet> crl_set;
@@ -54,6 +58,8 @@ bool StructTraits<cert_verifier::mojom::CertVerifierConfigDataView,
config->disable_symantec_enforcement = data.disable_symantec_enforcement();
config->crl_set = std::move(crl_set);
config->additional_trust_anchors = std::move(additional_trust_anchors);
+ config->additional_untrusted_authorities =
+ std::move(additional_untrusted_authorities);
return true;
}
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
index 9615febd651..a5102ce9f4b 100644
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
+++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits.h
@@ -71,6 +71,10 @@ struct StructTraits<cert_verifier::mojom::CertVerifierConfigDataView,
additional_trust_anchors(const net::CertVerifier::Config& config) {
return config.additional_trust_anchors;
}
+ static const std::vector<scoped_refptr<net::X509Certificate>>&
+ additional_untrusted_authorities(const net::CertVerifier::Config& config) {
+ return config.additional_untrusted_authorities;
+ }
static bool Read(cert_verifier::mojom::CertVerifierConfigDataView data,
net::CertVerifier::Config* config);
diff --git a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
index 99c0a5490a0..3388e84eb7a 100644
--- a/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/cert_verifier_mojom_traits_unittest.cc
@@ -101,6 +101,10 @@ bool ConfigsEqual(const net::CertVerifier::Config& config1,
config2.additional_trust_anchors))
return false;
+ if (!CertificateListsEqual(config1.additional_untrusted_authorities,
+ config2.additional_untrusted_authorities))
+ return false;
+
return true;
}
} // namespace
@@ -128,7 +132,7 @@ TEST(CertVerifierMojomTraitsTest, ConfigTrue) {
ASSERT_TRUE(ConfigsEqual(config, out_config));
}
-TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAnchors) {
+TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAdditionalCerts) {
std::string crl_set;
{
@@ -147,6 +151,9 @@ TEST(CertVerifierMojomTraitsTest, ConfigCRLAndAnchors) {
config.additional_trust_anchors.push_back(
net::ImportCertFromFile(certs_dir, "aia-root.pem"));
+ config.additional_untrusted_authorities.push_back(
+ net::ImportCertFromFile(certs_dir, "aia-intermediate.der"));
+
net::CertVerifier::Config out_config;
ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CertVerifierConfig>(
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
index d9f14efddb6..767d136b405 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.cc
@@ -3,6 +3,9 @@
// found in the LICENSE file.
#include "services/network/public/cpp/cert_verifier/mojo_cert_verifier.h"
+
+#include <memory>
+
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "net/base/net_errors.h"
@@ -62,9 +65,44 @@ class CertVerifierRequestImpl : public mojom::CertVerifierRequest,
};
} // namespace
+class MojoCertVerifier::MojoReconnector
+ : public mojom::URLLoaderFactoryConnector {
+ public:
+ MojoReconnector(
+ mojo::PendingReceiver<mojom::URLLoaderFactoryConnector> receiver,
+ base::RepeatingCallback<void(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>)> reconnector)
+ : receiver_(this, std::move(receiver)),
+ reconnector_(std::move(reconnector)) {}
+
+ // mojom::URLLoaderFactoryConnector implementation:
+ void CreateURLLoaderFactory(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+ url_loader_factory) override {
+ reconnector_.Run(std::move(url_loader_factory));
+ }
+
+ private:
+ mojo::Receiver<mojom::URLLoaderFactoryConnector> receiver_;
+ base::RepeatingCallback<void(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>
+ reconnector_;
+};
+
MojoCertVerifier::MojoCertVerifier(
- mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier)
- : mojo_cert_verifier_(std::move(mojo_cert_verifier)) {}
+ mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
+ base::RepeatingCallback<void(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>)> reconnector)
+ : mojo_cert_verifier_(std::move(mojo_cert_verifier)) {
+ mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector_remote;
+
+ reconnector_ = std::make_unique<MojoReconnector>(
+ reconnector_remote.InitWithNewPipeAndPassReceiver(),
+ std::move(reconnector));
+ mojo_cert_verifier_->EnableNetworkAccess(std::move(url_loader_factory),
+ std::move(reconnector_remote));
+}
MojoCertVerifier::~MojoCertVerifier() = default;
@@ -90,4 +128,8 @@ int MojoCertVerifier::Verify(
void MojoCertVerifier::SetConfig(const net::CertVerifier::Config& config) {
mojo_cert_verifier_->SetConfig(config);
}
+
+void MojoCertVerifier::FlushForTesting() {
+ mojo_cert_verifier_.FlushForTesting();
+}
} // namespace cert_verifier
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.h b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.h
index d61b9d04063..b51f2f6558a 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.h
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier.h
@@ -5,6 +5,8 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_MOJO_CERT_VERIFIER_H_
#define SERVICES_NETWORK_PUBLIC_CPP_CERT_VERIFIER_MOJO_CERT_VERIFIER_H_
+#include "base/callback_forward.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_export.h"
@@ -12,6 +14,7 @@
#include "net/cert/cert_verify_result.h"
#include "net/log/net_log_with_source.h"
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
+#include "services/network/public/mojom/network_context.mojom.h"
namespace cert_verifier {
@@ -19,8 +22,16 @@ namespace cert_verifier {
// verify certificates.
class MojoCertVerifier : public net::CertVerifier {
public:
- explicit MojoCertVerifier(
- mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier);
+ using ReconnectURLLoaderFactory = base::RepeatingCallback<void(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory>)>;
+
+ // The remote CertNetFetcher will use |url_loader_factory| for fetches. If
+ // |url_loader_factory| disconnects it will use |reconnector| to try to
+ // connect a new URLLoaderFactory.
+ MojoCertVerifier(
+ mojo::PendingRemote<mojom::CertVerifierService> mojo_cert_verifier,
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory,
+ ReconnectURLLoaderFactory reconnector);
~MojoCertVerifier() override;
// net::CertVerifier implementation:
@@ -31,8 +42,14 @@ class MojoCertVerifier : public net::CertVerifier {
const net::NetLogWithSource& net_log) override;
void SetConfig(const net::CertVerifier::Config& config) override;
+ // Flushes the underlying Mojo pipe.
+ void FlushForTesting();
+
private:
+ class MojoReconnector;
+
mojo::Remote<mojom::CertVerifierService> mojo_cert_verifier_;
+ std::unique_ptr<MojoReconnector> reconnector_;
};
} // namespace cert_verifier
diff --git a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
index a6b00cb61a6..d43349ff7bb 100644
--- a/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/mojo_cert_verifier_unittest.cc
@@ -7,9 +7,11 @@
#include <map>
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/run_loop.h"
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "net/base/test_completion_callback.h"
#include "net/cert/cert_status_flags.h"
#include "net/cert/cert_verifier.h"
@@ -36,12 +38,27 @@ net::CertVerifier::RequestParams GetDummyParams() {
/*sct_list=*/std::string());
}
+mojo::PendingRemote<network::mojom::URLLoaderFactory>
+CreateUnconnectedURLLoaderFactory() {
+ mojo::PendingRemote<network::mojom::URLLoaderFactory> url_loader_factory;
+ // Bind the factory, but don't bother connecting it.
+ ignore_result(url_loader_factory.InitWithNewPipeAndPassReceiver());
+ return url_loader_factory;
+}
+
class MojoCertVerifierTest : public PlatformTest {
public:
MojoCertVerifierTest()
: dummy_cv_service_(this),
cv_service_receiver_(&dummy_cv_service_),
- mojo_cert_verifier_(cv_service_receiver_.BindNewPipeAndPassRemote()) {}
+ mojo_cert_verifier_(
+ cv_service_receiver_.BindNewPipeAndPassRemote(),
+ CreateUnconnectedURLLoaderFactory(),
+ base::BindRepeating(&MojoCertVerifierTest::ReconnectCb,
+ base::Unretained(this))) {
+ // Any Mojo requests in the MojoCertVerifier constructor should run here.
+ mojo_cert_verifier_.FlushForTesting();
+ }
class DummyCVService final : public mojom::CertVerifierService {
public:
@@ -57,12 +74,24 @@ class MojoCertVerifierTest : public PlatformTest {
config_ = config;
}
+ void EnableNetworkAccess(
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>
+ url_loader_factory,
+ mojo::PendingRemote<mojom::URLLoaderFactoryConnector> reconnector)
+ override {
+ reconnector_.Bind(std::move(reconnector));
+ }
+
const net::CertVerifier::Config* config() const { return &config_; }
+ mojom::URLLoaderFactoryConnector* reconnector() {
+ return reconnector_.get();
+ }
private:
MojoCertVerifierTest* test_;
net::CertVerifier::Config config_;
+ mojo::Remote<mojom::URLLoaderFactoryConnector> reconnector_;
};
base::test::TaskEnvironment* task_environment() { return &task_environment_; }
@@ -97,6 +126,16 @@ class MojoCertVerifierTest : public PlatformTest {
void SimulateCVServiceDisconnect() { cv_service_receiver_.reset(); }
+ void ReconnectCb(mojo::PendingReceiver<network::mojom::URLLoaderFactory>
+ mojo_cert_verifier) {
+ if (reconnect_cb_)
+ reconnect_cb_.Run(std::move(mojo_cert_verifier));
+ }
+
+ void SetReconnectCb(MojoCertVerifier::ReconnectURLLoaderFactory cb) {
+ reconnect_cb_ = std::move(cb);
+ }
+
private:
std::map<net::CertVerifier::RequestParams,
mojo::Remote<mojom::CertVerifierRequest>>
@@ -109,6 +148,8 @@ class MojoCertVerifierTest : public PlatformTest {
MojoCertVerifier mojo_cert_verifier_;
+ MojoCertVerifier::ReconnectURLLoaderFactory reconnect_cb_;
+
net::NetLogWithSource empty_net_log_with_source_;
};
} // namespace
@@ -244,4 +285,22 @@ TEST_F(MojoCertVerifierTest, SendsConfig) {
ASSERT_TRUE(dummy_cv_service()->config()->disable_symantec_enforcement);
}
+TEST_F(MojoCertVerifierTest, ReconnectorCallsCb) {
+ base::RunLoop run_loop;
+ SetReconnectCb(base::BindLambdaForTesting(
+ [&](mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
+ run_loop.Quit();
+ }));
+
+ mojo::PendingRemote<network::mojom::URLLoaderFactory>
+ dummy_url_loader_factory_remote;
+ // Simulate a remote CertVerifierService trying to reconnect after
+ // disconnection. This should call the callback given to the MojoCertVerifier
+ // on construction.
+ dummy_cv_service()->reconnector()->CreateURLLoaderFactory(
+ dummy_url_loader_factory_remote.InitWithNewPipeAndPassReceiver());
+
+ run_loop.Run();
+}
+
} // namespace cert_verifier
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
index bd427654cbf..6ae235de565 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc
@@ -35,6 +35,13 @@ static CSPDirectiveName CSPFallback(CSPDirectiveName directive) {
case CSPDirectiveName::FormAction:
case CSPDirectiveName::NavigateTo:
case CSPDirectiveName::FrameAncestors:
+ case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::MediaSrc:
+ case CSPDirectiveName::ObjectSrc:
+ case CSPDirectiveName::ScriptSrc:
+ case CSPDirectiveName::StyleSrc:
+ case CSPDirectiveName::WorkerSrc:
+ case CSPDirectiveName::ConnectSrc:
return CSPDirectiveName::Unknown;
case CSPDirectiveName::FrameSrc:
@@ -78,6 +85,13 @@ const char* ErrorMessage(CSPDirectiveName directive) {
case CSPDirectiveName::ChildSrc:
case CSPDirectiveName::DefaultSrc:
case CSPDirectiveName::Unknown:
+ case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::MediaSrc:
+ case CSPDirectiveName::ObjectSrc:
+ case CSPDirectiveName::ScriptSrc:
+ case CSPDirectiveName::StyleSrc:
+ case CSPDirectiveName::WorkerSrc:
+ case CSPDirectiveName::ConnectSrc:
NOTREACHED();
return nullptr;
};
@@ -614,6 +628,20 @@ CSPDirectiveName ToCSPDirectiveName(const std::string& name) {
return CSPDirectiveName::NavigateTo;
if (name == "frame-ancestors")
return CSPDirectiveName::FrameAncestors;
+ if (name == "img-src")
+ return CSPDirectiveName::ImgSrc;
+ if (name == "media-src")
+ return CSPDirectiveName::MediaSrc;
+ if (name == "object-src")
+ return CSPDirectiveName::ObjectSrc;
+ if (name == "script-src")
+ return CSPDirectiveName::ScriptSrc;
+ if (name == "style-src")
+ return CSPDirectiveName::StyleSrc;
+ if (name == "worker-src")
+ return CSPDirectiveName::WorkerSrc;
+ if (name == "connect-src")
+ return CSPDirectiveName::ConnectSrc;
return CSPDirectiveName::Unknown;
}
@@ -631,6 +659,20 @@ std::string ToString(CSPDirectiveName name) {
return "navigate-to";
case CSPDirectiveName::FrameAncestors:
return "frame-ancestors";
+ case CSPDirectiveName::ImgSrc:
+ return "img-src";
+ case CSPDirectiveName::MediaSrc:
+ return "media-src";
+ case CSPDirectiveName::ObjectSrc:
+ return "object-src";
+ case CSPDirectiveName::ScriptSrc:
+ return "script-src";
+ case CSPDirectiveName::StyleSrc:
+ return "style-src";
+ case CSPDirectiveName::WorkerSrc:
+ return "worker-src";
+ case CSPDirectiveName::ConnectSrc:
+ return "connect-src";
case CSPDirectiveName::Unknown:
return "";
}
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
index 693f7952bcc..903aa5a2a25 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/network/content_security_policy/csp_source.h"
-#include "services/network/content_security_policy/csp_context.h"
+#include "services/network/public/cpp/content_security_policy/csp_source.h"
+#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "url/origin.h"
-namespace content {
+namespace network {
namespace {
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
index d973efffce1..d4897d169e5 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -81,6 +81,48 @@ bool EnumTraits<network::mojom::CookieSameSite, net::CookieSameSite>::FromMojom(
return false;
}
+network::mojom::CookieEffectiveSameSite EnumTraits<
+ network::mojom::CookieEffectiveSameSite,
+ net::CookieEffectiveSameSite>::ToMojom(net::CookieEffectiveSameSite input) {
+ switch (input) {
+ case net::CookieEffectiveSameSite::NO_RESTRICTION:
+ return network::mojom::CookieEffectiveSameSite::kNoRestriction;
+ case net::CookieEffectiveSameSite::LAX_MODE:
+ return network::mojom::CookieEffectiveSameSite::kLaxMode;
+ case net::CookieEffectiveSameSite::STRICT_MODE:
+ return network::mojom::CookieEffectiveSameSite::kStrictMode;
+ case net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
+ return network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe;
+ default:
+ break;
+ }
+ NOTREACHED();
+ return static_cast<network::mojom::CookieEffectiveSameSite>(input);
+}
+
+bool EnumTraits<network::mojom::CookieEffectiveSameSite,
+ net::CookieEffectiveSameSite>::
+ FromMojom(network::mojom::CookieEffectiveSameSite input,
+ net::CookieEffectiveSameSite* output) {
+ switch (input) {
+ case network::mojom::CookieEffectiveSameSite::kNoRestriction:
+ *output = net::CookieEffectiveSameSite::NO_RESTRICTION;
+ return true;
+ case network::mojom::CookieEffectiveSameSite::kLaxMode:
+ *output = net::CookieEffectiveSameSite::LAX_MODE;
+ return true;
+ case network::mojom::CookieEffectiveSameSite::kStrictMode:
+ *output = net::CookieEffectiveSameSite::STRICT_MODE;
+ return true;
+ case network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe:
+ *output = net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE;
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
network::mojom::CookieSourceScheme
EnumTraits<network::mojom::CookieSourceScheme,
net::CookieSourceScheme>::ToMojom(net::CookieSourceScheme input) {
@@ -351,10 +393,10 @@ bool StructTraits<
}
bool StructTraits<network::mojom::CookieInclusionStatusDataView,
- net::CanonicalCookie::CookieInclusionStatus>::
+ net::CookieInclusionStatus>::
Read(network::mojom::CookieInclusionStatusDataView status,
- net::CanonicalCookie::CookieInclusionStatus* out) {
- *out = net::CanonicalCookie::CookieInclusionStatus();
+ net::CookieInclusionStatus* out) {
+ *out = net::CookieInclusionStatus();
out->set_exclusion_reasons(status.exclusion_reasons());
out->set_warning_reasons(status.warning_reasons());
@@ -366,7 +408,7 @@ bool StructTraits<
net::CookieWithStatus>::Read(network::mojom::CookieWithStatusDataView c,
net::CookieWithStatus* out) {
net::CanonicalCookie cookie;
- net::CanonicalCookie::CookieInclusionStatus status;
+ net::CookieInclusionStatus status;
if (!c.ReadCookie(&cookie))
return false;
if (!c.ReadStatus(&status))
@@ -383,7 +425,7 @@ bool StructTraits<network::mojom::CookieAndLineWithStatusDataView,
net::CookieAndLineWithStatus* out) {
base::Optional<net::CanonicalCookie> cookie;
std::string cookie_string;
- net::CanonicalCookie::CookieInclusionStatus status;
+ net::CookieInclusionStatus status;
if (!c.ReadCookie(&cookie))
return false;
if (!c.ReadCookieString(&cookie_string))
@@ -397,6 +439,39 @@ bool StructTraits<network::mojom::CookieAndLineWithStatusDataView,
}
bool StructTraits<
+ network::mojom::CookieAccessResultDataView,
+ net::CookieAccessResult>::Read(network::mojom::CookieAccessResultDataView c,
+ net::CookieAccessResult* out) {
+ net::CookieEffectiveSameSite effective_same_site;
+ net::CookieInclusionStatus status;
+
+ if (!c.ReadEffectiveSameSite(&effective_same_site))
+ return false;
+ if (!c.ReadStatus(&status))
+ return false;
+
+ *out = {effective_same_site, status};
+
+ return true;
+}
+
+bool StructTraits<network::mojom::CookieWithAccessResultDataView,
+ net::CookieWithAccessResult>::
+ Read(network::mojom::CookieWithAccessResultDataView c,
+ net::CookieWithAccessResult* out) {
+ net::CanonicalCookie cookie;
+ net::CookieAccessResult access_result;
+ if (!c.ReadCookie(&cookie))
+ return false;
+ if (!c.ReadAccessResult(&access_result))
+ return false;
+
+ *out = {cookie, access_result};
+
+ return true;
+}
+
+bool StructTraits<
network::mojom::CookieChangeInfoDataView,
net::CookieChangeInfo>::Read(network::mojom::CookieChangeInfoDataView info,
net::CookieChangeInfo* out) {
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
index b9b4eec5df5..8b5243cafcf 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -8,8 +8,10 @@
#include "ipc/ipc_message_utils.h"
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/cookies/cookie_constants.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_options.h"
#include "services/network/public/mojom/cookie_manager.mojom.h"
@@ -30,6 +32,15 @@ struct EnumTraits<network::mojom::CookieSameSite, net::CookieSameSite> {
};
template <>
+struct EnumTraits<network::mojom::CookieEffectiveSameSite,
+ net::CookieEffectiveSameSite> {
+ static network::mojom::CookieEffectiveSameSite ToMojom(
+ net::CookieEffectiveSameSite input);
+ static bool FromMojom(network::mojom::CookieEffectiveSameSite input,
+ net::CookieEffectiveSameSite* output);
+};
+
+template <>
struct EnumTraits<network::mojom::CookieAccessSemantics,
net::CookieAccessSemantics> {
static network::mojom::CookieAccessSemantics ToMojom(
@@ -145,17 +156,15 @@ struct StructTraits<network::mojom::CanonicalCookieDataView,
template <>
struct StructTraits<network::mojom::CookieInclusionStatusDataView,
- net::CanonicalCookie::CookieInclusionStatus> {
- static uint32_t exclusion_reasons(
- const net::CanonicalCookie::CookieInclusionStatus& s) {
+ net::CookieInclusionStatus> {
+ static uint32_t exclusion_reasons(const net::CookieInclusionStatus& s) {
return s.exclusion_reasons();
}
- static uint32_t warning_reasons(
- const net::CanonicalCookie::CookieInclusionStatus& s) {
+ static uint32_t warning_reasons(const net::CookieInclusionStatus& s) {
return s.warning_reasons();
}
static bool Read(network::mojom::CookieInclusionStatusDataView status,
- net::CanonicalCookie::CookieInclusionStatus* out);
+ net::CookieInclusionStatus* out);
};
template <>
@@ -164,7 +173,7 @@ struct StructTraits<network::mojom::CookieWithStatusDataView,
static const net::CanonicalCookie& cookie(const net::CookieWithStatus& c) {
return c.cookie;
}
- static const net::CanonicalCookie::CookieInclusionStatus& status(
+ static const net::CookieInclusionStatus& status(
const net::CookieWithStatus& c) {
return c.status;
}
@@ -183,7 +192,7 @@ struct StructTraits<network::mojom::CookieAndLineWithStatusDataView,
const net::CookieAndLineWithStatus& c) {
return c.cookie_string;
}
- static const net::CanonicalCookie::CookieInclusionStatus& status(
+ static const net::CookieInclusionStatus& status(
const net::CookieAndLineWithStatus& c) {
return c.status;
}
@@ -192,6 +201,36 @@ struct StructTraits<network::mojom::CookieAndLineWithStatusDataView,
};
template <>
+struct StructTraits<network::mojom::CookieAccessResultDataView,
+ net::CookieAccessResult> {
+ static const net::CookieEffectiveSameSite& effective_same_site(
+ const net::CookieAccessResult& c) {
+ return c.effective_same_site;
+ }
+ static const net::CookieInclusionStatus& status(
+ const net::CookieAccessResult& c) {
+ return c.status;
+ }
+ static bool Read(network::mojom::CookieAccessResultDataView access_result,
+ net::CookieAccessResult* out);
+};
+
+template <>
+struct StructTraits<network::mojom::CookieWithAccessResultDataView,
+ net::CookieWithAccessResult> {
+ static const net::CanonicalCookie& cookie(
+ const net::CookieWithAccessResult& c) {
+ return c.cookie;
+ }
+ static const net::CookieAccessResult& access_result(
+ const net::CookieWithAccessResult& c) {
+ return c.access_result;
+ }
+ static bool Read(network::mojom::CookieWithAccessResultDataView cookie,
+ net::CookieWithAccessResult* out);
+};
+
+template <>
struct StructTraits<network::mojom::CookieChangeInfoDataView,
net::CookieChangeInfo> {
static const net::CanonicalCookie& cookie(const net::CookieChangeInfo& c) {
diff --git a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
index 6bdb434d7a7..d3be1aee9de 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc
@@ -59,34 +59,32 @@ TEST(CookieManagerTraitsTest, Roundtrips_CanonicalCookie) {
TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
// This status + warning combo doesn't really make sense. It's just an
// arbitrary selection of values to test the serialization/deserialization.
- net::CanonicalCookie::CookieInclusionStatus original =
- net::CanonicalCookie::CookieInclusionStatus::MakeFromReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY},
- {net::CanonicalCookie::CookieInclusionStatus::
+ net::CookieInclusionStatus original =
+ net::CookieInclusionStatus::MakeFromReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+ net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+ net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY},
+ {net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
- net::CanonicalCookie::CookieInclusionStatus::
- WARN_SAMESITE_NONE_INSECURE,
- net::CanonicalCookie::CookieInclusionStatus::
+ net::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE,
+ net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE});
- net::CanonicalCookie::CookieInclusionStatus copied;
+ net::CookieInclusionStatus copied;
EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieInclusionStatus>(
&original, &copied));
EXPECT_TRUE(copied.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_SAMESITE_LAX,
+ net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX,
+ net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
EXPECT_TRUE(copied.HasExactlyWarningReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
- net::CanonicalCookie::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE,
- net::CanonicalCookie::CookieInclusionStatus::
+ {net::CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+ net::CookieInclusionStatus::WARN_SAMESITE_NONE_INSECURE,
+ net::CookieInclusionStatus::
WARN_SAMESITE_UNSPECIFIED_LAX_ALLOW_UNSAFE}));
- net::CanonicalCookie::CookieInclusionStatus invalid;
+ net::CookieInclusionStatus invalid;
invalid.set_exclusion_reasons(~0u);
EXPECT_FALSE(
@@ -100,8 +98,8 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieWithStatus) {
/* secure = */ true, /* http_only = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
- net::CookieWithStatus original = {
- original_cookie, net::CanonicalCookie::CookieInclusionStatus()};
+ net::CookieWithStatus original = {original_cookie,
+ net::CookieInclusionStatus()};
net::CookieWithStatus copied;
diff --git a/chromium/services/network/public/cpp/cors/cors.cc b/chromium/services/network/public/cpp/cors/cors.cc
index 3c95e68e7ff..6e12d8f2970 100644
--- a/chromium/services/network/public/cpp/cors/cors.cc
+++ b/chromium/services/network/public/cpp/cors/cors.cc
@@ -616,6 +616,7 @@ bool CalculateCredentialsFlag(mojom::CredentialsMode credentials_mode,
// is true, and unset otherwise.
switch (credentials_mode) {
case network::mojom::CredentialsMode::kOmit:
+ case network::mojom::CredentialsMode::kOmitBug_775438_Workaround:
return false;
case network::mojom::CredentialsMode::kSameOrigin:
return response_tainting == network::mojom::FetchResponseType::kBasic;
diff --git a/chromium/services/network/public/cpp/cors/preflight_cache.cc b/chromium/services/network/public/cpp/cors/preflight_cache.cc
index 3e89dfb3da6..0049fa1bc3d 100644
--- a/chromium/services/network/public/cpp/cors/preflight_cache.cc
+++ b/chromium/services/network/public/cpp/cors/preflight_cache.cc
@@ -53,10 +53,6 @@ void PreflightCache::AppendEntry(
if (url_spec.length() >= kMaxKeyLength)
return;
- DCHECK(
- !network_isolation_key.GetFrameOrigin().has_value() ||
- (origin.opaque() && network_isolation_key.GetFrameOrigin()->opaque()) ||
- network_isolation_key.GetFrameOrigin()->IsSameOriginWith(origin));
auto key = std::make_tuple(origin, url_spec, network_isolation_key);
const auto existing_entry = cache_.find(key);
if (existing_entry == cache_.end()) {
@@ -80,10 +76,6 @@ bool PreflightCache::CheckIfRequestCanSkipPreflight(
const net::HttpRequestHeaders& request_headers,
bool is_revalidating) {
// Check if the entry exists in the cache.
- DCHECK(
- !network_isolation_key.GetFrameOrigin().has_value() ||
- (origin.opaque() && network_isolation_key.GetFrameOrigin()->opaque()) ||
- network_isolation_key.GetFrameOrigin()->IsSameOriginWith(origin));
auto key = std::make_tuple(origin, url.spec(), network_isolation_key);
auto cache_entry = cache_.find(key);
if (cache_entry == cache_.end()) {
diff --git a/chromium/services/network/public/cpp/crash_keys.cc b/chromium/services/network/public/cpp/crash_keys.cc
new file mode 100644
index 00000000000..45a4120bf81
--- /dev/null
+++ b/chromium/services/network/public/cpp/crash_keys.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 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 "services/network/public/cpp/crash_keys.h"
+
+#include <utility>
+
+#include "base/debug/crash_logging.h"
+
+namespace network {
+namespace debug {
+
+namespace {
+base::debug::CrashKeyString* GetCrashKey() {
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
+ "network_deserialization", base::debug::CrashKeySize::Size32);
+ return crash_key;
+}
+} // namespace
+
+void SetDeserializationCrashKeyString(base::StringPiece str) {
+ base::debug::SetCrashKeyString(GetCrashKey(), std::move(str));
+}
+
+void ClearDeserializationCrashKeyString() {
+ base::debug::ClearCrashKeyString(GetCrashKey());
+}
+
+} // namespace debug
+} // namespace network
diff --git a/chromium/services/network/public/cpp/crash_keys.h b/chromium/services/network/public/cpp/crash_keys.h
new file mode 100644
index 00000000000..16e6932bbd6
--- /dev/null
+++ b/chromium/services/network/public/cpp/crash_keys.h
@@ -0,0 +1,23 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_CRASH_KEYS_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_CRASH_KEYS_H_
+
+#include "base/component_export.h"
+#include "base/strings/string_piece_forward.h"
+
+namespace network {
+namespace debug {
+
+COMPONENT_EXPORT(NETWORK_CPP_CRASH_KEYS)
+void SetDeserializationCrashKeyString(base::StringPiece str);
+
+COMPONENT_EXPORT(NETWORK_CPP_CRASH_KEYS)
+void ClearDeserializationCrashKeyString();
+
+} // namespace debug
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_CRASH_KEYS_H_
diff --git a/chromium/services/network/public/cpp/data_element.cc b/chromium/services/network/public/cpp/data_element.cc
index a75bb59b4e0..9a959842e9d 100644
--- a/chromium/services/network/public/cpp/data_element.cc
+++ b/chromium/services/network/public/cpp/data_element.cc
@@ -20,7 +20,7 @@ const uint64_t DataElement::kUnknownSize;
DataElement::DataElement()
: type_(mojom::DataElementType::kUnknown),
- bytes_(NULL),
+ bytes_(nullptr),
offset_(0),
length_(std::numeric_limits<uint64_t>::max()) {}
diff --git a/chromium/services/network/public/cpp/data_element.h b/chromium/services/network/public/cpp/data_element.h
index c3bd96eb10d..26d0f4fc4fe 100644
--- a/chromium/services/network/public/cpp/data_element.h
+++ b/chromium/services/network/public/cpp/data_element.h
@@ -14,11 +14,11 @@
#include <string>
#include <vector>
+#include "base/check_op.h"
#include "base/component_export.h"
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/gtest_prod_util.h"
-#include "base/logging.h"
#include "base/time/time.h"
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
diff --git a/chromium/services/network/empty_url_loader_client.cc b/chromium/services/network/public/cpp/empty_url_loader_client.cc
index e19b1ba3723..6d869d05675 100644
--- a/chromium/services/network/empty_url_loader_client.cc
+++ b/chromium/services/network/public/cpp/empty_url_loader_client.cc
@@ -2,38 +2,56 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/network/empty_url_loader_client.h"
+#include "services/network/public/cpp/empty_url_loader_client.h"
#include <utility>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/threading/sequenced_task_runner_handle.h"
namespace network {
// static
-void EmptyURLLoaderClient::DrainURLRequest(
+void EmptyURLLoaderClientWrapper::DrainURLRequest(
mojo::PendingReceiver<mojom::URLLoaderClient> client_receiver,
mojo::PendingRemote<mojom::URLLoader> url_loader) {
- // Raw |new| is okay, because the newly constructed EmptyURLLoaderClient will
- // delete itself after consuming all the data/callbacks.
- new EmptyURLLoaderClient(std::move(client_receiver), std::move(url_loader));
+ // Raw |new| is okay, because the object will delete itself.
+ new EmptyURLLoaderClientWrapper(std::move(client_receiver),
+ std::move(url_loader));
}
-EmptyURLLoaderClient::EmptyURLLoaderClient(
+EmptyURLLoaderClientWrapper::EmptyURLLoaderClientWrapper(
mojo::PendingReceiver<mojom::URLLoaderClient> receiver,
mojo::PendingRemote<mojom::URLLoader> url_loader)
- : receiver_(this, std::move(receiver)), url_loader_(std::move(url_loader)) {
+ : receiver_(&client_, std::move(receiver)),
+ url_loader_(std::move(url_loader)) {
+ client_.Drain(base::BindOnce(&EmptyURLLoaderClientWrapper::DeleteSelf,
+ base::Unretained(this)));
receiver_.set_disconnect_handler(base::BindOnce(
- &EmptyURLLoaderClient::DeleteSelf, base::Unretained(this)));
+ &EmptyURLLoaderClientWrapper::DeleteSelf, base::Unretained(this)));
}
-EmptyURLLoaderClient::~EmptyURLLoaderClient() {}
+EmptyURLLoaderClientWrapper::~EmptyURLLoaderClientWrapper() = default;
-void EmptyURLLoaderClient::DeleteSelf() {
+void EmptyURLLoaderClientWrapper::DeleteSelf() {
delete this;
}
+EmptyURLLoaderClient::EmptyURLLoaderClient() = default;
+EmptyURLLoaderClient::~EmptyURLLoaderClient() = default;
+
+void EmptyURLLoaderClient::Drain(base::OnceClosure callback) {
+ DCHECK(!callback_);
+ callback_ = std::move(callback);
+ MaybeDone();
+}
+
+void EmptyURLLoaderClient::MaybeDone() {
+ if (done_ && callback_)
+ std::move(callback_).Run();
+}
+
void EmptyURLLoaderClient::OnReceiveResponse(
const mojom::URLResponseHeadPtr head) {}
@@ -59,7 +77,8 @@ void EmptyURLLoaderClient::OnStartLoadingResponseBody(
}
void EmptyURLLoaderClient::OnComplete(const URLLoaderCompletionStatus& status) {
- DeleteSelf();
+ done_ = true;
+ MaybeDone();
}
void EmptyURLLoaderClient::OnDataAvailable(const void* data, size_t num_bytes) {
diff --git a/chromium/services/network/empty_url_loader_client.h b/chromium/services/network/public/cpp/empty_url_loader_client.h
index e9320b69bed..bcff77f086d 100644
--- a/chromium/services/network/empty_url_loader_client.h
+++ b/chromium/services/network/public/cpp/empty_url_loader_client.h
@@ -2,11 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SERVICES_NETWORK_EMPTY_URL_LOADER_CLIENT_H_
-#define SERVICES_NETWORK_EMPTY_URL_LOADER_CLIENT_H_
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_EMPTY_URL_LOADER_CLIENT_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_EMPTY_URL_LOADER_CLIENT_H_
#include <memory>
+#include "base/callback_forward.h"
#include "base/macros.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
@@ -18,24 +19,18 @@
namespace network {
// Helper for draining/discarding data and callbacks that go to URLLoaderClient.
-class EmptyURLLoaderClient : public mojom::URLLoaderClient,
- public mojo::DataPipeDrainer::Client {
+class COMPONENT_EXPORT(NETWORK_CPP) EmptyURLLoaderClient
+ : public mojom::URLLoaderClient,
+ public mojo::DataPipeDrainer::Client {
public:
- // Binds |client_receiver| to a newly constructed EmptyURLLoaderClient which
- // will drain/discard all callbacks/data. Takes ownership of |url_loader| and
- // discards it (together with EmptyURLLoaderClient) when the URL request has
- // been completed.
- static void DrainURLRequest(
- mojo::PendingReceiver<mojom::URLLoaderClient> client_receiver,
- mojo::PendingRemote<mojom::URLLoader> url_loader);
+ EmptyURLLoaderClient();
+ ~EmptyURLLoaderClient() override;
- private:
- EmptyURLLoaderClient(
- mojo::PendingReceiver<mojom::URLLoaderClient> client_receiver,
- mojo::PendingRemote<mojom::URLLoader> url_loader);
+ // Calls |callback| when the request is done.
+ void Drain(base::OnceClosure callback);
- ~EmptyURLLoaderClient() override;
- void DeleteSelf();
+ private:
+ void MaybeDone();
// mojom::URLLoaderClient overrides:
void OnReceiveResponse(mojom::URLResponseHeadPtr head) override;
@@ -54,15 +49,39 @@ class EmptyURLLoaderClient : public mojom::URLLoaderClient,
void OnDataAvailable(const void* data, size_t num_bytes) override;
void OnDataComplete() override;
- mojo::Receiver<mojom::URLLoaderClient> receiver_;
-
std::unique_ptr<mojo::DataPipeDrainer> response_body_drainer_;
- mojo::Remote<mojom::URLLoader> url_loader_;
+ bool done_ = false;
+ base::OnceClosure callback_;
DISALLOW_COPY_AND_ASSIGN(EmptyURLLoaderClient);
};
+// Self-owned helper class for using EmptyURLLoaderClient.
+class COMPONENT_EXPORT(NETWORK_CPP) EmptyURLLoaderClientWrapper {
+ public:
+ // Binds |client_receiver| to a newly constructed EmptyURLLoaderClient which
+ // will drain/discard all callbacks/data. Takes ownership of |url_loader| and
+ // discards it (together with EmptyURLLoaderClient) when the URL request has
+ // been completed.
+ static void DrainURLRequest(
+ mojo::PendingReceiver<mojom::URLLoaderClient> client_receiver,
+ mojo::PendingRemote<mojom::URLLoader> url_loader);
+
+ ~EmptyURLLoaderClientWrapper();
+
+ private:
+ EmptyURLLoaderClientWrapper(
+ mojo::PendingReceiver<mojom::URLLoaderClient> receiver,
+ mojo::PendingRemote<mojom::URLLoader> url_loader);
+
+ void DeleteSelf();
+
+ EmptyURLLoaderClient client_;
+ mojo::Receiver<mojom::URLLoaderClient> receiver_;
+ mojo::Remote<mojom::URLLoader> url_loader_;
+};
+
} // namespace network
-#endif // SERVICES_NETWORK_EMPTY_URL_LOADER_CLIENT_H_
+#endif // SERVICES_NETWORK_PUBLIC_CPP_EMPTY_URL_LOADER_CLIENT_H_
diff --git a/chromium/services/network/public/cpp/features.cc b/chromium/services/network/public/cpp/features.cc
index 970b405187b..7ea2ac326c8 100644
--- a/chromium/services/network/public/cpp/features.cc
+++ b/chromium/services/network/public/cpp/features.cc
@@ -9,11 +9,6 @@
namespace network {
namespace features {
-// When kCapReferrerToOriginOnCrossOrigin is enabled, HTTP referrers on cross-
-// origin requests are restricted to contain at most the source origin.
-const base::Feature kCapReferrerToOriginOnCrossOrigin{
- "CapReferrerToOriginOnCrossOrigin", base::FEATURE_DISABLED_BY_DEFAULT};
-
// Enables Expect CT reporting, which sends reports for opted-in sites
// that don't serve sufficient Certificate Transparency information.
const base::Feature kExpectCTReporting{"ExpectCTReporting",
@@ -106,6 +101,12 @@ const base::Feature kCrossOriginOpenerPolicy {
const base::Feature kCrossOriginOpenerPolicyReporting{
"CrossOriginOpenerPolicyReporting", base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables Cross-Origin Opener Policy (COOP) access reporting.
+// https://github.com/camillelamy/explainers/blob/master/coop_reporting.md#report-blocked-accesses-to-other-windows
+const base::Feature kCrossOriginOpenerPolicyAccessReporting{
+ "CrossOriginOpenerPolicyAccessReporting",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// Enables Cross-Origin Embedder Policy (COEP).
// https://github.com/mikewest/corpp
// Currently this feature is enabled for all platforms except WebView.
@@ -156,12 +157,6 @@ const base::FeatureParam<std::string>
const base::Feature kDisableKeepaliveFetch{"DisableKeepaliveFetch",
base::FEATURE_DISABLED_BY_DEFAULT};
-// When kOutOfBlinkFrameAncestors is enabled, the frame-ancestors
-// directive is parsed from the Content-Security-Policy header in the network
-// service and enforced in the browser.
-const base::Feature kOutOfBlinkFrameAncestors{"OutOfBlinkFrameAncestors",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
// Attach the origin of the destination URL to the "origin" header
const base::Feature
kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess{
@@ -187,12 +182,29 @@ const base::Feature kCorbAllowlistAlsoAppliesToOorCors = {
const char kCorbAllowlistAlsoAppliesToOorCorsParamName[] =
"AllowlistForCorbAndCors";
+// Controls whether a |request_initiator| that mismatches
+// |request_initiator_site_lock| leads to 1) failing the HTTP request and 2)
+// calling mojo::ReportBadMessage (on desktop platforms, where NetworkService
+// is hosted outside of the Browser process, this leads to DumpWithoutCrashing
+// and does *not* lead to a renderer kill).
+//
+// See also https://crbug.com/920634
+const base::Feature kRequestInitiatorSiteLockEnfocement = {
+ "RequestInitiatorSiteLockEnfocement",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
// The preflight parser should reject Access-Control-Allow-* headers which do
// not conform to ABNF. But if the strict check is applied directly, some
// existing sites might fail to load. The feature flag controls whether a strict
// check will be used or not.
const base::Feature kStrictAccessControlAllowListCheck = {
- "StrictAccessControlAllowListCheck", base::FEATURE_DISABLED_BY_DEFAULT};
+ "StrictAccessControlAllowListCheck", base::FEATURE_ENABLED_BY_DEFAULT};
+
+// When the CertVerifierService is enabled, certificate verification will not be
+// performed in the network service, but will instead be brokered to a separate
+// cert verification service potentially running in a different process.
+const base::Feature kCertVerifierService{"CertVerifierService",
+ base::FEATURE_DISABLED_BY_DEFAULT};
// Enables preprocessing requests with the Trust Tokens API Fetch flags set,
// and handling their responses, according to the protocol.
@@ -230,9 +242,16 @@ const base::FeatureParam<TrustTokenOriginTrialSpec>
TrustTokenOriginTrialSpec::kOriginTrialNotRequired,
&kTrustTokenOriginTrialParamOptions};
+// Enables the Content Security Policy Embedded Enforcement check out of blink
+const base::Feature kOutOfBlinkCSPEE{"OutOfBlinkCSPEE",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
bool ShouldEnableOutOfBlinkCorsForTesting() {
return base::FeatureList::IsEnabled(features::kOutOfBlinkCors);
}
+const base::Feature kWebSocketReassembleShortMessages{
+ "WebSocketReassembleShortMessages", base::FEATURE_ENABLED_BY_DEFAULT};
+
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/features.h b/chromium/services/network/public/cpp/features.h
index 69eb7a29dea..213184d4cb4 100644
--- a/chromium/services/network/public/cpp/features.h
+++ b/chromium/services/network/public/cpp/features.h
@@ -13,8 +13,6 @@ namespace network {
namespace features {
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kCapReferrerToOriginOnCrossOrigin;
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kExpectCTReporting;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kNetworkErrorLogging;
@@ -41,6 +39,8 @@ extern const base::Feature kCrossOriginOpenerPolicy;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginOpenerPolicyReporting;
COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kCrossOriginOpenerPolicyAccessReporting;
+COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginEmbedderPolicy;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kBlockNonSecureExternalRequests;
@@ -56,8 +56,6 @@ extern const base::FeatureParam<std::string>
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kDisableKeepaliveFetch;
COMPONENT_EXPORT(NETWORK_CPP)
-extern const base::Feature kOutOfBlinkFrameAncestors;
-COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature
kDeriveOriginFromUrlForNeitherGetNorHeadRequestWhenHavingSpecialAccess;
COMPONENT_EXPORT(NETWORK_CPP)
@@ -72,7 +70,11 @@ extern const base::Feature kCorbAllowlistAlsoAppliesToOorCors;
COMPONENT_EXPORT(NETWORK_CPP)
extern const char kCorbAllowlistAlsoAppliesToOorCorsParamName[];
COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kRequestInitiatorSiteLockEnfocement;
+COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kStrictAccessControlAllowListCheck;
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kCertVerifierService;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kTrustTokens;
@@ -88,8 +90,14 @@ extern const base::FeatureParam<TrustTokenOriginTrialSpec>
kTrustTokenOperationsRequiringOriginTrial;
COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kOutOfBlinkCSPEE;
+
+COMPONENT_EXPORT(NETWORK_CPP)
bool ShouldEnableOutOfBlinkCorsForTesting();
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kWebSocketReassembleShortMessages;
+
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc b/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc
index 8cd78a620b7..9832b21aacd 100644
--- a/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -283,7 +283,7 @@ DnsQueryType EnumTraits<DnsQueryType, net::DnsQueryType>::ToMojom(
return DnsQueryType::PTR;
case net::DnsQueryType::SRV:
return DnsQueryType::SRV;
- case net::DnsQueryType::ESNI:
+ case net::DnsQueryType::INTEGRITY:
NOTIMPLEMENTED();
return DnsQueryType::UNSPECIFIED;
}
diff --git a/chromium/services/network/public/cpp/http_request_headers_mojom_traits.cc b/chromium/services/network/public/cpp/http_request_headers_mojom_traits.cc
index d6b2987bcc2..66bedc18330 100644
--- a/chromium/services/network/public/cpp/http_request_headers_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/http_request_headers_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "services/network/public/cpp/http_request_headers_mojom_traits.h"
#include "net/http/http_util.h"
+#include "services/network/public/cpp/crash_keys.h"
namespace mojo {
@@ -15,13 +16,17 @@ bool StructTraits<network::mojom::HttpRequestHeaderKeyValuePairDataView,
net::HttpRequestHeaders::HeaderKeyValuePair* item) {
if (!data.ReadKey(&item->key))
return false;
- if (!net::HttpUtil::IsValidHeaderName(item->key))
+ if (!net::HttpUtil::IsValidHeaderName(item->key)) {
+ network::debug::SetDeserializationCrashKeyString("header_key");
return false;
+ }
if (!data.ReadValue(&item->value))
return false;
item->value = std::string(net::HttpUtil::TrimLWS(item->value));
- if (!net::HttpUtil::IsValidHeaderValue(item->value))
+ if (!net::HttpUtil::IsValidHeaderValue(item->value)) {
+ network::debug::SetDeserializationCrashKeyString("header_value");
return false;
+ }
return true;
}
diff --git a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
index 07d848dbde8..8f797b5bd00 100644
--- a/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/isolation_info_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "services/network/public/cpp/isolation_info_mojom_traits.h"
#include "base/notreached.h"
+#include "services/network/public/cpp/crash_keys.h"
#include "services/network/public/cpp/site_for_cookies_mojom_traits.h"
namespace mojo {
@@ -51,9 +52,15 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>::
net::SiteForCookies site_for_cookies;
net::IsolationInfo::RedirectMode redirect_mode;
- if (!data.ReadTopFrameOrigin(&top_frame_origin) ||
- !data.ReadFrameOrigin(&frame_origin) ||
- !data.ReadSiteForCookies(&site_for_cookies) ||
+ if (!data.ReadTopFrameOrigin(&top_frame_origin)) {
+ network::debug::SetDeserializationCrashKeyString("isolation_top_origin");
+ return false;
+ }
+ if (!data.ReadFrameOrigin(&frame_origin)) {
+ network::debug::SetDeserializationCrashKeyString("isolation_frame_origin");
+ return false;
+ }
+ if (!data.ReadSiteForCookies(&site_for_cookies) ||
!data.ReadRedirectMode(&redirect_mode)) {
return false;
}
@@ -62,8 +69,10 @@ bool StructTraits<network::mojom::IsolationInfoDataView, net::IsolationInfo>::
net::IsolationInfo::CreateIfConsistent(redirect_mode, top_frame_origin,
frame_origin, site_for_cookies,
data.opaque_and_non_transient());
- if (!isolation_info)
+ if (!isolation_info) {
+ network::debug::SetDeserializationCrashKeyString("isolation_inconsistent");
return false;
+ }
*out = std::move(*isolation_info);
return true;
diff --git a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
index d66f2647790..9039014d7f8 100644
--- a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.cc
@@ -34,10 +34,14 @@ bool StructTraits<network::mojom::LoadTimingInfoDataView, net::LoadTimingInfo>::
data.ReadSendEnd(&out->send_end) &&
data.ReadReceiveHeadersStart(&out->receive_headers_start) &&
data.ReadReceiveHeadersEnd(&out->receive_headers_end) &&
+ data.ReadFirstEarlyHintsTime(&out->first_early_hints_time) &&
data.ReadPushStart(&out->push_start) &&
data.ReadPushEnd(&out->push_end) &&
data.ReadServiceWorkerStartTime(&out->service_worker_start_time) &&
- data.ReadServiceWorkerReadyTime(&out->service_worker_ready_time);
+ data.ReadServiceWorkerReadyTime(&out->service_worker_ready_time) &&
+ data.ReadServiceWorkerFetchStart(&out->service_worker_fetch_start) &&
+ data.ReadServiceWorkerRespondWithSettled(
+ &out->service_worker_respond_with_settled);
}
} // namespace mojo
diff --git a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
index c118264b586..0bec1dbc1b5 100644
--- a/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
+++ b/chromium/services/network/public/cpp/load_timing_info_mojom_traits.h
@@ -96,6 +96,11 @@ struct StructTraits<network::mojom::LoadTimingInfoDataView,
return obj.receive_headers_end;
}
+ static base::TimeTicks first_early_hints_time(
+ const net::LoadTimingInfo& obj) {
+ return obj.first_early_hints_time;
+ }
+
static base::TimeTicks push_start(const net::LoadTimingInfo& obj) {
return obj.push_start;
}
@@ -114,6 +119,16 @@ struct StructTraits<network::mojom::LoadTimingInfoDataView,
return obj.service_worker_ready_time;
}
+ static base::TimeTicks service_worker_fetch_start(
+ const net::LoadTimingInfo& obj) {
+ return obj.service_worker_fetch_start;
+ }
+
+ static base::TimeTicks service_worker_respond_with_settled(
+ const net::LoadTimingInfo& obj) {
+ return obj.service_worker_respond_with_settled;
+ }
+
static bool Read(network::mojom::LoadTimingInfoDataView obj,
net::LoadTimingInfo* output);
};
diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.cc b/chromium/services/network/public/cpp/net_ipc_param_traits.cc
index 8f6d970ee13..bb2f1be0aa0 100644
--- a/chromium/services/network/public/cpp/net_ipc_param_traits.cc
+++ b/chromium/services/network/public/cpp/net_ipc_param_traits.cc
@@ -489,6 +489,7 @@ void ParamTraits<net::LoadTimingInfo>::Write(base::Pickle* m,
WriteParam(m, p.send_end);
WriteParam(m, p.receive_headers_start);
WriteParam(m, p.receive_headers_end);
+ WriteParam(m, p.first_early_hints_time);
WriteParam(m, p.push_start);
WriteParam(m, p.push_end);
}
@@ -519,6 +520,7 @@ bool ParamTraits<net::LoadTimingInfo>::Read(const base::Pickle* m,
ReadParam(m, iter, &r->send_end) &&
ReadParam(m, iter, &r->receive_headers_start) &&
ReadParam(m, iter, &r->receive_headers_end) &&
+ ReadParam(m, iter, &r->first_early_hints_time) &&
ReadParam(m, iter, &r->push_start) && ReadParam(m, iter, &r->push_end);
}
@@ -557,6 +559,8 @@ void ParamTraits<net::LoadTimingInfo>::Log(const param_type& p,
l->append(", ");
LogParam(p.receive_headers_end, l);
l->append(", ");
+ LogParam(p.first_early_hints_time, l);
+ l->append(", ");
LogParam(p.push_start, l);
l->append(", ");
LogParam(p.push_end, l);
diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.h b/chromium/services/network/public/cpp/network_ipc_param_traits.h
index 3ddf58f64d2..90fb4bf7d95 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.h
@@ -49,8 +49,8 @@
namespace IPC {
-// TODO(Richard): Remove this traits after usage of FrameHostMsg_OpenURL_Params
-// disappears.
+// TODO(Richard): Remove this traits after usage of
+// content::mojom::OpenURLParams disappears.
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<network::DataElement> {
typedef network::DataElement param_type;
@@ -61,7 +61,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ParamTraits<network::DataElement> {
static void Log(const param_type& p, std::string* l);
};
-// TODO(Richard): Remove this traits after usage of FrameHostMsg_OpenURL_Params
+// TODO(Richard): Remove this traits after usage of OpenURLParams struct
// disappears.
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
diff --git a/chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc b/chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc
index 6eca5d7f68c..7722e574bb2 100644
--- a/chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc
+++ b/chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc
@@ -28,7 +28,8 @@ OptionalTrustTokenParams NonemptyTrustTokenParams() {
mojom::TrustTokenSignRequestData::kInclude,
/*include_timestamp_header=*/true,
url::Origin::Create(GURL("https://issuer.com")),
- std::vector<std::string>{"some_header", "another_header"});
+ std::vector<std::string>{"some_header", "another_header"},
+ "some additional signing data");
}
} // namespace
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser.cc b/chromium/services/network/public/cpp/origin_isolation_parser.cc
new file mode 100644
index 00000000000..b324c3d01e8
--- /dev/null
+++ b/chromium/services/network/public/cpp/origin_isolation_parser.cc
@@ -0,0 +1,15 @@
+// Copyright 2020 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 "services/network/public/cpp/origin_isolation_parser.h"
+#include "net/http/structured_headers.h"
+
+namespace network {
+
+bool ParseOriginIsolation(const std::string& header_value) {
+ const auto item = net::structured_headers::ParseItem(header_value);
+ return item && item->item.is_boolean() && item->item.GetBoolean();
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser.h b/chromium/services/network/public/cpp/origin_isolation_parser.h
new file mode 100644
index 00000000000..dd4f7d7fc81
--- /dev/null
+++ b/chromium/services/network/public/cpp/origin_isolation_parser.h
@@ -0,0 +1,23 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
+
+#include <string>
+#include "base/component_export.h"
+
+namespace network {
+
+// Parsing is done following the Origin-Isolation spec draft:
+// https://github.com/whatwg/html/pull/5545
+//
+// See the comment in network::PopulateParsedHeaders for restrictions on this
+// function.
+COMPONENT_EXPORT(NETWORK_CPP)
+bool ParseOriginIsolation(const std::string&);
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_ORIGIN_ISOLATION_PARSER_H_
diff --git a/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc b/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc
new file mode 100644
index 00000000000..0b53d3a0901
--- /dev/null
+++ b/chromium/services/network/public/cpp/origin_isolation_parser_unittest.cc
@@ -0,0 +1,31 @@
+// Copyright 2020 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 "services/network/public/cpp/origin_isolation_parser.h"
+
+#include <string>
+#include <vector>
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+
+TEST(OriginIsolationHeaderTest, Parse) {
+ EXPECT_EQ(ParseOriginIsolation(""), false);
+
+ EXPECT_EQ(ParseOriginIsolation("?1"), true);
+ EXPECT_EQ(ParseOriginIsolation("?0"), false);
+
+ EXPECT_EQ(ParseOriginIsolation("?1;param"), true);
+ EXPECT_EQ(ParseOriginIsolation("?1;param=value"), true);
+ EXPECT_EQ(ParseOriginIsolation("?1;param=value;param2=value2"), true);
+
+ EXPECT_EQ(ParseOriginIsolation("true"), false);
+ EXPECT_EQ(ParseOriginIsolation("\"?1\""), false);
+ EXPECT_EQ(ParseOriginIsolation("1"), false);
+ EXPECT_EQ(ParseOriginIsolation("?2"), false);
+ EXPECT_EQ(ParseOriginIsolation("(?1)"), false);
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/parsed_headers.cc b/chromium/services/network/public/cpp/parsed_headers.cc
index f4c4e3f09c1..dc7b9ae7adc 100644
--- a/chromium/services/network/public/cpp/parsed_headers.cc
+++ b/chromium/services/network/public/cpp/parsed_headers.cc
@@ -10,6 +10,7 @@
#include "services/network/public/cpp/cross_origin_embedder_policy_parser.h"
#include "services/network/public/cpp/cross_origin_opener_policy_parser.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/cpp/origin_isolation_parser.h"
namespace network {
@@ -20,16 +21,18 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
if (!headers)
return parsed_headers;
- if (base::FeatureList::IsEnabled(features::kOutOfBlinkFrameAncestors)) {
- AddContentSecurityPolicyFromHeaders(
- *headers, url, &parsed_headers->content_security_policy);
- }
+ AddContentSecurityPolicyFromHeaders(*headers, url,
+ &parsed_headers->content_security_policy);
parsed_headers->cross_origin_embedder_policy =
ParseCrossOriginEmbedderPolicy(*headers);
parsed_headers->cross_origin_opener_policy =
ParseCrossOriginOpenerPolicy(*headers);
+ std::string origin_isolation;
+ if (headers->GetNormalizedHeader("Origin-Isolation", &origin_isolation))
+ parsed_headers->origin_isolation = ParseOriginIsolation(origin_isolation);
+
std::string accept_ch;
if (headers->GetNormalizedHeader("Accept-CH", &accept_ch))
parsed_headers->accept_ch = ParseAcceptCH(accept_ch);
diff --git a/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.cc b/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.cc
new file mode 100644
index 00000000000..5d0619259b9
--- /dev/null
+++ b/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 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 "services/network/public/cpp/quic_transport_error_mojom_traits.h"
+
+namespace mojo {
+
+bool StructTraits<network::mojom::QuicTransportErrorDataView,
+ net::QuicTransportError>::
+ Read(network::mojom::QuicTransportErrorDataView in,
+ net::QuicTransportError* out) {
+ if (in.net_error() > 0) {
+ return false;
+ }
+ if (in.quic_error() < 0 || in.quic_error() >= quic::QUIC_LAST_ERROR) {
+ return false;
+ }
+ std::string details;
+ if (!in.ReadDetails(&details)) {
+ return false;
+ }
+
+ *out = net::QuicTransportError(
+ in.net_error(), static_cast<quic::QuicErrorCode>(in.quic_error()),
+ std::move(details), in.safe_to_report_details());
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.h b/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.h
new file mode 100644
index 00000000000..d86e513c4b4
--- /dev/null
+++ b/chromium/services/network/public/cpp/quic_transport_error_mojom_traits.h
@@ -0,0 +1,36 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_QUIC_TRANSPORT_ERROR_MOJOM_TRAITS_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_QUIC_TRANSPORT_ERROR_MOJOM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/struct_traits.h"
+#include "net/quic/quic_transport_error.h"
+#include "services/network/public/mojom/quic_transport.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
+ StructTraits<network::mojom::QuicTransportErrorDataView,
+ net::QuicTransportError> {
+ static int32_t net_error(const net::QuicTransportError& e) {
+ return e.net_error;
+ }
+ static int32_t quic_error(const net::QuicTransportError& e) {
+ return static_cast<int32_t>(e.quic_error);
+ }
+ static const std::string& details(const net::QuicTransportError& e) {
+ return e.details;
+ }
+ static bool safe_to_report_details(const net::QuicTransportError& e) {
+ return e.safe_to_report_details;
+ }
+ static bool Read(network::mojom::QuicTransportErrorDataView in,
+ net::QuicTransportError* out);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_QUIC_TRANSPORT_ERROR_MOJOM_TRAITS_H_
diff --git a/chromium/services/network/public/cpp/resource_request.cc b/chromium/services/network/public/cpp/resource_request.cc
index 2b2692f98d7..7d32256054a 100644
--- a/chromium/services/network/public/cpp/resource_request.cc
+++ b/chromium/services/network/public/cpp/resource_request.cc
@@ -154,6 +154,7 @@ net::URLRequest::ReferrerPolicy ReferrerPolicyForUrlRequest(
return net::URLRequest::
REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
}
+ NOTREACHED();
return net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
}
diff --git a/chromium/services/network/public/cpp/resource_request_body.h b/chromium/services/network/public/cpp/resource_request_body.h
index 6d4920d3d95..2634327fdac 100644
--- a/chromium/services/network/public/cpp/resource_request_body.h
+++ b/chromium/services/network/public/cpp/resource_request_body.h
@@ -80,6 +80,12 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
// support chunked uploads.
void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
chunked_data_pipe_getter);
+ void SetAllowHTTP1ForStreamingUpload(bool allow) {
+ allow_http1_for_streaming_upload_ = allow;
+ }
+ bool AllowHTTP1ForStreamingUpload() const {
+ return allow_http1_for_streaming_upload_;
+ }
const std::vector<DataElement>* elements() const { return &elements_; }
std::vector<DataElement>* elements_mutable() { return &elements_; }
@@ -117,6 +123,8 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
bool contains_sensitive_info_;
+ bool allow_http1_for_streaming_upload_ = true;
+
DISALLOW_COPY_AND_ASSIGN(ResourceRequestBody);
};
diff --git a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
index 18dc5d0e976..beea0a11e91 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -54,6 +54,7 @@
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "services/network/test/test_network_context_client.h"
#include "services/network/test/test_network_service_client.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -592,6 +593,12 @@ class SimpleURLLoaderTestBase {
network_service_remote.BindNewPipeAndPassReceiver());
network::mojom::NetworkContextParamsPtr context_params =
network::mojom::NetworkContextParams::New();
+
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
+
network_service_remote->CreateNetworkContext(
network_context_.BindNewPipeAndPassReceiver(),
std::move(context_params));
diff --git a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
index 74df0098fa7..282d0ef1e08 100644
--- a/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/site_for_cookies_mojom_traits.cc
@@ -4,6 +4,7 @@
#include "services/network/public/cpp/site_for_cookies_mojom_traits.h"
#include "net/base/features.h"
+#include "services/network/public/cpp/crash_keys.h"
namespace mojo {
@@ -11,13 +12,19 @@ bool StructTraits<network::mojom::SiteForCookiesDataView, net::SiteForCookies>::
Read(network::mojom::SiteForCookiesDataView data,
net::SiteForCookies* out) {
std::string scheme, registrable_domain;
- if (!data.ReadScheme(&scheme))
+ if (!data.ReadScheme(&scheme)) {
return false;
- if (!data.ReadRegistrableDomain(&registrable_domain))
+ }
+ if (!data.ReadRegistrableDomain(&registrable_domain)) {
return false;
+ }
- return net::SiteForCookies::FromWire(scheme, registrable_domain,
- data.schemefully_same(), out);
+ bool result = net::SiteForCookies::FromWire(scheme, registrable_domain,
+ data.schemefully_same(), out);
+ if (!result) {
+ network::debug::SetDeserializationCrashKeyString("site_for_cookie");
+ }
+ return result;
}
} // namespace mojo
diff --git a/chromium/services/network/public/cpp/spki_hash_set.cc b/chromium/services/network/public/cpp/spki_hash_set.cc
new file mode 100644
index 00000000000..e8f2e3521c2
--- /dev/null
+++ b/chromium/services/network/public/cpp/spki_hash_set.cc
@@ -0,0 +1,30 @@
+// Copyright 2020 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 "services/network/public/cpp/spki_hash_set.h"
+
+#include "base/check_op.h"
+#include "base/logging.h"
+#include "net/base/hash_value.h"
+
+namespace network {
+
+// static
+SPKIHashSet CreateSPKIHashSet(const std::vector<std::string>& fingerprints) {
+ SPKIHashSet spki_hash_list;
+ for (const std::string& fingerprint : fingerprints) {
+ net::HashValue hash;
+ if (!hash.FromString("sha256/" + fingerprint)) {
+ LOG(ERROR) << "Invalid SPKI: " << fingerprint;
+ continue;
+ }
+ net::SHA256HashValue sha256;
+ DCHECK_EQ(hash.size(), sizeof(sha256));
+ memcpy(&sha256, hash.data(), sizeof(sha256));
+ spki_hash_list.insert(sha256);
+ }
+ return spki_hash_list;
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/spki_hash_set.h b/chromium/services/network/public/cpp/spki_hash_set.h
new file mode 100644
index 00000000000..b8c304bcc72
--- /dev/null
+++ b/chromium/services/network/public/cpp/spki_hash_set.h
@@ -0,0 +1,28 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_SPKI_HASH_SET_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_SPKI_HASH_SET_H_
+
+#include "base/component_export.h"
+#include "base/containers/flat_set.h"
+
+namespace net {
+struct SHA256HashValue;
+} // namespace net
+
+namespace network {
+
+// SPKIHashSet is a set of SHA-256 SPKI fingerprints (RFC 7469, Section 2.4).
+using SPKIHashSet = base::flat_set<net::SHA256HashValue>;
+
+// CreateSPKIHashSet converts a vector of Base64-encoded SHA-256 SPKI
+// fingerprints into an SPKIHashSet. Invalid fingerprints are logged and
+// skipped.
+COMPONENT_EXPORT(NETWORK_CPP)
+SPKIHashSet CreateSPKIHashSet(const std::vector<std::string>& fingerprints);
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_SPKI_HASH_SET_H_
diff --git a/chromium/services/network/public/cpp/trust_token_operation_authorization.h b/chromium/services/network/public/cpp/trust_token_operation_authorization.h
new file mode 100644
index 00000000000..6996e1f7f9f
--- /dev/null
+++ b/chromium/services/network/public/cpp/trust_token_operation_authorization.h
@@ -0,0 +1,41 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_OPERATION_AUTHORIZATION_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_OPERATION_AUTHORIZATION_H_
+
+#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
+
+namespace network {
+
+// A Trust Tokens operation requires the 'trust-token-redemption' Feature Policy
+// feature if it's of type "redemption" or "signing" (as opposed to "issuance").
+//
+// Needing the top-level frame's authorization to execute a redemption operation
+// has two motivations: security and privacy.
+// - Security: Executing a redemption operation counts against rate limits,
+// currently indelible short of a user-initiated browsing data clear, that are
+// scoped to the redemption-time top frame origin. Using Feature Policy stops
+// subframes from denying service to ancestor frames by exhausting these rate
+// limits.
+// - Privacy: The results of a redemption operation ("signed redemption
+// records") are persistent first-party identifiers in the context of the top
+// frame at redemption time. Since embedded third-party frames are on the other
+// side of a privacy boundary, we’d like to prohibit these third-party frames
+// from having access to the redeeming-context SRRs without the top-level
+// frame's explicit consent.
+constexpr bool DoesTrustTokenOperationRequireFeaturePolicy(
+ mojom::TrustTokenOperationType type) {
+ switch (type) {
+ case mojom::TrustTokenOperationType::kRedemption:
+ case mojom::TrustTokenOperationType::kSigning:
+ return true;
+ case mojom::TrustTokenOperationType::kIssuance:
+ return false;
+ }
+}
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_OPERATION_AUTHORIZATION_H_
diff --git a/chromium/services/network/public/cpp/trust_token_parameterization.h b/chromium/services/network/public/cpp/trust_token_parameterization.h
new file mode 100644
index 00000000000..4bb09ab64ae
--- /dev/null
+++ b/chromium/services/network/public/cpp/trust_token_parameterization.h
@@ -0,0 +1,29 @@
+// Copyright 2020 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 SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_PARAMETERIZATION_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_PARAMETERIZATION_H_
+
+namespace network {
+
+// Note: This file contains Trust Tokens constants that are part of the network
+// service public API. Network service-internal Trust Tokens-related constants
+// live in a corresponding file in the network service-internal Trust Tokens
+// directory.
+
+// The maximum number of trust token issuers allowed to be associated with a
+// given top-level origin.
+//
+// This value is quite low because registering additional issuers with an origin
+// has a number of privacy risks (for instance, whether or not a user has any
+// tokens issued by a given issuer reveals one bit of identifying information).
+constexpr int kTrustTokenPerToplevelMaxNumberOfAssociatedIssuers = 2;
+
+// When the client provides custom signing data alongside a Trust Tokens signed
+// request, this is the data's maximum length in bytes.
+constexpr size_t kTrustTokenAdditionalSigningDataMaxSizeBytes = 1 << 11;
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_TRUST_TOKEN_PARAMETERIZATION_H_
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.cc b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
index 5c94c3cd869..ce1478f6df6 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
@@ -12,6 +12,7 @@
#include "mojo/public/cpp/base/file_path_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
+#include "services/network/public/cpp/crash_keys.h"
#include "services/network/public/cpp/http_request_headers_mojom_traits.h"
#include "services/network/public/cpp/isolation_info_mojom_traits.h"
#include "services/network/public/cpp/network_ipc_param_traits.h"
@@ -171,13 +172,30 @@ bool StructTraits<
network::mojom::URLRequestDataView,
network::ResourceRequest>::Read(network::mojom::URLRequestDataView data,
network::ResourceRequest* out) {
- if (!data.ReadMethod(&out->method) || !data.ReadUrl(&out->url) ||
- !data.ReadSiteForCookies(&out->site_for_cookies) ||
- !data.ReadTrustedParams(&out->trusted_params) ||
- !data.ReadRequestInitiator(&out->request_initiator) ||
- !data.ReadIsolatedWorldOrigin(&out->isolated_world_origin) ||
- !data.ReadReferrer(&out->referrer) ||
- !data.ReadReferrerPolicy(&out->referrer_policy) ||
+ if (!data.ReadMethod(&out->method)) {
+ return false;
+ }
+ if (!data.ReadUrl(&out->url)) {
+ network::debug::SetDeserializationCrashKeyString("url");
+ return false;
+ }
+ if (!data.ReadSiteForCookies(&out->site_for_cookies) ||
+ !data.ReadTrustedParams(&out->trusted_params)) {
+ return false;
+ }
+ if (!data.ReadRequestInitiator(&out->request_initiator)) {
+ network::debug::SetDeserializationCrashKeyString("request_initiator");
+ return false;
+ }
+ if (!data.ReadIsolatedWorldOrigin(&out->isolated_world_origin)) {
+ network::debug::SetDeserializationCrashKeyString("isolated_world_origin");
+ return false;
+ }
+ if (!data.ReadReferrer(&out->referrer)) {
+ network::debug::SetDeserializationCrashKeyString("referrer");
+ return false;
+ }
+ if (!data.ReadReferrerPolicy(&out->referrer_policy) ||
!data.ReadHeaders(&out->headers) ||
!data.ReadCorsExemptHeaders(&out->cors_exempt_headers) ||
!data.ReadPriority(&out->priority) ||
@@ -242,15 +260,27 @@ bool StructTraits<network::mojom::URLRequestBodyDataView,
return false;
body->set_identifier(data.identifier());
body->set_contains_sensitive_info(data.contains_sensitive_info());
+ body->SetAllowHTTP1ForStreamingUpload(
+ data.allow_http1_for_streaming_upload());
*out = std::move(body);
return true;
}
bool StructTraits<network::mojom::DataElementDataView, network::DataElement>::
Read(network::mojom::DataElementDataView data, network::DataElement* out) {
- if (!data.ReadPath(&out->path_) || !data.ReadFile(&out->file_) ||
- !data.ReadBlobUuid(&out->blob_uuid_) ||
- !data.ReadExpectedModificationTime(&out->expected_modification_time_)) {
+ if (!data.ReadPath(&out->path_)) {
+ network::debug::SetDeserializationCrashKeyString("data_element_path");
+ return false;
+ }
+ if (!data.ReadFile(&out->file_)) {
+ network::debug::SetDeserializationCrashKeyString("data_element_file");
+ return false;
+ }
+ if (!data.ReadBlobUuid(&out->blob_uuid_)) {
+ network::debug::SetDeserializationCrashKeyString("data_element_blob_uuid");
+ return false;
+ }
+ if (!data.ReadExpectedModificationTime(&out->expected_modification_time_)) {
return false;
}
if (data.type() == network::mojom::DataElementType::kBytes) {
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits.h b/chromium/services/network/public/cpp/url_request_mojom_traits.h
index 498c7bb6a78..9e1dd066185 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.h
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.h
@@ -288,6 +288,11 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
return r->contains_sensitive_info_;
}
+ static bool allow_http1_for_streaming_upload(
+ const scoped_refptr<network::ResourceRequestBody>& r) {
+ return r->allow_http1_for_streaming_upload_;
+ }
+
static bool Read(network::mojom::URLRequestBodyDataView data,
scoped_refptr<network::ResourceRequestBody>* out);
};
diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn
index a79516b579e..4d5bef25d3c 100644
--- a/chromium/services/network/public/mojom/BUILD.gn
+++ b/chromium/services/network/public/mojom/BUILD.gn
@@ -49,6 +49,22 @@ mojom("mojom_ip_address") {
"//services/network/public/cpp:cpp_base",
]
},
+ {
+ types = [
+ {
+ mojom = "network.mojom.ConnectionInfo"
+ cpp = "::net::HttpResponseInfo::ConnectionInfo"
+ },
+ ]
+ traits_headers = [
+ "//net/http/http_response_info.h",
+ "//services/network/public/cpp/network_ipc_param_traits.h",
+ ]
+ traits_public_deps = [
+ "//net",
+ "//services/network/public/cpp:cpp_base",
+ ]
+ },
]
cpp_typemaps = [
@@ -76,6 +92,21 @@ mojom("mojom_ip_address") {
[ "//services/network/public/cpp/address_list_mojom_traits.h" ]
traits_public_deps = [ "//net" ]
},
+ {
+ types = [
+ {
+ mojom = "network.mojom.QuicTransportError"
+ cpp = "::net::QuicTransportError"
+ },
+ ]
+ traits_headers = [
+ "//services/network/public/cpp/quic_transport_error_mojom_traits.h",
+ ]
+ traits_public_deps = [
+ "//net",
+ "//services/network/public/cpp:cpp_base",
+ ]
+ },
]
cpp_typemaps += shared_cpp_typemaps
@@ -325,6 +356,10 @@ mojom("cookies_mojom") {
cpp = "::net::CookieSameSite"
},
{
+ mojom = "network.mojom.CookieEffectiveSameSite"
+ cpp = "::net::CookieEffectiveSameSite"
+ },
+ {
mojom = "network.mojom.CookieSameSiteContext"
cpp = "::net::CookieOptions::SameSiteCookieContext"
},
@@ -342,11 +377,11 @@ mojom("cookies_mojom") {
},
{
mojom = "network.mojom.CookieInclusionStatusWarningReason"
- cpp = "::net::CanonicalCookie::CookieInclusionStatus::WarningReason"
+ cpp = "::net::CookieInclusionStatus::WarningReason"
},
{
mojom = "network.mojom.CookieInclusionStatus"
- cpp = "::net::CanonicalCookie::CookieInclusionStatus"
+ cpp = "::net::CookieInclusionStatus"
move_only = true
},
{
@@ -354,6 +389,10 @@ mojom("cookies_mojom") {
cpp = "::net::CookieWithStatus"
},
{
+ mojom = "network.mojom.CookieWithAccessResult"
+ cpp = "::net::CookieWithAccessResult"
+ },
+ {
mojom = "network.mojom.CookieAndLineWithStatus"
cpp = "::net::CookieAndLineWithStatus"
},
@@ -646,10 +685,6 @@ mojom("mojom") {
cpp = "::net::ct::CTPolicyCompliance"
},
{
- mojom = "network.mojom.ConnectionInfo"
- cpp = "::net::HttpResponseInfo::ConnectionInfo"
- },
- {
mojom = "network.mojom.CorsErrorStatus"
cpp = "::network::CorsErrorStatus"
},
diff --git a/chromium/services/network/public/mojom/cert_verifier_service.mojom b/chromium/services/network/public/mojom/cert_verifier_service.mojom
index 063549cae19..a6181fa2c5d 100644
--- a/chromium/services/network/public/mojom/cert_verifier_service.mojom
+++ b/chromium/services/network/public/mojom/cert_verifier_service.mojom
@@ -6,6 +6,7 @@ module cert_verifier.mojom;
import "mojo/public/mojom/base/big_buffer.mojom";
import "services/network/public/mojom/network_param.mojom";
+import "services/network/public/mojom/url_loader_factory.mojom";
// Mojo version of net::CertVerifier::RequestParams.
struct RequestParams {
@@ -25,12 +26,30 @@ struct CertVerifierConfig {
bool disable_symantec_enforcement;
mojo_base.mojom.BigBuffer crl_set;
array<network.mojom.X509Certificate> additional_trust_anchors;
+ array<network.mojom.X509Certificate> additional_untrusted_authorities;
+};
+
+// Allows the CertVerifierService to connect a new URLLoaderFactory if its
+// existing URLLoaderFactory is disconnected. The CertVerifierService uses the
+// URLLoaderFactory for AIA and OCSP fetching.
+interface URLLoaderFactoryConnector {
+ // Binds a URLLoaderFactory.
+ CreateURLLoaderFactory(
+ pending_receiver<network.mojom.URLLoaderFactory> url_loader_factory);
};
// An interface that verifies a certificate based on the |params|, and calls the
// |Complete| method on the returned CertVerifierRequest when the result is
// available.
interface CertVerifierService {
+ // |url_loader_factory| allows the CertVerifierService to connect to the
+ // network for things like AIA or OCSP. |reconnector| allows the CertVerifier
+ // to reconnect its URLLoaderFactory in case the network service disconnects
+ // its URLLoaderFactories without crashing. Must be called before Verify() to
+ // have an effect.
+ EnableNetworkAccess(
+ pending_remote<network.mojom.URLLoaderFactory> url_loader_factory,
+ pending_remote<URLLoaderFactoryConnector>? reconnector);
// Mojo IPC used to verify a certificate. Sends results to the
// |cert_verifier_request| interface when verification is complete.
Verify(RequestParams params,
diff --git a/chromium/services/network/public/mojom/content_security_policy.mojom b/chromium/services/network/public/mojom/content_security_policy.mojom
index 114377a2fe1..ca7d5062a8f 100644
--- a/chromium/services/network/public/mojom/content_security_policy.mojom
+++ b/chromium/services/network/public/mojom/content_security_policy.mojom
@@ -81,6 +81,13 @@ enum CSPDirectiveName {
FormAction,
NavigateTo,
FrameAncestors,
+ ImgSrc,
+ MediaSrc,
+ ObjectSrc,
+ ScriptSrc,
+ StyleSrc,
+ WorkerSrc,
+ ConnectSrc
};
struct ContentSecurityPolicy {
@@ -98,7 +105,8 @@ struct ContentSecurityPolicy {
bool treat_as_public_address = false;
// https://www.w3.org/TR/CSP3/#directive-sandbox
- WebSandboxFlags sandbox; // WebSandboxFlags::kNone.
+ // This uses the convention: kAll means "everything is allowed".
+ WebSandboxFlags sandbox = WebSandboxFlags.kAll;
ContentSecurityPolicyHeader header;
diff --git a/chromium/services/network/public/mojom/cookie_manager.mojom b/chromium/services/network/public/mojom/cookie_manager.mojom
index 045bcc71c67..07aaee6a595 100644
--- a/chromium/services/network/public/mojom/cookie_manager.mojom
+++ b/chromium/services/network/public/mojom/cookie_manager.mojom
@@ -78,6 +78,13 @@ enum CookieSameSite {
// Reserved 3 (was EXTENDED_MODE), next number is 4.
};
+enum CookieEffectiveSameSite {
+ kNoRestriction = 0,
+ kLaxMode = 1,
+ kStrictMode = 2,
+ kLaxModeAllowUnsafe = 3,
+};
+
enum ContextType {
CROSS_SITE,
SAME_SITE_LAX_METHOD_UNSAFE,
@@ -127,10 +134,10 @@ struct CanonicalCookie {
struct CookieInclusionStatus {
// Bitfield. Is defined in
- // net::CanonicalCookie::CookieInclusionStatus::ExclusionReason.
+ // net::CookieInclusionStatus::ExclusionReason.
+ // net::CookieInclusionStatus::WarningReason.
uint32 exclusion_reasons;
// Bitfield. Is defined in
- // net::CanonicalCookie::CookieInclusionStatus::WarningReason.
uint32 warning_reasons;
};
@@ -145,6 +152,16 @@ struct CookieAndLineWithStatus {
CookieInclusionStatus status;
};
+struct CookieAccessResult {
+ CookieEffectiveSameSite effective_same_site;
+ CookieInclusionStatus status;
+};
+
+struct CookieWithAccessResult {
+ CanonicalCookie cookie;
+ CookieAccessResult access_result;
+};
+
// Keep values here in sync with net::CookieChangeCause.
enum CookieChangeCause {
// The cookie was inserted.
@@ -276,8 +293,8 @@ interface CookieManager {
// blocked from being sent along with the reason each cookie was blocked. By
// default, that option is not set and |excluded_cookies| is an empty list.
GetCookieList(url.mojom.Url url, CookieOptions cookie_options)
- => (array<CookieWithStatus> cookies,
- array<CookieWithStatus> excluded_cookies);
+ => (array<CookieWithAccessResult> cookies,
+ array<CookieWithAccessResult> excluded_cookies);
// Set a cookie. |source_url| is used to check whether existing secure
// cookies can be overwritten (secure cookies may be created from a
diff --git a/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom b/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom
index 887426512d2..ac96351bc7a 100644
--- a/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom
+++ b/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom
@@ -4,6 +4,29 @@
module network.mojom;
+import "url/mojom/url.mojom";
+
+// Reports potential COOP violations. Implemented in the browser process.
+// TODO(ahemery, pmeuleman): Add extra coop breakage cases as listed in
+// https://docs.google.com/document/d/1zWqwI8PFrezwQpBSejIMUfdtsIYl9-h8epasdrDXVIM/edit
+interface CrossOriginOpenerPolicyReporter {
+
+ // When COOP triggers a browsing context group swap during a navigation, we
+ // lose the existing opener, which can create page breakage. We report such
+ // cases using this function.
+ // |is_reported_from_document| is true if the report is coming from the
+ // document begin navigated from. It is false if the report originates from
+ // the document we are navigating to.
+ // |is_report_only| is true if we are reporting a breakage that would have
+ // occurred if we enforced the reporting only values of COOP.
+ QueueOpenerBreakageReport(url.mojom.Url other_url,
+ bool is_reported_from_document,
+ bool is_report_only);
+
+ // Connects a new pipe to this instance.
+ Clone(pending_receiver<CrossOriginOpenerPolicyReporter> receiver);
+};
+
// Cross-Origin-Opener-Policy enum representing parsed values.
enum CrossOriginOpenerPolicyValue {
// Severs the opener relationship with openers/opened documents that are not
diff --git a/chromium/services/network/public/mojom/fetch_api.mojom b/chromium/services/network/public/mojom/fetch_api.mojom
index b6d2b5ea4fd..8b3f2f16df1 100644
--- a/chromium/services/network/public/mojom/fetch_api.mojom
+++ b/chromium/services/network/public/mojom/fetch_api.mojom
@@ -62,9 +62,21 @@ enum RedirectMode {
// Corresponds to Fetch request's "credentials mode":
// https://fetch.spec.whatwg.org/#concept-request-credentials-mode
enum CredentialsMode {
+ // TODO(https://crbug.com/775438): Due to a bug, this does not properly
+ // correspond to Fetch's "credentials mode", in that client certificates will
+ // be sent is available, or the handshake will be aborted in order to allow
+ // selecting a client cert. The correct behavior is to omit all client certs
+ // and continue the handshake without sending one if requested.
kOmit,
+
kSameOrigin,
kInclude,
+
+ // TODO(https://crbug.com/775438): This works around kOmit not doing the
+ // spec-defined behavior. This is a temporary workaround that explicitly
+ // indicates the caller wants the spec-defined behavior. It's named as such
+ // because this should be only temporary, until kOmit is fixed.
+ kOmitBug_775438_Workaround
};
// Corresponds to response types from the Fetch spec:
diff --git a/chromium/services/network/public/mojom/load_timing_info.mojom b/chromium/services/network/public/mojom/load_timing_info.mojom
index 2be0ef5a089..c8a6db8697e 100644
--- a/chromium/services/network/public/mojom/load_timing_info.mojom
+++ b/chromium/services/network/public/mojom/load_timing_info.mojom
@@ -29,6 +29,7 @@ struct LoadTimingInfo {
mojo_base.mojom.TimeTicks send_end;
mojo_base.mojom.TimeTicks receive_headers_start;
mojo_base.mojom.TimeTicks receive_headers_end;
+ mojo_base.mojom.TimeTicks first_early_hints_time;
mojo_base.mojom.TimeTicks push_start;
mojo_base.mojom.TimeTicks push_end;
@@ -39,4 +40,14 @@ struct LoadTimingInfo {
// The time immediately before dispatching fetch event in ServiceWorker.
// If the response is not provided by the ServiceWorker, kept empty.
mojo_base.mojom.TimeTicks service_worker_ready_time;
+
+ // The time immediately before the service worker fetch event handler runs.
+ // If the response is not provided by the service worker, kept empty.
+ // If respondWith() was not called, kept empty.
+ mojo_base.mojom.TimeTicks service_worker_fetch_start;
+
+ // The time when a service worker respondWith promise gets settled.
+ // If the response is not provided by the service worker, kept empty.
+ // If respondWith() was not called, kept empty.
+ mojo_base.mojom.TimeTicks service_worker_respond_with_settled;
};
diff --git a/chromium/services/network/public/mojom/network_context.mojom b/chromium/services/network/public/mojom/network_context.mojom
index 93a2baf855d..6d5110add0e 100644
--- a/chromium/services/network/public/mojom/network_context.mojom
+++ b/chromium/services/network/public/mojom/network_context.mojom
@@ -11,7 +11,7 @@ import "mojo/public/mojom/base/time.mojom";
import "mojo/public/mojom/base/unguessable_token.mojom";
import "mojo/public/mojom/base/values.mojom";
import "services/network/public/mojom/address_list.mojom";
-import "services/network/public/mojom/parsed_headers.mojom";
+import "services/network/public/mojom/cert_verifier_service.mojom";
import "services/network/public/mojom/cookie_access_observer.mojom";
import "services/network/public/mojom/cookie_manager.mojom";
import "services/network/public/mojom/default_credentials.mojom";
@@ -29,6 +29,7 @@ import "services/network/public/mojom/network_isolation_key.mojom";
import "services/network/public/mojom/isolation_info.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/origin_policy_manager.mojom";
+import "services/network/public/mojom/parsed_headers.mojom";
import "services/network/public/mojom/p2p.mojom";
import "services/network/public/mojom/p2p_trusted.mojom";
import "services/network/public/mojom/proxy_config.mojom";
@@ -123,6 +124,21 @@ struct CertVerifierCreationParams {
TrialComparisonCertVerifierParams? trial_comparison_cert_verifier_params;
};
+// Includes a pipe to a CertVerifierService for usage by the
+// NetworkContext.
+struct CertVerifierServiceRemoteParams {
+ // A pipe to the CertVerifierService.
+ pending_remote<cert_verifier.mojom.CertVerifierService>?
+ cert_verifier_service;
+};
+
+// Contains the parameters necessary to either connect to a CertVerifierService
+// or create a net::CertVerifier in the network service itself.
+union CertVerifierParams {
+ CertVerifierServiceRemoteParams remote_params;
+ CertVerifierCreationParams creation_params;
+};
+
// Client to update the custom proxy config.
interface CustomProxyConfigClient {
OnCustomProxyConfigUpdated(CustomProxyConfig proxy_config);
@@ -373,8 +389,9 @@ struct NetworkContextParams {
[EnableIf=is_ct_supported]
mojo_base.mojom.Time ct_log_update_time;
- // Contains the parameters used to instantiate a net::CertVerifier in-process.
- CertVerifierCreationParams? cert_verifier_creation_params;
+ // Contains either a pipe to a CertVerifierService, or parameters used to
+ // instantiate a net::CertVerifier in-process.
+ CertVerifierParams? cert_verifier_params;
// Initial additional certificates that will be used for certificate
// validation.
@@ -407,24 +424,6 @@ struct NetworkContextParams {
// decide. This should only be used by tests.
bool skip_reporting_send_permission_check = false;
- // Sets whether the NetworkContext should be used for globally scoped tasks
- // that need to make network requests. Currently this includes DNS over HTTPS
- // requests and certain cert validation requests (OCSP, AIA, etc) on some
- // platforms. May only be set to true the first NetworkContext created using
- // the NetworkService. Destroying a NetworkContext created with this set to
- // true will destroy all other NetworkContexts.
- //
- // A failure to mark a NetworkContext as being used by certificate
- // verification may result in incorrect certificate validation behaviors,
- // such as the inability to verify EV certificates, to build paths when
- // intermediates are missing, and to enforce revocation checking when it was
- // requested via policy.
- //
- // TODO(mmenke): Once NSS is not used on any platform for certificate
- // verification, we should consider using each URLRequestContext to do its own
- // validation.
- bool primary_network_context = false;
-
// Specifies the initial set of allowed and blocked origins for the
// URLLoaderFactory consumers to access beyond the same-origin-policy.
array<CorsOriginAccessPatterns> cors_origin_access_list;
@@ -587,6 +586,13 @@ struct ClientSecurityState {
IPAddressSpace ip_address_space = IPAddressSpace.kUnknown;
};
+// Whether to forbid all Trust Tokens redemption and signing operations
+// (https://github.com/wicg/trust-token-api).
+enum TrustTokenRedemptionPolicy {
+ kForbid,
+ kPotentiallyPermit,
+};
+
struct URLLoaderFactoryParams {
// Process requesting the URLLoaderFactory.
// Set to kBrowserProcessId to indicate the browser process.
@@ -598,10 +604,6 @@ struct URLLoaderFactoryParams {
// 2) Make this an *origin* lock (rather than a *site* lock).
url.mojom.Origin? request_initiator_site_lock;
- // For subresource requests from frames, |top_frame_origin| is the request's
- // top frame's origin.
- url.mojom.Origin? top_frame_origin;
-
// Cross-origin read blocking (CORB) configuration.
bool is_corb_enabled = true;
@@ -667,10 +669,33 @@ struct URLLoaderFactoryParams {
ClientSecurityState? client_security_state;
// Used to report CORP violations caused by COEP.
- CrossOriginEmbedderPolicyReporter? coep_reporter;
+ pending_remote<CrossOriginEmbedderPolicyReporter>? coep_reporter;
// Used to notify clients about cookie reads or writes.
- CookieAccessObserver? cookie_observer;
+ pending_remote<CookieAccessObserver>? cookie_observer;
+
+ // If this equals kForbid, the context to which this loader is bound does not
+ // allow any Trust Tokens (https://github.com/wicg/trust-token-api)
+ // redemption or signing operations.
+ //
+ // This is set to kForbid for requests from subframes with the
+ // `trust-token-redemption` Feature Policy feature disabled by (1) policies
+ // inherited from their parents, or (2) the frames' iframe tag attributes.
+ //
+ // Note: Response headers can also disable this Feature Policy feature.
+ // This will not necessarily be reflected in the the enum's value. The
+ // response headers' value is only available from an untrusted source.
+ // - If the renderer behaves correctly, renderer-side checks guarantee that
+ // these operations will not be executed in frames with the policy disabled
+ // via response headers.
+ // - If the renderer doesn't behave correctly, there's no point in
+ // propagating the renderer's untrusted report about the response headers'
+ // value.
+ //
+ // TODO(crbug.com/1071848): Once Feature Policy headers are available from a
+ // trusted source, it would be good to set this depending on the headers'
+ // values, too.
+ TrustTokenRedemptionPolicy trust_token_redemption_policy = kPotentiallyPermit;
};
// The |credentials| output parameter is given to URLRequest::SetAuth()
@@ -729,6 +754,8 @@ interface SSLPrivateKey {
// Callback interface for NetworkContext when routing identifiers aren't
// available. Otherwise generally callbacks from the network service go on
// NetworkServiceClient.
+//
+// Implemented by the browser process.
interface NetworkContextClient {
// Called when we receive an authentication failure.
// The |auth_challenge_responder| will respond to auth challenge with
@@ -821,6 +848,10 @@ interface NetworkContextClient {
// Represents a distinct context for making network requests, with its own
// storage (e.g. cookies and cache).
+//
+// NetworkContext is implemented by the network service. It is a trusted
+// interface that must not be sent to an untrusted process like a renderer
+// process. Only the browser process should have access to it.
interface NetworkContext {
// Sets a client for this network context.
SetClient(pending_remote<NetworkContextClient> client);
@@ -1026,7 +1057,8 @@ interface NetworkContext {
// header.
[EnableIf=is_ct_supported]
AddExpectCT(string host, mojo_base.mojom.Time expiry,
- bool enforce, url.mojom.Url report_uri) => (bool success);
+ bool enforce, url.mojom.Url report_uri,
+ NetworkIsolationKey network_isolation_key) => (bool success);
// Send a test CT report with dummy data for test purposes.
[EnableIf=is_ct_supported]
@@ -1035,7 +1067,9 @@ interface NetworkContext {
// Retrieves the expect CT state from the associated network context
// transport security state.
[EnableIf=is_ct_supported]
- GetExpectCTState(string domain) => (mojo_base.mojom.DictionaryValue state);
+ GetExpectCTState(string domain,
+ NetworkIsolationKey network_isolation_key)
+ => (mojo_base.mojom.DictionaryValue state);
// Creates a UDP socket. Caller can supply a |listener| interface pointer
// to listen for incoming datagrams. A null |listener| is acceptable if caller
@@ -1172,12 +1206,15 @@ interface NetworkContext {
// Creates a QuicTransport connection to |url|. |origin| is used for the
// client indication - see
// https://tools.ietf.org/html/draft-vvv-webtransport-quic-01#section-3.2 .
+ // When |fingerprints| is not empty, it is used to verify the certificate.
+ // https://wicg.github.io/web-transport/#dom-quictransportconfiguration-server_certificate_fingerprints
//
// It is recommended to detect mojo connection errors on |handshake_client|.
CreateQuicTransport(
url.mojom.Url url,
url.mojom.Origin origin,
NetworkIsolationKey network_isolation_key,
+ array<QuicTransportCertificateFingerprint> fingerprints,
pending_remote<QuicTransportHandshakeClient> handshake_client);
// Create a NetLogExporter, which helps export NetLog to an existing file.
@@ -1200,7 +1237,11 @@ interface NetworkContext {
NetworkIsolationKey network_isolation_key);
// Creates a P2PSocketManager instance, used for WebRTC.
+ // |network_isolation_key| is the network cache shard to associate with the
+ // P2PSocketManager instance, and affects DNS cache shard used and proxy
+ // connection sharing.
CreateP2PSocketManager(
+ NetworkIsolationKey network_isolation_key,
pending_remote<P2PTrustedSocketManagerClient> client,
pending_receiver<P2PTrustedSocketManager> trusted_socket_manager,
pending_receiver<P2PSocketManager> socket_manager);
@@ -1281,7 +1322,8 @@ interface NetworkContext {
url.mojom.Origin source_origin, array<CorsOriginPattern> allow_patterns,
array<CorsOriginPattern> block_patterns) => ();
- // Sets extra CORS safelisted request headers names dynamically.
+ // Sets extra CORS safelisted request headers names dynamically. Headers need
+ // to be in lower case.
SetCorsExtraSafelistedRequestHeaderNames(
array<string> cors_extra_safelisted_request_header_names);
diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom
index 565d98ad87c..6a016cc0eb0 100644
--- a/chromium/services/network/public/mojom/network_service.mojom
+++ b/chromium/services/network/public/mojom/network_service.mojom
@@ -42,7 +42,8 @@ struct LoadInfo {
uint64 upload_size;
};
-// Network service interface to the browser.
+// Implemented by the browser process. The network service sends messages to
+// the browser process over this interface.
interface NetworkServiceClient {
// Called periodically to update the client about progress of the current
// loads. To avoid flooding the client, it has to ack the update before it can
@@ -63,7 +64,7 @@ interface NetworkServiceClient {
int32 process_id,
int32 routing_id,
string devtool_request_id,
- array<CookieWithStatus> cookies_with_status,
+ array<CookieWithAccessResult> cookies_with_access_result,
array<HttpRawHeaderPair> headers);
// Called to send information about the cookies blocked from storage from a
@@ -149,10 +150,10 @@ struct HttpAuthDynamicParams {
// True if Negotiate SPNs (service principal names) should include ports
// when the port isn't a standard port (80 or 443).
- bool enable_negotiate_port = true;
+ bool enable_negotiate_port = false;
// Whether NTLM V2 is enabled on POSIX platforms. No effect elsewhere.
- bool ntlm_v2_enabled = false;
+ bool ntlm_v2_enabled = true;
// The AccountManager AccountManagerget.AccountsByTypeAndFeatures on Android
// when using Negotiate authentication.
@@ -203,7 +204,11 @@ struct LoggingSettings {
handle<platform> log_file_descriptor;
};
-// Browser interface to the network service.
+// Implemented by the network service. The browser process sends messages to
+// the network service over this interface.
+//
+// This is a trusted interface that only the browser process should have access
+// to. It must not be sent to any untrusted process like a renderer process.
interface NetworkService {
// Sets client used by all |NetworkContext|s creating by |NetworkService|.
// Pending requests may hang if the |client| pipe is closed before they
diff --git a/chromium/services/network/public/mojom/parsed_headers.mojom b/chromium/services/network/public/mojom/parsed_headers.mojom
index c2e5624a931..01f1bf852cb 100644
--- a/chromium/services/network/public/mojom/parsed_headers.mojom
+++ b/chromium/services/network/public/mojom/parsed_headers.mojom
@@ -23,6 +23,9 @@ struct ParsedHeaders {
// Cross-Origin-opener-Policy-Report-Only headers.
CrossOriginOpenerPolicy cross_origin_opener_policy;
+ // The parsed value of the Origin-Isolation header.
+ bool origin_isolation = false;
+
// The parsed Accept-CH from response headers.
//
// If this is missing, there is no valid accept-ch header, so client hints
diff --git a/chromium/services/network/public/mojom/proxy_resolving_socket.mojom b/chromium/services/network/public/mojom/proxy_resolving_socket.mojom
index 2fb1a981e9d..3c5d7906820 100644
--- a/chromium/services/network/public/mojom/proxy_resolving_socket.mojom
+++ b/chromium/services/network/public/mojom/proxy_resolving_socket.mojom
@@ -6,6 +6,7 @@ module network.mojom;
import "services/network/public/mojom/ip_endpoint.mojom";
import "services/network/public/mojom/mutable_network_traffic_annotation_tag.mojom";
+import "services/network/public/mojom/network_isolation_key.mojom";
import "services/network/public/mojom/network_param.mojom";
import "services/network/public/mojom/ssl_config.mojom";
import "services/network/public/mojom/tcp_socket.mojom";
@@ -52,19 +53,25 @@ struct ProxyResolvingSocketOptions {
// factory instance.
interface ProxyResolvingSocketFactory {
// Creates a socket connected to |url|. This connection might be done through
- // proxies if any is set in system's proxy settings. On success, |result| is
- // net::OK. Caller is to use |send_stream| to send data and
- // |receive_stream| to receive data over the connection. On failure, |result|
- // is a network error code. |local_addr| contains the local address of the
- // socket. |peer_addr| contains the peer address. If socket is connected to a
- // proxy, |peer_addr| will be null.
+ // proxies if any is set in system's proxy settings.
+ //
+ // |network_isolation_key| indicates the network storage shard to use for
+ // shared resources, such as the DNS cache and shared proxy connections.
+ //
+ // On success, |result| is net::OK. Caller is to use |send_stream| to send
+ // data and |receive_stream| to receive data over the connection. On failure,
+ // |result| is a network error code. |local_addr| contains the local address
+ // of the socket. |peer_addr| contains the peer address. If socket is
+ // connected to a proxy, |peer_addr| will be null.
//
// If socket is closed before the callback can be completed, the callback will
// be invoked with net::ERR_ABORTED.
//
// Any sockets that are created but are yet to be destroyed will be destroyed
// when the implementation of this factory goes away.
- CreateProxyResolvingSocket(url.mojom.Url url,
+ CreateProxyResolvingSocket(
+ url.mojom.Url url,
+ NetworkIsolationKey network_isolation_key,
ProxyResolvingSocketOptions? options,
MutableNetworkTrafficAnnotationTag traffic_annotation,
pending_receiver<ProxyResolvingSocket> socket,
diff --git a/chromium/services/network/public/mojom/quic_transport.mojom b/chromium/services/network/public/mojom/quic_transport.mojom
index 4ae510ce7b4..e8b4de15421 100644
--- a/chromium/services/network/public/mojom/quic_transport.mojom
+++ b/chromium/services/network/public/mojom/quic_transport.mojom
@@ -26,6 +26,14 @@ struct QuicTransportError {
bool safe_to_report_details = false;
};
+// The fingerprint of a certificate accompanied with the hash algorithm.
+// https://wicg.github.io/web-transport/#quic-transport-configuration
+// https://www.w3.org/TR/webrtc/#dom-rtcdtlsfingerprint
+struct QuicTransportCertificateFingerprint {
+ string algorithm;
+ string fingerprint;
+};
+
// A mojo interface for https://wicg.github.io/web-transport/#quic-transport.
interface QuicTransport {
// A datagram message is sent from the client. The response message represents
@@ -54,6 +62,9 @@ interface QuicTransport {
// be able to write any data to the stream, but it may be able to use other
// functions such as reading data from the stream.
SendFin(uint32 stream_id);
+
+ // Aborts the stream for |stream_id|.
+ AbortStream(uint32 stream_id, uint64 code);
};
// A mojo interface for the client of QuicTransport.
diff --git a/chromium/services/network/public/mojom/referrer_policy.mojom b/chromium/services/network/public/mojom/referrer_policy.mojom
index 4960fafb31d..b159d7cba5e 100644
--- a/chromium/services/network/public/mojom/referrer_policy.mojom
+++ b/chromium/services/network/public/mojom/referrer_policy.mojom
@@ -4,10 +4,7 @@
module network.mojom;
-// Don't make backwards-incompatible changes to this definition!
-// It's used in PageState serialization, so backwards incompatible changes
-// would cause stored PageState objects to be un-parseable. Please contact the
-// page state serialization owners before making such a change.
+[Stable]
enum ReferrerPolicy {
kAlways,
kDefault,
diff --git a/chromium/services/network/public/mojom/restricted_cookie_manager.mojom b/chromium/services/network/public/mojom/restricted_cookie_manager.mojom
index ed16a743b5f..8e3f1982686 100644
--- a/chromium/services/network/public/mojom/restricted_cookie_manager.mojom
+++ b/chromium/services/network/public/mojom/restricted_cookie_manager.mojom
@@ -62,11 +62,16 @@ interface RestrictedCookieManager {
// level frame or the script url for service workers. |site_for_cookies| is
// used to determine if a cookie is accessed in a third-party context.
// |top_frame_origin| is used to check for content settings.
- // |options| filters the returned list of cookies.
+ // |options| filters the returned list of cookies. The returned cookies
+ // include CookieAccessResult information of the cookie.
+ // Any information contained in the CookieInclusionStatus::WarningReasons
+ // as part of CookieAccessResult in the included cookies may be passed to an
+ // untrusted renderer.
GetAllForUrl(
url.mojom.Url url, SiteForCookies site_for_cookies,
url.mojom.Origin top_frame_origin,
- CookieManagerGetOptions options) => (array<CanonicalCookie> cookies);
+ CookieManagerGetOptions options) => (
+ array<CookieWithAccessResult> cookies);
SetCanonicalCookie(CanonicalCookie cookie,
url.mojom.Url url,
diff --git a/chromium/services/network/public/mojom/ssl_config.mojom b/chromium/services/network/public/mojom/ssl_config.mojom
index bab0033425a..f95093c16ae 100644
--- a/chromium/services/network/public/mojom/ssl_config.mojom
+++ b/chromium/services/network/public/mojom/ssl_config.mojom
@@ -22,7 +22,7 @@ struct SSLConfig {
// If true, enables TLS 1.3 downgrade hardening for connections using local
// trust anchors. (Hardening for known roots is always enabled.)
- bool tls13_hardening_for_local_anchors_enabled = false;
+ bool tls13_hardening_for_local_anchors_enabled = true;
// SSL 2.0 and 3.0 are not supported. Note these lines must be kept in sync
// with net/ssl/ssl_config.cc.
diff --git a/chromium/services/network/public/mojom/trust_tokens.mojom b/chromium/services/network/public/mojom/trust_tokens.mojom
index bb6a209f2cd..8f599953b9f 100644
--- a/chromium/services/network/public/mojom/trust_tokens.mojom
+++ b/chromium/services/network/public/mojom/trust_tokens.mojom
@@ -102,14 +102,21 @@ struct TrustTokenParams {
// or redeem a new token, evicting the SRR currently stored.
TrustTokenRefreshPolicy refresh_policy = kUseCached;
- // "sign_request_data", "include_timestamp_header", "issuer", and
- // "additional_signed_headers" are used only when "type" is "kSigning":
- // these parameters specify the manner in which the outgoing request should
- // be signed.
+ // The remaining members are used only when "type" is "kSigning": these
+ // parameters specify the manner in which the outgoing request should be
+ // signed, including optionally specifying additional data to add in
+ // browser-provided request headers (for instance, a timestamp or custom
+ // client-provided data).
TrustTokenSignRequestData sign_request_data = kOmit;
bool include_timestamp_header = false;
url.mojom.Origin? issuer;
array<string> additional_signed_headers;
+
+ // "possibly_unsafe_additional_signing_data", which stores the request's
+ // optional additionalSigningData Trust Tokens parameter, might not be a valid
+ // HTTP header value; it's the user's responsibility to ensure that it is safe
+ // to attach as a header prior to adding it to an outgoing request's headers.
+ string? possibly_unsafe_additional_signing_data;
};
// Result struct for a HasTrustTokens (see below) call:
diff --git a/chromium/services/network/public/mojom/url_loader.mojom b/chromium/services/network/public/mojom/url_loader.mojom
index 4f2a1e56c83..b3b921ae7a5 100644
--- a/chromium/services/network/public/mojom/url_loader.mojom
+++ b/chromium/services/network/public/mojom/url_loader.mojom
@@ -90,7 +90,7 @@ struct TrustedUrlRequestParams {
// Observer which should be notified when this URLRequest reads or writes
// a cookie. If this is set to non-null, the observer passed to
// URLLoaderFactory will be ignored.
- CookieAccessObserver? cookie_observer;
+ pending_remote<CookieAccessObserver>? cookie_observer;
};
// Typemapped to network::ResourceRequest.
@@ -355,7 +355,7 @@ struct URLRequest {
// practical terms, it's empty for requests that didn't go through a service
// worker, or if the original requestor is not a window. When the request
// goes through a service worker, the id is
- // ServiceWorkerProviderHost::fetch_request_window_id.
+ // ServiceWorkerContainerHost::fetch_request_window_id.
mojo_base.mojom.UnguessableToken? fetch_window_id;
// The ID that DevTools uses to track network requests. It is generated in the
@@ -402,6 +402,10 @@ struct URLRequestBody {
// Indicates whether the post data contains sensitive information like
// passwords.
bool contains_sensitive_info;
+
+ // Indicates whether fetch upload streaming is allowed/rejected over H/1.
+ // Even if this is false but there is a QUIC/H2 stream, the upload is allowed.
+ bool allow_http1_for_streaming_upload;
};
// Represents part of an upload body. This could be either one of bytes, file or
@@ -429,7 +433,13 @@ struct DataElement {
mojo_base.mojom.Time expected_modification_time;
};
+// URLLoader is an interface for performing a single request to a URL.
+//
// Destroying a URLLoader will cancel the associated request.
+//
+// A URLLoader is normally created and started using
+// URLLoaderFactory::CreateLoaderAndStart(). The result of the load is
+// communicated to the URLLoaderClient provided to that function.
interface URLLoader {
// If a disconnection is initiated by the client side, it may send the
// following disconnection reason, along with an application-defined string
@@ -480,6 +490,7 @@ interface URLLoader {
ResumeReadingBodyFromNet();
};
+// Receives messages from a single URLLoader.
interface URLLoaderClient {
// Called when the response head is received.
OnReceiveResponse(URLResponseHead head);
diff --git a/chromium/services/network/public/mojom/url_loader_factory.mojom b/chromium/services/network/public/mojom/url_loader_factory.mojom
index 3035dcf148d..8fecf02d4ff 100644
--- a/chromium/services/network/public/mojom/url_loader_factory.mojom
+++ b/chromium/services/network/public/mojom/url_loader_factory.mojom
@@ -29,16 +29,23 @@ const uint32 kURLLoadOptionBlockThirdPartyCookies = 64;
// service must set this.
const uint32 kURLLoadOptionAsCorsPreflight = 128;
+// URLLoaderFactory is an interface for requesting URLs. It creates URLLoader
+// instances. One URLLoader instance can load one URL.
interface URLLoaderFactory {
// Creates a URLLoader and starts loading with the given |request|. |client|'s
- // method will be called when certain events related to that loading
+ // methods will be called when certain events related to that loading
// (e.g., response arrival) happen.
+ //
// |routing_id| is the routing_id for subframe requests, and is the
// frame_tree_node_id for frame requests.
// TODO: once MojoLoading is only codepath and we have one factory per frame,
// remove this.
- // |request_id| is for compatibility with the existing Chrome IPC.
- // A pair (routing_id, request_id) is assumed to be unique within one factory.
+ //
+ // |request_id| is an arbitrary id for the request. The (routing_id,
+ // request_id) pair must be unique over all calls to CreateLoaderAndStart()
+ // on this factory.
+ //
+ // |options| is a bitfield of the options defined above.
CreateLoaderAndStart(pending_receiver<URLLoader> loader,
int32 routing_id,
int32 request_id,
diff --git a/chromium/services/network/public/mojom/url_response_head.mojom b/chromium/services/network/public/mojom/url_response_head.mojom
index b92cd66790e..0e4afd3eb8d 100644
--- a/chromium/services/network/public/mojom/url_response_head.mojom
+++ b/chromium/services/network/public/mojom/url_response_head.mojom
@@ -53,9 +53,11 @@ struct URLResponseHead {
// True if the request accessed the network in the process of retrieving data.
bool network_accessed = false;
- // The appcache this response was loaded from, or kAppCacheNoCacheId.
+ // The appcache this response was loaded from, or
+ // kAppCacheNoCacheId (hard-coded as 0 because services/network
+ // can't take a dependency on Blink).
// TODO(rdsmith): Remove conceptual dependence on appcache.
- int64 appcache_id;
+ int64 appcache_id = 0;
// The manifest url of the appcache this response was loaded from.
// Note: this value is only populated for main resource requests.
@@ -74,7 +76,7 @@ struct URLResponseHead {
bool was_fetched_via_spdy = false;
// True if the response was delivered after NPN is negotiated.
- bool was_alpn_negotiated;
+ bool was_alpn_negotiated = false;
// True if response could use alternate protocol. However, browser will
// ignore the alternate protocol when spdy is not enabled on browser side.
@@ -103,11 +105,21 @@ struct URLResponseHead {
// reissued by the renderer).
bool was_fetched_via_service_worker = false;
+ // Source of a serviceworker response - CacheStorage, HttpCache, Network or
+ // Unspecified (default).
+ // The value can be Unspecified in some cases including:
+ // 1. |was_fetched_via_service_worker| is false.
+ // 2. The service worker responded with an error (response status code is 0).
+ // 3. The service worker responded with a generated response, i.e.,
+ // `respondWith(new Response(...))`.
+ FetchResponseSource service_worker_response_source =
+ FetchResponseSource.kUnspecified;
+
// True when a request whose mode is |CORS| or |CORS-with-forced-preflight|
// is sent to a ServiceWorker but FetchEvent.respondWith is not called. So the
// renderer has to resend the request with skip service worker flag
// considering the CORS preflight logic.
- bool was_fallback_required_by_service_worker;
+ bool was_fallback_required_by_service_worker = false;
// The URL list of the Response object the service worker passed to
// respondWith() to create this response. For example, if the service worker
@@ -120,11 +132,13 @@ struct URLResponseHead {
array<url.mojom.Url> url_list_via_service_worker;
// https://fetch.spec.whatwg.org/#concept-response-type
- FetchResponseType response_type;
-
- // True when the response is served from the CacheStorage via the
- // ServiceWorker.
- bool is_in_cache_storage = false;
+ //
+ // TODO(falken): Initialize to kDefault per spec, if that doesn't
+ // break things. Previously this field was not being initialized
+ // explicitly, so it was zero-initializing which happens to be the
+ // kBasic type. So changing it to kDefault could potentially change
+ // behavior.
+ FetchResponseType response_type = FetchResponseType.kBasic;
// The cache name of the CacheStorage from where the response is served via
// the ServiceWorker. Empty if the response isn't from the CacheStorage.
diff --git a/chromium/services/network/public/mojom/websocket.mojom b/chromium/services/network/public/mojom/websocket.mojom
index 6972175e969..a9f92f3fb49 100644
--- a/chromium/services/network/public/mojom/websocket.mojom
+++ b/chromium/services/network/public/mojom/websocket.mojom
@@ -94,12 +94,6 @@ interface WebSocketClient {
WebSocketMessageType type,
uint64 data_length);
- // Add |quota| bytes of send quota. |quota| must be positive. Initial quota
- // is 0. The renderer will wait for an AddSendFlowControlQuota() message
- // before forwarding any messages to the browser. Total quota must never
- // exceed 0x7FFFFFFFFFFFFFFF bytes.
- AddSendFlowControlQuota(int64 quota);
-
// Drop the channel.
//
// When sent by the renderer, this will cause a Close message will be sent and
@@ -129,19 +123,6 @@ interface WebSocket {
const uint32 kInsufficientResources = 1;
const uint32 kInternalFailure = 2;
- // Send a non-control frame to the remote server.
- // - |fin| indicates that this frame is the last in the current message.
- // - |type| is the type of the message. On the first frame of a message, it
- // must be set to either WebSocketMessageType.TEXT or
- // WebSocketMessageType.BINARY. On subsequent frames, it must be set to
- // WebSocketMessageType.CONTINUATION, and the type is the same as that of
- // the first message. If |type| is WebSocketMessageType.TEXT, then the
- // concatenation of the |data| from every frame in the message must be valid
- // UTF-8. If |fin| is not set, |data| must be non-empty.
- SendFrame(bool fin,
- WebSocketMessageType type,
- mojo_base.mojom.ReadOnlyBuffer data);
-
// Sends a message via mojo datapipe to the remote server.
// - |type| is the type of the message. It must be set to either
// WebSocketMessageType.TEXT or WebSocketMessageType.BINARY.
diff --git a/chromium/services/network/quic_transport.cc b/chromium/services/network/quic_transport.cc
index 2a5e6d2561e..0ef85a5b839 100644
--- a/chromium/services/network/quic_transport.cc
+++ b/chromium/services/network/quic_transport.cc
@@ -19,6 +19,23 @@
namespace network {
+namespace {
+
+net::QuicTransportClient::Parameters CreateParameters(
+ const std::vector<mojom::QuicTransportCertificateFingerprintPtr>&
+ fingerprints) {
+ net::QuicTransportClient::Parameters params;
+
+ for (const auto& fingerprint : fingerprints) {
+ params.server_certificate_fingerprints.push_back(
+ quic::CertificateFingerprint{.algorithm = fingerprint->algorithm,
+ .fingerprint = fingerprint->fingerprint});
+ }
+ return params;
+}
+
+} // namespace
+
class QuicTransport::Stream final {
public:
class StreamVisitor final : public quic::QuicTransportStream::Visitor {
@@ -118,6 +135,19 @@ class QuicTransport::Stream final {
MaySendFin();
}
+ void Abort(quic::QuicRstStreamErrorCode code) {
+ auto* stream = incoming_ ? incoming_ : outgoing_;
+ if (!stream) {
+ return;
+ }
+ stream->Reset(code);
+ incoming_ = nullptr;
+ outgoing_ = nullptr;
+ readable_watcher_.Cancel();
+ readable_.reset();
+ MayDisposeLater();
+ }
+
~Stream() { transport_->transport_->session()->CloseStream(id_); }
private:
@@ -278,12 +308,14 @@ class QuicTransport::Stream final {
// This must be the last member.
base::WeakPtrFactory<Stream> weak_factory_{this};
-};
+}; // namespace network
QuicTransport::QuicTransport(
const GURL& url,
const url::Origin& origin,
const net::NetworkIsolationKey& key,
+ const std::vector<mojom::QuicTransportCertificateFingerprintPtr>&
+ fingerprints,
NetworkContext* context,
mojo::PendingRemote<mojom::QuicTransportHandshakeClient> handshake_client)
: transport_(std::make_unique<net::QuicTransportClient>(
@@ -291,7 +323,8 @@ QuicTransport::QuicTransport(
origin,
this,
key,
- context->url_request_context())),
+ context->url_request_context(),
+ CreateParameters(fingerprints))),
context_(context),
receiver_(this),
handshake_client_(std::move(handshake_client)) {
@@ -390,6 +423,18 @@ void QuicTransport::SendFin(uint32_t stream) {
it->second->NotifyFinFromClient();
}
+void QuicTransport::AbortStream(uint32_t stream, uint64_t code) {
+ auto it = streams_.find(stream);
+ if (it == streams_.end()) {
+ return;
+ }
+ auto code_to_pass = quic::QuicRstStreamErrorCode::QUIC_STREAM_NO_ERROR;
+ if (code < quic::QuicRstStreamErrorCode::QUIC_STREAM_LAST_ERROR) {
+ code_to_pass = static_cast<quic::QuicRstStreamErrorCode>(code);
+ }
+ it->second->Abort(code_to_pass);
+}
+
void QuicTransport::OnConnected() {
if (torn_down_) {
return;
@@ -413,12 +458,9 @@ void QuicTransport::OnConnectionFailed() {
DCHECK(handshake_client_);
- const net::QuicTransportError& error = transport_->error();
// Here we assume that the error is not going to handed to the
// initiator renderer.
- handshake_client_->OnHandshakeFailed(mojom::QuicTransportError::New(
- error.net_error, static_cast<int>(error.quic_error), error.details,
- error.safe_to_report_details));
+ handshake_client_->OnHandshakeFailed(transport_->error());
TearDown();
}
diff --git a/chromium/services/network/quic_transport.h b/chromium/services/network/quic_transport.h
index 4dc8c6e5e2b..62031970fd1 100644
--- a/chromium/services/network/quic_transport.h
+++ b/chromium/services/network/quic_transport.h
@@ -43,12 +43,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) QuicTransport final
mojo::ScopedDataPipeProducerHandle)>;
using UnidirectionalStreamAcceptanceCallback =
base::OnceCallback<void(uint32_t, mojo::ScopedDataPipeConsumerHandle)>;
- QuicTransport(const GURL& url,
- const url::Origin& origin,
- const net::NetworkIsolationKey& key,
- NetworkContext* context,
- mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
- handshake_client);
+ QuicTransport(
+ const GURL& url,
+ const url::Origin& origin,
+ const net::NetworkIsolationKey& key,
+ const std::vector<mojom::QuicTransportCertificateFingerprintPtr>&
+ fingerprints,
+ NetworkContext* context,
+ mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
+ handshake_client);
~QuicTransport() override;
// mojom::QuicTransport implementation:
@@ -62,6 +65,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) QuicTransport final
void AcceptUnidirectionalStream(
UnidirectionalStreamAcceptanceCallback callback) override;
void SendFin(uint32_t stream_id) override;
+ void AbortStream(uint32_t stream_id, uint64_t code) override;
// net::QuicTransportClient::Visitor implementation:
void OnConnected() override;
diff --git a/chromium/services/network/quic_transport_unittest.cc b/chromium/services/network/quic_transport_unittest.cc
index 4bfedb17689..78cb99af781 100644
--- a/chromium/services/network/quic_transport_unittest.cc
+++ b/chromium/services/network/quic_transport_unittest.cc
@@ -13,16 +13,64 @@
#include "base/test/task_environment.h"
#include "net/cert/mock_cert_verifier.h"
#include "net/dns/mock_host_resolver.h"
+#include "net/quic/crypto/proof_source_chromium.h"
+#include "net/test/test_data_directory.h"
#include "net/third_party/quiche/src/quic/test_tools/crypto_test_utils.h"
#include "net/tools/quic/quic_transport_simple_server.h"
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/public/mojom/network_context.mojom.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
namespace {
+// A clock that only mocks out WallNow(), but uses real Now() and
+// ApproximateNow(). Useful for certificate verification.
+class TestWallClock : public quic::QuicClock {
+ public:
+ quic::QuicTime Now() const override {
+ return quic::QuicChromiumClock::GetInstance()->Now();
+ }
+ quic::QuicTime ApproximateNow() const override {
+ return quic::QuicChromiumClock::GetInstance()->ApproximateNow();
+ }
+ quic::QuicWallTime WallNow() const override { return wall_now_; }
+
+ void set_wall_now(quic::QuicWallTime now) { wall_now_ = now; }
+
+ private:
+ quic::QuicWallTime wall_now_ = quic::QuicWallTime::Zero();
+};
+
+class TestConnectionHelper : public quic::QuicConnectionHelperInterface {
+ public:
+ const quic::QuicClock* GetClock() const override { return &clock_; }
+ quic::QuicRandom* GetRandomGenerator() override {
+ return quic::QuicRandom::GetInstance();
+ }
+ quic::QuicBufferAllocator* GetStreamSendBufferAllocator() override {
+ return &allocator_;
+ }
+
+ TestWallClock& clock() { return clock_; }
+
+ private:
+ TestWallClock clock_;
+ quic::SimpleBufferAllocator allocator_;
+};
+
+mojom::NetworkContextParamsPtr CreateNetworkContextParams() {
+ auto context_params = mojom::NetworkContextParams::New();
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test CertVerifier behavior.
+ context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
+ return context_params;
+}
+
// We don't use mojo::BlockingCopyToString because it leads to deadlocks.
std::string Read(mojo::ScopedDataPipeConsumerHandle readable) {
std::string output;
@@ -69,7 +117,8 @@ class TestHandshakeClient final : public mojom::QuicTransportHandshakeClient {
std::move(callback_).Run();
}
- void OnHandshakeFailed(mojom::QuicTransportErrorPtr error) override {
+ void OnHandshakeFailed(
+ const base::Optional<net::QuicTransportError>& error) override {
has_seen_handshake_failure_ = true;
receiver_.reset();
std::move(callback_).Run();
@@ -186,6 +235,9 @@ quic::ParsedQuicVersion GetTestVersion() {
class QuicTransportTest : public testing::Test {
public:
QuicTransportTest()
+ : QuicTransportTest(
+ quic::test::crypto_test_utils::ProofSourceForTesting()) {}
+ explicit QuicTransportTest(std::unique_ptr<quic::ProofSource> proof_source)
: version_(GetTestVersion()),
origin_(url::Origin::Create(GURL("https://example.org/"))),
task_environment_(base::test::TaskEnvironment::MainThreadType::IO),
@@ -193,10 +245,8 @@ class QuicTransportTest : public testing::Test {
network_context_remote_(mojo::NullRemote()),
network_context_(network_service_.get(),
network_context_remote_.BindNewPipeAndPassReceiver(),
- mojom::NetworkContextParams::New()),
- server_(/* port= */ 0,
- {origin_},
- quic::test::crypto_test_utils::ProofSourceForTesting()) {
+ CreateNetworkContextParams()),
+ server_(/* port= */ 0, {origin_}, std::move(proof_source)) {
EXPECT_EQ(EXIT_SUCCESS, server_.Start());
cert_verifier_.set_default_result(net::OK);
@@ -215,20 +265,31 @@ class QuicTransportTest : public testing::Test {
const GURL& url,
const url::Origin& origin,
const net::NetworkIsolationKey& key,
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints,
mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
handshake_client) {
- network_context_.CreateQuicTransport(url, origin, key,
- std::move(handshake_client));
+ network_context_.CreateQuicTransport(
+ url, origin, key, std::move(fingerprints), std::move(handshake_client));
}
void CreateQuicTransport(
const GURL& url,
const url::Origin& origin,
mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
handshake_client) {
- CreateQuicTransport(url, origin, net::NetworkIsolationKey(),
+ CreateQuicTransport(url, origin, net::NetworkIsolationKey(), {},
std::move(handshake_client));
}
+ void CreateQuicTransport(
+ const GURL& url,
+ const url::Origin& origin,
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints,
+ mojo::PendingRemote<mojom::QuicTransportHandshakeClient>
+ handshake_client) {
+ CreateQuicTransport(url, origin, net::NetworkIsolationKey(),
+ std::move(fingerprints), std::move(handshake_client));
+ }
+
GURL GetURL(base::StringPiece suffix) {
return GURL(quiche::QuicheStrCat("quic-transport://test.example.com:",
server_.server_address().port(), suffix));
@@ -236,6 +297,7 @@ class QuicTransportTest : public testing::Test {
const url::Origin& origin() const { return origin_; }
const NetworkContext& network_context() const { return network_context_; }
+ NetworkContext& mutable_network_context() { return network_context_; }
void RunPendingTasks() {
base::RunLoop run_loop;
@@ -509,5 +571,83 @@ TEST_F(QuicTransportTest, EchoOnBidirectionalStream) {
EXPECT_TRUE(client.stream_is_closed_as_incoming_stream(stream_id));
}
+class QuicTransportWithCustomCertificateTest : public QuicTransportTest {
+ public:
+ QuicTransportWithCustomCertificateTest()
+ : QuicTransportTest(CreateProofSource()) {
+ auto helper = std::make_unique<TestConnectionHelper>();
+ // Set clock to a time in which quic-short-lived.pem is valid
+ // (2020-06-05T20:35:00.000Z).
+ helper->clock().set_wall_now(
+ quic::QuicWallTime::FromUNIXSeconds(1591389300));
+ mutable_network_context()
+ .url_request_context()
+ ->quic_context()
+ ->SetHelperForTesting(std::move(helper));
+ }
+ ~QuicTransportWithCustomCertificateTest() override = default;
+
+ static std::unique_ptr<quic::ProofSource> CreateProofSource() {
+ auto proof_source = std::make_unique<net::ProofSourceChromium>();
+ base::FilePath certs_dir = net::GetTestCertsDirectory();
+ EXPECT_TRUE(proof_source->Initialize(
+ certs_dir.AppendASCII("quic-short-lived.pem"),
+ certs_dir.AppendASCII("quic-leaf-cert.key"),
+ certs_dir.AppendASCII("quic-leaf-cert.key.sct")));
+ return proof_source;
+ }
+};
+
+TEST_F(QuicTransportWithCustomCertificateTest, WithValidFingerprint) {
+ base::RunLoop run_loop_for_handshake;
+ mojo::PendingRemote<mojom::QuicTransportHandshakeClient> handshake_client;
+ TestHandshakeClient test_handshake_client(
+ handshake_client.InitWithNewPipeAndPassReceiver(),
+ run_loop_for_handshake.QuitClosure());
+
+ auto fingerprint = mojom::QuicTransportCertificateFingerprint::New(
+ "sha-256",
+ "ED:3D:D7:C3:67:10:94:68:D1:DC:D1:26:5C:B2:74:D7:1C:"
+ "A2:63:3E:94:94:C0:84:39:D6:64:FA:08:B9:77:37");
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints;
+ fingerprints.push_back(std::move(fingerprint));
+
+ CreateQuicTransport(GetURL("/discard"), origin(), std::move(fingerprints),
+ std::move(handshake_client));
+
+ run_loop_for_handshake.Run();
+
+ EXPECT_TRUE(test_handshake_client.has_seen_connection_establishment());
+ EXPECT_FALSE(test_handshake_client.has_seen_handshake_failure());
+ EXPECT_FALSE(test_handshake_client.has_seen_mojo_connection_error());
+ EXPECT_EQ(1u, network_context().NumOpenQuicTransports());
+}
+
+TEST_F(QuicTransportWithCustomCertificateTest, WithInvalidFingerprint) {
+ base::RunLoop run_loop_for_handshake;
+ mojo::PendingRemote<mojom::QuicTransportHandshakeClient> handshake_client;
+ TestHandshakeClient test_handshake_client(
+ handshake_client.InitWithNewPipeAndPassReceiver(),
+ run_loop_for_handshake.QuitClosure());
+
+ auto fingerprint = network::mojom::QuicTransportCertificateFingerprint::New(
+ "sha-256",
+ "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:"
+ "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00");
+
+ std::vector<mojom::QuicTransportCertificateFingerprintPtr> fingerprints;
+ fingerprints.push_back(std::move(fingerprint));
+
+ CreateQuicTransport(GetURL("/discard"), origin(), std::move(fingerprints),
+ std::move(handshake_client));
+
+ run_loop_for_handshake.Run();
+
+ EXPECT_FALSE(test_handshake_client.has_seen_connection_establishment());
+ EXPECT_TRUE(test_handshake_client.has_seen_handshake_failure());
+ EXPECT_FALSE(test_handshake_client.has_seen_mojo_connection_error());
+ EXPECT_EQ(0u, network_context().NumOpenQuicTransports());
+}
+
} // namespace
} // namespace network
diff --git a/chromium/services/network/restricted_cookie_manager.cc b/chromium/services/network/restricted_cookie_manager.cc
index 80c2d2c6e12..888cc78e436 100644
--- a/chromium/services/network/restricted_cookie_manager.cc
+++ b/chromium/services/network/restricted_cookie_manager.cc
@@ -84,9 +84,32 @@ net::CookieOptions MakeOptionsForGet(
return options;
}
-} // namespace
+void MarkSameSiteCompatPairs(std::vector<net::CookieWithStatus>& cookie_list,
+ const net::CookieOptions& options) {
+ // If the context is same-site then there cannot be any SameSite-by-default
+ // warnings, so the compat pair warning is irrelevant.
+ if (options.same_site_cookie_context().GetContextForCookieInclusion() >
+ net::CookieOptions::SameSiteCookieContext::ContextType::
+ SAME_SITE_LAX_METHOD_UNSAFE) {
+ return;
+ }
+ if (cookie_list.size() < 2)
+ return;
+ for (size_t i = 0; i < cookie_list.size() - 1; ++i) {
+ const net::CanonicalCookie& c1 = cookie_list[i].cookie;
+ for (size_t j = i + 1; j < cookie_list.size(); ++j) {
+ const net::CanonicalCookie& c2 = cookie_list[j].cookie;
+ if (net::cookie_util::IsSameSiteCompatPair(c1, c2, options)) {
+ cookie_list[i].status.AddWarningReason(
+ net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR);
+ cookie_list[j].status.AddWarningReason(
+ net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR);
+ }
+ }
+ }
+}
-using CookieInclusionStatus = net::CanonicalCookie::CookieInclusionStatus;
+} // namespace
class RestrictedCookieManager::Listener : public base::LinkNode<Listener> {
public:
@@ -129,7 +152,7 @@ class RestrictedCookieManager::Listener : public base::LinkNode<Listener> {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!change.cookie
.IncludeForRequestURL(url_, options_, change.access_semantics)
- .IsInclude()) {
+ .status.IsInclude()) {
return;
}
@@ -238,22 +261,28 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
const net::CookieOptions& net_options,
mojom::CookieManagerGetOptionsPtr options,
GetAllForUrlCallback callback,
- const net::CookieStatusList& cookie_list,
- const net::CookieStatusList& excluded_cookies) {
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
bool blocked = !cookie_settings_->IsCookieAccessAllowed(
url, site_for_cookies.RepresentativeUrl(), top_frame_origin);
- std::vector<net::CanonicalCookie> result;
+ std::vector<net::CookieWithAccessResult> result;
std::vector<net::CookieWithStatus> result_with_status;
// TODO(https://crbug.com/977040): Remove once samesite tightening up is
// rolled out.
- for (const auto& cookie_and_status : excluded_cookies) {
- if (cookie_and_status.status.ShouldWarn()) {
+ // |result_with_status| is populated with excluded cookies here based on
+ // warnings present before WARN_SAMESITE_COMPAT_PAIR can be applied by
+ // MarkSameSiteCompatPairs(). This is ok because WARN_SAMESITE_COMPAT_PAIR is
+ // irrelevant unless WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT is already
+ // present.
+ for (const auto& cookie_and_access_result : excluded_cookies) {
+ if (cookie_and_access_result.access_result.status.ShouldWarn()) {
result_with_status.push_back(
- {cookie_and_status.cookie, cookie_and_status.status});
+ {cookie_and_access_result.cookie,
+ cookie_and_access_result.access_result.status});
}
}
@@ -262,9 +291,9 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
mojom::CookieMatchType match_type = options->match_type;
const std::string& match_name = options->name;
// TODO(https://crbug.com/993843): Use the statuses passed in |cookie_list|.
- for (size_t i = 0; i < cookie_list.size(); ++i) {
- const net::CanonicalCookie& cookie = cookie_list[i].cookie;
- CookieInclusionStatus status = cookie_list[i].status;
+ for (const net::CookieWithAccessResult& cookie_item : cookie_list) {
+ const net::CanonicalCookie& cookie = cookie_item.cookie;
+ net::CookieInclusionStatus status = cookie_item.access_result.status;
const std::string& cookie_name = cookie.Name();
if (match_type == mojom::CookieMatchType::EQUALS) {
@@ -281,14 +310,18 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
if (blocked) {
status.AddExclusionReason(
- CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
} else {
- result.push_back(cookie);
+ result.push_back(cookie_item);
}
result_with_status.push_back({cookie, status});
}
if (cookie_observer_) {
+ // Mark the CookieInclusionStatuses of items in |result_with_status| if they
+ // are part of a presumed SameSite compatibility pair.
+ MarkSameSiteCompatPairs(result_with_status, net_options);
+
cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
mojom::CookieAccessDetails::Type::kRead, url, site_for_cookies,
result_with_status, base::nullopt));
@@ -319,21 +352,24 @@ void RestrictedCookieManager::SetCanonicalCookie(
bool blocked = !cookie_settings_->IsCookieAccessAllowed(
url, site_for_cookies.RepresentativeUrl(), top_frame_origin);
- CookieInclusionStatus status;
+ net::CookieInclusionStatus status;
if (blocked)
- status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
+ status.AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
// Don't allow URLs with leading dots like https://.some-weird-domain.com
// This probably never happens.
if (!net::cookie_util::DomainIsHostOnly(url.host()))
- status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
+ status.AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN);
// Don't allow setting cookies on other domains.
// TODO(crbug.com/996786): This should never happen. This should eventually
// result in a renderer kill, but for now just log metrics.
bool domain_match = cookie.IsDomainMatch(url.host());
if (!domain_match)
- status.AddExclusionReason(CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
+ status.AddExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
UMA_HISTOGRAM_BOOLEAN(
"Net.RestrictedCookieManager.SetCanonicalCookieDomainMatch",
domain_match);
@@ -384,12 +420,12 @@ void RestrictedCookieManager::SetCanonicalCookieResult(
const net::CanonicalCookie& cookie,
const net::CookieOptions& net_options,
SetCanonicalCookieCallback user_callback,
- net::CanonicalCookie::CookieInclusionStatus status) {
+ net::CookieInclusionStatus status) {
std::vector<net::CookieWithStatus> notify;
// TODO(https://crbug.com/977040): Only report pure INCLUDE once samesite
// tightening up is rolled out.
DCHECK(!status.HasExclusionReason(
- CookieInclusionStatus::EXCLUDE_USER_PREFERENCES));
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES));
if (status.IsInclude() || status.ShouldWarn()) {
if (cookie_observer_) {
@@ -474,7 +510,7 @@ void RestrictedCookieManager::GetCookiesString(
std::move(match_options),
base::BindOnce(
[](GetCookiesStringCallback user_callback,
- const std::vector<net::CanonicalCookie>& cookies) {
+ const std::vector<net::CookieWithAccessResult>& cookies) {
std::move(user_callback)
.Run(net::CanonicalCookie::BuildCookieLine(cookies));
},
diff --git a/chromium/services/network/restricted_cookie_manager.h b/chromium/services/network/restricted_cookie_manager.h
index 20cdccd5836..1b0b50812e5 100644
--- a/chromium/services/network/restricted_cookie_manager.h
+++ b/chromium/services/network/restricted_cookie_manager.h
@@ -16,6 +16,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/cookies/canonical_cookie.h"
#include "net/cookies/cookie_change_dispatcher.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/site_for_cookies.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
@@ -111,18 +112,17 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
const net::CookieOptions& net_options,
mojom::CookieManagerGetOptionsPtr options,
GetAllForUrlCallback callback,
- const net::CookieStatusList& cookie_list,
- const net::CookieStatusList& excluded_cookies);
+ const net::CookieAccessResultList& cookie_list,
+ const net::CookieAccessResultList& excluded_cookies);
// Reports the result of setting the cookie to |network_context_client_|, and
// invokes the user callback.
- void SetCanonicalCookieResult(
- const GURL& url,
- const net::SiteForCookies& site_for_cookies,
- const net::CanonicalCookie& cookie,
- const net::CookieOptions& net_options,
- SetCanonicalCookieCallback user_callback,
- net::CanonicalCookie::CookieInclusionStatus status);
+ void SetCanonicalCookieResult(const GURL& url,
+ const net::SiteForCookies& site_for_cookies,
+ const net::CanonicalCookie& cookie,
+ const net::CookieOptions& net_options,
+ SetCanonicalCookieCallback user_callback,
+ net::CookieInclusionStatus status);
// Called when the Mojo pipe associated with a listener is closed.
void RemoveChangeListener(Listener* listener);
diff --git a/chromium/services/network/restricted_cookie_manager_unittest.cc b/chromium/services/network/restricted_cookie_manager_unittest.cc
index 9b5e887a703..36db8313971 100644
--- a/chromium/services/network/restricted_cookie_manager_unittest.cc
+++ b/chromium/services/network/restricted_cookie_manager_unittest.cc
@@ -12,11 +12,11 @@
#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
-#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/system/functions.h"
#include "net/base/features.h"
#include "net/cookies/canonical_cookie_test_helpers.h"
#include "net/cookies/cookie_constants.h"
@@ -44,16 +44,14 @@ class RecordingCookieObserver : public network::mojom::CookieAccessObserver {
// The vector is merely to permit use of MatchesCookieLine, there is always
// one thing.
std::vector<net::CanonicalCookie> cookie;
- net::CanonicalCookie::CookieInclusionStatus status;
+ net::CookieInclusionStatus status;
base::Optional<std::string> devtools_request_id;
};
RecordingCookieObserver() = default;
~RecordingCookieObserver() override = default;
- const std::vector<CookieOp>& recorded_activity() const {
- return recorded_activity_;
- }
+ std::vector<CookieOp>& recorded_activity() { return recorded_activity_; }
mojo::PendingRemote<mojom::CookieAccessObserver> GetRemote() {
mojo::PendingRemote<mojom::CookieAccessObserver> remote;
@@ -94,6 +92,7 @@ class RestrictedCookieManagerSync {
: cookie_service_(cookie_service) {}
~RestrictedCookieManagerSync() {}
+ // Wraps GetAllForUrl() but discards CookieAccessResult from returned cookies.
std::vector<net::CanonicalCookie> GetAllForUrl(
const GURL& url,
const GURL& site_for_cookies,
@@ -105,8 +104,30 @@ class RestrictedCookieManagerSync {
url, net::SiteForCookies::FromUrl(site_for_cookies), top_frame_origin,
std::move(options),
base::BindLambdaForTesting(
- [&run_loop,
- &result](const std::vector<net::CanonicalCookie>& backend_result) {
+ [&run_loop, &result](const std::vector<net::CookieWithAccessResult>&
+ backend_result) {
+ result = net::cookie_util::StripAccessResults(backend_result);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ return result;
+ }
+
+ // Returns full CookieWithAccessResult from the backend.
+ // TODO(chlily): Convert calls to the above method to this one.
+ std::vector<net::CookieWithAccessResult> GetAllForUrlWithAccessResult(
+ const GURL& url,
+ const GURL& site_for_cookies,
+ const url::Origin& top_frame_origin,
+ mojom::CookieManagerGetOptionsPtr options) {
+ base::RunLoop run_loop;
+ std::vector<net::CookieWithAccessResult> result;
+ cookie_service_->GetAllForUrl(
+ url, net::SiteForCookies::FromUrl(site_for_cookies), top_frame_origin,
+ std::move(options),
+ base::BindLambdaForTesting(
+ [&run_loop, &result](const std::vector<net::CookieWithAccessResult>&
+ backend_result) {
result = backend_result;
run_loop.Quit();
}));
@@ -170,13 +191,12 @@ class RestrictedCookieManagerTest
~RestrictedCookieManagerTest() override {}
void SetUp() override {
- mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
+ mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
&RestrictedCookieManagerTest::OnBadMessage, base::Unretained(this)));
}
void TearDown() override {
- mojo::core::SetDefaultProcessErrorCallback(
- mojo::core::ProcessErrorCallback());
+ mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}
// Set a canonical cookie directly into the store.
@@ -184,17 +204,31 @@ class RestrictedCookieManagerTest
bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
std::string source_scheme,
bool can_modify_httponly) {
- net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
- callback;
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
net::CookieOptions options;
if (can_modify_httponly)
options.set_include_httponly();
cookie_monster_.SetCanonicalCookieAsync(
std::make_unique<net::CanonicalCookie>(cookie),
net::cookie_util::SimulatedCookieSource(cookie, source_scheme), options,
- base::BindOnce(&net::ResultSavingCookieCallback<
- net::CanonicalCookie::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback)));
+ callback.WaitUntilDone();
+ return callback.result().IsInclude();
+ }
+
+ // Set a canonical cookie directly into the store.
+ // Uses a cookie options that will succeed at setting any cookie.
+ bool EnsureSetCanonicalCookie(const net::CanonicalCookie& cookie) {
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
+ cookie_monster_.SetCanonicalCookieAsync(
+ std::make_unique<net::CanonicalCookie>(cookie),
+ net::cookie_util::SimulatedCookieSource(cookie, "https"),
+ net::CookieOptions::MakeAllInclusive(),
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback)));
callback.WaitUntilDone();
return callback.result().IsInclude();
}
@@ -243,8 +277,7 @@ class RestrictedCookieManagerTest
received_bad_message_ = true;
}
- const std::vector<RecordingCookieObserver::CookieOp>& recorded_activity()
- const {
+ std::vector<RecordingCookieObserver::CookieOp>& recorded_activity() {
return recording_client_.recorded_activity();
}
@@ -483,8 +516,7 @@ TEST_P(RestrictedCookieManagerTest, GetAllForUrlPolicy) {
net::MatchesCookieLine("cookie-name=cookie-value"));
EXPECT_TRUE(
recorded_activity()[1].status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_USER_PREFERENCES}));
+ {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
}
TEST_P(RestrictedCookieManagerTest, GetAllForUrlPolicyWarnActual) {
@@ -530,8 +562,7 @@ TEST_P(RestrictedCookieManagerTest, GetAllForUrlPolicyWarnActual) {
net::MatchesCookieLine("cookie-name=cookie-value"));
EXPECT_TRUE(
recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_SAMESITE_NONE_INSECURE}));
+ {net::CookieInclusionStatus::EXCLUDE_SAMESITE_NONE_INSECURE}));
}
TEST_P(RestrictedCookieManagerTest, SetCanonicalCookie) {
@@ -596,7 +627,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieValidateDomain) {
url::Origin::Create(GURL("https://example.com"))));
ASSERT_EQ(1u, recorded_activity().size());
EXPECT_TRUE(recorded_activity()[0].status.HasExclusionReason(
- net::CanonicalCookie::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH));
+ net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH));
auto options = mojom::CookieManagerGetOptions::New();
options->name = "cookie";
@@ -708,8 +739,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookiePolicy) {
EXPECT_THAT(recorded_activity()[1].cookie, net::MatchesCookieLine("A2=B2"));
EXPECT_TRUE(
recorded_activity()[1].status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_USER_PREFERENCES}));
+ {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
// Read back, in first-party context
auto options = mojom::CookieManagerGetOptions::New();
@@ -755,7 +785,7 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookiePolicyWarnActual) {
EXPECT_THAT(recorded_activity()[0].cookie, net::MatchesCookieLine("A=B"));
EXPECT_TRUE(
recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
+ {net::CookieInclusionStatus::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
}
@@ -857,6 +887,233 @@ TEST_P(RestrictedCookieManagerTest, SameSiteCookiesSpecialScheme) {
EXPECT_THAT(cookies, testing::SizeIs(0));
}
+// Test that the WARN_SAMESITE_COMPAT_PAIR warning is applied correctly to
+// CookieInclusionStatuses passed to the CookieAccessObserver,
+// but does not get into the cookies returned to the renderer.
+TEST_P(RestrictedCookieManagerTest, SameSiteCompatPairWarning_AppliedOnGet) {
+ // Set cookies directly into the store that form a compat pair.
+ ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie(
+ "name", "value", "example.com", "/", base::Time(), base::Time(),
+ base::Time(), /* secure = */ true,
+ /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT)));
+ ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie(
+ "name_legacy", "value", "example.com", "/", base::Time(), base::Time(),
+ base::Time(), /* secure = */ true,
+ /* httponly = */ false, net::CookieSameSite::UNSPECIFIED,
+ net::COOKIE_PRIORITY_DEFAULT)));
+
+ // Get cookies from the RestrictedCookieManager in a same-site context (should
+ // not trigger warnings).
+ {
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "name";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ std::vector<net::CookieWithAccessResult> cookies =
+ sync_service_->GetAllForUrlWithAccessResult(
+ GURL("https://example.com/test/"), GURL("https://example.com"),
+ url::Origin::Create(GURL("https://example.com")),
+ std::move(options));
+
+ ASSERT_THAT(cookies, testing::SizeIs(2));
+ EXPECT_EQ("name", cookies[0].cookie.Name());
+ EXPECT_EQ("name_legacy", cookies[1].cookie.Name());
+
+ // No warning is applied to returned cookies.
+ EXPECT_EQ(net::CookieInclusionStatus(), cookies[0].access_result.status);
+ EXPECT_EQ(net::CookieInclusionStatus(), cookies[1].access_result.status);
+ }
+
+ // No warning is applied to the CookieInclusionStatuses passed to the
+ // CookieAccessObserver.
+ ASSERT_EQ(2u, recorded_activity().size());
+ EXPECT_EQ(recorded_activity()[0].get, true);
+ EXPECT_EQ(recorded_activity()[0].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[0].site_for_cookies, "https://example.com/");
+ EXPECT_THAT(recorded_activity()[0].cookie,
+ net::MatchesCookieLine("name=value"));
+ EXPECT_EQ(net::CookieInclusionStatus(), recorded_activity()[0].status);
+ EXPECT_EQ(recorded_activity()[1].get, true);
+ EXPECT_EQ(recorded_activity()[1].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[1].site_for_cookies, "https://example.com/");
+ EXPECT_THAT(recorded_activity()[1].cookie,
+ net::MatchesCookieLine("name_legacy=value"));
+ EXPECT_EQ(net::CookieInclusionStatus(), recorded_activity()[1].status);
+
+ recorded_activity().clear();
+
+ // Get cookies from the RestrictedCookieManager in a cross-site context to
+ // trigger warnings.
+ service_->OverrideSiteForCookiesForTesting(
+ net::SiteForCookies::FromUrl(GURL("https://notexample.com")));
+ {
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "name";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ std::vector<net::CookieWithAccessResult> cookies =
+ sync_service_->GetAllForUrlWithAccessResult(
+ GURL("https://example.com/test/"), GURL("https://notexample.com"),
+ url::Origin::Create(GURL("https://example.com")),
+ std::move(options));
+
+ ASSERT_THAT(cookies, testing::SizeIs(1));
+ EXPECT_EQ("name", cookies[0].cookie.Name());
+
+ // The warning is not applied to returned cookies.
+ EXPECT_EQ(net::CookieInclusionStatus(), cookies[0].access_result.status);
+ }
+
+ // The warning is applied to the CookieInclusionStatuses passed to the
+ // CookieAccessObserver.
+ ASSERT_EQ(2u, recorded_activity().size());
+ EXPECT_EQ(recorded_activity()[0].get, true);
+ EXPECT_EQ(recorded_activity()[0].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[0].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[0].cookie,
+ net::MatchesCookieLine("name_legacy=value"));
+ EXPECT_TRUE(
+ recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
+ EXPECT_TRUE(recorded_activity()[0].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+ net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR}));
+ EXPECT_EQ(recorded_activity()[1].get, true);
+ EXPECT_EQ(recorded_activity()[1].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[1].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[1].cookie,
+ net::MatchesCookieLine("name=value"));
+ EXPECT_TRUE(recorded_activity()[1].status.IsInclude());
+ EXPECT_TRUE(recorded_activity()[1].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR}));
+}
+
+// Test that the WARN_SAMESITE_COMPAT_PAIR warning is not applied if either of
+// the cookies in the pair is HttpOnly and the access is from a script.
+TEST_P(RestrictedCookieManagerTest, SameSiteCompatPairWarning_HttpOnly) {
+ // Use a cross-site context to trigger warnings.
+ service_->OverrideSiteForCookiesForTesting(
+ net::SiteForCookies::FromUrl(GURL("https://notexample.com")));
+
+ // Set cookies directly into the store that form a compat pair.
+ // One of them is HttpOnly.
+ ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie(
+ "name", "value", "example.com", "/", base::Time(), base::Time(),
+ base::Time(), /* secure = */ true,
+ /* httponly = */ true, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT)));
+ ASSERT_TRUE(EnsureSetCanonicalCookie(net::CanonicalCookie(
+ "name_legacy", "value", "example.com", "/", base::Time(), base::Time(),
+ base::Time(), /* secure = */ true,
+ /* httponly = */ false, net::CookieSameSite::UNSPECIFIED,
+ net::COOKIE_PRIORITY_DEFAULT)));
+
+ // Get cookies from the RestrictedCookieManager in a cross-site context.
+ {
+ auto options = mojom::CookieManagerGetOptions::New();
+ options->name = "name";
+ options->match_type = mojom::CookieMatchType::STARTS_WITH;
+
+ std::vector<net::CookieWithAccessResult> cookies =
+ sync_service_->GetAllForUrlWithAccessResult(
+ GURL("https://example.com/test/"), GURL("https://notexample.com"),
+ url::Origin::Create(GURL("https://example.com")),
+ std::move(options));
+
+ if (GetParam() == mojom::RestrictedCookieManagerRole::SCRIPT) {
+ ASSERT_THAT(cookies, testing::SizeIs(0));
+ } else { // mojom::RestrictedCookieManagerRole::NETWORK
+ ASSERT_THAT(cookies, testing::SizeIs(1));
+ EXPECT_EQ("name", cookies[0].cookie.Name());
+
+ // The warning is not applied to returned cookies.
+ EXPECT_EQ(net::CookieInclusionStatus(), cookies[0].access_result.status);
+ }
+ }
+
+ ASSERT_EQ(GetParam() == mojom::RestrictedCookieManagerRole::SCRIPT ? 1u : 2u,
+ recorded_activity().size());
+ EXPECT_EQ(recorded_activity()[0].get, true);
+ EXPECT_EQ(recorded_activity()[0].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[0].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[0].cookie,
+ net::MatchesCookieLine("name_legacy=value"));
+ EXPECT_TRUE(
+ recorded_activity()[0].status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
+ if (GetParam() == mojom::RestrictedCookieManagerRole::SCRIPT) {
+ // No compat pair warning in script context.
+ EXPECT_TRUE(
+ recorded_activity()[0].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::
+ WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
+ return;
+ }
+ // Compat pair warning is applied in a network context.
+ EXPECT_TRUE(recorded_activity()[0].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT,
+ net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR}));
+
+ EXPECT_EQ(recorded_activity()[1].get, true);
+ EXPECT_EQ(recorded_activity()[1].url, "https://example.com/test/");
+ EXPECT_EQ(recorded_activity()[1].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[1].cookie,
+ net::MatchesCookieLine("name=value"));
+ EXPECT_TRUE(recorded_activity()[1].status.IsInclude());
+ EXPECT_TRUE(recorded_activity()[1].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR}));
+}
+
+// Test that compat pair warning is not applied when RestrictedCookieManager
+// sets a cookie.
+TEST_P(RestrictedCookieManagerTest, SameSiteCompatPairWarning_NotAppliedOnSet) {
+ // Even a cross-site context should not apply warnings for setting cookies.
+ service_->OverrideSiteForCookiesForTesting(
+ net::SiteForCookies::FromUrl(GURL("https://notexample.com")));
+
+ {
+ // SameSite=None cookie is set.
+ auto cookie = net::CanonicalCookie::Create(
+ GURL("https://example.com"), "A=B; SameSite=none; Secure",
+ base::Time::Now(), base::nullopt /* server_time */);
+ EXPECT_TRUE(sync_service_->SetCanonicalCookie(
+ *cookie, GURL("https://example.com"), GURL("https://notexample.com"),
+ url::Origin::Create(GURL("https://example.com"))));
+ }
+ ASSERT_EQ(1u, recorded_activity().size());
+ EXPECT_EQ(recorded_activity()[0].get, false);
+ EXPECT_EQ(recorded_activity()[0].url, "https://example.com/");
+ EXPECT_EQ(recorded_activity()[0].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[0].cookie, net::MatchesCookieLine("A=B"));
+ EXPECT_EQ(net::CookieInclusionStatus(), recorded_activity()[0].status);
+
+ {
+ // Legacy cookie is rejected.
+ auto cookie = net::CanonicalCookie::Create(GURL("https://example.com"),
+ "A_compat=B", base::Time::Now(),
+ base::nullopt /* server_time */);
+ EXPECT_FALSE(sync_service_->SetCanonicalCookie(
+ *cookie, GURL("https://example.com"), GURL("https://notexample.com"),
+ url::Origin::Create(GURL("https://example.com"))));
+ }
+ ASSERT_EQ(2u, recorded_activity().size());
+ EXPECT_EQ(recorded_activity()[1].get, false);
+ EXPECT_EQ(recorded_activity()[1].url, "https://example.com/");
+ EXPECT_EQ(recorded_activity()[1].site_for_cookies, "https://notexample.com/");
+ EXPECT_THAT(recorded_activity()[1].cookie,
+ net::MatchesCookieLine("A_compat=B"));
+ EXPECT_TRUE(
+ recorded_activity()[1].status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
+ EXPECT_TRUE(recorded_activity()[1].status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::
+ WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
+}
+
namespace {
// Stashes the cookie changes it receives, for testing.
@@ -1033,13 +1290,12 @@ TEST_P(RestrictedCookieManagerTest, ChangeNotificationIncludesAccessSemantics) {
base::nullopt);
// Set cookie directly into the CookieMonster, using all-inclusive options.
- net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
- callback;
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
cookie_monster_.SetCanonicalCookieAsync(
std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(&net::ResultSavingCookieCallback<
- net::CanonicalCookie::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback)));
callback.WaitUntilDone();
ASSERT_TRUE(callback.result().IsInclude());
@@ -1089,14 +1345,13 @@ TEST_P(RestrictedCookieManagerTest, NoChangeNotificationForNonlegacyCookie) {
base::Time::Now(), base::nullopt);
// Set cookies directly into the CookieMonster, using all-inclusive options.
- net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
- callback1;
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback1;
cookie_monster_.SetCanonicalCookieAsync(
std::move(unspecified_cookie), cookie_url,
net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(&net::ResultSavingCookieCallback<
- net::CanonicalCookie::CookieInclusionStatus>::Run,
- base::Unretained(&callback1)));
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback1)));
callback1.WaitUntilDone();
ASSERT_TRUE(callback1.result().IsInclude());
@@ -1105,14 +1360,13 @@ TEST_P(RestrictedCookieManagerTest, NoChangeNotificationForNonlegacyCookie) {
base::RunLoop().RunUntilIdle();
ASSERT_THAT(listener.observed_changes(), testing::SizeIs(0));
- net::ResultSavingCookieCallback<net::CanonicalCookie::CookieInclusionStatus>
- callback2;
+ net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback2;
cookie_monster_.SetCanonicalCookieAsync(
std::move(samesite_none_cookie), cookie_url,
net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(&net::ResultSavingCookieCallback<
- net::CanonicalCookie::CookieInclusionStatus>::Run,
- base::Unretained(&callback2)));
+ base::BindOnce(
+ &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
+ base::Unretained(&callback2)));
callback2.WaitUntilDone();
ASSERT_TRUE(callback2.result().IsInclude());
diff --git a/chromium/services/network/ssl_config_service_mojo_unittest.cc b/chromium/services/network/ssl_config_service_mojo_unittest.cc
index 54459ce6469..8679184550f 100644
--- a/chromium/services/network/ssl_config_service_mojo_unittest.cc
+++ b/chromium/services/network/ssl_config_service_mojo_unittest.cc
@@ -4,6 +4,7 @@
#include "services/network/ssl_config_service_mojo.h"
+#include "base/feature_list.h"
#include "base/files/file_util.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
@@ -28,8 +29,10 @@
#include "net/url_request/url_request_context.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/mojom/network_service.mojom.h"
#include "services/network/public/mojom/ssl_config.mojom.h"
+#include "services/network/test/fake_test_cert_verifier_params_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -156,6 +159,12 @@ class NetworkServiceSSLConfigServiceTest : public testing::Test {
// stores it in |network_context_|.
void SetUpNetworkContext(
mojom::NetworkContextParamsPtr network_context_params) {
+ // Use a dummy CertVerifier that always passes cert verification, since
+ // these unittests don't need to test the behavior of a real CertVerifier.
+ // There are a parallel set of tests in services/cert_verifier/ that *do*
+ // test CertVerifier behavior.
+ network_context_params->cert_verifier_params =
+ FakeTestCertVerifierParamsFactory::GetCertVerifierParams();
ssl_config_client_.reset();
network_context_params->ssl_config_client_receiver =
ssl_config_client_.BindNewPipeAndPassReceiver();
@@ -432,10 +441,10 @@ TEST_F(NetworkServiceSSLConfigServiceTest,
TEST_F(NetworkServiceSSLConfigServiceTest, InitialConfigTLS13Hardening) {
net::SSLContextConfig expected_net_config;
- expected_net_config.tls13_hardening_for_local_anchors_enabled = true;
+ expected_net_config.tls13_hardening_for_local_anchors_enabled = false;
mojom::SSLConfigPtr mojo_config = mojom::SSLConfig::New();
- mojo_config->tls13_hardening_for_local_anchors_enabled = true;
+ mojo_config->tls13_hardening_for_local_anchors_enabled = false;
RunConversionTests(*mojo_config, expected_net_config);
}
@@ -489,66 +498,5 @@ TEST_F(NetworkServiceSSLConfigServiceTest, CanShareConnectionWithClientCerts) {
config_service->CanShareConnectionWithClientCerts("example.net"));
}
-#if !defined(OS_IOS) && !defined(OS_ANDROID)
-TEST_F(NetworkServiceSSLConfigServiceTest, CRLSetIsApplied) {
- SetUpNetworkContext(mojom::NetworkContextParams::New());
-
- SSLConfigServiceMojo* config_service = static_cast<SSLConfigServiceMojo*>(
- network_context_->url_request_context()->ssl_config_service());
-
- scoped_refptr<net::X509Certificate> root_cert =
- net::CreateCertificateChainFromFile(
- net::GetTestCertsDirectory(), "root_ca_cert.pem",
- net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
- ASSERT_TRUE(root_cert);
- net::ScopedTestRoot test_root(root_cert.get());
-
- scoped_refptr<net::X509Certificate> cert =
- net::CreateCertificateChainFromFile(
- net::GetTestCertsDirectory(), "ok_cert.pem",
- net::X509Certificate::FORMAT_PEM_CERT_SEQUENCE);
- ASSERT_TRUE(cert);
-
- // Ensure that |cert| is trusted without any CRLSet explicitly configured.
- net::TestCompletionCallback callback1;
- net::CertVerifyResult cert_verify_result1;
- std::unique_ptr<net::CertVerifier::Request> request1;
- int result = network_context_->url_request_context()->cert_verifier()->Verify(
- net::CertVerifier::RequestParams(cert, "127.0.0.1",
- /*flags=*/0,
- /*ocsp_response=*/std::string(),
- /*sct_list=*/std::string()),
- &cert_verify_result1, callback1.callback(), &request1,
- net::NetLogWithSource());
- ASSERT_THAT(callback1.GetResult(result), net::test::IsOk());
-
- // Configure an explicit CRLSet that removes trust in |leaf_cert| by SPKI.
- base::StringPiece spki;
- ASSERT_TRUE(net::asn1::ExtractSPKIFromDERCert(
- net::x509_util::CryptoBufferAsStringPiece(root_cert->cert_buffer()),
- &spki));
- net::SHA256HashValue spki_sha256;
- crypto::SHA256HashString(spki, spki_sha256.data, sizeof(spki_sha256.data));
-
- config_service->OnNewCRLSet(net::CRLSet::ForTesting(
- false, &spki_sha256, cert->serial_number(), "", {}));
-
- // Ensure that |cert| is revoked, due to the CRLSet being applied.
- net::TestCompletionCallback callback2;
- net::CertVerifyResult cert_verify_result2;
- std::unique_ptr<net::CertVerifier::Request> request2;
- result = network_context_->url_request_context()->cert_verifier()->Verify(
- net::CertVerifier::RequestParams(cert, "127.0.0.1",
- /*flags=*/0,
- /*ocsp_response=*/std::string(),
- /*sct_list=*/std::string()),
- &cert_verify_result2, callback2.callback(), &request2,
- net::NetLogWithSource());
- ASSERT_THAT(callback2.GetResult(result),
- net::test::IsError(net::ERR_CERT_REVOKED));
-}
-
-#endif // !defined(OS_IOS) && !defined(OS_ANDROID)
-
} // namespace
} // namespace network
diff --git a/chromium/services/network/tls_client_socket_unittest.cc b/chromium/services/network/tls_client_socket_unittest.cc
index f5aa04d3371..4c13918e9d3 100644
--- a/chromium/services/network/tls_client_socket_unittest.cc
+++ b/chromium/services/network/tls_client_socket_unittest.cc
@@ -19,6 +19,7 @@
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/completion_once_callback.h"
#include "net/base/net_errors.h"
+#include "net/base/network_isolation_key.h"
#include "net/base/test_completion_callback.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/socket/server_socket.h"
@@ -175,7 +176,7 @@ class TLSClientSocketTestBase {
base::RunLoop run_loop;
int net_error = net::ERR_FAILED;
proxy_resolving_factory_->CreateProxyResolvingSocket(
- url, nullptr /* options */,
+ url, net::NetworkIsolationKey(), nullptr /* options */,
net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
std::move(receiver), mojo::NullRemote() /* observer */,
base::BindLambdaForTesting(
diff --git a/chromium/services/network/trust_tokens/BUILD.gn b/chromium/services/network/trust_tokens/BUILD.gn
index a575ad1abbc..2e105004a31 100644
--- a/chromium/services/network/trust_tokens/BUILD.gn
+++ b/chromium/services/network/trust_tokens/BUILD.gn
@@ -80,6 +80,7 @@ source_set("trust_tokens") {
deps = [
":storage_proto",
"//base",
+ "//base/util/values:values_util",
"//components/cbor",
"//components/sqlite_proto",
"//services/network/public/cpp",
diff --git a/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc b/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc
index b886aa93fda..f94124aa50f 100644
--- a/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc
+++ b/chromium/services/network/trust_tokens/has_trust_tokens_answerer_unittest.cc
@@ -6,6 +6,7 @@
#include "base/strings/stringprintf.h"
#include "base/test/bind_test_util.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
diff --git a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h b/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h
index a84afe1ebbf..26103396b58 100644
--- a/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h
+++ b/chromium/services/network/trust_tokens/signed_redemption_record_serialization.h
@@ -9,6 +9,7 @@
#include "base/containers/span.h"
#include "base/optional.h"
+#include "base/strings/string_piece_forward.h"
#include "base/time/time.h"
namespace network {
diff --git a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
index 8fb3c7fc162..f7593979961 100644
--- a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
+++ b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.cc
@@ -6,6 +6,7 @@
#include "base/callback_forward.h"
#include "base/files/file_path.h"
+#include "base/files/file_util.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequenced_task_runner.h"
#include "base/strings/string_split.h"
@@ -145,6 +146,11 @@ void SQLiteTrustTokenPersister::CreateForFilePath(
TrustTokenDatabaseOwner::Create(
/*db_opener=*/base::BindOnce(
[](const base::FilePath& path, sql::Database* db) {
+ const base::FilePath directory = path.DirName();
+ if (!base::PathExists(directory) &&
+ !base::CreateDirectory(directory)) {
+ return false;
+ }
return db->Open(path);
},
path),
diff --git a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.h b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.h
index 04f18b8488d..2081479ac1e 100644
--- a/chromium/services/network/trust_tokens/sqlite_trust_token_persister.h
+++ b/chromium/services/network/trust_tokens/sqlite_trust_token_persister.h
@@ -39,7 +39,8 @@ class SQLiteTrustTokenPersister : public TrustTokenPersister {
// Constructs a SQLiteTrustTokenPersister backed by an on-disk
// database:
// - |db_task_runner| will be used for posting blocking database IO;
- // - |path| will store the database.
+ // - |path| will store the database; if its parent directory doesn't exist,
+ // the method will attempt to create the directory.
// - |flush_delay_for_writes| is the maximum time before each write is flushed
// to the underlying database.
//
diff --git a/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc b/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
index a4416358354..908d96fd0eb 100644
--- a/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
+++ b/chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc
@@ -9,6 +9,7 @@
#include "base/files/file.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
@@ -87,4 +88,34 @@ TEST(SQLiteTrustTokenPersister, PutReinitializeAndGet) {
base::DeleteFile(temp_path, false);
}
+// Ensure that it's possible to create a Trust Tokens persister on top of a
+// directory that does not already exist (regression test for
+// crbug.com/1098019).
+TEST(SQLiteTrustTokenPersister, NonexistentDirectory) {
+ base::test::TaskEnvironment env;
+
+ base::ScopedTempDir temp_dir;
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
+ base::FilePath temp_path = temp_dir.GetPath().Append(
+ FILE_PATH_LITERAL("some-nonexistent-directory/my-database"));
+ ASSERT_FALSE(base::PathExists(temp_path.DirName()));
+
+ std::unique_ptr<SQLiteTrustTokenPersister> persister;
+ SQLiteTrustTokenPersister::CreateForFilePath(
+ base::ThreadTaskRunnerHandle::Get(), temp_path,
+ /*flush_delay_for_writes=*/base::TimeDelta(),
+ base::BindLambdaForTesting(
+ [&persister](std::unique_ptr<SQLiteTrustTokenPersister> created) {
+ persister = std::move(created);
+ base::RunLoop().Quit();
+ }));
+ env.RunUntilIdle(); // Allow initialization to complete.
+ ASSERT_TRUE(persister);
+
+ persister.reset();
+ // Wait until the persister's TrustTokenDatabaseOwner finishes closing its
+ // database asynchronously, so as not to leak after the test concludes.
+ env.RunUntilIdle();
+}
+
} // namespace network
diff --git a/chromium/services/network/trust_tokens/trust_token_http_headers.cc b/chromium/services/network/trust_tokens/trust_token_http_headers.cc
index 2054fe3272e..9a29a03306a 100644
--- a/chromium/services/network/trust_tokens/trust_token_http_headers.cc
+++ b/chromium/services/network/trust_tokens/trust_token_http_headers.cc
@@ -13,7 +13,8 @@ const std::vector<base::StringPiece>& TrustTokensRequestHeaders() {
static base::NoDestructor<std::vector<base::StringPiece>> headers{
{kTrustTokensRequestHeaderSecSignature,
kTrustTokensRequestHeaderSecSignedRedemptionRecord,
- kTrustTokensRequestHeaderSecTime, kTrustTokensSecTrustTokenHeader}};
+ kTrustTokensRequestHeaderSecTime, kTrustTokensSecTrustTokenHeader,
+ kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData}};
return *headers;
}
diff --git a/chromium/services/network/trust_tokens/trust_token_http_headers.h b/chromium/services/network/trust_tokens/trust_token_http_headers.h
index 74d54967163..4bb6247c946 100644
--- a/chromium/services/network/trust_tokens/trust_token_http_headers.h
+++ b/chromium/services/network/trust_tokens/trust_token_http_headers.h
@@ -44,6 +44,11 @@ constexpr char kTrustTokensRequestHeaderSecSignedRedemptionRecord[] =
// header denotes an empty list.
constexpr char kTrustTokensRequestHeaderSignedHeaders[] = "Signed-Headers";
+// As a request header, provides optional additional client-specified signing
+// data alongside signed requests.
+constexpr char kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData[] =
+ "Sec-Trust-Tokens-Additional-Signing-Data";
+
// Returns a view of all of the Trust Tokens-internal request headers.
// This vector contains all of the headers that clients must not provide on
// requests bearing Trust Tokens operations, because they are added internally
diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc
index 888129d8f71..6bcfe8abe58 100644
--- a/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc
+++ b/chromium/services/network/trust_tokens/trust_token_key_commitment_parser.cc
@@ -144,7 +144,7 @@ const char kTrustTokenKeyCommitmentKeyField[] = "Y";
// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#bookmark=id.6wh9crbxdizi
// {
-// "batchsize" : ..., // Optional batch size; value of type int.
+// "batchsize" : ..., // Batch size; value of type int.
// "srrkey" : ..., // Required Signed Redemption Record (SRR)
// // verification key, in base64.
//
diff --git a/chromium/services/network/trust_tokens/trust_token_parameterization.h b/chromium/services/network/trust_tokens/trust_token_parameterization.h
index 77f9af67e7c..93209d72c3f 100644
--- a/chromium/services/network/trust_tokens/trust_token_parameterization.h
+++ b/chromium/services/network/trust_tokens/trust_token_parameterization.h
@@ -11,6 +11,11 @@
namespace network {
+// Note: Some of the constants in this file might spiritually be part of the
+// network service public API and belong in the corresponding
+// services/network/public file; just because they're currently here, not there,
+// doesn't mean there's necessarily a reason they can't be moved.
+
// Priority for running blocking Trust Tokens database IO. This is given value
// USER_VISIBLE because Trust Tokens DB operations can sometimes be in the
// loading critical path, but generally only for subresources.
@@ -48,14 +53,6 @@ constexpr size_t kTrustTokenKeyCommitmentRegistryMaxSizeBytes = 1 << 22;
// 500 is chosen as a high-but-not-excessive value for initial experimentation.
constexpr int kTrustTokenPerIssuerTokenCapacity = 500;
-// The maximum number of trust token issuers allowed to be associated with a
-// given top-level origin.
-//
-// This value is quite low because registering additional issuers with an origin
-// has a number of privacy risks (for instance, whether or not a user has any
-// tokens issued by a given issuer reveals one bit of identifying information).
-constexpr int kTrustTokenPerToplevelMaxNumberOfAssociatedIssuers = 2;
-
// The maximum Trust Tokens batch size (i.e., number of tokens to request from
// an issuer).
constexpr int kMaximumTrustTokenIssuanceBatchSize = 100;
diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc
index 5fd1bc39281..130509bbee4 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc
@@ -13,6 +13,7 @@
#include "net/log/net_log_with_source.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "services/network/trust_tokens/boringssl_trust_token_issuance_cryptographer.h"
#include "services/network/trust_tokens/boringssl_trust_token_redemption_cryptographer.h"
@@ -21,6 +22,7 @@
#include "services/network/trust_tokens/suitable_trust_token_origin.h"
#include "services/network/trust_tokens/trust_token_http_headers.h"
#include "services/network/trust_tokens/trust_token_key_commitment_controller.h"
+#include "services/network/trust_tokens/trust_token_parameterization.h"
#include "services/network/trust_tokens/trust_token_request_canonicalizer.h"
#include "services/network/trust_tokens/trust_token_request_issuance_helper.h"
#include "services/network/trust_tokens/trust_token_request_redemption_helper.h"
@@ -140,9 +142,10 @@ void TrustTokenRequestHelperFactory::ConstructHelperUsingStore(
TrustTokenRequestSigningHelper::Params signing_params(
std::move(*maybe_issuer), top_frame_origin,
std::move(params->additional_signed_headers),
- params->include_timestamp_header, params->sign_request_data);
+ params->include_timestamp_header, params->sign_request_data,
+ params->possibly_unsafe_additional_signing_data);
- LogOutcome(net_log, "Missing/unsuitable 'issuer' parameter");
+ LogOutcome(net_log, "Success");
std::move(done).Run(std::unique_ptr<TrustTokenRequestHelper>(
new TrustTokenRequestSigningHelper(
store, std::move(signing_params),
diff --git a/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc
index 61082ec429b..10c2b2cbb41 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc
@@ -12,10 +12,12 @@
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/optional_trust_token_params.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/test/trust_token_test_util.h"
#include "services/network/trust_tokens/trust_token_http_headers.h"
+#include "services/network/trust_tokens/trust_token_parameterization.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -163,6 +165,20 @@ TEST_F(TrustTokenRequestHelperFactoryTest,
mojom::TrustTokenOperationStatus::kInvalidArgument);
}
+TEST_F(TrustTokenRequestHelperFactoryTest,
+ WillCreateSigningHelperWithAdditionalData) {
+ auto request = CreateSuitableRequest();
+
+ auto params = suitable_params().Clone();
+ params->type = mojom::TrustTokenOperationType::kSigning;
+ params->possibly_unsafe_additional_signing_data =
+ std::string(kTrustTokenAdditionalSigningDataMaxSizeBytes, 'a');
+
+ auto result = CreateHelperAndWaitForResult(suitable_request(), *params);
+ ASSERT_TRUE(result.ok());
+ EXPECT_TRUE(result.TakeOrCrash());
+}
+
TEST_F(TrustTokenRequestHelperFactoryTest, CreatesSigningHelper) {
auto params = suitable_params().Clone();
params->type = mojom::TrustTokenOperationType::kSigning;
diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
index 0bafdc97d9f..7799e2af869 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper_unittest.cc
@@ -14,6 +14,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/trust_tokens/proto/public.pb.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc
index 492987da51c..87661babf5c 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper_unittest.cc
@@ -14,6 +14,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "services/network/trust_tokens/proto/public.pb.h"
#include "services/network/trust_tokens/test/trust_token_test_util.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc
index 682b698cc07..5a185ef4261 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.cc
@@ -22,6 +22,7 @@
#include "net/http/structured_headers.h"
#include "net/url_request/url_request.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "services/network/trust_tokens/proto/public.pb.h"
#include "services/network/trust_tokens/trust_token_http_headers.h"
@@ -76,6 +77,7 @@ base::Optional<std::vector<std::string>> ParseTrustTokenSignedHeadersHeader(
const char* const TrustTokenRequestSigningHelper::kSignableRequestHeaders[]{
kTrustTokensRequestHeaderSecSignedRedemptionRecord,
kTrustTokensRequestHeaderSecTime,
+ kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData,
};
constexpr char
@@ -201,16 +203,20 @@ TrustTokenRequestSigningHelper::TrustTokenRequestSigningHelper(
TrustTokenRequestSigningHelper::~TrustTokenRequestSigningHelper() = default;
-Params::Params(SuitableTrustTokenOrigin issuer,
- SuitableTrustTokenOrigin toplevel,
- std::vector<std::string> additional_headers_to_sign,
- bool should_add_timestamp,
- mojom::TrustTokenSignRequestData sign_request_data)
+Params::Params(
+ SuitableTrustTokenOrigin issuer,
+ SuitableTrustTokenOrigin toplevel,
+ std::vector<std::string> additional_headers_to_sign,
+ bool should_add_timestamp,
+ mojom::TrustTokenSignRequestData sign_request_data,
+ base::Optional<std::string> possibly_unsafe_additional_signing_data)
: issuer(std::move(issuer)),
toplevel(std::move(toplevel)),
additional_headers_to_sign(std::move(additional_headers_to_sign)),
should_add_timestamp(should_add_timestamp),
- sign_request_data(sign_request_data) {}
+ sign_request_data(sign_request_data),
+ possibly_unsafe_additional_signing_data(
+ possibly_unsafe_additional_signing_data) {}
Params::Params(SuitableTrustTokenOrigin issuer,
SuitableTrustTokenOrigin toplevel)
@@ -279,6 +285,43 @@ void TrustTokenRequestSigningHelper::Begin(
return;
}
+ if (params_.possibly_unsafe_additional_signing_data) {
+ if (params_.possibly_unsafe_additional_signing_data->size() >
+ kTrustTokenAdditionalSigningDataMaxSizeBytes) {
+ LogOutcome(net_log_, "Overly long additionalSigningData");
+
+ AttachSignedRedemptionRecordHeader(request, std::string());
+ std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
+ return;
+ }
+
+ if (!net::HttpUtil::IsValidHeaderValue(
+ *params_.possibly_unsafe_additional_signing_data)) {
+ LogOutcome(net_log_,
+ "additionalSigningData was not a valid HTTP header value");
+
+ AttachSignedRedemptionRecordHeader(request, std::string());
+ std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
+ return;
+ }
+
+ // |request| is guaranteed to not have
+ // kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData because
+ // network::TrustTokenRequestHeaders() contains this header name, so the
+ // request would have been rejected as failing a precondition if the header
+ // were present.
+ DCHECK(!request->extra_request_headers().HasHeader(
+ kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData));
+
+ request->SetExtraRequestHeaderByName(
+ kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData,
+ *params_.possibly_unsafe_additional_signing_data,
+ /*overwrite=*/true);
+
+ params_.additional_headers_to_sign.push_back(
+ kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData);
+ }
+
base::Optional<std::vector<std::string>> maybe_headers_to_sign =
GetHeadersToSignAndUpdateSignedHeadersHeader(
request, params_.additional_headers_to_sign);
diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h
index 0520b20d17c..831ee3a68b4 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h
+++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper.h
@@ -77,7 +77,8 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
SuitableTrustTokenOrigin toplevel,
std::vector<std::string> additional_headers_to_sign,
bool should_add_timestamp,
- mojom::TrustTokenSignRequestData sign_request_data);
+ mojom::TrustTokenSignRequestData sign_request_data,
+ base::Optional<std::string> possibly_unsafe_additional_signing_data);
// Minimal convenience constructor. Other fields have reasonable defaults,
// but it's necessary to have |issuer| and |toplevel| at construction time
@@ -119,6 +120,18 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
// kHeadersOnly, the request's headers will be the only request data used.
// If it is kOmit, no signature will be attached.
mojom::TrustTokenSignRequestData sign_request_data;
+
+ // |possibly_unsafe_additional_signing_data| stores the contents of
+ // arbitrary extra client-provided data to include in the outgoing request's
+ // Sec-Trust-Tokens-Additional-Signing-Data header.
+ //
+ // If this is longer than 2048 or not valid to include as a header value,
+ // the signing operation will fail.
+ //
+ // Otherwise, the value will be attached in the
+ // Sec-Trust-Tokens-Additional-Signing-Data header and the header name will
+ // be added to the list of headers to sign.
+ base::Optional<std::string> possibly_unsafe_additional_signing_data;
};
// Class Signer is responsible for the actual generation of signatures over
@@ -177,8 +190,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
// 1. The caller specified headers for signing other than those in
// kSignableRequestHeaders (or if the request has a malformed or otherwise
// invalid signed issuers list in its Signed-Headers header); or
- // 2. |token_store_| contains no SRR for this issuer-toplevel pair,
- // returns kOk and attaches an empty Sec-Signed-Redemption-Record header; or
+ // 2. |token_store_| contains no SRR for this issuer-toplevel pair; or
// 3. an internal error occurs during signing or header serialization.
//
// POSTCONDITIONS:
diff --git a/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc b/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
index 09f2b070816..08a9bad1ae9 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc
@@ -26,6 +26,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "services/network/trust_tokens/proto/public.pb.h"
#include "services/network/trust_tokens/test/signed_request_verification_util.h"
@@ -500,9 +501,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyTimestampHeader) {
std::string signature_string;
ASSERT_NO_FATAL_FAILURE(
AssertHasSignatureAndExtract(*my_request, &signature_string));
- std::string retrieved_url_spec;
+ std::string retrieved_timestamp;
ASSERT_NO_FATAL_FAILURE(AssertDecodesToCborAndExtractField(
- signature_string, "sec-time", &retrieved_url_spec));
+ signature_string, "sec-time", &retrieved_timestamp));
}
// Test a round-trip sign-and-verify additionally signing over the destination
@@ -593,4 +594,117 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty()));
}
+// Test a round-trip sign-and-verify with signed headers when adding additional
+// signing data.
+TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyAdditionalSigningData) {
+ std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+ TrustTokenRequestSigningHelper::Params params(
+ *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")),
+ *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")));
+ params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly;
+ params.possibly_unsafe_additional_signing_data =
+ "some additional data to sign";
+
+ SignedTrustTokenRedemptionRecord record;
+ record.set_body("I am a signed token redemption record");
+ record.set_public_key("key");
+ store->SetRedemptionRecord(params.issuer, params.toplevel, record);
+
+ auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>();
+ TrustTokenRequestSigningHelper helper(store.get(), std::move(params),
+ std::make_unique<IdentitySigner>(),
+ std::move(canonicalizer));
+
+ auto my_request = MakeURLRequest("https://destination.com/");
+ my_request->set_initiator(
+ url::Origin::Create(GURL("https://initiator.com/")));
+ mojom::TrustTokenOperationStatus result =
+ ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
+
+ EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
+ ASSERT_NO_FATAL_FAILURE(
+ ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
+ my_request.get()));
+
+ std::string signature_string;
+ ASSERT_NO_FATAL_FAILURE(
+ AssertHasSignatureAndExtract(*my_request, &signature_string));
+ std::string retrieved_additional_signing_data;
+ ASSERT_NO_FATAL_FAILURE(AssertDecodesToCborAndExtractField(
+ signature_string, "sec-trust-tokens-additional-signing-data",
+ &retrieved_additional_signing_data));
+
+ EXPECT_EQ(retrieved_additional_signing_data, "some additional data to sign");
+}
+
+TEST_F(TrustTokenRequestSigningHelperTest,
+ RejectsOnOverlongAdditionalSigningData) {
+ std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+ TrustTokenRequestSigningHelper::Params params(
+ *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")),
+ *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")));
+ params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly;
+ params.possibly_unsafe_additional_signing_data =
+ std::string(kTrustTokenAdditionalSigningDataMaxSizeBytes + 1, 'a');
+
+ SignedTrustTokenRedemptionRecord my_record;
+ my_record.set_public_key("key");
+ store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+
+ TrustTokenRequestSigningHelper helper(
+ store.get(), std::move(params), std::make_unique<FakeSigner>(),
+ std::make_unique<TrustTokenRequestCanonicalizer>());
+
+ auto my_request = MakeURLRequest("https://destination.com/");
+ my_request->set_initiator(
+ url::Origin::Create(GURL("https://initiator.com/")));
+
+ mojom::TrustTokenOperationStatus result =
+ ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
+
+ // In failure cases, the signing helper should return kOk but attach an empty
+ // SRR header.
+ EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
+ EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty()));
+ EXPECT_THAT(*my_request, Not(Header("Signed-Headers")));
+ EXPECT_THAT(*my_request,
+ Not(Header("Sec-Trust-Tokens-Additional-Signing-Data")));
+}
+
+TEST_F(TrustTokenRequestSigningHelperTest,
+ RejectsOnAdditionalSigningDataThatIsNotAValidHeaderValue) {
+ std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
+
+ TrustTokenRequestSigningHelper::Params params(
+ *SuitableTrustTokenOrigin::Create(GURL("https://issuer.com")),
+ *SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")));
+ params.sign_request_data = mojom::TrustTokenSignRequestData::kHeadersOnly;
+ params.possibly_unsafe_additional_signing_data = "\r";
+
+ SignedTrustTokenRedemptionRecord my_record;
+ my_record.set_public_key("key");
+ store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+
+ TrustTokenRequestSigningHelper helper(
+ store.get(), std::move(params), std::make_unique<FakeSigner>(),
+ std::make_unique<TrustTokenRequestCanonicalizer>());
+
+ auto my_request = MakeURLRequest("https://destination.com/");
+ my_request->set_initiator(
+ url::Origin::Create(GURL("https://initiator.com/")));
+
+ mojom::TrustTokenOperationStatus result =
+ ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
+
+ // In failure cases, the signing helper should return kOk but attach an empty
+ // SRR header.
+ EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
+ EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty()));
+ EXPECT_THAT(*my_request, Not(Header("Signed-Headers")));
+ EXPECT_THAT(*my_request,
+ Not(Header("Sec-Trust-Tokens-Additional-Signing-Data")));
+}
+
} // namespace network
diff --git a/chromium/services/network/trust_tokens/trust_token_store.cc b/chromium/services/network/trust_tokens/trust_token_store.cc
index e9568c59d0c..090531035f4 100644
--- a/chromium/services/network/trust_tokens/trust_token_store.cc
+++ b/chromium/services/network/trust_tokens/trust_token_store.cc
@@ -10,6 +10,7 @@
#include "base/optional.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/trust_tokens.mojom-forward.h"
#include "services/network/trust_tokens/in_memory_trust_token_persister.h"
#include "services/network/trust_tokens/proto/public.pb.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_store_unittest.cc b/chromium/services/network/trust_tokens/trust_token_store_unittest.cc
index 5f5f231be28..8819797097b 100644
--- a/chromium/services/network/trust_tokens/trust_token_store_unittest.cc
+++ b/chromium/services/network/trust_tokens/trust_token_store_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
+#include "services/network/public/cpp/trust_token_parameterization.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/trust_tokens/in_memory_trust_token_persister.h"
#include "services/network/trust_tokens/proto/public.pb.h"
diff --git a/chromium/services/network/trust_tokens/types.cc b/chromium/services/network/trust_tokens/types.cc
index dfa993f2ed3..5911600dbb0 100644
--- a/chromium/services/network/trust_tokens/types.cc
+++ b/chromium/services/network/trust_tokens/types.cc
@@ -2,24 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/network/trust_tokens/types.h"
#include "base/time/time.h"
-#include "base/value_conversions.h"
-#include "base/values.h"
-#include "url/origin.h"
+#include "base/util/values/values_util.h"
namespace network {
namespace internal {
base::Optional<base::Time> StringToTime(base::StringPiece my_string) {
- base::Time ret;
- if (!base::GetValueAsTime(base::Value(my_string), &ret))
- return base::nullopt;
- return ret;
+ return util::ValueToTime(base::Value(my_string));
}
std::string TimeToString(base::Time my_time) {
- return base::CreateTimeValue(my_time).GetString();
+ return util::TimeToValue(my_time).GetString();
}
} // namespace internal
diff --git a/chromium/services/network/url_loader.cc b/chromium/services/network/url_loader.cc
index c9e8660da7a..9d2d455613f 100644
--- a/chromium/services/network/url_loader.cc
+++ b/chromium/services/network/url_loader.cc
@@ -35,6 +35,7 @@
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cookies/canonical_cookie.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/static_cookie_policy.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_connection_status_flags.h"
@@ -44,12 +45,12 @@
#include "net/url_request/url_request_context_getter.h"
#include "services/network/chunked_data_pipe_upload_data_stream.h"
#include "services/network/data_pipe_element_reader.h"
-#include "services/network/empty_url_loader_client.h"
#include "services/network/network_usage_accumulator.h"
#include "services/network/origin_policy/origin_policy_constants.h"
#include "services/network/origin_policy/origin_policy_manager.h"
#include "services/network/public/cpp/constants.h"
#include "services/network/public/cpp/cross_origin_resource_policy.h"
+#include "services/network/public/cpp/empty_url_loader_client.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/cpp/network_switches.h"
@@ -316,14 +317,13 @@ class SSLPrivateKeyInternal : public net::SSLPrivateKey {
DISALLOW_COPY_AND_ASSIGN(SSLPrivateKeyInternal);
};
-bool ShouldNotifyAboutCookie(
- net::CanonicalCookie::CookieInclusionStatus status) {
+bool ShouldNotifyAboutCookie(net::CookieInclusionStatus status) {
// Notify about cookies actually used, and those blocked by preferences ---
// for purposes of cookie UI --- as well those carrying warnings pertaining to
// SameSite features, in order to issue a deprecation warning for them.
return status.IsInclude() || status.ShouldWarn() ||
- status.HasExclusionReason(net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_USER_PREFERENCES);
+ status.HasExclusionReason(
+ net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
}
mojom::HttpRawRequestResponseInfoPtr BuildRawRequestResponseInfo(
@@ -416,6 +416,39 @@ const struct {
{"Via", ConcerningHeaderId::kVia},
};
+void ReportFetchUploadStreamingUMA(const net::URLRequest* request,
+ bool allow_http1_for_streaming_upload) {
+ // Same as tools/metrics/histograms/enums.xml's.
+ enum class HttpProtocolScheme {
+ kHTTP1_1 = 0,
+ kHTTP2 = 1,
+ kQUIC = 2,
+ kMaxValue = kQUIC
+ } protocol;
+ const auto connection_info = request->response_info().connection_info;
+ switch (net::HttpResponseInfo::ConnectionInfoToCoarse(connection_info)) {
+ case net::HttpResponseInfo::CONNECTION_INFO_COARSE_HTTP1:
+ protocol = HttpProtocolScheme::kHTTP1_1;
+ break;
+ case net::HttpResponseInfo::CONNECTION_INFO_COARSE_HTTP2:
+ protocol = HttpProtocolScheme::kHTTP2;
+ break;
+ case net::HttpResponseInfo::CONNECTION_INFO_COARSE_QUIC:
+ protocol = HttpProtocolScheme::kQUIC;
+ break;
+ case net::HttpResponseInfo::CONNECTION_INFO_COARSE_OTHER:
+ protocol = HttpProtocolScheme::kHTTP1_1;
+ break;
+ }
+ if (allow_http1_for_streaming_upload) {
+ base::UmaHistogramEnumeration("Net.Fetch.UploadStreamingProtocolAllowH1",
+ protocol);
+ } else {
+ base::UmaHistogramEnumeration("Net.Fetch.UploadStreamingProtocolNotAllowH1",
+ protocol);
+ }
+}
+
} // namespace
URLLoader::URLLoader(
@@ -427,6 +460,7 @@ URLLoader::URLLoader(
int32_t options,
const ResourceRequest& request,
mojo::PendingRemote<mojom::URLLoaderClient> url_loader_client,
+ base::Optional<DataPipeUseTracker> response_body_use_tracker,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const mojom::URLLoaderFactoryParams* factory_params,
mojom::CrossOriginEmbedderPolicyReporter* coep_reporter,
@@ -456,6 +490,7 @@ URLLoader::URLLoader(
do_not_prompt_for_login_(request.do_not_prompt_for_login),
receiver_(this, std::move(url_loader_receiver)),
url_loader_client_(std::move(url_loader_client)),
+ response_body_use_tracker_(std::move(response_body_use_tracker)),
writable_handle_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
base::SequencedTaskRunnerHandle::Get()),
@@ -477,7 +512,11 @@ URLLoader::URLLoader(
origin_policy_manager_(nullptr),
trust_token_helper_factory_(std::move(trust_token_helper_factory)),
isolated_world_origin_(request.isolated_world_origin),
- cookie_observer_(std::move(cookie_observer)) {
+ cookie_observer_(std::move(cookie_observer)),
+ has_fetch_streaming_upload_body_(HasFetchStreamingUploadBody(&request)),
+ allow_http1_for_streaming_upload_(
+ request.request_body &&
+ request.request_body->AllowHTTP1ForStreamingUpload()) {
DCHECK(delete_callback_);
DCHECK(factory_params_);
if (url_loader_header_client &&
@@ -581,13 +620,17 @@ URLLoader::URLLoader(
// net::LOAD_DO_NOT_* are in the process of being converted to
// credentials_mode. See https://crbug.com/799935.
// TODO(crbug.com/943939): Make this work with CredentialsMode::kSameOrigin.
- if (request.credentials_mode == mojom::CredentialsMode::kOmit) {
+ if (request.credentials_mode == mojom::CredentialsMode::kOmit ||
+ request.credentials_mode ==
+ mojom::CredentialsMode::kOmitBug_775438_Workaround) {
const auto creds_mask = net::LOAD_DO_NOT_SAVE_COOKIES |
net::LOAD_DO_NOT_SEND_COOKIES |
net::LOAD_DO_NOT_SEND_AUTH_DATA;
DCHECK((request.load_flags & creds_mask) == 0 ||
(request.load_flags & creds_mask) == creds_mask);
url_request_->set_allow_credentials(false);
+ url_request_->set_send_client_certs(request.credentials_mode ==
+ mojom::CredentialsMode::kOmit);
}
url_request_->SetRequestHeadersCallback(base::BindRepeating(
@@ -990,8 +1033,33 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
url_loader_client_->OnReceiveRedirect(redirect_info, std::move(response));
}
+// static
+bool URLLoader::HasFetchStreamingUploadBody(const ResourceRequest* request) {
+ // Follows blink::mojom::ResourceType::kXhr.
+ const int kXhr = 13;
+ if (request->resource_type != kXhr)
+ return false;
+ const ResourceRequestBody* request_body = request->request_body.get();
+ if (!request_body)
+ return false;
+ const std::vector<DataElement>* elements = request_body->elements();
+ if (elements->size() == 0u)
+ return false;
+ // https://fetch.spec.whatwg.org/#concept-bodyinit-extract
+ // Body's source is null means the body is not extracted from ReadableStream.
+ // See blink::PopulateResourceRequest() for actual construction.
+ if (elements->size() > 1u)
+ return false;
+ return elements->at(0).type() == mojom::DataElementType::kChunkedDataPipe;
+}
+
void URLLoader::OnAuthRequired(net::URLRequest* url_request,
const net::AuthChallengeInfo& auth_info) {
+ if (has_fetch_streaming_upload_body_) {
+ NotifyCompleted(net::ERR_FAILED);
+ // |this| may have been deleted.
+ return;
+ }
if (!network_context_client_) {
OnAuthCredentials(base::nullopt);
return;
@@ -1074,6 +1142,10 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
has_received_response_ = true;
ReportFlaggedResponseCookies();
+ if (has_fetch_streaming_upload_body_) {
+ ReportFetchUploadStreamingUMA(url_request_.get(),
+ allow_http1_for_streaming_upload_);
+ }
if (net_error != net::OK) {
NotifyCompleted(net_error);
@@ -1092,6 +1164,9 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
NotifyCompleted(net::ERR_INSUFFICIENT_RESOURCES);
return;
}
+ if (response_body_use_tracker_) {
+ response_body_use_tracker_->Activate();
+ }
DCHECK(response_body_stream_.is_valid());
DCHECK(consumer_handle_.is_valid());
@@ -1563,6 +1638,7 @@ void URLLoader::NotifyCompleted(int error_code) {
KeepaliveRequestResult::kErrorBeforeResponseArrival);
}
}
+ response_body_use_tracker_ = base::nullopt;
// Ensure sending the final upload progress message here, since
// OnResponseCompleted can be called without OnResponseStarted on cancellation
// or error cases.
@@ -1685,6 +1761,8 @@ void URLLoader::CompletePendingWrite(bool success) {
// destroyed.
response_body_stream_ =
pending_write_->Complete(pending_write_buffer_offset_);
+ } else {
+ response_body_use_tracker_ = base::nullopt;
}
total_written_bytes_ += pending_write_buffer_offset_;
pending_write_ = nullptr;
@@ -1717,10 +1795,13 @@ void URLLoader::SetRawRequestHeadersAndNotify(
if (cookie_observer_) {
net::CookieStatusList reported_cookies;
- for (const auto& cookie_and_status : url_request_->maybe_sent_cookies()) {
- if (ShouldNotifyAboutCookie(cookie_and_status.status)) {
+ for (const auto& cookie_with_access_result :
+ url_request_->maybe_sent_cookies()) {
+ if (ShouldNotifyAboutCookie(
+ cookie_with_access_result.access_result.status)) {
reported_cookies.push_back(
- {cookie_and_status.cookie, cookie_and_status.status});
+ {cookie_with_access_result.cookie,
+ cookie_with_access_result.access_result.status});
}
}
@@ -1873,7 +1954,7 @@ URLLoader::BlockResponseForCorbResult URLLoader::BlockResponseForCorb() {
// Discard any remaining callbacks or data by rerouting the pipes to
// EmptyURLLoaderClient.
receiver_.reset();
- EmptyURLLoaderClient::DrainURLRequest(
+ EmptyURLLoaderClientWrapper::DrainURLRequest(
url_loader_client_.BindNewPipeAndPassReceiver(),
receiver_.BindNewPipeAndPassRemote());
receiver_.set_disconnect_handler(
diff --git a/chromium/services/network/url_loader.h b/chromium/services/network/url_loader.h
index a8c41f64ae6..33e6b100ef3 100644
--- a/chromium/services/network/url_loader.h
+++ b/chromium/services/network/url_loader.h
@@ -29,6 +29,7 @@
#include "net/url_request/url_request.h"
#include "services/network/cross_origin_read_blocking.h"
#include "services/network/keepalive_statistics_recorder.h"
+#include "services/network/network_service.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
#include "services/network/public/mojom/cross_origin_embedder_policy.mojom-forward.h"
@@ -46,7 +47,7 @@
namespace net {
class HttpResponseHeaders;
class URLRequestContext;
-}
+} // namespace net
namespace network {
@@ -104,6 +105,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
int32_t options,
const ResourceRequest& request,
mojo::PendingRemote<mojom::URLLoaderClient> url_loader_client,
+ base::Optional<DataPipeUseTracker> response_body_use_tracker,
const net::NetworkTrafficAnnotationTag& traffic_annotation,
const mojom::URLLoaderFactoryParams* factory_params,
mojom::CrossOriginEmbedderPolicyReporter* reporter,
@@ -208,6 +210,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
const net::HttpRequestHeaders& request_headers,
bool added_during_redirect);
+ static bool HasFetchStreamingUploadBody(const ResourceRequest*);
+
private:
// This class is used to set the URLLoader as user data on a URLRequest. This
// is used instead of URLLoader directly because SetUserData requires a
@@ -359,6 +363,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
int64_t total_written_bytes_ = 0;
mojo::ScopedDataPipeProducerHandle response_body_stream_;
+ base::Optional<DataPipeUseTracker> response_body_use_tracker_;
scoped_refptr<NetToMojoPendingBuffer> pending_write_;
uint32_t pending_write_buffer_size_ = 0;
uint32_t pending_write_buffer_offset_ = 0;
@@ -490,6 +495,14 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// Observer listening to all cookie reads and writes made by this request.
mojo::Remote<mojom::CookieAccessObserver> cookie_observer_;
+ // Indicates |url_request_| is fetch upload request and that has streaming
+ // body.
+ const bool has_fetch_streaming_upload_body_;
+
+ // Indicates whether fetch upload streaming is allowed/rejected over H/1.
+ // Even if this is false but there is a QUIC/H2 stream, the upload is allowed.
+ const bool allow_http1_for_streaming_upload_;
+
base::WeakPtrFactory<URLLoader> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(URLLoader);
diff --git a/chromium/services/network/url_loader.md b/chromium/services/network/url_loader.md
new file mode 100644
index 00000000000..18d5e490493
--- /dev/null
+++ b/chromium/services/network/url_loader.md
@@ -0,0 +1,7 @@
+# URLLoader
+TODO(loading-dev): Write brief description about URLLoaderFactory, URLLoader and
+URLLoaderClient.
+
+A deck that explains how Mojo connections for these URLLoader classes can be
+established to issue a network request with diagrams:
+https://docs.google.com/presentation/d/1ku7pkh09h6sQ6epudsVvHehRzvanAU7ckzfiVvMoljo/edit?usp=sharing
diff --git a/chromium/services/network/url_loader_factory.cc b/chromium/services/network/url_loader_factory.cc
index 965b6bd501e..c8f02a3760f 100644
--- a/chromium/services/network/url_loader_factory.cc
+++ b/chromium/services/network/url_loader_factory.cc
@@ -24,6 +24,7 @@
#include "services/network/network_usage_accumulator.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/resource_request.h"
+#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/resource_scheduler/resource_scheduler_client.h"
#include "services/network/trust_tokens/trust_token_request_helper_factory.h"
#include "services/network/url_loader.h"
@@ -130,6 +131,7 @@ void URLLoaderFactory::CreateLoaderAndStart(
mojom::NetworkServiceClient* network_service_client = nullptr;
base::WeakPtr<KeepaliveStatisticsRecorder> keepalive_statistics_recorder;
base::WeakPtr<NetworkUsageAccumulator> network_usage_accumulator;
+ base::Optional<DataPipeUseTracker> data_pipe_use_tracker;
if (context_->network_service()) {
network_service_client = context_->network_service()->client();
keepalive_statistics_recorder = context_->network_service()
@@ -137,6 +139,8 @@ void URLLoaderFactory::CreateLoaderAndStart(
->AsWeakPtr();
network_usage_accumulator =
context_->network_service()->network_usage_accumulator()->AsWeakPtr();
+ data_pipe_use_tracker.emplace(context_->network_service(),
+ DataPipeUser::kUrlLoader);
}
bool exhausted = false;
@@ -259,6 +263,7 @@ void URLLoaderFactory::CreateLoaderAndStart(
base::BindOnce(&cors::CorsURLLoaderFactory::DestroyURLLoader,
base::Unretained(cors_url_loader_factory_)),
std::move(receiver), options, url_request, std::move(client),
+ std::move(data_pipe_use_tracker),
static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
params_.get(), coep_reporter_ ? coep_reporter_.get() : nullptr,
request_id, keepalive_request_size, resource_scheduler_client_,
diff --git a/chromium/services/network/url_loader_unittest.cc b/chromium/services/network/url_loader_unittest.cc
index 9b9a75c283a..dc8375fd926 100644
--- a/chromium/services/network/url_loader_unittest.cc
+++ b/chromium/services/network/url_loader_unittest.cc
@@ -50,6 +50,7 @@
#include "net/cert/internal/parse_name.h"
#include "net/cert/test_root_certs.h"
#include "net/cookies/cookie_change_dispatcher.h"
+#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_util.h"
#include "net/dns/mock_host_resolver.h"
#include "net/http/http_response_info.h"
@@ -502,7 +503,8 @@ class URLLoaderTest : public testing::Test {
network_context_client.get(),
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), options, request,
- client_.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client_.CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -1080,7 +1082,8 @@ TEST_F(URLLoaderTest, DestroyOnURLLoaderPipeClosed) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -1136,7 +1139,8 @@ TEST_F(URLLoaderTest, CloseResponseBodyConsumerBeforeProducer) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -1194,9 +1198,9 @@ TEST_F(URLLoaderTest, PauseReadingBodyFromNetBeforeResponseHeaders) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -1274,9 +1278,9 @@ TEST_F(URLLoaderTest, PauseReadingBodyFromNetWhenReadIsPending) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -1343,9 +1347,9 @@ TEST_F(URLLoaderTest, ResumeReadingBodyFromNetAfterClosingConsumer) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -1407,9 +1411,9 @@ TEST_F(URLLoaderTest, MultiplePauseResumeReadingBodyFromNet) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -1662,9 +1666,9 @@ TEST_F(URLLoaderTest, UploadFileCanceled) {
network_context_client.get(),
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -1850,9 +1854,9 @@ TEST_F(URLLoaderTest, UploadChunkedDataPipe) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- nullptr /* resource_scheduler_client */,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, nullptr /* resource_scheduler_client */,
nullptr /* keepalive_statistics_reporter */,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
@@ -1922,7 +1926,8 @@ TEST_F(URLLoaderTest, RedirectModifiedHeaders) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr,
0 /* request_id */, 0 /* keepalive_request_size */,
@@ -1980,7 +1985,8 @@ TEST_F(URLLoaderTest, RedirectFailsOnModifyUnsafeHeader) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client.CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2021,7 +2027,8 @@ TEST_F(URLLoaderTest, RedirectLogsModifiedConcerningHeader) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client.CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2076,7 +2083,8 @@ TEST_F(URLLoaderTest, RedirectRemoveHeader) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2121,7 +2129,8 @@ TEST_F(URLLoaderTest, RedirectRemoveHeaderAndAddItBack) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2170,7 +2179,8 @@ TEST_F(URLLoaderTest, UpgradeAddsSecHeaders) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2223,7 +2233,8 @@ TEST_F(URLLoaderTest, DowngradeRemovesSecHeaders) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2285,7 +2296,8 @@ TEST_F(URLLoaderTest, RedirectChainRemovesAndAddsSecHeaders) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2353,7 +2365,9 @@ TEST_F(URLLoaderTest, RedirectSecHeadersUser) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ request, client()->CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2387,7 +2401,9 @@ TEST_F(URLLoaderTest, RedirectDirectlyModifiedSecHeadersUser) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ request, client()->CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2494,7 +2510,8 @@ TEST_F(URLLoaderTest, ResourceSchedulerIntegration) {
nullptr /* network_context_client */,
NeverInvokedDeleteLoaderCallback(),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client.CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2518,7 +2535,8 @@ TEST_F(URLLoaderTest, ResourceSchedulerIntegration) {
context(), nullptr /* network_service_client */,
nullptr /* network_context_client */, NeverInvokedDeleteLoaderCallback(),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2557,7 +2575,9 @@ TEST_F(URLLoaderTest, ReadPipeClosedWhileReadTaskPosted) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ request, client()->CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2637,7 +2657,7 @@ class MockCookieObserver : public network::mojom::CookieAccessObserver {
// The full details are available for the tests to query manually, but
// they are not covered by operator== (and testing::ElementsAre).
GURL url;
- net::CanonicalCookie::CookieInclusionStatus status;
+ net::CookieInclusionStatus status;
};
mojo::PendingRemote<mojom::CookieAccessObserver> GetRemote() {
@@ -2696,11 +2716,11 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
int32_t process_id,
int32_t routing_id,
const std::string& devtools_request_id,
- const net::CookieStatusList& cookies_with_status,
+ const net::CookieAccessResultList& cookies_with_access_result,
std::vector<network::mojom::HttpRawHeaderPairPtr> headers) override {
raw_request_cookies_.insert(raw_request_cookies_.end(),
- cookies_with_status.begin(),
- cookies_with_status.end());
+ cookies_with_access_result.begin(),
+ cookies_with_access_result.end());
devtools_request_id_ = devtools_request_id;
@@ -2758,7 +2778,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
return raw_response_cookies_;
}
- const net::CookieStatusList& raw_request_cookies() const {
+ const net::CookieAccessResultList& raw_request_cookies() const {
return raw_request_cookies_;
}
@@ -2775,7 +2795,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
std::string devtools_request_id_;
base::Optional<std::string> raw_response_headers_;
- net::CookieStatusList raw_request_cookies_;
+ net::CookieAccessResultList raw_request_cookies_;
base::OnceClosure wait_for_raw_request_;
size_t wait_for_raw_request_goal_ = 0u;
@@ -2947,7 +2967,8 @@ TEST_F(URLLoaderTest, SetAuth) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -2993,7 +3014,8 @@ TEST_F(URLLoaderTest, CancelAuth) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3039,7 +3061,8 @@ TEST_F(URLLoaderTest, TwoChallenges) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3086,7 +3109,8 @@ TEST_F(URLLoaderTest, NoAuthRequiredForFavicon) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3132,7 +3156,8 @@ TEST_F(URLLoaderTest, HttpAuthResponseHeadersAvailable) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3176,7 +3201,8 @@ TEST_F(URLLoaderTest, CorbEffectiveWithCors) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3218,7 +3244,8 @@ TEST_F(URLLoaderTest, CorbExcludedWithNoCors) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3263,7 +3290,8 @@ TEST_F(URLLoaderTest, CorbEffectiveWithNoCorsWhenNoActualPlugin) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3300,7 +3328,9 @@ TEST_F(URLLoaderTest, FollowRedirectTwice) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ request, client()->CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3404,7 +3434,8 @@ TEST_F(URLLoaderTest, ClientAuthRespondTwice) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3457,9 +3488,9 @@ TEST_F(URLLoaderTest, ClientAuthDestroyResponder) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -3501,9 +3532,9 @@ TEST_F(URLLoaderTest, ClientAuthCancelConnection) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -3544,7 +3575,8 @@ TEST_F(URLLoaderTest, ClientAuthCancelCertificateSelection) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3596,7 +3628,8 @@ TEST_F(URLLoaderTest, ClientAuthNoCertificate) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3653,7 +3686,8 @@ TEST_F(URLLoaderTest, ClientAuthCertificateWithValidSignature) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3712,7 +3746,8 @@ TEST_F(URLLoaderTest, ClientAuthCertificateWithInvalidSignature) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3753,9 +3788,9 @@ TEST_F(URLLoaderTest, BlockAllCookies) {
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(),
mojom::kURLLoadOptionBlockAllCookies, request, client()->CreateRemote(),
- TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
- 0 /* request_id */, 0 /* keepalive_request_size */,
- resource_scheduler_client(), nullptr,
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -3783,7 +3818,8 @@ TEST_F(URLLoaderTest, BlockOnlyThirdPartyCookies) {
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(),
mojom::kURLLoadOptionBlockThirdPartyCookies, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3812,7 +3848,9 @@ TEST_F(URLLoaderTest, AllowAllCookies) {
context(), &network_service_client, nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ request, client()->CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt, TRAFFIC_ANNOTATION_FOR_TESTS,
+ &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3822,6 +3860,180 @@ TEST_F(URLLoaderTest, AllowAllCookies) {
EXPECT_TRUE(url_loader->AllowCookies(first_party_url, site_for_cookies));
EXPECT_TRUE(url_loader->AllowCookies(third_party_url, site_for_cookies));
}
+
+// Tests that a request with CredentialsMode::kOmit still sends client
+// certificates. This should be removed when crbug.com/775438 is fixed.
+TEST_F(URLLoaderTest, CredentialsModeOmit) {
+ // Set up a server that requires certificates.
+ net::SSLServerConfig ssl_config;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
+ net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+ test_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("services/test/data")));
+ ASSERT_TRUE(test_server.Start());
+
+ // Make sure the client has valid certificates.
+ std::unique_ptr<net::FakeClientCertIdentity> identity =
+ net::FakeClientCertIdentity::CreateFromCertAndKeyFiles(
+ net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
+ ASSERT_TRUE(identity);
+ scoped_refptr<TestSSLPrivateKey> private_key =
+ base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
+
+ MockNetworkServiceClient network_service_client;
+ MockNetworkContextClient network_context_client;
+ network_context_client.set_certificate_response(
+ MockNetworkContextClient::CertificateResponse::
+ VALID_CERTIFICATE_SIGNATURE);
+ network_context_client.set_private_key(private_key);
+ network_context_client.set_certificate(identity->certificate());
+
+ ResourceRequest request =
+ CreateResourceRequest("GET", test_server.GetURL("/simple_page.html"));
+ request.credentials_mode = mojom::CredentialsMode::kOmit;
+
+ base::RunLoop delete_run_loop;
+ mojo::Remote<mojom::URLLoader> loader;
+ std::unique_ptr<URLLoader> url_loader;
+ mojom::URLLoaderFactoryParams params;
+ params.process_id = kProcessId;
+ params.is_corb_enabled = false;
+ url_loader = std::make_unique<URLLoader>(
+ context(), &network_service_client, &network_context_client,
+ DeleteLoaderCallback(&delete_run_loop, &url_loader),
+ loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ nullptr /* network_usage_accumulator */, nullptr /* header_client */,
+ nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
+ mojo::NullRemote() /* cookie_observer */);
+
+ client()->RunUntilComplete();
+ delete_run_loop.Run();
+
+ EXPECT_EQ(net::OK, client()->completion_status().error_code);
+}
+
+// Tests that a request with CredentialsMode::kOmitBug_775438_Workaround
+// doesn't send client certificates.
+TEST_F(URLLoaderTest, CredentialsModeOmitWorkaround) {
+ // Set up a server that requires certificates.
+ net::SSLServerConfig ssl_config;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::REQUIRE_CLIENT_CERT;
+ net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+ test_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("services/test/data")));
+ ASSERT_TRUE(test_server.Start());
+
+ // Make sure the client has valid certificates.
+ std::unique_ptr<net::FakeClientCertIdentity> identity =
+ net::FakeClientCertIdentity::CreateFromCertAndKeyFiles(
+ net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
+ ASSERT_TRUE(identity);
+ scoped_refptr<TestSSLPrivateKey> private_key =
+ base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
+
+ MockNetworkServiceClient network_service_client;
+ MockNetworkContextClient network_context_client;
+ network_context_client.set_certificate_response(
+ MockNetworkContextClient::CertificateResponse::
+ VALID_CERTIFICATE_SIGNATURE);
+ network_context_client.set_private_key(private_key);
+ network_context_client.set_certificate(identity->certificate());
+
+ ResourceRequest request =
+ CreateResourceRequest("GET", test_server.GetURL("/simple_page.html"));
+ request.credentials_mode = mojom::CredentialsMode::kOmitBug_775438_Workaround;
+
+ base::RunLoop delete_run_loop;
+ mojo::Remote<mojom::URLLoader> loader;
+ std::unique_ptr<URLLoader> url_loader;
+ mojom::URLLoaderFactoryParams params;
+ params.process_id = kProcessId;
+ params.is_corb_enabled = false;
+ url_loader = std::make_unique<URLLoader>(
+ context(), &network_service_client, &network_context_client,
+ DeleteLoaderCallback(&delete_run_loop, &url_loader),
+ loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ nullptr /* network_usage_accumulator */, nullptr /* header_client */,
+ nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
+ mojo::NullRemote() /* cookie_observer */);
+
+ client()->RunUntilComplete();
+ delete_run_loop.Run();
+
+ EXPECT_EQ(0, network_context_client.on_certificate_requested_counter());
+ EXPECT_NE(net::OK, client()->completion_status().error_code);
+}
+
+// Tests that a request with CredentialsMode::kOmitBug_775438_Workaround
+// doesn't send client certificates with a server that optionally requires
+// certificates.
+TEST_F(URLLoaderTest, CredentialsModeOmitWorkaroundWithOptionalCerts) {
+ // Set up a server that requires certificates.
+ net::SSLServerConfig ssl_config;
+ ssl_config.client_cert_type =
+ net::SSLServerConfig::ClientCertType::OPTIONAL_CLIENT_CERT;
+ net::EmbeddedTestServer test_server(net::EmbeddedTestServer::TYPE_HTTPS);
+ test_server.SetSSLConfig(net::EmbeddedTestServer::CERT_OK, ssl_config);
+ test_server.AddDefaultHandlers(
+ base::FilePath(FILE_PATH_LITERAL("services/test/data")));
+ ASSERT_TRUE(test_server.Start());
+
+ // Make sure the client has valid certificates.
+ std::unique_ptr<net::FakeClientCertIdentity> identity =
+ net::FakeClientCertIdentity::CreateFromCertAndKeyFiles(
+ net::GetTestCertsDirectory(), "client_1.pem", "client_1.pk8");
+ ASSERT_TRUE(identity);
+ scoped_refptr<TestSSLPrivateKey> private_key =
+ base::MakeRefCounted<TestSSLPrivateKey>(identity->ssl_private_key());
+
+ MockNetworkServiceClient network_service_client;
+ MockNetworkContextClient network_context_client;
+ network_context_client.set_certificate_response(
+ MockNetworkContextClient::CertificateResponse::
+ VALID_CERTIFICATE_SIGNATURE);
+ network_context_client.set_private_key(private_key);
+ network_context_client.set_certificate(identity->certificate());
+
+ ResourceRequest request =
+ CreateResourceRequest("GET", test_server.GetURL("/simple_page.html"));
+ request.credentials_mode = mojom::CredentialsMode::kOmitBug_775438_Workaround;
+
+ base::RunLoop delete_run_loop;
+ mojo::Remote<mojom::URLLoader> loader;
+ std::unique_ptr<URLLoader> url_loader;
+ mojom::URLLoaderFactoryParams params;
+ params.process_id = kProcessId;
+ params.is_corb_enabled = false;
+ url_loader = std::make_unique<URLLoader>(
+ context(), &network_service_client, &network_context_client,
+ DeleteLoaderCallback(&delete_run_loop, &url_loader),
+ loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ /*coep_reporter=*/nullptr, 0 /* request_id */,
+ 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ nullptr /* network_usage_accumulator */, nullptr /* header_client */,
+ nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
+ mojo::NullRemote() /* cookie_observer */);
+
+ client()->RunUntilComplete();
+ delete_run_loop.Run();
+
+ EXPECT_EQ(0, network_context_client.on_certificate_requested_counter());
+ EXPECT_EQ(net::OK, client()->completion_status().error_code);
+}
#endif // !defined(OS_IOS)
TEST_F(URLLoaderTest, CookieReporting) {
@@ -3843,9 +4055,11 @@ TEST_F(URLLoaderTest, CookieReporting) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -3875,9 +4089,11 @@ TEST_F(URLLoaderTest, CookieReporting) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -3914,7 +4130,8 @@ TEST_F(URLLoaderTest, CookieReportingRedirect) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -3958,9 +4175,11 @@ TEST_F(URLLoaderTest, CookieReportingAuth) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -4003,9 +4222,11 @@ TEST_F(URLLoaderTest, RawRequestCookies) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4019,8 +4240,8 @@ TEST_F(URLLoaderTest, RawRequestCookies) {
network_service_client.raw_request_cookies()[0].cookie.Name());
EXPECT_EQ("b",
network_service_client.raw_request_cookies()[0].cookie.Value());
- EXPECT_TRUE(
- network_service_client.raw_request_cookies()[0].status.IsInclude());
+ EXPECT_TRUE(network_service_client.raw_request_cookies()[0]
+ .access_result.status.IsInclude());
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4054,9 +4275,11 @@ TEST_F(URLLoaderTest, RawRequestCookiesFlagged) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4071,9 +4294,8 @@ TEST_F(URLLoaderTest, RawRequestCookiesFlagged) {
EXPECT_EQ("b",
network_service_client.raw_request_cookies()[0].cookie.Value());
EXPECT_TRUE(network_service_client.raw_request_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_NOT_ON_PATH}));
+ .access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_NOT_ON_PATH}));
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4098,9 +4320,11 @@ TEST_F(URLLoaderTest, RawResponseCookies) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4145,9 +4369,11 @@ TEST_F(URLLoaderTest, RawResponseCookiesInvalid) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4159,10 +4385,10 @@ TEST_F(URLLoaderTest, RawResponseCookiesInvalid) {
network_service_client.WaitUntilRawResponse(1u);
// On these failures the cookie object is not created
EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie);
- EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_FAILURE_TO_STORE}));
+ EXPECT_TRUE(
+ network_service_client.raw_response_cookies()[0]
+ .status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4191,7 +4417,9 @@ TEST_F(URLLoaderTest, RawResponseCookiesRedirect) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -4243,7 +4471,9 @@ TEST_F(URLLoaderTest, RawResponseCookiesRedirect) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.BindNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -4262,8 +4492,7 @@ TEST_F(URLLoaderTest, RawResponseCookiesRedirect) {
network_service_client.raw_response_cookies()[0].cookie->IsSecure());
EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
.status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_SECURE_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
}
}
@@ -4291,9 +4520,11 @@ TEST_F(URLLoaderTest, RawResponseCookiesAuth) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4336,9 +4567,11 @@ TEST_F(URLLoaderTest, RawResponseCookiesAuth) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4352,8 +4585,7 @@ TEST_F(URLLoaderTest, RawResponseCookiesAuth) {
network_service_client.raw_response_cookies()[0].cookie->IsSecure());
EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
.status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_SECURE_ONLY}));
+ {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4379,9 +4611,11 @@ TEST_F(URLLoaderTest, RawResponseQUIC) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
mojo::NullRemote() /* cookie_observer */);
@@ -4431,9 +4665,11 @@ TEST_F(URLLoaderTest, CookieReportingCategories) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -4452,11 +4688,11 @@ TEST_F(URLLoaderTest, CookieReportingCategories) {
if (net::cookie_util::IsSameSiteByDefaultCookiesEnabled()) {
EXPECT_TRUE(cookie_observer.observed_cookies()[0]
.status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
+ {net::CookieInclusionStatus::
EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
}
EXPECT_TRUE(cookie_observer.observed_cookies()[0].status.HasWarningReason(
- net::CanonicalCookie::CookieInclusionStatus::WarningReason::
+ net::CookieInclusionStatus::WarningReason::
WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT));
}
@@ -4486,9 +4722,11 @@ TEST_F(URLLoaderTest, CookieReportingCategories) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -4501,10 +4739,10 @@ TEST_F(URLLoaderTest, CookieReportingCategories) {
EXPECT_THAT(cookie_observer.observed_cookies(),
testing::ElementsAre(MockCookieObserver::CookieDetails{
CookieAccessType::kChange, "a", "b", false}));
- EXPECT_TRUE(cookie_observer.observed_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
- {net::CanonicalCookie::CookieInclusionStatus::
- EXCLUDE_USER_PREFERENCES}));
+ EXPECT_TRUE(
+ cookie_observer.observed_cookies()[0]
+ .status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES}));
test_network_delegate()->set_cookie_options(0);
}
@@ -4528,9 +4766,11 @@ TEST_F(URLLoaderTest, CookieReportingCategories) {
context(), &network_service_client, &network_context_client,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), mojom::kURLLoadOptionNone,
- request, loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS,
- &params, /*coep_reporter=*/nullptr, 0 /* request_id */,
- 0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
+ request, loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params, /*coep_reporter=*/nullptr,
+ 0 /* request_id */, 0 /* keepalive_request_size */,
+ resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
nullptr /* origin_policy_manager */, nullptr /* trust_token_helper */,
cookie_observer.GetRemote());
@@ -4620,7 +4860,9 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -4672,7 +4914,9 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -4711,7 +4955,9 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -4756,7 +5002,9 @@ TEST_F(URLLoaderTest, OriginPolicyManagerCalled) {
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader.InitWithNewPipeAndPassReceiver(), 0, request,
- loader_client.CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ loader_client.CreateRemote(),
+ /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -5001,7 +5249,8 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest,
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -5056,7 +5305,8 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest,
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -5100,7 +5350,8 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest,
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -5143,7 +5394,8 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest,
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
@@ -5185,7 +5437,8 @@ TEST_P(URLLoaderSyncOrAsyncTrustTokenOperationTest,
nullptr /* network_context_client */,
DeleteLoaderCallback(&delete_run_loop, &url_loader),
loader_remote.InitWithNewPipeAndPassReceiver(), 0, request,
- client()->CreateRemote(), TRAFFIC_ANNOTATION_FOR_TESTS, &params,
+ client()->CreateRemote(), /*reponse_body_use_tracker=*/base::nullopt,
+ TRAFFIC_ANNOTATION_FOR_TESTS, &params,
/*coep_reporter=*/nullptr, 0 /* request_id */,
0 /* keepalive_request_size */, resource_scheduler_client(), nullptr,
nullptr /* network_usage_accumulator */, nullptr /* header_client */,
diff --git a/chromium/services/network/websocket.cc b/chromium/services/network/websocket.cc
index ee535a0aa2c..dcf9d7ccb77 100644
--- a/chromium/services/network/websocket.cc
+++ b/chromium/services/network/websocket.cc
@@ -11,9 +11,11 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/feature_list.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/strcat.h"
#include "base/strings/string_number_conversions.h"
@@ -36,11 +38,16 @@
#include "net/websockets/websocket_frame.h" // for WebSocketFrameHeader::OpCode
#include "net/websockets/websocket_handshake_request_info.h"
#include "net/websockets/websocket_handshake_response_info.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/websocket_factory.h"
namespace network {
namespace {
+// What is considered a "small message" for the purposes of small message
+// reassembly.
+constexpr uint64_t kSmallMessageThreshhold = 1 << 16;
+
// Convert a mojom::WebSocketMessageType to a
// net::WebSocketFrameHeader::OpCode
net::WebSocketFrameHeader::OpCode MessageTypeToOpCode(
@@ -118,14 +125,13 @@ class WebSocket::WebSocketEventHandler final
void OnAddChannelResponse(
std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
const std::string& selected_subprotocol,
- const std::string& extensions,
- int64_t send_flow_control_quota) override;
+ const std::string& extensions) override;
void OnDataFrame(bool fin,
WebSocketMessageType type,
base::span<const char> payload) override;
+ void OnSendDataFrameDone() override;
bool HasPendingDataFrames() override;
void OnClosingHandshake() override;
- void OnSendFlowControlQuotaAdded(int64_t quota) override;
void OnDropChannel(bool was_clean,
uint16_t code,
const std::string& reason) override;
@@ -172,8 +178,7 @@ void WebSocket::WebSocketEventHandler::OnCreateURLRequest(
void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
std::unique_ptr<net::WebSocketHandshakeResponseInfo> response,
const std::string& selected_protocol,
- const std::string& extensions,
- int64_t send_flow_control_quota) {
+ const std::string& extensions) {
DVLOG(3) << "WebSocketEventHandler::OnAddChannelResponse @"
<< reinterpret_cast<void*>(this) << " selected_protocol=\""
<< selected_protocol << "\""
@@ -206,6 +211,7 @@ void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
impl_->Reset();
return;
}
+ impl_->data_pipe_use_tracker_.Activate();
const MojoResult mojo_result = impl_->writable_watcher_.Watch(
impl_->writable_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
MOJO_WATCH_CONDITION_SATISFIED,
@@ -241,8 +247,6 @@ void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
impl_->header_client_.reset();
impl_->client_.set_disconnect_handler(base::BindOnce(
&WebSocket::OnConnectionError, base::Unretained(impl_), FROM_HERE));
-
- impl_->client_->AddSendFlowControlQuota(send_flow_control_quota);
}
void WebSocket::WebSocketEventHandler::OnDataFrame(
@@ -259,6 +263,11 @@ void WebSocket::WebSocketEventHandler::OnDataFrame(
impl_->SendPendingDataFrames();
}
+void WebSocket::WebSocketEventHandler::OnSendDataFrameDone() {
+ impl_->ResumeDataPipeReading();
+ return;
+}
+
bool WebSocket::WebSocketEventHandler::HasPendingDataFrames() {
return !impl_->pending_data_frames_.empty();
}
@@ -270,14 +279,6 @@ void WebSocket::WebSocketEventHandler::OnClosingHandshake() {
impl_->client_->OnClosingHandshake();
}
-void WebSocket::WebSocketEventHandler::OnSendFlowControlQuotaAdded(
- int64_t quota) {
- DVLOG(3) << "WebSocketEventHandler::OnSendFlowControlQuotaAdded @"
- << reinterpret_cast<void*>(this) << " quota=" << quota;
-
- impl_->client_->AddSendFlowControlQuota(quota);
-}
-
void WebSocket::WebSocketEventHandler::OnDropChannel(
bool was_clean,
uint16_t code,
@@ -370,6 +371,14 @@ int WebSocket::WebSocketEventHandler::OnAuthRequired(
return net::ERR_IO_PENDING;
}
+struct WebSocket::CloseInfo {
+ CloseInfo(uint16_t code, const std::string& reason)
+ : code(code), reason(reason) {}
+
+ const uint16_t code;
+ const std::string reason;
+};
+
WebSocket::WebSocket(
WebSocketFactory* factory,
const GURL& url,
@@ -386,6 +395,7 @@ WebSocket::WebSocket(
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
WebSocketThrottler::PendingConnection pending_connection_tracker,
+ DataPipeUseTracker data_pipe_use_tracker,
base::TimeDelta delay)
: factory_(factory),
handshake_client_(std::move(handshake_client)),
@@ -404,7 +414,10 @@ WebSocket::WebSocket(
base::ThreadTaskRunnerHandle::Get()),
readable_watcher_(FROM_HERE,
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
- base::ThreadTaskRunnerHandle::Get()) {
+ base::ThreadTaskRunnerHandle::Get()),
+ data_pipe_use_tracker_(std::move(data_pipe_use_tracker)),
+ reassemble_short_messages_(base::FeatureList::IsEnabled(
+ network::features::kWebSocketReassembleShortMessages)) {
DCHECK(handshake_client_);
// If |require_network_isolation_key| is set on the URLRequestContext,
// |isolation_info| must not be empty.
@@ -447,32 +460,6 @@ WebSocket::~WebSocket() {
// static
const void* const WebSocket::kUserDataKey = &WebSocket::kUserDataKey;
-void WebSocket::SendFrame(bool fin,
- mojom::WebSocketMessageType type,
- base::span<const uint8_t> data) {
- DVLOG(3) << "WebSocket::SendFrame @" << reinterpret_cast<void*>(this)
- << " fin=" << fin << " type=" << type << " data is " << data.size()
- << " bytes";
-
- DCHECK(channel_)
- << "WebSocket::SendFrame is called but there is no active channel.";
- DCHECK(handshake_succeeded_);
- // This is guaranteed by the maximum size enforced on mojo messages.
- DCHECK_LE(data.size(), static_cast<size_t>(INT_MAX));
-
- // This is guaranteed by mojo.
- DCHECK(IsKnownEnumValue(type));
-
- // TODO(darin): Avoid this copy.
- auto data_to_pass = base::MakeRefCounted<net::IOBuffer>(data.size());
- memcpy(data_to_pass->data(), data.data(), data.size());
-
- // It's okay to ignore the result here because we don't access |this| after
- // this point.
- ignore_result(channel_->SendFrame(fin, MessageTypeToOpCode(type),
- std::move(data_to_pass), data.size()));
-}
-
void WebSocket::SendMessage(mojom::WebSocketMessageType type,
uint64_t data_length) {
DVLOG(3) << "WebSocket::SendMessage @" << reinterpret_cast<void*>(this)
@@ -489,11 +476,15 @@ void WebSocket::SendMessage(mojom::WebSocketMessageType type,
}
DCHECK(IsKnownEnumValue(type));
- pending_send_data_frames_.push(DataFrame(type, data_length));
+ const bool do_not_fragment =
+ reassemble_short_messages_ && data_length <= kSmallMessageThreshhold;
+
+ pending_send_data_frames_.push(DataFrame(type, data_length, do_not_fragment));
// Safe if ReadAndSendFromDataPipe() deletes |this| because this method is
// only called from mojo.
- ReadAndSendFromDataPipe();
+ if (!blocked_on_websocket_channel_)
+ ReadAndSendFromDataPipe();
}
void WebSocket::StartReceiving() {
@@ -503,13 +494,19 @@ void WebSocket::StartReceiving() {
void WebSocket::StartClosingHandshake(uint16_t code,
const std::string& reason) {
- DVLOG(3) << "WebSocket::StartClosingHandshake @"
- << reinterpret_cast<void*>(this) << " code=" << code << " reason=\""
- << reason << "\"";
+ DVLOG(3) << "WebSocket::StartClosingHandshake @" << this << " code=" << code
+ << " reason=\"" << reason << "\"";
- DCHECK(channel_)
- << "WebSocket::SendFrame is called but there is no active channel.";
+ DCHECK(channel_) << "WebSocket::StartClosingHandshake is called but there is "
+ "no active channel.";
DCHECK(handshake_succeeded_);
+ if (!pending_send_data_frames_.empty()) {
+ // This has only been observed happening on Windows 7, but the Mojo API
+ // doesn't guarantee that it won't happen on other platforms.
+ pending_start_closing_handshake_ =
+ std::make_unique<CloseInfo>(code, reason);
+ return;
+ }
ignore_result(channel_->StartClosingHandshake(code, reason));
}
@@ -628,6 +625,7 @@ void WebSocket::SendPendingDataFrames() {
<< reinterpret_cast<void*>(this)
<< ", pending_data_frames_.size=" << pending_data_frames_.size()
<< ", wait_for_writable_?" << wait_for_writable_;
+
if (wait_for_writable_) {
return;
}
@@ -714,7 +712,9 @@ void WebSocket::ReadAndSendFromDataPipe() {
&buffer, &readable_size, MOJO_READ_DATA_FLAG_NONE);
if (begin_result == MOJO_RESULT_SHOULD_WAIT) {
wait_for_readable_ = true;
- readable_watcher_.ArmOrNotify();
+ if (!blocked_on_websocket_channel_) {
+ readable_watcher_.ArmOrNotify();
+ }
return;
}
if (begin_result == MOJO_RESULT_FAILED_PRECONDITION) {
@@ -722,18 +722,55 @@ void WebSocket::ReadAndSendFromDataPipe() {
}
DCHECK_EQ(begin_result, MOJO_RESULT_OK);
+ if (readable_size < data_frame.data_length && data_frame.do_not_fragment &&
+ !message_under_reassembly_) {
+ // The cast is needed to unambiguously select a constructor on 32-bit
+ // platforms.
+ message_under_reassembly_ = base::MakeRefCounted<net::IOBuffer>(
+ base::checked_cast<size_t>(data_frame.data_length));
+ DCHECK_EQ(bytes_reassembled_, 0u);
+ }
+
+ if (message_under_reassembly_) {
+ const size_t bytes_to_copy =
+ std::min(static_cast<uint64_t>(readable_size),
+ data_frame.data_length - bytes_reassembled_);
+ memcpy(message_under_reassembly_->data() + bytes_reassembled_, buffer,
+ bytes_to_copy);
+ bytes_reassembled_ += bytes_to_copy;
+
+ const MojoResult end_result = readable_->EndReadData(bytes_to_copy);
+ DCHECK_EQ(end_result, MOJO_RESULT_OK);
+
+ DCHECK_LE(bytes_reassembled_, data_frame.data_length);
+ if (bytes_reassembled_ == data_frame.data_length) {
+ bytes_reassembled_ = 0;
+ blocked_on_websocket_channel_ = true;
+ if (channel_->SendFrame(
+ /*fin=*/true, MessageTypeToOpCode(data_frame.type),
+ std::move(message_under_reassembly_), data_frame.data_length) ==
+ net::WebSocketChannel::CHANNEL_DELETED) {
+ // |this| has been deleted.
+ return;
+ }
+ pending_send_data_frames_.pop();
+ }
+
+ continue;
+ }
+
const size_t size_to_send =
std::min(static_cast<uint64_t>(readable_size), data_frame.data_length);
auto data_to_pass = base::MakeRefCounted<net::IOBuffer>(size_to_send);
const bool is_final = (size_to_send == data_frame.data_length);
memcpy(data_to_pass->data(), buffer, size_to_send);
+ blocked_on_websocket_channel_ = true;
if (channel_->SendFrame(is_final, MessageTypeToOpCode(data_frame.type),
std::move(data_to_pass), size_to_send) ==
net::WebSocketChannel::CHANNEL_DELETED) {
// |this| has been deleted.
return;
}
-
const MojoResult end_result = readable_->EndReadData(size_to_send);
DCHECK_EQ(end_result, MOJO_RESULT_OK);
@@ -746,7 +783,17 @@ void WebSocket::ReadAndSendFromDataPipe() {
data_frame.type = mojom::WebSocketMessageType::CONTINUATION;
data_frame.data_length -= size_to_send;
}
- return;
+ if (pending_start_closing_handshake_) {
+ std::unique_ptr<CloseInfo> close_info =
+ std::move(pending_start_closing_handshake_);
+ ignore_result(
+ channel_->StartClosingHandshake(close_info->code, close_info->reason));
+ }
+}
+
+void WebSocket::ResumeDataPipeReading() {
+ blocked_on_websocket_channel_ = false;
+ readable_watcher_.ArmOrNotify();
}
void WebSocket::OnSSLCertificateErrorResponse(
@@ -811,6 +858,7 @@ void WebSocket::Reset() {
auth_handler_.reset();
header_client_.reset();
receiver_.reset();
+ data_pipe_use_tracker_.Reset();
// net::WebSocketChannel requires that we delete it at this point.
channel_.reset();
diff --git a/chromium/services/network/websocket.h b/chromium/services/network/websocket.h
index 234d92ff3ef..4d4f3ef8c08 100644
--- a/chromium/services/network/websocket.h
+++ b/chromium/services/network/websocket.h
@@ -15,6 +15,7 @@
#include "base/containers/queue.h"
#include "base/containers/span.h"
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
#include "base/time/time.h"
@@ -22,6 +23,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/websockets/websocket_event_interface.h"
+#include "services/network/network_service.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/network/public/mojom/websocket.mojom.h"
#include "services/network/websocket_throttler.h"
@@ -34,9 +36,10 @@ class Location;
} // namespace base
namespace net {
+class IOBuffer;
class IsolationInfo;
-class SiteForCookies;
class SSLInfo;
+class SiteForCookies;
class WebSocketChannel;
} // namespace net
@@ -66,13 +69,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
WebSocketThrottler::PendingConnection pending_connection_tracker,
+ DataPipeUseTracker,
base::TimeDelta delay);
~WebSocket() override;
// mojom::WebSocket methods:
- void SendFrame(bool fin,
- mojom::WebSocketMessageType type,
- base::span<const uint8_t> data) override;
void SendMessage(mojom::WebSocketMessageType type,
uint64_t data_length) override;
void StartReceiving() override;
@@ -102,6 +103,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
private:
class WebSocketEventHandler;
+ struct CloseInfo;
// This class is used to set the WebSocket as user data on a URLRequest. This
// is used instead of WebSocket directly because SetUserData requires a
@@ -120,10 +122,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
};
struct DataFrame final {
- DataFrame(mojom::WebSocketMessageType type, uint64_t data_length)
- : type(type), data_length(data_length) {}
+ DataFrame(mojom::WebSocketMessageType type,
+ uint64_t data_length,
+ bool do_not_fragment)
+ : type(type),
+ data_length(data_length),
+ do_not_fragment(do_not_fragment) {}
mojom::WebSocketMessageType type;
uint64_t data_length;
+ const bool do_not_fragment;
};
void OnConnectionError(const base::Location& set_from);
@@ -165,6 +172,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
// ReadAndSendFromDataPipe() may indirectly delete |this|.
void ReadAndSendFromDataPipe();
+ void ResumeDataPipeReading();
// |factory_| owns |this|.
WebSocketFactory* const factory_;
@@ -210,6 +218,30 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
mojo::SimpleWatcher readable_watcher_;
base::queue<DataFrame> pending_send_data_frames_;
bool wait_for_readable_ = false;
+ bool blocked_on_websocket_channel_ = false;
+
+ DataPipeUseTracker data_pipe_use_tracker_;
+
+ // True if we should preserve the old behaviour where <=64KB messages were
+ // never fragmented.
+ // TODO(ricea): Remove the flag once we know whether we really need this or
+ // not. See https://crbug.com/1086273.
+ const bool reassemble_short_messages_;
+
+ // Temporary buffer for storage of short messages that have been fragmented by
+ // the data pipe. Only messages that are actually fragmented are copied into
+ // here.
+ scoped_refptr<net::IOBuffer> message_under_reassembly_;
+
+ // Number of bytes that have been written to |message_under_reassembly_| so
+ // far.
+ size_t bytes_reassembled_ = 0;
+
+ // Set when StartClosingHandshake() is called while
+ // |pending_send_data_frames_| is non-empty. This can happen due to a race
+ // condition between the readable signal on the data pipe and the channel on
+ // which StartClosingHandshake() is called.
+ std::unique_ptr<CloseInfo> pending_start_closing_handshake_;
base::WeakPtrFactory<WebSocket> weak_ptr_factory_{this};
diff --git a/chromium/services/network/websocket_factory.cc b/chromium/services/network/websocket_factory.cc
index 37c59b0dfa2..597b4bcfdc6 100644
--- a/chromium/services/network/websocket_factory.cc
+++ b/chromium/services/network/websocket_factory.cc
@@ -64,6 +64,7 @@ void WebSocketFactory::CreateWebSocket(
options, has_raw_headers_access, std::move(handshake_client),
std::move(auth_handler), std::move(header_client),
throttler_.IssuePendingConnectionTracker(process_id),
+ DataPipeUseTracker(context_->network_service(), DataPipeUser::kWebSocket),
throttler_.CalculateDelay(process_id)));
}
diff --git a/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc b/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
index 5dadce21f92..ecdbe6dfd9e 100644
--- a/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
+++ b/chromium/services/preferences/tracked/pref_hash_filter_unittest.cc
@@ -542,7 +542,7 @@ class PrefHashFilterTest : public testing::TestWithParam<EnforcementLevel>,
public prefs::mojom::ResetOnLoadObserver {
public:
PrefHashFilterTest()
- : mock_pref_hash_store_(NULL),
+ : mock_pref_hash_store_(nullptr),
pref_store_contents_(new base::DictionaryValue),
mock_validation_delegate_record_(new MockValidationDelegateRecord),
mock_validation_delegate_(mock_validation_delegate_record_),
diff --git a/chromium/services/preferences/tracked/registry_hash_store_contents_win.cc b/chromium/services/preferences/tracked/registry_hash_store_contents_win.cc
index 9aee82ae4e9..8b28d3560ff 100644
--- a/chromium/services/preferences/tracked/registry_hash_store_contents_win.cc
+++ b/chromium/services/preferences/tracked/registry_hash_store_contents_win.cc
@@ -7,6 +7,7 @@
#include <windows.h>
#include "base/check_op.h"
+#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
diff --git a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
index 6e58b1737a9..1c79e005fc3 100644
--- a/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
+++ b/chromium/services/proxy_resolver/mojo_proxy_resolver_v8_tracing_bindings.h
@@ -9,7 +9,7 @@
#include <string>
#include <utility>
-#include "base/logging.h"
+#include "base/check.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_checker.h"
#include "net/base/address_family.h"
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/graph.h b/chromium/services/resource_coordinator/memory_instrumentation/graph.h
index a85dc515c5c..5b0251728bd 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/graph.h
+++ b/chromium/services/resource_coordinator/memory_instrumentation/graph.h
@@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// This file is being migrated to the //third_party/perfetto repository
+// as part of the plan in http://crbug.com/1095982. Until the migration
+// is finished, there will be two copies around. Contact
+// mobica-google-contributors@mobica.com if you feel you need to make
+// non-trivial changes to this file.
+
#ifndef SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_H_
#define SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_H_
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/graph_processor.h b/chromium/services/resource_coordinator/memory_instrumentation/graph_processor.h
index 1cf7252b324..2ef6d3b559d 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/graph_processor.h
+++ b/chromium/services/resource_coordinator/memory_instrumentation/graph_processor.h
@@ -2,6 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// This file is being migrated to the //third_party/perfetto repository
+// as part of the plan in http://crbug.com/1095982. Until the migration
+// is finished, there will be two copies around. Contact
+// mobica-google-contributors@mobica.com if you feel you need to make
+// non-trivial changes to this file.
+
#ifndef SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_PROCESSOR_H_
#define SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_GRAPH_PROCESSOR_H_
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
index 58944b0c534..1e95e345556 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h
@@ -45,21 +45,32 @@ class COMPONENT_EXPORT(
#endif
#if defined(OS_LINUX) || defined(OS_ANDROID)
- // Provides information on the dump state of resident pages.
+ // Provides information on the dump state of resident pages. These values are
+ // written to logs. New enum values can be added, but existing enums must
+ // never be renumbered or deleted and reused.
enum class MappedAndResidentPagesDumpState {
// Access to /proc/<pid>/pagemap can be denied for android devices running
// a kernel version < 4.4.
- kAccessPagemapDenied,
- kFailure,
- kSuccess
+ kAccessPagemapDenied = 0,
+ kFailure = 1,
+ kSuccess = 2,
+
+ // Must be equal to the greatest among enumeraiton values.
+ kMaxValue = kSuccess
};
- // Depends on /proc/self/pagemap to determine mapped and resident pages
- // within bounds (start_address inclusive and end_address exclusive).
- // It does not use mincore() because it only checks to see
- // if the page is in the cache and up to date.
- // mincore() has no guarantee a page has been mapped by the current process.
- // Guaranteed to work on Android.
+ // Fills out a bitmap of memory pages accessed by the current process that are
+ // still in pagecache.
+ //
+ // Depends on /proc/self/pagemap to determine the mapped and resident pages
+ // within bounds (|start_address| inclusive and |end_address| exclusive).
+ //
+ // Does not use mincore() because the latter only reports resident pages. The
+ // mincore() would report a page as resident if that page was accessed from a
+ // different process (such as the commonly used prefetch of the native
+ // library).
+ //
+ // Tested only on Android.
static MappedAndResidentPagesDumpState GetMappedAndResidentPages(
const size_t start_address,
const size_t end_address,
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
index 1eabb897893..c3af87bba04 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_linux.cc
@@ -14,6 +14,7 @@
#include "base/files/file_util.h"
#include "base/files/scoped_file.h"
#include "base/format_macros.h"
+#include "base/metrics/histogram_macros.h"
#include "base/process/process_metrics.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
@@ -280,9 +281,13 @@ bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
OSMetrics::GetMappedAndResidentPages(base::android::kStartOfText,
base::android::kEndOfText,
&accessed_pages_bitmap);
+ UMA_HISTOGRAM_ENUMERATION(
+ "Memory.NativeLibrary.MappedAndResidentMemoryFootprintCollectionStatus",
+ state);
// MappedAndResidentPagesDumpState |state| can be |kAccessPagemapDenied|
- // for Android devices running a kernel version < 4.4.
+ // for Android devices running a kernel version < 4.4 or because the process
+ // is not "dumpable", as described in proc(5).
if (state != OSMetrics::MappedAndResidentPagesDumpState::kSuccess)
return state != OSMetrics::MappedAndResidentPagesDumpState::kFailure;
diff --git a/chromium/services/service_manager/embedder/main.cc b/chromium/services/service_manager/embedder/main.cc
index f9c275cdd78..d277d1eea17 100644
--- a/chromium/services/service_manager/embedder/main.cc
+++ b/chromium/services/service_manager/embedder/main.cc
@@ -361,8 +361,7 @@ int Main(const MainParams& params) {
mojo_config.is_broker_process = true;
}
mojo_config.max_message_num_bytes = kMaximumMojoMessageSize;
- delegate->OverrideMojoConfiguration(&mojo_config);
- mojo::core::Init(mojo_config);
+ delegate->InitializeMojo(&mojo_config);
ui::RegisterPathProvider();
diff --git a/chromium/services/service_manager/embedder/main_delegate.cc b/chromium/services/service_manager/embedder/main_delegate.cc
index 439504e5012..65dec35a7a6 100644
--- a/chromium/services/service_manager/embedder/main_delegate.cc
+++ b/chromium/services/service_manager/embedder/main_delegate.cc
@@ -24,8 +24,7 @@ ProcessType MainDelegate::OverrideProcessType() {
return ProcessType::kDefault;
}
-void MainDelegate::OverrideMojoConfiguration(
- mojo::core::Configuration* config) {}
+void MainDelegate::InitializeMojo(mojo::core::Configuration* config) {}
std::vector<Manifest> MainDelegate::GetServiceManifests() {
return std::vector<Manifest>();
diff --git a/chromium/services/service_manager/embedder/main_delegate.h b/chromium/services/service_manager/embedder/main_delegate.h
index 70f9a3ed232..abced50cb03 100644
--- a/chromium/services/service_manager/embedder/main_delegate.h
+++ b/chromium/services/service_manager/embedder/main_delegate.h
@@ -71,8 +71,9 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) MainDelegate {
// return |ProcessType::kDefault| to avoid overriding.
virtual ProcessType OverrideProcessType();
- // Allows the embedder to override the process-wide Mojop configuration.
- virtual void OverrideMojoConfiguration(mojo::core::Configuration* config);
+ // Allows the embedder to override the process-wide Mojo configuration and
+ // initialization.
+ virtual void InitializeMojo(mojo::core::Configuration* config);
// Gets the list of service manifests with which to initialize the Service
// Manager. This list must describe the complete set of usable services in
diff --git a/chromium/services/service_manager/embedder/switches.cc b/chromium/services/service_manager/embedder/switches.cc
index 8337a14af77..7bc83d1a551 100644
--- a/chromium/services/service_manager/embedder/switches.cc
+++ b/chromium/services/service_manager/embedder/switches.cc
@@ -58,9 +58,6 @@ const char kServiceRequestChannelToken[] = "service-request-channel-token";
// global descriptor table.
const char kSharedFiles[] = "shared-files";
-// The prefix used when starting the zygote process. (i.e. 'gdb --args')
-const char kZygoteCmdPrefix[] = "zygote-cmd-prefix";
-
// Causes the process to run as a zygote.
const char kZygoteProcess[] = "zygote";
diff --git a/chromium/services/service_manager/embedder/switches.h b/chromium/services/service_manager/embedder/switches.h
index 548165e5d12..3b6690aa501 100644
--- a/chromium/services/service_manager/embedder/switches.h
+++ b/chromium/services/service_manager/embedder/switches.h
@@ -38,9 +38,6 @@ COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES)
extern const char kSharedFiles[];
COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES)
-extern const char kZygoteCmdPrefix[];
-
-COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER_SWITCHES)
extern const char kZygoteProcess[];
} // namespace switches
diff --git a/chromium/services/service_manager/public/cpp/binder_registry.h b/chromium/services/service_manager/public/cpp/binder_registry.h
index 15ddeac97cd..2144d87dff2 100644
--- a/chromium/services/service_manager/public/cpp/binder_registry.h
+++ b/chromium/services/service_manager/public/cpp/binder_registry.h
@@ -10,6 +10,7 @@
#include <string>
#include "base/callback.h"
+#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -27,19 +28,6 @@ class BinderRegistryWithArgs {
BinderRegistryWithArgs() {}
~BinderRegistryWithArgs() = default;
- // Adds an interface inferring the interface name via the templated
- // parameter Interface::Name_
- // Usage example: //services/service_manager/README.md#OnBindInterface
- template <typename Interface>
- void AddInterface(
- const base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>,
- BinderArgs...)>& callback,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner = nullptr) {
- SetInterfaceBinder(
- Interface::Name_,
- std::make_unique<CallbackBinder<Interface, BinderArgs...>>(
- callback, task_runner));
- }
template <typename Interface>
void AddInterface(
const base::RepeatingCallback<void(mojo::PendingReceiver<Interface>,
diff --git a/chromium/services/service_manager/public/cpp/connector.h b/chromium/services/service_manager/public/cpp/connector.h
index a3b4953978d..0453141851d 100644
--- a/chromium/services/service_manager/public/cpp/connector.h
+++ b/chromium/services/service_manager/public/cpp/connector.h
@@ -192,19 +192,6 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT Connector {
}
template <typename Interface>
- void BindInterface(const ServiceFilter& filter,
- mojo::InterfacePtr<Interface>* ptr) {
- BindInterface(filter, mojo::MakeRequest(ptr));
- }
-
- template <typename Interface>
- void BindInterface(const std::string& service_name,
- mojo::InterfacePtr<Interface>* ptr) {
- return BindInterface(ServiceFilter::ByName(service_name),
- mojo::MakeRequest(ptr));
- }
-
- template <typename Interface>
void BindInterface(const std::string& service_name,
mojo::PendingReceiver<Interface> receiver) {
return BindInterface(ServiceFilter::ByName(service_name),
diff --git a/chromium/services/service_manager/public/cpp/interface_binder.h b/chromium/services/service_manager/public/cpp/interface_binder.h
index 96e12e88d31..ac357f663ec 100644
--- a/chromium/services/service_manager/public/cpp/interface_binder.h
+++ b/chromium/services/service_manager/public/cpp/interface_binder.h
@@ -9,7 +9,6 @@
#include <utility>
#include "base/bind.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
@@ -31,8 +30,8 @@ class InterfaceBinder {
virtual ~InterfaceBinder() {}
// Asks the InterfaceBinder to bind an implementation of the specified
- // interface to the request passed via |handle|. If the InterfaceBinder binds
- // an implementation it must take ownership of the request handle.
+ // interface to the receiver passed via |handle|. If the InterfaceBinder binds
+ // an implementation it must take ownership of the receiver handle.
virtual void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle,
BinderArgs... args) = 0;
@@ -42,18 +41,12 @@ template <typename Interface, typename... BinderArgs>
class CallbackBinder : public InterfaceBinder<BinderArgs...> {
public:
using BindCallback =
- base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>,
+ base::RepeatingCallback<void(mojo::PendingReceiver<Interface>,
BinderArgs...)>;
CallbackBinder(const BindCallback& callback,
const scoped_refptr<base::SequencedTaskRunner>& task_runner)
: callback_(callback), task_runner_(task_runner) {}
- CallbackBinder(
- const base::RepeatingCallback<void(mojo::PendingReceiver<Interface>,
- BinderArgs...)>& callback,
- const scoped_refptr<base::SequencedTaskRunner>& task_runner)
- : CallbackBinder(base::BindRepeating(&RunBindReceiverCallback, callback),
- task_runner) {}
~CallbackBinder() override = default;
private:
@@ -61,28 +54,28 @@ class CallbackBinder : public InterfaceBinder<BinderArgs...> {
void BindInterface(const std::string& interface_name,
mojo::ScopedMessagePipeHandle handle,
BinderArgs... args) override {
- mojo::InterfaceRequest<Interface> request(std::move(handle));
+ mojo::PendingReceiver<Interface> receiver(std::move(handle));
if (task_runner_) {
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&CallbackBinder::RunCallback, callback_,
- std::move(request), args...));
+ std::move(receiver), args...));
} else {
- RunCallback(callback_, std::move(request), args...);
+ RunCallback(callback_, std::move(receiver), args...);
}
}
static void RunCallback(const BindCallback& callback,
- mojo::InterfaceRequest<Interface> request,
+ mojo::PendingReceiver<Interface> receiver,
BinderArgs... args) {
- callback.Run(std::move(request), args...);
+ callback.Run(std::move(receiver), args...);
}
static void RunBindReceiverCallback(
const base::RepeatingCallback<void(mojo::PendingReceiver<Interface>,
BinderArgs...)>& callback,
- mojo::InterfaceRequest<Interface> request,
+ mojo::PendingReceiver<Interface> receiver,
BinderArgs... args) {
- callback.Run(std::move(request), args...);
+ callback.Run(std::move(receiver), args...);
}
const BindCallback callback_;
diff --git a/chromium/services/service_manager/public/cpp/interface_provider.h b/chromium/services/service_manager/public/cpp/interface_provider.h
index 6b5f693afc4..9d65071c00c 100644
--- a/chromium/services/service_manager/public/cpp/interface_provider.h
+++ b/chromium/services/service_manager/public/cpp/interface_provider.h
@@ -16,7 +16,7 @@ namespace service_manager {
// Encapsulates a mojo::PendingRemote|Remote<mojom::InterfaceProvider>
// implemented in a remote application. Provides two main features:
-// - a typesafe GetInterface() method for binding InterfacePtrs.
+// - a typesafe GetInterface() method for binding Interface remotes.
// - a testing API that allows local callbacks to be registered that bind
// requests for remote interfaces.
// An instance of this class is used by the GetInterface() methods on
@@ -87,18 +87,11 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
base::WeakPtr<InterfaceProvider> GetWeakPtr();
- // Binds a passed in interface pointer to an implementation of the interface
- // in the remote application using MakeRequest. The interface pointer can
- // immediately be used to start sending requests to the remote interface.
- // Uses templated parameters in order to work with weak interfaces in blink.
- template <typename... Args>
- void GetInterface(Args&&... args) {
- GetInterface(MakeRequest(std::forward<Args>(args)...));
- }
- template <typename Interface>
- void GetInterface(mojo::InterfaceRequest<Interface> request) {
- GetInterfaceByName(Interface::Name_, std::move(request.PassMessagePipe()));
- }
+ // Binds a passed in pending receiver to an implementation of the interface in
+ // the remote application. The mojo remote associated to the interface in the
+ // local application can immediately be used to start sending requests to the
+ // remote interface. Uses templated parameters in order to work with weak
+ // interfaces in blink.
template <typename Interface>
void GetInterface(mojo::PendingReceiver<Interface> receiver) {
GetInterfaceByName(Interface::Name_, receiver.PassPipe());
@@ -106,23 +99,7 @@ class SERVICE_MANAGER_PUBLIC_CPP_EXPORT InterfaceProvider {
void GetInterfaceByName(const std::string& name,
mojo::ScopedMessagePipeHandle request_handle);
- // Returns a callback to GetInterface<Interface>(). This can be passed to
- // BinderRegistry::AddInterface() to forward requests.
- template <typename Interface>
- base::RepeatingCallback<void(mojo::InterfaceRequest<Interface>)>
- CreateInterfaceFactory() {
- return base::BindRepeating(
- &InterfaceProvider::BindInterfaceRequestFromSource<Interface>,
- GetWeakPtr());
- }
-
private:
- template <typename Interface>
- void BindInterfaceRequestFromSource(
- mojo::InterfaceRequest<Interface> request) {
- GetInterface<Interface>(std::move(request));
- }
-
void SetBinderForName(
const std::string& name,
base::RepeatingCallback<void(mojo::ScopedMessagePipeHandle)> binder) {
diff --git a/chromium/services/service_manager/public/cpp/local_interface_provider.h b/chromium/services/service_manager/public/cpp/local_interface_provider.h
index abf1f739a6f..10e4e840ed1 100644
--- a/chromium/services/service_manager/public/cpp/local_interface_provider.h
+++ b/chromium/services/service_manager/public/cpp/local_interface_provider.h
@@ -6,8 +6,6 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_PROVIDER_BASE_H_
#include "base/macros.h"
-#include "mojo/public/cpp/bindings/interface_ptr.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/system/message_pipe.h"
#include "services/service_manager/public/cpp/export.h"
@@ -18,19 +16,6 @@ class LocalInterfaceProvider {
public:
virtual ~LocalInterfaceProvider() = default;
- // Binds |ptr| to an implementation of Interface in the remote application.
- // |ptr| can immediately be used to start sending requests to the remote
- // interface.
- template <typename Interface>
- void GetInterface(mojo::InterfacePtr<Interface>* ptr) {
- mojo::MessagePipe pipe;
- ptr->Bind(mojo::InterfacePtrInfo<Interface>(std::move(pipe.handle0), 0u));
- GetInterface(Interface::Name_, std::move(pipe.handle1));
- }
- template <typename Interface>
- void GetInterface(mojo::InterfaceRequest<Interface> request) {
- GetInterface(Interface::Name_, std::move(request.PassMessagePipe()));
- }
template <typename Interface>
void GetInterface(mojo::PendingReceiver<Interface> receiver) {
GetInterface(Interface::Name_, std::move(receiver.PassPipe()));
diff --git a/chromium/services/service_manager/sandbox/BUILD.gn b/chromium/services/service_manager/sandbox/BUILD.gn
index 0e9bfbf0327..21749ad3322 100644
--- a/chromium/services/service_manager/sandbox/BUILD.gn
+++ b/chromium/services/service_manager/sandbox/BUILD.gn
@@ -79,6 +79,8 @@ component("sandbox") {
sources += [
"linux/bpf_ime_policy_linux.cc",
"linux/bpf_ime_policy_linux.h",
+ "linux/bpf_tts_policy_linux.cc",
+ "linux/bpf_tts_policy_linux.h",
]
}
if (is_mac) {
diff --git a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc b/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
index 2747e169d6a..0d178b90d10 100644
--- a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
+++ b/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
@@ -28,10 +28,10 @@
#include "base/command_line.h"
#include "base/containers/span.h"
#include "base/files/file_util.h"
-#include "base/fuchsia/default_context.h"
#include "base/fuchsia/default_job.h"
#include "base/fuchsia/filtered_service_directory.h"
#include "base/fuchsia/fuchsia_logging.h"
+#include "base/fuchsia/process_context.h"
#include "base/path_service.h"
#include "base/process/launch.h"
#include "base/process/process.h"
@@ -167,7 +167,7 @@ SandboxPolicyFuchsia::SandboxPolicyFuchsia(service_manager::SandboxType type) {
service_directory_task_runner_ = base::ThreadTaskRunnerHandle::Get();
service_directory_ =
std::make_unique<base::fuchsia::FilteredServiceDirectory>(
- base::fuchsia::ComponentContextForCurrentProcess()->svc().get());
+ base::ComponentContextForProcess()->svc().get());
for (const char* service_name : kDefaultServices) {
service_directory_->AddService(service_name);
}
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.cc
new file mode 100644
index 00000000000..812072395ec
--- /dev/null
+++ b/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.cc
@@ -0,0 +1,34 @@
+// Copyright 2020 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 "services/service_manager/sandbox/linux/bpf_tts_policy_linux.h"
+
+#include <sys/socket.h>
+
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
+#include "sandbox/linux/syscall_broker/broker_process.h"
+#include "sandbox/linux/system_headers/linux_syscalls.h"
+#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+
+using sandbox::bpf_dsl::Allow;
+using sandbox::bpf_dsl::ResultExpr;
+using sandbox::bpf_dsl::Trap;
+using sandbox::syscall_broker::BrokerProcess;
+
+namespace service_manager {
+
+TtsProcessPolicy::TtsProcessPolicy() {}
+
+TtsProcessPolicy::~TtsProcessPolicy() {}
+
+ResultExpr TtsProcessPolicy::EvaluateSyscall(int sysno) const {
+ auto* broker_process = SandboxLinux::GetInstance()->broker_process();
+ if (broker_process->IsSyscallAllowed(sysno))
+ return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
+
+ return BPFBasePolicy::EvaluateSyscall(sysno);
+}
+
+} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.h
new file mode 100644
index 00000000000..a562a68cfce
--- /dev/null
+++ b/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.h
@@ -0,0 +1,27 @@
+// Copyright 2020 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 SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_TTS_POLICY_LINUX_H_
+#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_TTS_POLICY_LINUX_H_
+
+#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
+#include "services/service_manager/sandbox/export.h"
+#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
+
+namespace service_manager {
+
+class SERVICE_MANAGER_SANDBOX_EXPORT TtsProcessPolicy : public BPFBasePolicy {
+ public:
+ TtsProcessPolicy();
+ ~TtsProcessPolicy() override;
+
+ sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TtsProcessPolicy);
+};
+
+} // namespace service_manager
+
+#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_TTS_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_linux.h b/chromium/services/service_manager/sandbox/linux/sandbox_linux.h
index 9f67272c5e2..6a17f9edb63 100644
--- a/chromium/services/service_manager/sandbox/linux/sandbox_linux.h
+++ b/chromium/services/service_manager/sandbox/linux/sandbox_linux.h
@@ -9,7 +9,7 @@
#include <string>
#include <vector>
-#include "base/logging.h"
+#include "base/check_op.h"
#include "base/macros.h"
#include "base/posix/global_descriptors.h"
#include "sandbox/linux/syscall_broker/broker_command.h"
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc b/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc
index e2f22540a5a..1c16d68df91 100644
--- a/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc
+++ b/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc
@@ -54,6 +54,7 @@
#if defined(OS_CHROMEOS)
#include "services/service_manager/sandbox/linux/bpf_ime_policy_linux.h"
+#include "services/service_manager/sandbox/linux/bpf_tts_policy_linux.h"
#endif // defined(OS_CHROMEOS)
using sandbox::BaselinePolicy;
@@ -185,6 +186,8 @@ std::unique_ptr<BPFBasePolicy> SandboxSeccompBPF::PolicyForSandboxType(
#if defined(OS_CHROMEOS)
case SandboxType::kIme:
return std::make_unique<ImeProcessPolicy>();
+ case SandboxType::kTts:
+ return std::make_unique<TtsProcessPolicy>();
#endif // defined(OS_CHROMEOS)
case SandboxType::kZygoteIntermediateSandbox:
case SandboxType::kNoSandbox:
@@ -228,6 +231,7 @@ void SandboxSeccompBPF::RunSandboxSanityChecks(
} break;
#if defined(OS_CHROMEOS)
case SandboxType::kIme:
+ case SandboxType::kTts:
#endif // defined(OS_CHROMEOS)
case SandboxType::kAudio:
case SandboxType::kSharingService:
diff --git a/chromium/services/service_manager/sandbox/sandbox_type.cc b/chromium/services/service_manager/sandbox/sandbox_type.cc
index 9ea1cccb467..de79b63b7de 100644
--- a/chromium/services/service_manager/sandbox/sandbox_type.cc
+++ b/chromium/services/service_manager/sandbox/sandbox_type.cc
@@ -8,6 +8,7 @@
#include "base/check.h"
#include "base/feature_list.h"
+#include "base/logging.h"
#include "base/notreached.h"
#include "services/service_manager/sandbox/features.h"
#include "services/service_manager/sandbox/switches.h"
@@ -26,6 +27,7 @@ bool IsUnsandboxedSandboxType(SandboxType sandbox_type) {
service_manager::features::kXRSandbox);
case SandboxType::kProxyResolver:
case SandboxType::kPdfConversion:
+ case SandboxType::kIconReader:
return false;
#endif
case SandboxType::kAudio:
@@ -57,6 +59,7 @@ bool IsUnsandboxedSandboxType(SandboxType sandbox_type) {
#endif
#if defined(OS_CHROMEOS)
case SandboxType::kIme:
+ case SandboxType::kTts:
#endif
#if !defined(OS_MACOSX)
case SandboxType::kSharingService:
@@ -116,9 +119,11 @@ void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
case SandboxType::kXrCompositing:
case SandboxType::kProxyResolver:
case SandboxType::kPdfConversion:
+ case SandboxType::kIconReader:
#endif // defined(OS_WIN)
#if defined(OS_CHROMEOS)
case SandboxType::kIme:
+ case SandboxType::kTts:
#endif // defined(OS_CHROMEOS)
#if !defined(OS_MACOSX)
case SandboxType::kSharingService:
@@ -237,10 +242,14 @@ std::string StringFromUtilitySandboxType(SandboxType sandbox_type) {
return switches::kProxyResolverSandbox;
case SandboxType::kPdfConversion:
return switches::kPdfConversionSandbox;
+ case SandboxType::kIconReader:
+ return switches::kIconReaderSandbox;
#endif // defined(OS_WIN)
#if defined(OS_CHROMEOS)
case SandboxType::kIme:
return switches::kImeSandbox;
+ case SandboxType::kTts:
+ return switches::kTtsSandbox;
#endif // defined(OS_CHROMEOS)
// The following are not utility processes so should not occur.
case SandboxType::kRenderer:
@@ -287,6 +296,8 @@ SandboxType UtilitySandboxTypeFromString(const std::string& sandbox_string) {
return SandboxType::kProxyResolver;
if (sandbox_string == switches::kPdfConversionSandbox)
return SandboxType::kPdfConversion;
+ if (sandbox_string == switches::kIconReaderSandbox)
+ return SandboxType::kIconReader;
#endif
if (sandbox_string == switches::kAudioSandbox)
return SandboxType::kAudio;
@@ -297,6 +308,8 @@ SandboxType UtilitySandboxTypeFromString(const std::string& sandbox_string) {
#if defined(OS_CHROMEOS)
if (sandbox_string == switches::kImeSandbox)
return SandboxType::kIme;
+ if (sandbox_string == switches::kTtsSandbox)
+ return SandboxType::kTts;
#endif // defined(OS_CHROMEOS)
return SandboxType::kUtility;
}
diff --git a/chromium/services/service_manager/sandbox/sandbox_type.h b/chromium/services/service_manager/sandbox/sandbox_type.h
index 0eb1e615939..b35e3950ccf 100644
--- a/chromium/services/service_manager/sandbox/sandbox_type.h
+++ b/chromium/services/service_manager/sandbox/sandbox_type.h
@@ -30,6 +30,9 @@ enum class SandboxType {
// The PDF conversion service process used in printing.
kPdfConversion,
+
+ // The icon reader service.
+ kIconReader,
#endif
#if defined(OS_FUCHSIA)
@@ -69,6 +72,8 @@ enum class SandboxType {
#if defined(OS_CHROMEOS)
kIme,
+ // Text-to-speech.
+ kTts,
#endif // defined(OS_CHROMEOS)
#if defined(OS_LINUX)
diff --git a/chromium/services/service_manager/sandbox/switches.cc b/chromium/services/service_manager/sandbox/switches.cc
index 863638ae365..e635d4e8eed 100644
--- a/chromium/services/service_manager/sandbox/switches.cc
+++ b/chromium/services/service_manager/sandbox/switches.cc
@@ -36,10 +36,12 @@ const char kVideoCaptureSandbox[] = "video_capture";
const char kPdfConversionSandbox[] = "pdf_conversion";
const char kProxyResolverSandbox[] = "proxy_resolver";
const char kXrCompositingSandbox[] = "xr_compositing";
+const char kIconReaderSandbox[] = "icon_reader";
#endif // OS_WIN
#if defined(OS_CHROMEOS)
const char kImeSandbox[] = "ime";
+const char kTtsSandbox[] = "tts";
#endif // OS_CHROMEOS
// Flags owned by the service manager sandbox.
@@ -80,6 +82,7 @@ const char kGpuSandboxAllowSysVShm[] = "gpu-sandbox-allow-sysv-shm";
const char kGpuSandboxFailuresFatal[] = "gpu-sandbox-failures-fatal";
// Disables the sandbox for all process types that are normally sandboxed.
+// Meant to be used as a browser-level switch for testing purposes only.
const char kNoSandbox[] = "no-sandbox";
#if defined(OS_LINUX)
diff --git a/chromium/services/service_manager/sandbox/switches.h b/chromium/services/service_manager/sandbox/switches.h
index 0deedde8296..6d66ab6c4f2 100644
--- a/chromium/services/service_manager/sandbox/switches.h
+++ b/chromium/services/service_manager/sandbox/switches.h
@@ -35,10 +35,12 @@ SERVICE_MANAGER_SANDBOX_EXPORT extern const char kVideoCaptureSandbox[];
SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPdfConversionSandbox[];
SERVICE_MANAGER_SANDBOX_EXPORT extern const char kProxyResolverSandbox[];
SERVICE_MANAGER_SANDBOX_EXPORT extern const char kXrCompositingSandbox[];
+SERVICE_MANAGER_SANDBOX_EXPORT extern const char kIconReaderSandbox[];
#endif // OS_WIN
#if defined(OS_CHROMEOS)
SERVICE_MANAGER_SANDBOX_EXPORT extern const char kImeSandbox[];
+SERVICE_MANAGER_SANDBOX_EXPORT extern const char kTtsSandbox[];
#endif // OS_CHROMEOS
// Flags owned by the service manager sandbox.
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h b/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h
index 5470fe1ada6..1f89e7ee7a9 100644
--- a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h
+++ b/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h
@@ -14,7 +14,6 @@
#include <vector>
#include "base/callback.h"
-#include "base/logging.h"
#include "base/sequenced_task_runner.h"
#include "base/values.h"
#include "sandbox/constants.h"
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_win.cc b/chromium/services/service_manager/sandbox/win/sandbox_win.cc
index a05106e2611..cde75bd0710 100644
--- a/chromium/services/service_manager/sandbox/win/sandbox_win.cc
+++ b/chromium/services/service_manager/sandbox/win/sandbox_win.cc
@@ -33,6 +33,7 @@
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/system/sys_info.h"
+#include "base/trace_event/trace_arguments.h"
#include "base/trace_event/trace_event.h"
#include "base/win/iat_patch_function.h"
#include "base/win/scoped_handle.h"
@@ -44,6 +45,7 @@
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sandbox_nt_util.h"
#include "sandbox/win/src/sandbox_policy_base.h"
+#include "sandbox/win/src/sandbox_policy_diagnostic.h"
#include "sandbox/win/src/win_utils.h"
#include "services/service_manager/sandbox/features.h"
#include "services/service_manager/sandbox/sandbox_type.h"
@@ -150,6 +152,26 @@ const wchar_t* const kTroublesomeDlls[] = {
const base::Feature kEnableCsrssLockdownFeature{
"EnableCsrssLockdown", base::FEATURE_DISABLED_BY_DEFAULT};
+// Helps emit trace events for sandbox policy. This mediates memory between
+// chrome.exe and chrome.dll.
+class PolicyTraceHelper : public base::trace_event::ConvertableToTraceFormat {
+ public:
+ PolicyTraceHelper(sandbox::TargetPolicy* policy) {
+ // |info| must live until JsonString() output is copied.
+ std::unique_ptr<sandbox::PolicyInfo> info = policy->GetPolicyInfo();
+ json_string_ = std::string(info->JsonString());
+ }
+ ~PolicyTraceHelper() override = default;
+
+ // ConvertableToTraceFormat.
+ void AppendAsTraceFormat(std::string* out) const override {
+ out->append(json_string_);
+ }
+
+ private:
+ std::string json_string_;
+}; // PolicyTraceHelper
+
#if !defined(NACL_WIN64)
// Adds the policy rules for the path and path\ with the semantic |access|.
// If |children| is set to true, we need to add the wildcard rules to also
@@ -599,14 +621,15 @@ base::string16 GetAppContainerProfileName(
sandbox_type == SandboxType::kXrCompositing);
auto sha1 = base::SHA1HashString(appcontainer_id);
std::string sandbox_base_name = (sandbox_type == SandboxType::kXrCompositing)
- ? std::string("chrome.sandbox.xrdevice")
- : std::string("chrome.sandbox.gpu");
+ ? std::string("cr.sb.xr")
+ : std::string("cr.sb.gpu");
std::string profile_name = base::StrCat(
{sandbox_base_name, base::HexEncode(sha1.data(), sha1.size())});
// CreateAppContainerProfile requires that the profile name is at most 64
- // characters. The size of sha1 is a constant 40, so validate that the base
- // names are sufficiently short that the total length is valid.
- DCHECK_LE(profile_name.length(), 64U);
+ // characters but 50 on WCOS systems. The size of sha1 is a constant 40,
+ // so validate that the base names are sufficiently short that the total
+ // length is valid on all systems.
+ DCHECK_LE(profile_name.length(), 50U);
return base::UTF8ToWide(profile_name);
}
@@ -845,6 +868,7 @@ bool SandboxWin::InitTargetServices(sandbox::TargetServices* target_services) {
return sandbox::SBOX_ALL_OK == result;
}
+// static
sandbox::ResultCode SandboxWin::StartSandboxedProcess(
base::CommandLine* cmd_line,
const std::string& process_type,
@@ -929,7 +953,8 @@ sandbox::ResultCode SandboxWin::StartSandboxedProcess(
if (!cmd_line->HasSwitch(switches::kAllowThirdPartyModules))
mitigations |= sandbox::MITIGATION_FORCE_MS_SIGNED_BINS;
if (sandbox_type == SandboxType::kNetwork ||
- sandbox_type == SandboxType::kAudio) {
+ sandbox_type == SandboxType::kAudio ||
+ sandbox_type == SandboxType::kIconReader) {
mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
}
// TODO(wfh): Relax strict handle checks for network process until root cause
@@ -1017,20 +1042,17 @@ sandbox::ResultCode SandboxWin::StartSandboxedProcess(
cmd_line->GetCommandLineString().c_str(), policy, &last_warning,
&last_error, &temp_process_info);
- // TODO(1059129) Remove logging and underlying plumbing on expiry.
- // This must be logged after spawning the process as the policy
- // memory is not committed until the target process is attached to
- // the sandbox policy. Max is kPolMemSize from sandbox_policy_base.cc.
- if (result == sandbox::SBOX_ALL_OK) {
- UMA_HISTOGRAM_CUSTOM_COUNTS("Process.Sandbox.PolicyGlobalSizeOnSuccess",
- policy->GetPolicyGlobalSize(), 16, 14 * 4096,
- 50);
- }
-
base::win::ScopedProcessInformation target(temp_process_info);
TRACE_EVENT_END0("startup", "StartProcessWithAccess::LAUNCHPROCESS");
+ // Trace policy as processes are started. Useful for both failure and success.
+ TRACE_EVENT_INSTANT2(TRACE_DISABLED_BY_DEFAULT("sandbox"), "processLaunch",
+ TRACE_EVENT_SCOPE_PROCESS, "sandboxType",
+ GetSandboxTypeInEnglish(delegate->GetSandboxType()),
+ "policy",
+ std::make_unique<PolicyTraceHelper>(policy.get()));
+
if (sandbox::SBOX_ALL_OK != result) {
base::UmaHistogramSparse("Process.Sandbox.Launch.Error", last_error);
if (result == sandbox::SBOX_ERROR_GENERIC)
@@ -1057,6 +1079,7 @@ sandbox::ResultCode SandboxWin::StartSandboxedProcess(
return sandbox::SBOX_ALL_OK;
}
+// static
sandbox::ResultCode SandboxWin::GetPolicyDiagnostics(
base::OnceCallback<void(base::Value)> response) {
CHECK(g_broker_services);
@@ -1072,4 +1095,44 @@ void BlocklistAddOneDllForTesting(const wchar_t* module_name,
BlocklistAddOneDll(module_name, check_in_browser, policy);
}
+// static
+std::string SandboxWin::GetSandboxTypeInEnglish(SandboxType sandbox_type) {
+ switch (sandbox_type) {
+ case SandboxType::kNoSandbox:
+ return "Unsandboxed";
+ case SandboxType::kNoSandboxAndElevatedPrivileges:
+ return "Unsandboxed (Elevated)";
+ case SandboxType::kXrCompositing:
+ return "XR Compositing";
+ case SandboxType::kRenderer:
+ return "Renderer";
+ case SandboxType::kUtility:
+ return "Utility";
+ case SandboxType::kGpu:
+ return "GPU";
+ case SandboxType::kPpapi:
+ return "PPAPI";
+ case SandboxType::kNetwork:
+ return "Network";
+ case SandboxType::kCdm:
+ return "CDM";
+ case SandboxType::kPrintCompositor:
+ return "Print Compositor";
+ case SandboxType::kAudio:
+ return "Audio";
+ case SandboxType::kSpeechRecognition:
+ return "Speech Recognition";
+ case SandboxType::kProxyResolver:
+ return "Proxy Resolver";
+ case SandboxType::kPdfConversion:
+ return "PDF Conversion";
+ case SandboxType::kSharingService:
+ return "Sharing";
+ case SandboxType::kVideoCapture:
+ return "Video Capture";
+ case SandboxType::kIconReader:
+ return "Icon Reader";
+ }
+}
+
} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_win.h b/chromium/services/service_manager/sandbox/win/sandbox_win.h
index b39b213ec05..6614a82461e 100644
--- a/chromium/services/service_manager/sandbox/win/sandbox_win.h
+++ b/chromium/services/service_manager/sandbox/win/sandbox_win.h
@@ -87,6 +87,9 @@ class SERVICE_MANAGER_SANDBOX_EXPORT SandboxWin {
// will be an empty value if an error is encountered.
static sandbox::ResultCode GetPolicyDiagnostics(
base::OnceCallback<void(base::Value)> response);
+
+ // Provides a friendly name for the sandbox for chrome://sandbox and tracing.
+ static std::string GetSandboxTypeInEnglish(SandboxType sandbox_type);
};
SERVICE_MANAGER_SANDBOX_EXPORT
diff --git a/chromium/services/service_manager/service_instance.h b/chromium/services/service_manager/service_instance.h
index 513d58c9acb..20a3700f130 100644
--- a/chromium/services/service_manager/service_instance.h
+++ b/chromium/services/service_manager/service_instance.h
@@ -12,7 +12,6 @@
#include <string>
#include "base/containers/unique_ptr_adapters.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/optional.h"
diff --git a/chromium/services/service_manager/service_manager.cc b/chromium/services/service_manager/service_manager.cc
index cb0a52ba8bd..ceb1ea74f24 100644
--- a/chromium/services/service_manager/service_manager.cc
+++ b/chromium/services/service_manager/service_manager.cc
@@ -86,9 +86,8 @@ class DefaultServiceProcessHost : public ServiceProcessHost {
#else
// TODO(https://crbug.com/781334): Support sandboxing.
CHECK_EQ(sandbox_type, SandboxType::kNoSandbox);
- return launcher_
- .Start(identity, SandboxType::kNoSandbox, std::move(callback))
- .PassInterface();
+ return launcher_.Start(identity, SandboxType::kNoSandbox,
+ std::move(callback));
#endif // defined(OS_IOS)
}
diff --git a/chromium/services/service_manager/service_process_launcher.cc b/chromium/services/service_manager/service_process_launcher.cc
index a87a5339a24..2a738f1ab64 100644
--- a/chromium/services/service_manager/service_process_launcher.cc
+++ b/chromium/services/service_manager/service_process_launcher.cc
@@ -93,9 +93,10 @@ ServiceProcessLauncher::~ServiceProcessLauncher() {
FROM_HERE, base::BindOnce(&ProcessState::StopInBackground, state_));
}
-mojom::ServicePtr ServiceProcessLauncher::Start(const Identity& target,
- SandboxType sandbox_type,
- ProcessReadyCallback callback) {
+mojo::PendingRemote<mojom::Service> ServiceProcessLauncher::Start(
+ const Identity& target,
+ SandboxType sandbox_type,
+ ProcessReadyCallback callback) {
DCHECK(!state_);
const base::CommandLine& parent_command_line =
@@ -139,7 +140,7 @@ mojom::ServicePtr ServiceProcessLauncher::Start(const Identity& target,
channel.PrepareToPassRemoteEndpoint(&handle_passing_info,
child_command_line.get());
mojo::OutgoingInvitation invitation;
- mojom::ServicePtr client =
+ auto client =
PassServiceRequestOnCommandLine(&invitation, child_command_line.get());
if (delegate_) {
@@ -160,14 +161,15 @@ mojom::ServicePtr ServiceProcessLauncher::Start(const Identity& target,
}
// static
-mojom::ServicePtr ServiceProcessLauncher::PassServiceRequestOnCommandLine(
+mojo::PendingRemote<mojom::Service>
+ServiceProcessLauncher::PassServiceRequestOnCommandLine(
mojo::OutgoingInvitation* invitation,
base::CommandLine* command_line) {
const auto attachment_name = base::NumberToString(base::RandUint64());
command_line->AppendSwitchASCII(switches::kServiceRequestAttachmentName,
attachment_name);
- return mojom::ServicePtr{
- mojom::ServicePtrInfo{invitation->AttachMessagePipe(attachment_name), 0}};
+ return mojo::PendingRemote<mojom::Service>(
+ invitation->AttachMessagePipe(attachment_name), 0);
}
base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
diff --git a/chromium/services/service_manager/service_process_launcher.h b/chromium/services/service_manager/service_process_launcher.h
index 12ad8867691..1b0b04ff5c5 100644
--- a/chromium/services/service_manager/service_process_launcher.h
+++ b/chromium/services/service_manager/service_process_launcher.h
@@ -15,6 +15,7 @@
#include "base/memory/weak_ptr.h"
#include "base/process/process.h"
#include "base/sequenced_task_runner.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/service_process_launcher_delegate.h"
@@ -47,9 +48,9 @@ class ServiceProcessLauncher {
// |Start()|s the child process; calls |DidStart()| (on the thread on which
// |Start()| was called) when the child has been started (or failed to start).
- mojom::ServicePtr Start(const Identity& target,
- SandboxType sandbox_type,
- ProcessReadyCallback callback);
+ mojo::PendingRemote<mojom::Service> Start(const Identity& target,
+ SandboxType sandbox_type,
+ ProcessReadyCallback callback);
// Exposed publicly for use in tests. Creates a new Service pipe, passing the
// ServiceRequest end through |*invitation| with an identifier stashed in
@@ -57,7 +58,7 @@ class ServiceProcessLauncher {
// from the invitation.
//
// Returns the corresponding ServicePtr endpoint.
- static mojom::ServicePtr PassServiceRequestOnCommandLine(
+ static mojo::PendingRemote<mojom::Service> PassServiceRequestOnCommandLine(
mojo::OutgoingInvitation* invitation,
base::CommandLine* command_line);
diff --git a/chromium/services/service_manager/zygote/BUILD.gn b/chromium/services/service_manager/zygote/BUILD.gn
deleted file mode 100644
index da276ffcc78..00000000000
--- a/chromium/services/service_manager/zygote/BUILD.gn
+++ /dev/null
@@ -1,82 +0,0 @@
-# Copyright 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.
-
-import("//build/buildflag_header.gni")
-import("//build/config/nacl/config.gni")
-import("//services/service_manager/zygote/common/zygote_features.gni")
-
-if (is_linux) {
- component("zygote") {
- if (is_nacl_nonsfi) {
- # When running the nacl toolchain is_linux is false so *_linux.cc files are
- # excluded. Reset the filter so they are included.
- set_sources_assignment_filter([])
- }
-
- sources = [
- "common/common_sandbox_support_linux.cc",
- "common/common_sandbox_support_linux.h",
- "common/zygote_fork_delegate_linux.h",
- "common/zygote_handle.h",
- "host/zygote_communication_linux.cc",
- "host/zygote_communication_linux.h",
- "host/zygote_host_impl_linux.cc",
- "host/zygote_host_impl_linux.h",
- "zygote_linux.cc",
- "zygote_linux.h",
- "zygote_main.h",
- "zygote_main_linux.cc",
- ]
-
- if (use_zygote_handle) {
- sources += [
- "common/zygote_handle.h",
- "host/zygote_handle_linux.cc",
- ]
- }
-
- public_deps = [
- ":zygote_buildflags",
- ":zygote_util",
- ]
-
- deps = [
- "//base",
- "//base:i18n",
- "//ipc",
- "//sandbox",
- "//services/service_manager/embedder",
- "//services/service_manager/sandbox",
- "//third_party/icu",
- ]
-
- defines = [ "IS_SERVICE_MANAGER_ZYGOTE_IMPL" ]
- }
-}
-
-source_set("zygote_util") {
- if (is_nacl_nonsfi) {
- # When running the nacl toolchain is_linux is false so *_linux.cc files are
- # excluded. Reset the filter so they are included.
- set_sources_assignment_filter([])
- }
-
- sources = [
- "common/send_zygote_child_ping_linux.cc",
- "common/send_zygote_child_ping_linux.h",
- "common/zygote_commands_linux.h",
- ]
-
- deps = [
- "//base",
- "//services/service_manager/sandbox:sanitizer_buildflags",
- ]
-
- defines = [ "IS_SERVICE_MANAGER_ZYGOTE_IMPL" ]
-}
-
-buildflag_header("zygote_buildflags") {
- header = "common/zygote_buildflags.h"
- flags = [ "USE_ZYGOTE_HANDLE=$use_zygote_handle" ]
-}
diff --git a/chromium/services/service_manager/zygote/DEPS b/chromium/services/service_manager/zygote/DEPS
deleted file mode 100644
index ec69c8f59a8..00000000000
--- a/chromium/services/service_manager/zygote/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+sandbox",
-]
diff --git a/chromium/services/service_manager/zygote/OWNERS b/chromium/services/service_manager/zygote/OWNERS
deleted file mode 100644
index d38314f3fdd..00000000000
--- a/chromium/services/service_manager/zygote/OWNERS
+++ /dev/null
@@ -1,7 +0,0 @@
-jln@chromium.org
-palmer@chromium.org
-rsesek@chromium.org
-tsepez@chromium.org
-
-# TEAM: security-dev@chromium.org
-# COMPONENT: Internals>Sandbox
diff --git a/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.cc b/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.cc
deleted file mode 100644
index 742fab4472b..00000000000
--- a/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.cc
+++ /dev/null
@@ -1,38 +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 "services/service_manager/zygote/common/common_sandbox_support_linux.h"
-
-#include "base/pickle.h"
-#include "base/posix/global_descriptors.h"
-#include "base/posix/unix_domain_socket.h"
-#include "services/service_manager/embedder/descriptors.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-namespace service_manager {
-
-#if !defined(OS_NACL_NONSFI)
-int SharedMemoryIPCSupport::MakeSharedMemorySegment(size_t length,
- bool executable) {
- base::Pickle request;
- request.WriteInt(
- service_manager::SandboxLinux::METHOD_MAKE_SHARED_MEMORY_SEGMENT);
- request.WriteUInt32(length);
- request.WriteBool(executable);
- uint8_t reply_buf[10];
- int result_fd;
- ssize_t result = base::UnixDomainSocket::SendRecvMsg(
- GetSandboxFD(), reply_buf, sizeof(reply_buf), &result_fd, request);
- if (result == -1)
- return -1;
- return result_fd;
-}
-#endif
-
-int GetSandboxFD() {
- return service_manager::kSandboxIPCChannel +
- base::GlobalDescriptors::kBaseDescriptor;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.h b/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.h
deleted file mode 100644
index 051d8ba0318..00000000000
--- a/chromium/services/service_manager/zygote/common/common_sandbox_support_linux.h
+++ /dev/null
@@ -1,42 +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 SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
-
-#include <stddef.h>
-
-#include "base/component_export.h"
-#include "build/build_config.h"
-
-class NaClListener;
-
-namespace service_manager {
-
-#if !defined(OS_NACL_NONSFI)
-// TODO(crbug.com/982879): Remove this when NaCl is unshipped.
-class COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) SharedMemoryIPCSupport {
- private:
- friend class ::NaClListener;
-
- // Returns a file descriptor for a shared memory segment. The
- // executable flag indicates that the caller intends to use mprotect
- // with PROT_EXEC after making a mapping, but not that it intends to
- // mmap with PROT_EXEC in the first place. (Some systems, such as
- // ChromeOS, disallow PROT_EXEC in mmap on /dev/shm files but do allow
- // PROT_EXEC in mprotect on mappings from such files. This function
- // can yield an object that has that constraint.)
- static int MakeSharedMemorySegment(size_t length, bool executable);
-
- SharedMemoryIPCSupport() = delete;
-};
-#endif
-
-// Gets the well-known file descriptor on which we expect to find the
-// sandbox IPC channel.
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) int GetSandboxFD();
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_COMMON_SANDBOX_SUPPORT_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.cc b/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.cc
deleted file mode 100644
index 1245398f52c..00000000000
--- a/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.cc
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2014 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 "services/service_manager/zygote/common/send_zygote_child_ping_linux.h"
-
-#include <vector>
-
-#include "base/posix/unix_domain_socket.h"
-#include "services/service_manager/zygote/common/zygote_commands_linux.h"
-
-namespace service_manager {
-
-bool SendZygoteChildPing(int fd) {
- return base::UnixDomainSocket::SendMsg(fd, kZygoteChildPingMessage,
- sizeof(kZygoteChildPingMessage),
- std::vector<int>());
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.h b/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.h
deleted file mode 100644
index 66aff241a95..00000000000
--- a/chromium/services/service_manager/zygote/common/send_zygote_child_ping_linux.h
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright 2014 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 SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
-
-#include "base/component_export.h"
-
-namespace service_manager {
-
-// Sends a zygote child "ping" message to browser process via socket |fd|.
-// Returns true on success.
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) bool SendZygoteChildPing(int fd);
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_SEND_ZYGOTE_CHILD_PING_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/common/zygote_commands_linux.h b/chromium/services/service_manager/zygote/common/zygote_commands_linux.h
deleted file mode 100644
index b1d7c718a8d..00000000000
--- a/chromium/services/service_manager/zygote/common/zygote_commands_linux.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright (c) 2012 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 SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_COMMANDS_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_COMMANDS_LINUX_H_
-
-#include <stddef.h>
-
-#include "base/posix/global_descriptors.h"
-
-namespace service_manager {
-
-// Contents of the initial message sent from the zygote to the browser right
-// after it starts.
-static const char kZygoteBootMessage[] = "ZYGOTE_BOOT";
-
-// Contents of the initial message sent from the zygote to the browser when it
-// is ready to go.
-static const char kZygoteHelloMessage[] = "ZYGOTE_OK";
-
-// Message sent by zygote children to the browser so the browser can discover
-// the sending child's process ID.
-static const char kZygoteChildPingMessage[] = "CHILD_PING";
-
-// Maximum allowable length for messages sent to the zygote.
-const size_t kZygoteMaxMessageLength = 12288;
-
-// File descriptors initialized by the Zygote Host
-const int kZygoteSocketPairFd = base::GlobalDescriptors::kBaseDescriptor;
-
-// These are the command codes used on the wire between the browser and the
-// zygote.
-enum {
- // Fork off a new renderer.
- kZygoteCommandFork = 0,
-
- // Reap a renderer child.
- kZygoteCommandReap = 1,
-
- // Check what happened to a child process.
- kZygoteCommandGetTerminationStatus = 2,
-
- // Read a bitmask of kSandboxLinux*
- kZygoteCommandGetSandboxStatus = 3,
-
- // Not a real zygote command, but a subcommand used during the zygote fork
- // protocol. Sends the child's PID as seen from the browser process.
- kZygoteCommandForkRealPID = 4
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_COMMANDS_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/common/zygote_features.gni b/chromium/services/service_manager/zygote/common/zygote_features.gni
deleted file mode 100644
index c7580b35ff3..00000000000
--- a/chromium/services/service_manager/zygote/common/zygote_features.gni
+++ /dev/null
@@ -1,5 +0,0 @@
-# Copyright 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.
-
-use_zygote_handle = is_posix && !is_android && !is_mac
diff --git a/chromium/services/service_manager/zygote/common/zygote_fork_delegate_linux.h b/chromium/services/service_manager/zygote/common/zygote_fork_delegate_linux.h
deleted file mode 100644
index aec457b8750..00000000000
--- a/chromium/services/service_manager/zygote/common/zygote_fork_delegate_linux.h
+++ /dev/null
@@ -1,90 +0,0 @@
-// Copyright (c) 2012 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 SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
-
-#include <unistd.h>
-
-#include <string>
-#include <vector>
-
-// TODO(jln) base::TerminationStatus should be forward declared when switching
-// to C++11.
-#include "base/process/kill.h"
-
-namespace service_manager {
-
-// The ZygoteForkDelegate allows the Chrome Linux zygote to delegate
-// fork operations to another class that knows how to do some
-// specialized version of fork.
-class ZygoteForkDelegate {
- public:
- // A ZygoteForkDelegate is created during Chrome linux zygote
- // initialization, and provides "fork()" functionality as an
- // alternative to forking the zygote. A new delegate is passed in
- // as an argument to ZygoteMain().
- virtual ~ZygoteForkDelegate() {}
-
- // Initialization happens in the zygote after it has been
- // started by ZygoteMain.
- // If |enable_layer1_sandbox| is true, the delegate must enable a
- // layer-1 sandbox such as the setuid sandbox.
- virtual void Init(int sandboxdesc, bool enable_layer1_sandbox) = 0;
-
- // After Init, supply a UMA_HISTOGRAM_ENUMERATION the delegate would like
- // reported to the browser process. (Note: Because these reports are
- // piggy-backed onto fork responses that don't otherwise contain UMA reports,
- // this method may not be called until much later.)
- virtual void InitialUMA(std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) = 0;
-
- // Returns 'true' if the delegate would like to handle a given fork
- // request. Otherwise returns false. Optionally, fills in uma_name et al
- // with a report the helper wants to make via UMA_HISTOGRAM_ENUMERATION.
- virtual bool CanHelp(const std::string& process_type,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) = 0;
-
- // Indexes of FDs in the vector passed to Fork().
- enum {
- // Used to pass in the descriptor for talking to the Browser.
- // Because the children use ChannelMojo, this is actually the Mojo fd.
- kBrowserFDIndex,
- // The PID oracle is used in the protocol for discovering the
- // child process's real PID from within the SUID sandbox.
- // The child process is required to write to the socket after
- // successfully forking.
- kPIDOracleFDIndex,
- kNumPassedFDs // Number of FDs in the vector passed to Fork().
- };
-
- // Delegate forks, returning a -1 on failure. Outside the
- // suid sandbox, Fork() returns the Linux process ID.
- // This method is not aware of any potential pid namespaces, so it'll
- // return a raw pid just like fork() would.
- // Delegate is responsible for communicating the channel ID to the
- // newly created child process.
- virtual pid_t Fork(const std::string& process_type,
- const std::vector<int>& fds,
- const std::string& channel_id) = 0;
-
- // The fork delegate must also assume the role of waiting for its children
- // since the caller will not be their parents and cannot do it. |pid| here
- // should be a pid that has been returned by the Fork() method. i.e. This
- // method is completely unaware of eventual PID namespaces due to sandboxing.
- // |known_dead| indicates that the process is already dead and that a
- // blocking wait() should be performed. In this case, GetTerminationStatus()
- // will send a SIGKILL to the target process first.
- virtual bool GetTerminationStatus(pid_t pid,
- bool known_dead,
- base::TerminationStatus* status,
- int* exit_code) = 0;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_FORK_DELEGATE_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/common/zygote_handle.h b/chromium/services/service_manager/zygote/common/zygote_handle.h
deleted file mode 100644
index 07efadf6807..00000000000
--- a/chromium/services/service_manager/zygote/common/zygote_handle.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 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 SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_HANDLE_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_HANDLE_H_
-
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/component_export.h"
-#include "base/files/scoped_file.h"
-#include "build/build_config.h"
-#include "services/service_manager/zygote/common/zygote_buildflags.h"
-
-#if !BUILDFLAG(USE_ZYGOTE_HANDLE)
-#error "Can not use zygote handles without USE_ZYGOTE_HANDLE"
-#endif
-
-namespace service_manager {
-
-#if defined(OS_POSIX)
-class ZygoteCommunication;
-using ZygoteHandle = ZygoteCommunication*;
-#else
-// Perhaps other ports may USE_ZYGOTE_HANDLE here somdeday.
-#error "Can not use zygote handles on this platform"
-#endif // defined(OS_POSIX)
-
-using ZygoteLaunchCallback =
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)>;
-
-// Allocates and initializes the global generic zygote process, and returns the
-// ZygoteHandle used to communicate with it. |launch_cb| is a callback that
-// should actually launch the process, after adding additional command line
-// switches to the ones composed by this function. It returns the pid created,
-// and provides a control fd for it.
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE)
-ZygoteHandle CreateGenericZygote(ZygoteLaunchCallback launch_cb);
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteHandle GetGenericZygote();
-
-// Similar to the above but for creating an unsandboxed zygote from which
-// processes which need non-generic sandboxes can be derived.
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE)
-ZygoteHandle CreateUnsandboxedZygote(ZygoteLaunchCallback launch_cb);
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteHandle GetUnsandboxedZygote();
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_COMMON_ZYGOTE_HANDLE_H_
diff --git a/chromium/services/service_manager/zygote/host/zygote_communication_linux.cc b/chromium/services/service_manager/zygote/host/zygote_communication_linux.cc
deleted file mode 100644
index a3a1fc73bea..00000000000
--- a/chromium/services/service_manager/zygote/host/zygote_communication_linux.cc
+++ /dev/null
@@ -1,321 +0,0 @@
-// Copyright 2015 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 "services/service_manager/zygote/host/zygote_communication_linux.h"
-
-#include <string.h>
-#include <sys/socket.h>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/i18n/unicodestring.h"
-#include "base/logging.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/path_service.h"
-#include "base/pickle.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/stl_util.h"
-#include "services/service_manager/embedder/result_codes.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "services/service_manager/zygote/common/zygote_commands_linux.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace service_manager {
-
-ZygoteCommunication::ZygoteCommunication(ZygoteType type)
- : type_(type),
- pid_(),
- sandbox_status_(0),
- have_read_sandbox_status_word_(false),
- init_(false) {}
-
-ZygoteCommunication::~ZygoteCommunication() {}
-
-bool ZygoteCommunication::SendMessage(const base::Pickle& data,
- const std::vector<int>* fds) {
- DCHECK(control_fd_.is_valid());
- CHECK(data.size() <= kZygoteMaxMessageLength)
- << "Trying to send too-large message to zygote (sending " << data.size()
- << " bytes, max is " << kZygoteMaxMessageLength << ")";
- CHECK(!fds || fds->size() <= base::UnixDomainSocket::kMaxFileDescriptors)
- << "Trying to send message with too many file descriptors to zygote "
- << "(sending " << fds->size() << ", max is "
- << base::UnixDomainSocket::kMaxFileDescriptors << ")";
-
- return base::UnixDomainSocket::SendMsg(control_fd_.get(), data.data(),
- data.size(),
- fds ? *fds : std::vector<int>());
-}
-
-ssize_t ZygoteCommunication::ReadSandboxStatus() {
- DCHECK(control_fd_.is_valid());
- // At startup we send a kZygoteCommandGetSandboxStatus request to the zygote,
- // but don't wait for the reply. Thus, the first time that we read from the
- // zygote, we get the reply to that request.
- ssize_t bytes_read = HANDLE_EINTR(
- read(control_fd_.get(), &sandbox_status_, sizeof(sandbox_status_)));
- if (bytes_read != sizeof(sandbox_status_)) {
- return -1;
- }
- return bytes_read;
-}
-
-ssize_t ZygoteCommunication::ReadReply(void* buf, size_t buf_len) {
- DCHECK(control_fd_.is_valid());
- if (!have_read_sandbox_status_word_) {
- if (ReadSandboxStatus() == -1) {
- return -1;
- }
- have_read_sandbox_status_word_ = true;
- base::UmaHistogramSparse("Linux.SandboxStatus", sandbox_status_);
- }
-
- return HANDLE_EINTR(read(control_fd_.get(), buf, buf_len));
-}
-
-pid_t ZygoteCommunication::ForkRequest(
- const std::vector<std::string>& argv,
- const base::FileHandleMappingVector& mapping,
- const std::string& process_type) {
- DCHECK(init_);
-
- base::Pickle pickle;
- int raw_socks[2];
- PCHECK(0 == socketpair(AF_UNIX, SOCK_SEQPACKET, 0, raw_socks));
- base::ScopedFD my_sock(raw_socks[0]);
- base::ScopedFD peer_sock(raw_socks[1]);
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(my_sock.get()));
-
- pickle.WriteInt(kZygoteCommandFork);
- pickle.WriteString(process_type);
- pickle.WriteInt(argv.size());
- for (std::vector<std::string>::const_iterator i = argv.begin();
- i != argv.end(); ++i)
- pickle.WriteString(*i);
- std::unique_ptr<icu::TimeZone> timezone(icu::TimeZone::createDefault());
- icu::UnicodeString timezone_id;
- pickle.WriteString16(
- base::i18n::UnicodeStringToString16(timezone->getID(timezone_id)));
-
- // Fork requests contain one file descriptor for the PID oracle, and one
- // more for each file descriptor mapping for the child process.
- const size_t num_fds_to_send = 1 + mapping.size();
- pickle.WriteInt(num_fds_to_send);
-
- std::vector<int> fds;
-
- // First FD to send is peer_sock.
- // TODO(morrita): Ideally, this should be part of the mapping so that
- // PosixFileDescriptorInfo can manages its lifetime.
- fds.push_back(peer_sock.get());
-
- // The rest come from mapping.
- for (const auto& item : mapping) {
- fds.push_back(item.first);
- pickle.WriteUInt32(item.second);
- }
-
- // Sanity check that we've populated |fds| correctly.
- DCHECK_EQ(num_fds_to_send, fds.size());
-
- pid_t pid;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, &fds))
- return base::kNullProcessHandle;
- peer_sock.reset();
-
- {
- char buf[sizeof(kZygoteChildPingMessage) + 1];
- std::vector<base::ScopedFD> recv_fds;
- base::ProcessId real_pid;
-
- ssize_t n = base::UnixDomainSocket::RecvMsgWithPid(
- my_sock.get(), buf, sizeof(buf), &recv_fds, &real_pid);
- if (n != sizeof(kZygoteChildPingMessage) ||
- 0 != memcmp(buf, kZygoteChildPingMessage,
- sizeof(kZygoteChildPingMessage))) {
- // Zygote children should still be trustworthy when they're supposed to
- // ping us, so something's broken if we don't receive a valid ping.
- LOG(ERROR) << "Did not receive ping from zygote child";
- NOTREACHED();
- real_pid = -1;
- }
- my_sock.reset();
-
- // Always send PID back to zygote.
- base::Pickle pid_pickle;
- pid_pickle.WriteInt(kZygoteCommandForkRealPID);
- pid_pickle.WriteInt(real_pid);
- if (!SendMessage(pid_pickle, nullptr))
- return base::kNullProcessHandle;
- }
-
- // Read the reply, which pickles the PID and an optional UMA enumeration.
- static const unsigned kMaxReplyLength = 2048;
- char buf[kMaxReplyLength];
- const ssize_t len = ReadReply(buf, sizeof(buf));
-
- base::Pickle reply_pickle(buf, len);
- base::PickleIterator iter(reply_pickle);
- if (len <= 0 || !iter.ReadInt(&pid))
- return base::kNullProcessHandle;
-
- // If there is a nonempty UMA name string, then there is a UMA
- // enumeration to record.
- std::string uma_name;
- int uma_sample;
- int uma_boundary_value;
- if (iter.ReadString(&uma_name) && !uma_name.empty() &&
- iter.ReadInt(&uma_sample) && iter.ReadInt(&uma_boundary_value)) {
- // We cannot use the UMA_HISTOGRAM_ENUMERATION macro here,
- // because that's only for when the name is the same every time.
- // Here we're using whatever name we got from the other side.
- // But since it's likely that the same one will be used repeatedly
- // (even though it's not guaranteed), we cache it here.
- static base::HistogramBase* uma_histogram;
- if (!uma_histogram || uma_histogram->histogram_name() != uma_name) {
- uma_histogram = base::LinearHistogram::FactoryGet(
- uma_name, 1, uma_boundary_value, uma_boundary_value + 1,
- base::HistogramBase::kUmaTargetedHistogramFlag);
- }
- uma_histogram->Add(uma_sample);
- }
-
- if (pid <= 0)
- return base::kNullProcessHandle;
- }
-
- ZygoteChildBorn(pid);
- return pid;
-}
-
-void ZygoteCommunication::EnsureProcessTerminated(pid_t process) {
- DCHECK(init_);
- base::Pickle pickle;
-
- pickle.WriteInt(kZygoteCommandReap);
- pickle.WriteInt(process);
- if (!SendMessage(pickle, nullptr))
- LOG(ERROR) << "Failed to send Reap message to zygote";
- ZygoteChildDied(process);
-}
-
-void ZygoteCommunication::ZygoteChildBorn(pid_t process) {
- base::AutoLock lock(child_tracking_lock_);
- bool new_element_inserted =
- list_of_running_zygote_children_.insert(process).second;
- DCHECK(new_element_inserted);
-}
-
-void ZygoteCommunication::ZygoteChildDied(pid_t process) {
- base::AutoLock lock(child_tracking_lock_);
- size_t num_erased = list_of_running_zygote_children_.erase(process);
- DCHECK_EQ(1U, num_erased);
-}
-
-void ZygoteCommunication::Init(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher) {
- CHECK(!init_);
-
- base::FilePath chrome_path;
- CHECK(base::PathService::Get(base::FILE_EXE, &chrome_path));
-
- base::CommandLine cmd_line(chrome_path);
- cmd_line.AppendSwitchASCII(switches::kProcessType, switches::kZygoteProcess);
-
- if (type_ == ZygoteType::kUnsandboxed)
- cmd_line.AppendSwitch(switches::kNoZygoteSandbox);
-
- const base::CommandLine& browser_command_line =
- *base::CommandLine::ForCurrentProcess();
- if (browser_command_line.HasSwitch(switches::kZygoteCmdPrefix)) {
- cmd_line.PrependWrapper(
- browser_command_line.GetSwitchValueNative(switches::kZygoteCmdPrefix));
- }
- // Append any switches from the service manager that need to be forwarded on
- // to the zygote/renderers.
- static const char* const kForwardSwitches[] = {
- service_manager::switches::kAllowSandboxDebugging,
- service_manager::switches::kDisableInProcessStackTraces,
- service_manager::switches::kDisableSeccompFilterSandbox,
- service_manager::switches::kNoSandbox,
- };
- cmd_line.CopySwitchesFrom(browser_command_line, kForwardSwitches,
- base::size(kForwardSwitches));
-
- pid_ = std::move(launcher).Run(&cmd_line, &control_fd_);
-
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetSandboxStatus);
- if (!SendMessage(pickle, nullptr))
- LOG(FATAL) << "Cannot communicate with zygote";
-
- init_ = true;
-}
-
-base::TerminationStatus ZygoteCommunication::GetTerminationStatus(
- base::ProcessHandle handle,
- bool known_dead,
- int* exit_code) {
- DCHECK(init_);
- base::Pickle pickle;
- pickle.WriteInt(kZygoteCommandGetTerminationStatus);
- pickle.WriteBool(known_dead);
- pickle.WriteInt(handle);
-
- static const unsigned kMaxMessageLength = 128;
- char buf[kMaxMessageLength];
- ssize_t len;
- {
- base::AutoLock lock(control_lock_);
- if (!SendMessage(pickle, nullptr))
- LOG(ERROR) << "Failed to send GetTerminationStatus message to zygote";
- len = ReadReply(buf, sizeof(buf));
- }
-
- // Set this now to handle the error cases.
- if (exit_code)
- *exit_code = RESULT_CODE_NORMAL_EXIT;
- int status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
-
- if (len == -1) {
- PLOG(WARNING) << "Error reading message from zygote";
- } else if (len == 0) {
- LOG(WARNING) << "Socket closed prematurely.";
- } else {
- base::Pickle read_pickle(buf, len);
- int tmp_status, tmp_exit_code;
- base::PickleIterator iter(read_pickle);
- if (!iter.ReadInt(&tmp_status) || !iter.ReadInt(&tmp_exit_code)) {
- LOG(WARNING)
- << "Error parsing GetTerminationStatus response from zygote.";
- } else {
- if (exit_code)
- *exit_code = tmp_exit_code;
- status = tmp_status;
- }
- }
-
- if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
- ZygoteChildDied(handle);
- }
- return static_cast<base::TerminationStatus>(status);
-}
-
-int ZygoteCommunication::GetSandboxStatus() {
- if (have_read_sandbox_status_word_) {
- return sandbox_status_;
- }
- if (ReadSandboxStatus() == -1) {
- return 0;
- }
- have_read_sandbox_status_word_ = true;
- base::UmaHistogramSparse("Linux.SandboxStatus", sandbox_status_);
- return sandbox_status_;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/host/zygote_communication_linux.h b/chromium/services/service_manager/zygote/host/zygote_communication_linux.h
deleted file mode 100644
index 77878c78bbf..00000000000
--- a/chromium/services/service_manager/zygote/host/zygote_communication_linux.h
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2015 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 SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include <sys/types.h>
-
-#include "base/callback.h"
-#include "base/component_export.h"
-#include "base/files/scoped_file.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/lock.h"
-
-namespace base {
-class Pickle;
-} // namespace base
-
-namespace service_manager {
-
-// Handles interprocess communication with the Linux zygote process. The zygote
-// does not use standard Chrome IPC or mojo, see:
-// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md
-class COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteCommunication {
- public:
- enum class ZygoteType { kSandboxed, kUnsandboxed };
- explicit ZygoteCommunication(ZygoteType type);
- ~ZygoteCommunication();
-
- void Init(
- base::OnceCallback<pid_t(base::CommandLine*, base::ScopedFD*)> launcher);
-
- // Tries to start a process of type indicated by process_type.
- // Returns its pid on success, otherwise base::kNullProcessHandle;
- pid_t ForkRequest(const std::vector<std::string>& command_line,
- const base::FileHandleMappingVector& mapping,
- const std::string& process_type);
-
- void EnsureProcessTerminated(pid_t process);
-
- // Should be called every time a Zygote child died.
- void ZygoteChildDied(pid_t process);
-
- // Get the termination status (and, optionally, the exit code) of
- // the process. |exit_code| is set to the exit code of the child
- // process. (|exit_code| may be NULL.)
- // Unfortunately the Zygote can not accurately figure out if a process
- // is already dead without waiting synchronously for it.
- // |known_dead| should be set to true when we already know that the process
- // is dead. When |known_dead| is false, processes could be seen as
- // still running, even when they're not. When |known_dead| is true, the
- // process will be SIGKILL-ed first (which should have no effect if it was
- // really dead). This is to prevent a waiting waitpid() from blocking in
- // a single-threaded Zygote. See https://crbug.com/157458.
- base::TerminationStatus GetTerminationStatus(base::ProcessHandle handle,
- bool known_dead,
- int* exit_code);
-
- // Returns the sandbox status of this zygote.
- int GetSandboxStatus();
-
- private:
- // Should be called every time a Zygote child is born.
- void ZygoteChildBorn(pid_t process);
-
- // Read the reply from the zygote.
- ssize_t ReadReply(void* buf, size_t buf_len);
-
- // Sends |data| to the zygote via |control_fd_|. If |fds| is non-NULL, the
- // included file descriptors will also be passed. The caller is responsible
- // for acquiring |control_lock_|.
- bool SendMessage(const base::Pickle& data, const std::vector<int>* fds);
-
- // Get the sandbox status from the zygote.
- ssize_t ReadSandboxStatus();
-
- // Indicates whether the Zygote starts unsandboxed or not.
- const ZygoteType type_;
-
- base::ScopedFD control_fd_; // the socket to the zygote.
- // A lock protecting all communication with the zygote. This lock must be
- // acquired before sending a command and released after the result has been
- // received.
- base::Lock control_lock_;
- // The pid of the zygote.
- pid_t pid_;
- // The list of running zygote children.
- std::set<pid_t> list_of_running_zygote_children_;
- // The lock to guard the list of running zygote children.
- base::Lock child_tracking_lock_;
- int sandbox_status_;
- bool have_read_sandbox_status_word_;
- // Set to true when the zygote is initialized successfully.
- bool init_;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_COMMUNICATION_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/host/zygote_handle_linux.cc b/chromium/services/service_manager/zygote/host/zygote_handle_linux.cc
deleted file mode 100644
index 30f135244be..00000000000
--- a/chromium/services/service_manager/zygote/host/zygote_handle_linux.cc
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 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.
-
-#include "services/service_manager/zygote/common/zygote_handle.h"
-
-#include "services/service_manager/zygote/host/zygote_communication_linux.h"
-
-namespace service_manager {
-namespace {
-
-// Intentionally leaked.
-ZygoteHandle g_generic_zygote = nullptr;
-ZygoteHandle g_unsandboxed_zygote = nullptr;
-
-} // namespace
-
-ZygoteHandle CreateGenericZygote(ZygoteLaunchCallback launch_cb) {
- CHECK(!g_generic_zygote);
- g_generic_zygote =
- new ZygoteCommunication(ZygoteCommunication::ZygoteType::kSandboxed);
- g_generic_zygote->Init(std::move(launch_cb));
- return g_generic_zygote;
-}
-
-ZygoteHandle GetGenericZygote() {
- CHECK(g_generic_zygote);
- return g_generic_zygote;
-}
-
-ZygoteHandle CreateUnsandboxedZygote(ZygoteLaunchCallback launch_cb) {
- CHECK(!g_unsandboxed_zygote);
- g_unsandboxed_zygote =
- new ZygoteCommunication(ZygoteCommunication::ZygoteType::kUnsandboxed);
- g_unsandboxed_zygote->Init(std::move(launch_cb));
- return g_unsandboxed_zygote;
-}
-
-ZygoteHandle GetUnsandboxedZygote() {
- CHECK(g_unsandboxed_zygote);
- return g_unsandboxed_zygote;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.cc b/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.cc
deleted file mode 100644
index 08ecc3c80c0..00000000000
--- a/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.cc
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright (c) 2012 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 "services/service_manager/zygote/host/zygote_host_impl_linux.h"
-
-#include <stdlib.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-
-#include "base/allocator/allocator_extension.h"
-#include "base/files/file_enumerator.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/process/kill.h"
-#include "base/process/memory.h"
-#include "base/strings/string_number_conversions.h"
-#include "build/build_config.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_host.h"
-#include "sandbox/linux/suid/common/sandbox.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "services/service_manager/zygote/common/zygote_commands_linux.h"
-
-namespace service_manager {
-
-namespace {
-
-// Receive a fixed message on fd and return the sender's PID.
-// Returns true if the message received matches the expected message.
-bool ReceiveFixedMessage(int fd,
- const char* expect_msg,
- size_t expect_len,
- base::ProcessId* sender_pid) {
- // Allocate an extra byte of buffer space so we can check that we received
- // exactly |expect_len| bytes, and the message wasn't just truncated to fit.
- char buf[expect_len + 1];
- std::vector<base::ScopedFD> fds_vec;
-
- const ssize_t len = base::UnixDomainSocket::RecvMsgWithPid(
- fd, buf, sizeof(buf), &fds_vec, sender_pid);
- if (static_cast<size_t>(len) != expect_len)
- return false;
- if (memcmp(buf, expect_msg, expect_len) != 0)
- return false;
- if (!fds_vec.empty())
- return false;
- return true;
-}
-
-} // namespace
-
-// static
-ZygoteHost* ZygoteHost::GetInstance() {
- return ZygoteHostImpl::GetInstance();
-}
-
-ZygoteHostImpl::ZygoteHostImpl()
- : use_namespace_sandbox_(false),
- use_suid_sandbox_(false),
- use_suid_sandbox_for_adj_oom_score_(false),
- sandbox_binary_(),
- zygote_pids_lock_(),
- zygote_pids_() {}
-
-ZygoteHostImpl::~ZygoteHostImpl() {}
-
-// static
-ZygoteHostImpl* ZygoteHostImpl::GetInstance() {
- return base::Singleton<ZygoteHostImpl>::get();
-}
-
-void ZygoteHostImpl::Init(const base::CommandLine& command_line) {
- if (command_line.HasSwitch(service_manager::switches::kNoSandbox)) {
- return;
- }
-
- // Exit early if running as root without --no-sandbox. See
- // https://crbug.com/638180.
- // When running as root with the sandbox enabled, the browser process
- // crashes on zygote initialization. Running as root with the sandbox
- // is not supported, and if Chrome were able to display UI it would be showing
- // an error message. With the zygote crashing it doesn't even get to that,
- // so print an error message on the console.
- uid_t uid = 0;
- gid_t gid = 0;
- if (!sandbox::Credentials::GetRESIds(&uid, &gid) || uid == 0) {
- LOG(ERROR) << "Running as root without --"
- << service_manager::switches::kNoSandbox
- << " is not supported. See https://crbug.com/638180.";
- exit(EXIT_FAILURE);
- }
-
- {
- std::unique_ptr<sandbox::SetuidSandboxHost> setuid_sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_binary_ = setuid_sandbox_host->GetSandboxBinaryPath().value();
- }
-
- if (!command_line.HasSwitch(
- service_manager::switches::kDisableNamespaceSandbox) &&
- sandbox::Credentials::CanCreateProcessInNewUserNS()) {
- use_namespace_sandbox_ = true;
- } else if (!command_line.HasSwitch(
- service_manager::switches::kDisableSetuidSandbox) &&
- !sandbox_binary_.empty()) {
- use_suid_sandbox_ = true;
-
- // Use the SUID sandbox for adjusting OOM scores when we are using
- // the setuid sandbox. This is needed beacuse the processes are
- // non-dumpable, so /proc/pid/oom_score_adj can only be written by
- // root.
- use_suid_sandbox_for_adj_oom_score_ = use_suid_sandbox_;
- } else {
- LOG(FATAL)
- << "No usable sandbox! Update your kernel or see "
- "https://chromium.googlesource.com/chromium/src/+/master/"
- "docs/linux/suid_sandbox_development.md for more information on "
- "developing with the SUID sandbox. "
- "If you want to live dangerously and need an immediate workaround, "
- "you can try using --"
- << service_manager::switches::kNoSandbox << ".";
- }
-}
-
-void ZygoteHostImpl::AddZygotePid(pid_t pid) {
- base::AutoLock lock(zygote_pids_lock_);
- zygote_pids_.insert(pid);
-}
-
-bool ZygoteHostImpl::IsZygotePid(pid_t pid) {
- base::AutoLock lock(zygote_pids_lock_);
- return zygote_pids_.find(pid) != zygote_pids_.end();
-}
-
-void ZygoteHostImpl::SetRendererSandboxStatus(int status) {
- renderer_sandbox_status_ = status;
-}
-
-int ZygoteHostImpl::GetRendererSandboxStatus() const {
- return renderer_sandbox_status_;
-}
-
-pid_t ZygoteHostImpl::LaunchZygote(
- base::CommandLine* cmd_line,
- base::ScopedFD* control_fd,
- base::FileHandleMappingVector additional_remapped_fds) {
- int fds[2];
- CHECK_EQ(0, socketpair(AF_UNIX, SOCK_SEQPACKET, 0, fds));
- CHECK(base::UnixDomainSocket::EnableReceiveProcessId(fds[0]));
-
- base::LaunchOptions options;
- options.fds_to_remap = std::move(additional_remapped_fds);
- options.fds_to_remap.emplace_back(fds[1], kZygoteSocketPairFd);
-
- const bool is_sandboxed_zygote =
- !cmd_line->HasSwitch(service_manager::switches::kNoZygoteSandbox);
-
- base::ScopedFD dummy_fd;
- if (is_sandboxed_zygote && use_suid_sandbox_) {
- std::unique_ptr<sandbox::SetuidSandboxHost> sandbox_host(
- sandbox::SetuidSandboxHost::Create());
- sandbox_host->PrependWrapper(cmd_line);
- sandbox_host->SetupLaunchOptions(&options, &dummy_fd);
- sandbox_host->SetupLaunchEnvironment();
- }
-
- base::Process process =
- (is_sandboxed_zygote && use_namespace_sandbox_)
- ? sandbox::NamespaceSandbox::LaunchProcess(*cmd_line, options)
- : base::LaunchProcess(*cmd_line, options);
- CHECK(process.IsValid()) << "Failed to launch zygote process";
-
- dummy_fd.reset();
- close(fds[1]);
- control_fd->reset(fds[0]);
-
- pid_t pid = process.Pid();
-
- if (is_sandboxed_zygote && (use_namespace_sandbox_ || use_suid_sandbox_)) {
- // The namespace and SUID sandbox will execute the zygote in a new
- // PID namespace, and the main zygote process will then fork from
- // there. Watch now our elaborate dance to find and validate the
- // zygote's PID.
-
- // First we receive a message from the zygote boot process.
- base::ProcessId boot_pid;
- CHECK(ReceiveFixedMessage(fds[0], kZygoteBootMessage,
- sizeof(kZygoteBootMessage), &boot_pid));
-
- // Within the PID namespace, the zygote boot process thinks it's PID 1,
- // but its real PID can never be 1. This gives us a reliable test that
- // the kernel is translating the sender's PID to our namespace.
- CHECK_GT(boot_pid, 1)
- << "Received invalid process ID for zygote; kernel might be too old? "
- "See crbug.com/357670 or try using --"
- << service_manager::switches::kNoSandbox << " to workaround.";
-
- // Now receive the message that the zygote's ready to go, along with the
- // main zygote process's ID.
- pid_t real_pid;
- CHECK(ReceiveFixedMessage(fds[0], kZygoteHelloMessage,
- sizeof(kZygoteHelloMessage), &real_pid));
- CHECK_GT(real_pid, 1);
-
- if (real_pid != pid) {
- // Reap the sandbox.
- base::EnsureProcessGetsReaped(std::move(process));
- }
- pid = real_pid;
- }
-
- AddZygotePid(pid);
- return pid;
-}
-
-#if !defined(OS_OPENBSD)
-void ZygoteHostImpl::AdjustRendererOOMScore(base::ProcessHandle pid,
- int score) {
- // 1) You can't change the oom_score_adj of a non-dumpable process
- // (EPERM) unless you're root. Because of this, we can't set the
- // oom_adj from the browser process.
- //
- // 2) We can't set the oom_score_adj before entering the sandbox
- // because the zygote is in the sandbox and the zygote is as
- // critical as the browser process. Its oom_adj value shouldn't
- // be changed.
- //
- // 3) A non-dumpable process can't even change its own oom_score_adj
- // because it's root owned 0644. The sandboxed processes don't
- // even have /proc, but one could imagine passing in a descriptor
- // from outside.
- //
- // So, in the normal case, we use the SUID binary to change it for us.
- // However, Fedora (and other SELinux systems) don't like us touching other
- // process's oom_score_adj (or oom_adj) values
- // (https://bugzilla.redhat.com/show_bug.cgi?id=581256).
- //
- // The offical way to get the SELinux mode is selinux_getenforcemode, but I
- // don't want to add another library to the build as it's sure to cause
- // problems with other, non-SELinux distros.
- //
- // So we just check for files in /selinux. This isn't foolproof, but it's not
- // bad and it's easy.
-
- static bool selinux;
- static bool selinux_valid = false;
-
- if (!selinux_valid) {
- const base::FilePath kSelinuxPath("/selinux");
- base::FileEnumerator en(kSelinuxPath, false, base::FileEnumerator::FILES);
- bool has_selinux_files = !en.Next().empty();
-
- selinux =
- has_selinux_files && access(kSelinuxPath.value().c_str(), X_OK) == 0;
- selinux_valid = true;
- }
-
- if (!use_suid_sandbox_for_adj_oom_score_) {
- if (!base::AdjustOOMScore(pid, score))
- PLOG(ERROR) << "Failed to adjust OOM score of renderer with pid " << pid;
- return;
- }
-
- if (selinux)
- return;
-
- // If heap profiling is running, these processes are not exiting, at least
- // on ChromeOS. The easiest thing to do is not launch them when profiling.
- // TODO(stevenjb): Investigate further and fix.
- if (base::allocator::IsHeapProfilerRunning())
- return;
-
- std::vector<std::string> adj_oom_score_cmdline;
- adj_oom_score_cmdline.push_back(sandbox_binary_);
- adj_oom_score_cmdline.push_back(sandbox::kAdjustOOMScoreSwitch);
- adj_oom_score_cmdline.push_back(base::NumberToString(pid));
- adj_oom_score_cmdline.push_back(base::NumberToString(score));
-
- // sandbox_helper_process is a setuid binary.
- base::LaunchOptions options;
- options.allow_new_privs = true;
-
- base::Process sandbox_helper_process =
- base::LaunchProcess(adj_oom_score_cmdline, options);
- if (sandbox_helper_process.IsValid())
- base::EnsureProcessGetsReaped(std::move(sandbox_helper_process));
-}
-#endif
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.h b/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.h
deleted file mode 100644
index 64d6c45680d..00000000000
--- a/chromium/services/service_manager/zygote/host/zygote_host_impl_linux.h
+++ /dev/null
@@ -1,75 +0,0 @@
-// Copyright (c) 2012 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 SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
-
-#include <sys/types.h>
-
-#include <set>
-#include <string>
-
-#include "base/command_line.h"
-#include "base/component_export.h"
-#include "base/files/scoped_file.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/lock.h"
-
-#include "services/service_manager/zygote/zygote_host_linux.h"
-
-namespace base {
-template <typename Type>
-struct DefaultSingletonTraits;
-} // namespace base
-
-namespace service_manager {
-
-class COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteHostImpl
- : public ZygoteHost {
- public:
- // Returns the singleton instance.
- static ZygoteHostImpl* GetInstance();
-
- void Init(const base::CommandLine& cmd_line);
-
- // Returns whether or not this pid is the pid of a zygote.
- bool IsZygotePid(pid_t pid) override;
-
- void SetRendererSandboxStatus(int status);
- int GetRendererSandboxStatus() const override;
-
- pid_t LaunchZygote(base::CommandLine* cmd_line,
- base::ScopedFD* control_fd,
- base::FileHandleMappingVector additional_remapped_fds);
-
- void AdjustRendererOOMScore(base::ProcessHandle process_handle,
- int score) override;
- bool HasZygote() { return !zygote_pids_.empty(); }
-
- private:
- friend struct base::DefaultSingletonTraits<ZygoteHostImpl>;
-
- ZygoteHostImpl();
- ~ZygoteHostImpl() override;
-
- // Tells the ZygoteHost the PIDs of all the zygotes.
- void AddZygotePid(pid_t pid);
-
- int renderer_sandbox_status_;
-
- bool use_namespace_sandbox_;
- bool use_suid_sandbox_;
- bool use_suid_sandbox_for_adj_oom_score_;
- std::string sandbox_binary_;
-
- // This lock protects the |zygote_pids_| set.
- base::Lock zygote_pids_lock_;
- // This is a set of PIDs representing all the running zygotes.
- std::set<pid_t> zygote_pids_;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_HOST_ZYGOTE_HOST_IMPL_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/zygote_host_linux.h b/chromium/services/service_manager/zygote/zygote_host_linux.h
deleted file mode 100644
index 8e6416debe6..00000000000
--- a/chromium/services/service_manager/zygote/zygote_host_linux.h
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2012 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 SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_HOST_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_HOST_LINUX_H_
-
-#include <unistd.h>
-
-#include "base/component_export.h"
-#include "base/process/process.h"
-
-namespace service_manager {
-
-// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md
-
-// The zygote host is an interface, in the browser process, to the zygote
-// process.
-class ZygoteHost {
- public:
- // Returns the singleton instance.
- static COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE) ZygoteHost* GetInstance();
-
- virtual ~ZygoteHost() {}
-
- // Returns the pid of the Zygote process.
- virtual bool IsZygotePid(pid_t pid) = 0;
-
- // Returns an int which is a bitmask of kSandboxLinux* values. Only valid
- // after the first render has been forked.
- virtual int GetRendererSandboxStatus() const = 0;
-
- // Adjust the OOM score of the given renderer's PID. The allowed
- // range for the score is [0, 1000], where higher values are more
- // likely to be killed by the OOM killer.
- virtual void AdjustRendererOOMScore(base::ProcessHandle process_handle,
- int score) = 0;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_HOST_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/zygote_linux.cc b/chromium/services/service_manager/zygote/zygote_linux.cc
deleted file mode 100644
index aa601ab28d7..00000000000
--- a/chromium/services/service_manager/zygote/zygote_linux.cc
+++ /dev/null
@@ -1,659 +0,0 @@
-// Copyright (c) 2012 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 "services/service_manager/zygote/zygote_linux.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <signal.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include <utility>
-
-#include "base/command_line.h"
-#include "base/files/file_util.h"
-#include "base/linux_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/pickle.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/global_descriptors.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/process/kill.h"
-#include "base/process/launch.h"
-#include "base/process/process.h"
-#include "base/process/process_handle.h"
-#include "base/time/time.h"
-#include "base/trace_event/trace_event.h"
-#include "build/build_config.h"
-#include "ipc/ipc_channel.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "services/service_manager/embedder/descriptors.h"
-#include "services/service_manager/embedder/result_codes.h"
-#include "services/service_manager/embedder/set_process_title.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "services/service_manager/zygote/common/send_zygote_child_ping_linux.h"
-#include "services/service_manager/zygote/common/zygote_commands_linux.h"
-#include "services/service_manager/zygote/common/zygote_fork_delegate_linux.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-// See
-// https://chromium.googlesource.com/chromium/src/+/master/docs/linux/zygote.md
-
-namespace service_manager {
-
-namespace {
-
-// NOP function. See below where this handler is installed.
-void SIGCHLDHandler(int signal) {}
-
-int LookUpFd(const base::GlobalDescriptors::Mapping& fd_mapping, uint32_t key) {
- for (size_t index = 0; index < fd_mapping.size(); ++index) {
- if (fd_mapping[index].key == key)
- return fd_mapping[index].fd;
- }
- return -1;
-}
-
-void KillAndReap(pid_t pid, ZygoteForkDelegate* helper) {
- if (helper) {
- // Helper children may be forked in another PID namespace, so |pid| might
- // be meaningless to us; or we just might not be able to directly send it
- // signals. So we can't kill it.
- // Additionally, we're not its parent, so we can't reap it anyway.
- // TODO(mdempsky): Extend the ZygoteForkDelegate API to handle this.
- LOG(WARNING) << "Unable to kill or reap helper children";
- return;
- }
-
- // Kill the child process in case it's not already dead, so we can safely
- // perform a blocking wait.
- PCHECK(0 == kill(pid, SIGKILL));
- PCHECK(pid == HANDLE_EINTR(waitpid(pid, nullptr, 0)));
-}
-
-} // namespace
-
-Zygote::Zygote(int sandbox_flags,
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers,
- const base::GlobalDescriptors::Descriptor& ipc_backchannel)
- : sandbox_flags_(sandbox_flags),
- helpers_(std::move(helpers)),
- initial_uma_index_(0),
- to_reap_(),
- ipc_backchannel_(ipc_backchannel) {}
-
-Zygote::~Zygote() {}
-
-bool Zygote::ProcessRequests() {
- // A SOCK_SEQPACKET socket is installed in fd 3. We get commands from the
- // browser on it.
- // A SOCK_DGRAM is installed in fd 5. This is the sandbox IPC channel.
- // See
- // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md
-
- // We need to accept SIGCHLD, even though our handler is a no-op because
- // otherwise we cannot wait on children. (According to POSIX 2001.)
- struct sigaction action;
- memset(&action, 0, sizeof(action));
- action.sa_handler = &SIGCHLDHandler;
- PCHECK(sigaction(SIGCHLD, &action, nullptr) == 0);
-
- // Block SIGCHLD until a child might be ready to reap.
- sigset_t sigset;
- sigset_t orig_sigmask;
- PCHECK(sigemptyset(&sigset) == 0);
- PCHECK(sigaddset(&sigset, SIGCHLD) == 0);
- PCHECK(sigprocmask(SIG_BLOCK, &sigset, &orig_sigmask) == 0);
-
- if (UsingSUIDSandbox() || UsingNSSandbox()) {
- // Let the ZygoteHost know we are ready to go.
- // The receiving code is in
- // content/browser/zygote_host/zygote_host_impl_linux.cc.
- bool r = base::UnixDomainSocket::SendMsg(
- kZygoteSocketPairFd, kZygoteHelloMessage, sizeof(kZygoteHelloMessage),
- std::vector<int>());
-#if defined(OS_CHROMEOS)
- LOG_IF(WARNING, !r) << "Sending zygote magic failed";
- // Exit normally on chromeos because session manager may send SIGTERM
- // right after the process starts and it may fail to send zygote magic
- // number to browser process.
- if (!r)
- _exit(service_manager::RESULT_CODE_NORMAL_EXIT);
-#else
- CHECK(r) << "Sending zygote magic failed";
-#endif
- }
-
- sigset_t ppoll_sigmask = orig_sigmask;
- PCHECK(sigdelset(&ppoll_sigmask, SIGCHLD) == 0);
- struct pollfd pfd;
- pfd.fd = kZygoteSocketPairFd;
- pfd.events = POLLIN;
-
- struct timespec timeout;
- timeout.tv_sec = 2;
- timeout.tv_nsec = 0;
-
- for (;;) {
- struct timespec* timeout_ptr = nullptr;
- if (!to_reap_.empty())
- timeout_ptr = &timeout;
- int rc = ppoll(&pfd, 1, timeout_ptr, &ppoll_sigmask);
- PCHECK(rc >= 0 || errno == EINTR);
- ReapChildren();
-
- if (pfd.revents & POLLIN) {
- // This function call can return multiple times, once per fork().
- if (HandleRequestFromBrowser(kZygoteSocketPairFd)) {
- PCHECK(sigprocmask(SIG_SETMASK, &orig_sigmask, nullptr) == 0);
- return true;
- }
- }
- }
- // The loop should not be exited unless a request was successfully processed.
- NOTREACHED();
- return false;
-}
-
-bool Zygote::ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child) {
- pid_t pid = child->internal_pid;
- pid_t r = HANDLE_EINTR(waitpid(pid, nullptr, WNOHANG));
- if (r > 0) {
- if (r != pid) {
- DLOG(ERROR) << "While waiting for " << pid
- << " to terminate, "
- "waitpid returned "
- << r;
- }
- return r == pid;
- }
- if ((now - child->time_of_reap_request).InSeconds() < 2) {
- return false;
- }
- // If the process has been requested reaped >= 2 seconds ago, kill it.
- if (!child->sent_sigkill) {
- if (kill(pid, SIGKILL) != 0)
- DPLOG(ERROR) << "Sending SIGKILL to process " << pid << " failed";
-
- child->sent_sigkill = true;
- }
- return false;
-}
-
-void Zygote::ReapChildren() {
- base::TimeTicks now = base::TimeTicks::Now();
- std::vector<ZygoteProcessInfo>::iterator it = to_reap_.begin();
- while (it != to_reap_.end()) {
- if (ReapChild(now, &(*it))) {
- it = to_reap_.erase(it);
- } else {
- it++;
- }
- }
-}
-
-bool Zygote::GetProcessInfo(base::ProcessHandle pid,
- ZygoteProcessInfo* process_info) {
- DCHECK(process_info);
- const ZygoteProcessMap::const_iterator it = process_info_map_.find(pid);
- if (it == process_info_map_.end()) {
- return false;
- }
- *process_info = it->second;
- return true;
-}
-
-bool Zygote::UsingSUIDSandbox() const {
- return sandbox_flags_ & service_manager::SandboxLinux::kSUID;
-}
-
-bool Zygote::UsingNSSandbox() const {
- return sandbox_flags_ & service_manager::SandboxLinux::kUserNS;
-}
-
-bool Zygote::HandleRequestFromBrowser(int fd) {
- std::vector<base::ScopedFD> fds;
- char buf[kZygoteMaxMessageLength];
- const ssize_t len =
- base::UnixDomainSocket::RecvMsg(fd, buf, sizeof(buf), &fds);
-
- if (len == 0 || (len == -1 && errno == ECONNRESET)) {
- // EOF from the browser. We should die.
- // TODO(eugenis): call __sanititizer_cov_dump() here to obtain code
- // coverage for the Zygote. Currently it's not possible because of
- // confusion over who is responsible for closing the file descriptor.
- _exit(0);
- return false;
- }
-
- if (len == -1) {
- PLOG(ERROR) << "Error reading message from browser";
- return false;
- }
-
- base::Pickle pickle(buf, len);
- base::PickleIterator iter(pickle);
-
- int kind;
- if (iter.ReadInt(&kind)) {
- switch (kind) {
- case kZygoteCommandFork:
- // This function call can return multiple times, once per fork().
- return HandleForkRequest(fd, iter, std::move(fds));
-
- case kZygoteCommandReap:
- if (!fds.empty())
- break;
- HandleReapRequest(fd, iter);
- return false;
- case kZygoteCommandGetTerminationStatus:
- if (!fds.empty())
- break;
- HandleGetTerminationStatus(fd, iter);
- return false;
- case kZygoteCommandGetSandboxStatus:
- HandleGetSandboxStatus(fd, iter);
- return false;
- case kZygoteCommandForkRealPID:
- // This shouldn't happen in practice, but some failure paths in
- // HandleForkRequest (e.g., if ReadArgsAndFork fails during depickling)
- // could leave this command pending on the socket.
- LOG(ERROR) << "Unexpected real PID message from browser";
- NOTREACHED();
- return false;
- default:
- NOTREACHED();
- break;
- }
- }
-
- LOG(WARNING) << "Error parsing message from browser";
- return false;
-}
-
-void Zygote::HandleReapRequest(int fd, base::PickleIterator iter) {
- base::ProcessId child;
-
- if (!iter.ReadInt(&child)) {
- LOG(WARNING) << "Error parsing reap request from browser";
- return;
- }
-
- ZygoteProcessInfo child_info;
- if (!GetProcessInfo(child, &child_info)) {
- LOG(ERROR) << "Child not found!";
- NOTREACHED();
- return;
- }
- child_info.time_of_reap_request = base::TimeTicks::Now();
-
- if (!child_info.started_from_helper) {
- to_reap_.push_back(child_info);
- } else {
- // For processes from the helper, send a GetTerminationStatus request
- // with known_dead set to true.
- // This is not perfect, as the process may be killed instantly, but is
- // better than ignoring the request.
- base::TerminationStatus status;
- int exit_code;
- bool got_termination_status =
- GetTerminationStatus(child, true /* known_dead */, &status, &exit_code);
- DCHECK(got_termination_status);
- }
- process_info_map_.erase(child);
-}
-
-bool Zygote::GetTerminationStatus(base::ProcessHandle real_pid,
- bool known_dead,
- base::TerminationStatus* status,
- int* exit_code) {
- ZygoteProcessInfo child_info;
- if (!GetProcessInfo(real_pid, &child_info)) {
- LOG(ERROR) << "Zygote::GetTerminationStatus for unknown PID " << real_pid;
- NOTREACHED();
- return false;
- }
- // We know about |real_pid|.
- const base::ProcessHandle child = child_info.internal_pid;
- if (child_info.started_from_helper) {
- if (!child_info.started_from_helper->GetTerminationStatus(
- child, known_dead, status, exit_code)) {
- return false;
- }
- } else {
- // Handle the request directly.
- if (known_dead) {
- *status = base::GetKnownDeadTerminationStatus(child, exit_code);
- } else {
- // We don't know if the process is dying, so get its status but don't
- // wait.
- *status = base::GetTerminationStatus(child, exit_code);
- }
- }
- // Successfully got a status for |real_pid|.
- if (*status != base::TERMINATION_STATUS_STILL_RUNNING) {
- // Time to forget about this process.
- process_info_map_.erase(real_pid);
- }
-
- if (WIFEXITED(*exit_code)) {
- const int exit_status = WEXITSTATUS(*exit_code);
- if (exit_status == sandbox::NamespaceSandbox::SignalExitCode(SIGINT) ||
- exit_status == sandbox::NamespaceSandbox::SignalExitCode(SIGTERM)) {
- *status = base::TERMINATION_STATUS_PROCESS_WAS_KILLED;
- }
- }
-
- return true;
-}
-
-void Zygote::HandleGetTerminationStatus(int fd, base::PickleIterator iter) {
- bool known_dead;
- base::ProcessHandle child_requested;
-
- if (!iter.ReadBool(&known_dead) || !iter.ReadInt(&child_requested)) {
- LOG(WARNING) << "Error parsing GetTerminationStatus request "
- << "from browser";
- return;
- }
-
- base::TerminationStatus status;
- int exit_code;
-
- bool got_termination_status =
- GetTerminationStatus(child_requested, known_dead, &status, &exit_code);
- if (!got_termination_status) {
- // Assume that if we can't find the child in the sandbox, then
- // it terminated normally.
- NOTREACHED();
- status = base::TERMINATION_STATUS_NORMAL_TERMINATION;
- exit_code = service_manager::RESULT_CODE_NORMAL_EXIT;
- }
-
- base::Pickle write_pickle;
- write_pickle.WriteInt(static_cast<int>(status));
- write_pickle.WriteInt(exit_code);
- ssize_t written =
- HANDLE_EINTR(write(fd, write_pickle.data(), write_pickle.size()));
- if (written != static_cast<ssize_t>(write_pickle.size()))
- PLOG(ERROR) << "write";
-}
-
-int Zygote::ForkWithRealPid(const std::string& process_type,
- const base::GlobalDescriptors::Mapping& fd_mapping,
- const std::string& channel_id,
- base::ScopedFD pid_oracle,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) {
- ZygoteForkDelegate* helper = nullptr;
- for (auto i = helpers_.begin(); i != helpers_.end(); ++i) {
- if ((*i)->CanHelp(process_type, uma_name, uma_sample, uma_boundary_value)) {
- helper = i->get();
- break;
- }
- }
-
- base::ScopedFD read_pipe, write_pipe;
- base::ProcessId pid = 0;
- if (helper) {
- int mojo_channel_fd = LookUpFd(fd_mapping, kMojoIPCChannel);
- if (mojo_channel_fd < 0) {
- DLOG(ERROR) << "Failed to find kMojoIPCChannel in FD mapping";
- return -1;
- }
- std::vector<int> fds;
- fds.push_back(mojo_channel_fd); // kBrowserFDIndex
- fds.push_back(pid_oracle.get()); // kPIDOracleFDIndex
- pid = helper->Fork(process_type, fds, channel_id);
-
- // Helpers should never return in the child process.
- CHECK_NE(pid, 0);
- } else {
- PCHECK(base::CreatePipe(&read_pipe, &write_pipe));
- if (sandbox_flags_ & service_manager::SandboxLinux::kPIDNS &&
- sandbox_flags_ & service_manager::SandboxLinux::kUserNS) {
- pid = sandbox::NamespaceSandbox::ForkInNewPidNamespace(
- /*drop_capabilities_in_child=*/true);
- } else {
- pid = sandbox::Credentials::ForkAndDropCapabilitiesInChild();
- }
- }
-
- if (pid == 0) {
- // In the child process.
-
- // If the process is the init process inside a PID namespace, it must have
- // explicit signal handlers.
- if (getpid() == 1) {
- static const int kTerminationSignals[] = {
- SIGINT, SIGTERM, SIGHUP, SIGQUIT, SIGABRT, SIGPIPE, SIGUSR1, SIGUSR2};
- for (const int sig : kTerminationSignals) {
- sandbox::NamespaceSandbox::InstallTerminationSignalHandler(
- sig, sandbox::NamespaceSandbox::SignalExitCode(sig));
- }
- }
-
- write_pipe.reset();
-
- // Ping the PID oracle socket so the browser can find our PID.
- CHECK(SendZygoteChildPing(pid_oracle.get()));
-
- // Now read back our real PID from the zygote.
- base::ProcessId real_pid;
- if (!base::ReadFromFD(read_pipe.get(), reinterpret_cast<char*>(&real_pid),
- sizeof(real_pid))) {
- LOG(FATAL) << "Failed to synchronise with parent zygote process";
- }
- if (real_pid <= 0) {
- LOG(FATAL) << "Invalid pid from parent zygote";
- }
- // Sandboxed processes need to send the global, non-namespaced PID when
- // setting up an IPC channel to their parent.
- IPC::Channel::SetGlobalPid(real_pid);
- // Force the real PID so chrome event data have a PID that corresponds
- // to system trace event data.
- base::trace_event::TraceLog::GetInstance()->SetProcessID(
- static_cast<int>(real_pid));
- base::InitUniqueIdForProcessInPidNamespace(real_pid);
- return 0;
- }
-
- // In the parent process.
- if (pid < 0) {
- // Fork failed.
- return -1;
- }
-
- read_pipe.reset();
- pid_oracle.reset();
-
- // Always receive a real PID from the zygote host, though it might
- // be invalid (see below).
- base::ProcessId real_pid = -1;
- {
- std::vector<base::ScopedFD> recv_fds;
- char buf[kZygoteMaxMessageLength];
- const ssize_t len = base::UnixDomainSocket::RecvMsg(
- kZygoteSocketPairFd, buf, sizeof(buf), &recv_fds);
-
- if (len > 0) {
- CHECK(recv_fds.empty());
-
- base::Pickle pickle(buf, len);
- base::PickleIterator iter(pickle);
-
- int kind;
- CHECK(iter.ReadInt(&kind));
- CHECK(kind == kZygoteCommandForkRealPID);
- CHECK(iter.ReadInt(&real_pid));
- }
- }
-
- // If we successfully forked a child, but it crashed without sending
- // a message to the browser, the browser won't have found its PID.
- if (real_pid < 0) {
- KillAndReap(pid, helper);
- return -1;
- }
-
- // If we're not using a helper, send the PID back to the child process.
- if (!helper) {
- ssize_t written =
- HANDLE_EINTR(write(write_pipe.get(), &real_pid, sizeof(real_pid)));
- if (written != sizeof(real_pid)) {
- KillAndReap(pid, helper);
- return -1;
- }
- }
-
- // Now set-up this process to be tracked by the Zygote.
- if (process_info_map_.find(real_pid) != process_info_map_.end()) {
- LOG(ERROR) << "Already tracking PID " << real_pid;
- NOTREACHED();
- }
- process_info_map_[real_pid].internal_pid = pid;
- process_info_map_[real_pid].started_from_helper = helper;
-
- return real_pid;
-}
-
-base::ProcessId Zygote::ReadArgsAndFork(base::PickleIterator iter,
- std::vector<base::ScopedFD> fds,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value) {
- std::vector<std::string> args;
- int argc = 0;
- int numfds = 0;
- base::GlobalDescriptors::Mapping mapping;
- std::string process_type;
- std::string channel_id;
- const std::string channel_id_prefix =
- std::string("--") +
- service_manager::switches::kServiceRequestChannelToken + std::string("=");
-
- if (!iter.ReadString(&process_type))
- return -1;
- if (!iter.ReadInt(&argc))
- return -1;
-
- for (int i = 0; i < argc; ++i) {
- std::string arg;
- if (!iter.ReadString(&arg))
- return -1;
- args.push_back(arg);
- if (arg.compare(0, channel_id_prefix.length(), channel_id_prefix) == 0)
- channel_id = arg.substr(channel_id_prefix.length());
- }
-
- // timezone_id is obtained from ICU in zygote host so that it can't be
- // invalid. For an unknown reason, if an invalid ID is passed down here, the
- // worst result would be that timezone would be set to Etc/Unknown.
- base::string16 timezone_id;
- if (!iter.ReadString16(&timezone_id))
- return -1;
- icu::TimeZone::adoptDefault(icu::TimeZone::createTimeZone(
- icu::UnicodeString(FALSE, timezone_id.data(), timezone_id.length())));
-
- if (!iter.ReadInt(&numfds))
- return -1;
- if (numfds != static_cast<int>(fds.size()))
- return -1;
-
- // First FD is the PID oracle socket.
- if (fds.size() < 1)
- return -1;
- base::ScopedFD pid_oracle(std::move(fds[0]));
-
- // Remaining FDs are for the global descriptor mapping.
- for (int i = 1; i < numfds; ++i) {
- base::GlobalDescriptors::Key key;
- if (!iter.ReadUInt32(&key))
- return -1;
- mapping.push_back(base::GlobalDescriptors::Descriptor(key, fds[i].get()));
- }
-
- mapping.push_back(ipc_backchannel_);
-
- // Returns twice, once per process.
- base::ProcessId child_pid =
- ForkWithRealPid(process_type, mapping, channel_id, std::move(pid_oracle),
- uma_name, uma_sample, uma_boundary_value);
- if (!child_pid) {
- // This is the child process.
-
- // Our socket from the browser.
- PCHECK(0 == IGNORE_EINTR(close(kZygoteSocketPairFd)));
-
- // Pass ownership of file descriptors from fds to GlobalDescriptors.
- for (base::ScopedFD& fd : fds)
- ignore_result(fd.release());
- base::GlobalDescriptors::GetInstance()->Reset(mapping);
-
- // Reset the process-wide command line to our new command line.
- base::CommandLine::Reset();
- base::CommandLine::Init(0, nullptr);
- base::CommandLine::ForCurrentProcess()->InitFromArgv(args);
-
- // Update the process title. The argv was already cached by the call to
- // SetProcessTitleFromCommandLine in ChromeMain, so we can pass NULL here
- // (we don't have the original argv at this point).
- service_manager::SetProcessTitleFromCommandLine(nullptr);
- } else if (child_pid < 0) {
- LOG(ERROR) << "Zygote could not fork: process_type " << process_type
- << " numfds " << numfds << " child_pid " << child_pid;
- }
- return child_pid;
-}
-
-bool Zygote::HandleForkRequest(int fd,
- base::PickleIterator iter,
- std::vector<base::ScopedFD> fds) {
- std::string uma_name;
- int uma_sample;
- int uma_boundary_value;
- base::ProcessId child_pid = ReadArgsAndFork(iter, std::move(fds), &uma_name,
- &uma_sample, &uma_boundary_value);
- if (child_pid == 0)
- return true;
- // If there's no UMA report for this particular fork, then check if any
- // helpers have an initial UMA report for us to send instead.
- while (uma_name.empty() && initial_uma_index_ < helpers_.size()) {
- helpers_[initial_uma_index_++]->InitialUMA(&uma_name, &uma_sample,
- &uma_boundary_value);
- }
- // Must always send reply, as ZygoteHost blocks while waiting for it.
- base::Pickle reply_pickle;
- reply_pickle.WriteInt(child_pid);
- reply_pickle.WriteString(uma_name);
- if (!uma_name.empty()) {
- reply_pickle.WriteInt(uma_sample);
- reply_pickle.WriteInt(uma_boundary_value);
- }
- if (HANDLE_EINTR(write(fd, reply_pickle.data(), reply_pickle.size())) !=
- static_cast<ssize_t>(reply_pickle.size()))
- PLOG(ERROR) << "write";
- return false;
-}
-
-bool Zygote::HandleGetSandboxStatus(int fd, base::PickleIterator iter) {
- if (HANDLE_EINTR(write(fd, &sandbox_flags_, sizeof(sandbox_flags_))) !=
- sizeof(sandbox_flags_)) {
- PLOG(ERROR) << "write";
- }
-
- return false;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/zygote/zygote_linux.h b/chromium/services/service_manager/zygote/zygote_linux.h
deleted file mode 100644
index 840aa17a093..00000000000
--- a/chromium/services/service_manager/zygote/zygote_linux.h
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (c) 2012 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 SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/containers/small_map.h"
-#include "base/files/scoped_file.h"
-#include "base/posix/global_descriptors.h"
-#include "base/process/kill.h"
-#include "base/process/process.h"
-#include "base/process/process_handle.h"
-#include "base/time/time.h"
-
-namespace base {
-class PickleIterator;
-}
-
-namespace service_manager {
-
-class ZygoteForkDelegate;
-
-// This is the object which implements the zygote. The ZygoteMain function,
-// which is called from ChromeMain, simply constructs one of these objects and
-// runs it.
-class Zygote {
- public:
- Zygote(int sandbox_flags,
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers,
- const base::GlobalDescriptors::Descriptor& ipc_backchannel);
- ~Zygote();
-
- bool ProcessRequests();
-
- private:
- struct ZygoteProcessInfo {
- // Pid from inside the Zygote's PID namespace.
- base::ProcessHandle internal_pid;
- // Keeps track of which fork delegate helper the process was started from.
- ZygoteForkDelegate* started_from_helper;
- // Records when the browser requested the zygote to reap this process.
- base::TimeTicks time_of_reap_request;
- // Notes whether the zygote has sent SIGKILL to this process.
- bool sent_sigkill;
- };
- using ZygoteProcessMap =
- base::small_map<std::map<base::ProcessHandle, ZygoteProcessInfo>>;
-
- // Retrieve a ZygoteProcessInfo from the process_info_map_.
- // Returns true and write to process_info if |pid| can be found, return
- // false otherwise.
- bool GetProcessInfo(base::ProcessHandle pid, ZygoteProcessInfo* process_info);
-
- // Returns true if the SUID sandbox is active.
- bool UsingSUIDSandbox() const;
- // Returns true if the NS sandbox is active.
- bool UsingNSSandbox() const;
-
- // ---------------------------------------------------------------------------
- // Requests from the browser...
-
- // Read and process a request from the browser. Returns true if we are in a
- // new process and thus need to unwind back into ChromeMain.
- bool HandleRequestFromBrowser(int fd);
-
- void HandleReapRequest(int fd, base::PickleIterator iter);
-
- // Get the termination status of |real_pid|. |real_pid| is the PID as it
- // appears outside of the sandbox.
- // Return true if it managed to get the termination status and return the
- // status in |status| and the exit code in |exit_code|.
- bool GetTerminationStatus(base::ProcessHandle real_pid,
- bool known_dead,
- base::TerminationStatus* status,
- int* exit_code);
-
- void HandleGetTerminationStatus(int fd, base::PickleIterator iter);
-
- // This is equivalent to fork(), except that, when using the SUID sandbox, it
- // returns the real PID of the child process as it appears outside the
- // sandbox, rather than returning the PID inside the sandbox. The child's
- // real PID is determined by having it call
- // service_manager::SendZygoteChildPing(int) using the |pid_oracle|
- // descriptor.
- // Finally, when using a ZygoteForkDelegate helper, |uma_name|, |uma_sample|,
- // and |uma_boundary_value| may be set if the helper wants to make a UMA
- // report via UMA_HISTOGRAM_ENUMERATION.
- int ForkWithRealPid(const std::string& process_type,
- const base::GlobalDescriptors::Mapping& fd_mapping,
- const std::string& channel_id,
- base::ScopedFD pid_oracle,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value);
-
- // Unpacks process type and arguments from |iter| and forks a new process.
- // Returns -1 on error, otherwise returns twice, returning 0 to the child
- // process and the child process ID to the parent process, like fork().
- base::ProcessId ReadArgsAndFork(base::PickleIterator iter,
- std::vector<base::ScopedFD> fds,
- std::string* uma_name,
- int* uma_sample,
- int* uma_boundary_value);
-
- // Handle a 'fork' request from the browser: this means that the browser
- // wishes to start a new renderer. Returns true if we are in a new process,
- // otherwise writes the child_pid back to the browser via |fd|. Writes a
- // child_pid of -1 on error.
- bool HandleForkRequest(int fd,
- base::PickleIterator iter,
- std::vector<base::ScopedFD> fds);
-
- bool HandleGetSandboxStatus(int fd, base::PickleIterator iter);
-
- // Attempt to reap the child process by calling waitpid, and return
- // whether successful. If the process has not terminated within
- // 2 seconds of its reap request, send it SIGKILL.
- bool ReapChild(const base::TimeTicks& now, ZygoteProcessInfo* child);
-
- // Attempt to reap all outstanding children in |to_reap_|.
- void ReapChildren();
-
- // The Zygote needs to keep some information about each process. Most
- // notably what the PID of the process is inside the PID namespace of
- // the Zygote and whether or not a process was started by the
- // ZygoteForkDelegate helper.
- ZygoteProcessMap process_info_map_;
-
- const int sandbox_flags_;
- std::vector<std::unique_ptr<ZygoteForkDelegate>> helpers_;
-
- // Count of how many fork delegates for which we've invoked InitialUMA().
- size_t initial_uma_index_;
-
- // The vector contains the child processes that need to be reaped.
- std::vector<ZygoteProcessInfo> to_reap_;
-
- // Sandbox IPC channel for renderers to invoke services from the browser. See
- // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md
- base::GlobalDescriptors::Descriptor ipc_backchannel_;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_LINUX_H_
diff --git a/chromium/services/service_manager/zygote/zygote_main.h b/chromium/services/service_manager/zygote/zygote_main.h
deleted file mode 100644
index 8de1e6abc32..00000000000
--- a/chromium/services/service_manager/zygote/zygote_main.h
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (c) 2013 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 SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_MAIN_H_
-#define SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_MAIN_H_
-
-#include <memory>
-#include <vector>
-
-#include "base/component_export.h"
-#include "build/build_config.h"
-
-namespace service_manager {
-
-class ZygoteForkDelegate;
-
-// |delegate| must outlive this call.
-COMPONENT_EXPORT(SERVICE_MANAGER_ZYGOTE)
-bool ZygoteMain(
- std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates);
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_ZYGOTE_ZYGOTE_MAIN_H_
diff --git a/chromium/services/service_manager/zygote/zygote_main_linux.cc b/chromium/services/service_manager/zygote/zygote_main_linux.cc
deleted file mode 100644
index cf9ec082e69..00000000000
--- a/chromium/services/service_manager/zygote/zygote_main_linux.cc
+++ /dev/null
@@ -1,245 +0,0 @@
-// Copyright (c) 2012 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 "services/service_manager/zygote/zygote_main.h"
-
-#include <dlfcn.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <signal.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/prctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/rand_util.h"
-#include "base/strings/safe_sprintf.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/system/sys_info.h"
-#include "build/build_config.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/init_process_reaper.h"
-#include "sandbox/linux/services/libc_interceptor.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/services/thread_helpers.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
-#include "services/service_manager/embedder/descriptors.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "services/service_manager/sandbox/switches.h"
-#include "services/service_manager/zygote/common/common_sandbox_support_linux.h"
-#include "services/service_manager/zygote/common/zygote_commands_linux.h"
-#include "services/service_manager/zygote/common/zygote_fork_delegate_linux.h"
-#include "services/service_manager/zygote/zygote_linux.h"
-#include "third_party/icu/source/i18n/unicode/timezone.h"
-
-namespace service_manager {
-
-namespace {
-
-void CloseFds(const std::vector<int>& fds) {
- for (const auto& it : fds) {
- PCHECK(0 == IGNORE_EINTR(close(it)));
- }
-}
-
-base::OnceClosure ClosureFromTwoClosures(base::OnceClosure one,
- base::OnceClosure two) {
- return base::BindOnce(
- [](base::OnceClosure one, base::OnceClosure two) {
- if (!one.is_null())
- std::move(one).Run();
- if (!two.is_null())
- std::move(two).Run();
- },
- std::move(one), std::move(two));
-}
-
-} // namespace
-
-// This function triggers the static and lazy construction of objects that need
-// to be created before imposing the sandbox.
-static void ZygotePreSandboxInit() {
- base::RandUint64();
-
- base::SysInfo::AmountOfPhysicalMemory();
- base::SysInfo::NumberOfProcessors();
-
- // ICU DateFormat class (used in base/time_format.cc) needs to get the
- // Olson timezone ID by accessing the zoneinfo files on disk. After
- // TimeZone::createDefault is called once here, the timezone ID is
- // cached and there's no more need to access the file system.
- std::unique_ptr<icu::TimeZone> zone(icu::TimeZone::createDefault());
-}
-
-static bool CreateInitProcessReaper(
- base::OnceClosure post_fork_parent_callback) {
- // The current process becomes init(1), this function returns from a
- // newly created process.
- if (!sandbox::CreateInitProcessReaper(std::move(post_fork_parent_callback))) {
- LOG(ERROR) << "Error creating an init process to reap zombies";
- return false;
- }
- return true;
-}
-
-// Enter the setuid sandbox. This requires the current process to have been
-// created through the setuid sandbox.
-static bool EnterSuidSandbox(sandbox::SetuidSandboxClient* setuid_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- DCHECK(setuid_sandbox);
- DCHECK(setuid_sandbox->IsSuidSandboxChild());
-
- // Use the SUID sandbox. This still allows the seccomp sandbox to
- // be enabled by the process later.
-
- if (!setuid_sandbox->IsSuidSandboxUpToDate()) {
- LOG(WARNING) << "You are using a wrong version of the setuid binary!\n"
- "Please read "
- "https://chromium.googlesource.com/chromium/src/+/master/"
- "docs/linux/suid_sandbox_development.md."
- "\n\n";
- }
-
- if (!setuid_sandbox->ChrootMe())
- return false;
-
- if (setuid_sandbox->IsInNewPIDNamespace()) {
- CHECK_EQ(1, getpid())
- << "The SUID sandbox created a new PID namespace but Zygote "
- "is not the init process. Please, make sure the SUID "
- "binary is up to date.";
- }
-
- if (getpid() == 1) {
- // The setuid sandbox has created a new PID namespace and we need
- // to assume the role of init.
- CHECK(CreateInitProcessReaper(std::move(post_fork_parent_callback)));
- }
-
- CHECK(service_manager::SandboxDebugHandling::SetDumpableStatusAndHandlers());
- return true;
-}
-
-static void DropAllCapabilities(int proc_fd) {
- CHECK(sandbox::Credentials::DropAllCapabilities(proc_fd));
-}
-
-static void EnterNamespaceSandbox(service_manager::SandboxLinux* linux_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- linux_sandbox->EngageNamespaceSandbox(true /* from_zygote */);
- if (getpid() == 1) {
- CHECK(CreateInitProcessReaper(ClosureFromTwoClosures(
- base::BindOnce(DropAllCapabilities, linux_sandbox->proc_fd()),
- std::move(post_fork_parent_callback))));
- }
-}
-
-static void EnterLayerOneSandbox(service_manager::SandboxLinux* linux_sandbox,
- const bool using_layer1_sandbox,
- base::OnceClosure post_fork_parent_callback) {
- DCHECK(linux_sandbox);
-
- ZygotePreSandboxInit();
-
-// Check that the pre-sandbox initialization didn't spawn threads.
-// It's not just our code which may do so - some system-installed libraries
-// are known to be culprits, e.g. lttng.
-#if !defined(THREAD_SANITIZER)
- CHECK(sandbox::ThreadHelpers::IsSingleThreaded());
-#endif
-
- sandbox::SetuidSandboxClient* setuid_sandbox =
- linux_sandbox->setuid_sandbox_client();
- if (setuid_sandbox->IsSuidSandboxChild()) {
- CHECK(
- EnterSuidSandbox(setuid_sandbox, std::move(post_fork_parent_callback)))
- << "Failed to enter setuid sandbox";
- } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
- EnterNamespaceSandbox(linux_sandbox, std::move(post_fork_parent_callback));
- } else {
- CHECK(!using_layer1_sandbox);
- }
-}
-
-bool ZygoteMain(
- std::vector<std::unique_ptr<ZygoteForkDelegate>> fork_delegates) {
- sandbox::SetAmZygoteOrRenderer(true, GetSandboxFD());
-
- auto* linux_sandbox = service_manager::SandboxLinux::GetInstance();
-
- // Skip pre-initializing sandbox when sandbox is disabled for
- // https://crbug.com/444900.
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- service_manager::switches::kNoSandbox) &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- service_manager::switches::kNoZygoteSandbox)) {
- // This will pre-initialize the various sandboxes that need it.
- linux_sandbox->PreinitializeSandbox();
- }
-
- const bool using_setuid_sandbox =
- linux_sandbox->setuid_sandbox_client()->IsSuidSandboxChild();
- const bool using_namespace_sandbox =
- sandbox::NamespaceSandbox::InNewUserNamespace();
- const bool using_layer1_sandbox =
- using_setuid_sandbox || using_namespace_sandbox;
-
- if (using_setuid_sandbox) {
- linux_sandbox->setuid_sandbox_client()->CloseDummyFile();
- }
-
- if (using_layer1_sandbox) {
- // Let the ZygoteHost know we're booting up.
- if (!base::UnixDomainSocket::SendMsg(
- kZygoteSocketPairFd, kZygoteBootMessage, sizeof(kZygoteBootMessage),
- std::vector<int>())) {
- // This is not a CHECK failure because the browser process could either
- // crash or quickly exit while the zygote is starting. In either case a
- // zygote crash is not useful. https://crbug.com/692227
- PLOG(ERROR) << "Failed sending zygote boot message";
- _exit(1);
- }
- }
-
- VLOG(1) << "ZygoteMain: initializing " << fork_delegates.size()
- << " fork delegates";
- for (const auto& fork_delegate : fork_delegates) {
- fork_delegate->Init(GetSandboxFD(), using_layer1_sandbox);
- }
-
- // Turn on the first layer of the sandbox if the configuration warrants it.
- EnterLayerOneSandbox(
- linux_sandbox, using_layer1_sandbox,
- base::BindOnce(CloseFds, linux_sandbox->GetFileDescriptorsToClose()));
-
- const int sandbox_flags = linux_sandbox->GetStatus();
- const bool setuid_sandbox_engaged =
- !!(sandbox_flags & service_manager::SandboxLinux::kSUID);
- CHECK_EQ(using_setuid_sandbox, setuid_sandbox_engaged);
-
- const bool namespace_sandbox_engaged =
- !!(sandbox_flags & service_manager::SandboxLinux::kUserNS);
- CHECK_EQ(using_namespace_sandbox, namespace_sandbox_engaged);
-
- Zygote zygote(sandbox_flags, std::move(fork_delegates),
- base::GlobalDescriptors::Descriptor(
- static_cast<uint32_t>(kSandboxIPCChannel), GetSandboxFD()));
-
- // This function call can return multiple times, once per fork().
- return zygote.ProcessRequests();
-}
-
-} // namespace service_manager
diff --git a/chromium/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java b/chromium/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
index 19f96b32d2c..e96cb1ffa9e 100644
--- a/chromium/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
+++ b/chromium/services/shape_detection/android/junit/src/org/chromium/shape_detection/BitmapUtilsTest.java
@@ -24,7 +24,7 @@ import org.chromium.skia.mojom.ImageInfo;
* Test suite for conversion-to-Frame utils.
*/
@RunWith(BaseRobolectricTestRunner.class)
-@Config(manifest = Config.NONE)
+@Config(sdk = 21, manifest = Config.NONE)
public class BitmapUtilsTest {
private static final int VALID_WIDTH = 1;
private static final int VALID_HEIGHT = 1;
diff --git a/chromium/services/shape_detection/barcode_detection_impl_mac_vision_api.h b/chromium/services/shape_detection/barcode_detection_impl_mac_vision_api.h
index 9438277f6eb..809c4b57521 100644
--- a/chromium/services/shape_detection/barcode_detection_impl_mac_vision_api.h
+++ b/chromium/services/shape_detection/barcode_detection_impl_mac_vision_api.h
@@ -12,6 +12,7 @@
#import <Foundation/Foundation.h>
#include "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
namespace shape_detection {
diff --git a/chromium/services/shape_detection/detection_utils_win.cc b/chromium/services/shape_detection/detection_utils_win.cc
index 2d8c73dc4e6..f865ebb60ca 100644
--- a/chromium/services/shape_detection/detection_utils_win.cc
+++ b/chromium/services/shape_detection/detection_utils_win.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/check_op.h"
#include "base/logging.h"
#include "base/numerics/checked_math.h"
#include "base/win/winrt_storage_util.h"
diff --git a/chromium/services/tracing/BUILD.gn b/chromium/services/tracing/BUILD.gn
index 65fad54a857..bcb2fe7993d 100644
--- a/chromium/services/tracing/BUILD.gn
+++ b/chromium/services/tracing/BUILD.gn
@@ -82,9 +82,12 @@ source_set("tests") {
"perfetto/perfetto_integration_unittest.cc",
"public/cpp/perfetto/java_heap_profiler/hprof_buffer_android_unittest.cc",
"public/cpp/perfetto/java_heap_profiler/hprof_parser_android_unittest.cc",
+ "public/cpp/perfetto/producer_test_utils.cc",
+ "public/cpp/perfetto/producer_test_utils.h",
"public/cpp/perfetto/task_runner_unittest.cc",
"public/cpp/perfetto/trace_event_data_source_unittest.cc",
"public/cpp/perfetto/traced_value_proto_writer_unittest.cc",
+ "public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc",
"public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc",
]
diff --git a/chromium/services/tracing/DEPS b/chromium/services/tracing/DEPS
index 744fe92bc54..fcde8ac081b 100644
--- a/chromium/services/tracing/DEPS
+++ b/chromium/services/tracing/DEPS
@@ -9,9 +9,4 @@ specific_include_rules = {
'stack_unwinder_android_unittest.cc': [
"+services/tracing/jni_headers",
],
- # Temporary to research https://crbug.com/1074115
- # TODO(crbug.com/1074115): Remove this
- 'producer_client.cc': [
- "+components/crash/core/app/crashpad.h",
- ],
}
diff --git a/chromium/services/tracing/perfetto/consumer_host.cc b/chromium/services/tracing/perfetto/consumer_host.cc
index f6cb275cf51..67a3d1b0e0f 100644
--- a/chromium/services/tracing/perfetto/consumer_host.cc
+++ b/chromium/services/tracing/perfetto/consumer_host.cc
@@ -26,7 +26,7 @@
#include "mojo/public/cpp/bindings/strong_binding.h"
#include "mojo/public/cpp/system/wait.h"
#include "services/tracing/perfetto/perfetto_service.h"
-#include "services/tracing/public/cpp/trace_event_args_whitelist.h"
+#include "services/tracing/public/cpp/trace_event_args_allowlist.h"
#include "third_party/perfetto/include/perfetto/ext/trace_processor/export_json.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/observable_events.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/slice.h"
@@ -382,9 +382,9 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson(
base::SequencedTaskRunnerHandle::Get());
if (privacy_filtering_enabled) {
- // For filtering/whitelisting to be possible at JSON export time,
+ // For filtering/allowlisting to be possible at JSON export time,
// filtering must not have been enabled during proto emission time
- // (or there's nothing to pass through the whitelist).
+ // (or there's nothing to pass through the allowlist).
DCHECK(!privacy_filtering_enabled_);
privacy_filtering_enabled_ = true;
}
@@ -408,9 +408,9 @@ void ConsumerHost::TracingSession::ExportJson() {
->GetArgumentFilterPredicate()
.is_null()) {
base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
- base::BindRepeating(&IsTraceEventArgsWhitelisted));
+ base::BindRepeating(&IsTraceEventArgsAllowlisted));
base::trace_event::TraceLog::GetInstance()->SetMetadataFilterPredicate(
- base::BindRepeating(&IsMetadataWhitelisted));
+ base::BindRepeating(&IsMetadataAllowlisted));
}
perfetto::trace_processor::json::ArgumentFilterPredicate argument_filter;
diff --git a/chromium/services/tracing/perfetto/perfetto_service.h b/chromium/services/tracing/perfetto/perfetto_service.h
index a54618ff0e8..edba7d6ab58 100644
--- a/chromium/services/tracing/perfetto/perfetto_service.h
+++ b/chromium/services/tracing/perfetto/perfetto_service.h
@@ -11,7 +11,6 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "mojo/public/cpp/bindings/strong_binding_set.h"
#include "mojo/public/cpp/bindings/unique_receiver_set.h"
#include "services/tracing/perfetto/consumer_host.h"
#include "services/tracing/public/cpp/perfetto/task_runner.h"
diff --git a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
index d7433465e08..3982a6823fb 100644
--- a/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
+++ b/chromium/services/tracing/perfetto/privacy_filtered_fields-inl.h
@@ -30,8 +30,10 @@ constexpr int kClockIndices[] = {1, 2, 3, 4, -1};
constexpr MessageInfo kClock = {kClockIndices, nullptr};
// Proto Message: ClockSnapshot
-constexpr int kClockSnapshotIndices[] = {1, -1};
-constexpr MessageInfo const* kClockSnapshotComplexMessages[] = {&kClock};
+// Manually allowlisted: 2 (primary_trace_clock).
+constexpr int kClockSnapshotIndices[] = {1, 2, -1};
+constexpr MessageInfo const* kClockSnapshotComplexMessages[] = {&kClock,
+ nullptr};
constexpr MessageInfo kClockSnapshot = {kClockSnapshotIndices,
kClockSnapshotComplexMessages};
@@ -154,15 +156,21 @@ constexpr int kComponentInfoIndices[] = {1, 2, -1};
constexpr MessageInfo kComponentInfo = {kComponentInfoIndices, nullptr};
// Proto Message: ChromeLatencyInfo
-constexpr int kChromeLatencyInfoIndices[] = {1, 2, 3, 4, 5, -1};
+constexpr int kChromeLatencyInfoIndices[] = {1, 2, 3, 4, 5, 6, -1};
constexpr MessageInfo const* kChromeLatencyInfoComplexMessages[] = {
- nullptr, nullptr, nullptr, &kComponentInfo, nullptr};
+ nullptr, nullptr, nullptr, &kComponentInfo, nullptr, nullptr};
constexpr MessageInfo kChromeLatencyInfo = {kChromeLatencyInfoIndices,
kChromeLatencyInfoComplexMessages};
+// Proto Message: ChromeFrameReporter
+constexpr int kChromeFrameReporterIndices[] = {1, 2, 3, 4, -1};
+constexpr MessageInfo kChromeFrameReporter = {kChromeFrameReporterIndices,
+ nullptr};
+
// Proto Message: TrackEvent
-constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 9, 10, 11, 12, 16,
- 17, 24, 25, 26, 27, 28, 29, 30, 31, -1};
+constexpr int kTrackEventIndices[] = {1, 2, 3, 5, 6, 9, 10,
+ 11, 12, 16, 17, 24, 25, 26,
+ 27, 28, 29, 30, 31, 32, -1};
constexpr MessageInfo const* kTrackEventComplexMessages[] = {
nullptr,
nullptr,
@@ -182,7 +190,8 @@ constexpr MessageInfo const* kTrackEventComplexMessages[] = {
&kChromeHistogramSample,
&kChromeLatencyInfo,
nullptr,
- nullptr};
+ nullptr,
+ &kChromeFrameReporter};
constexpr MessageInfo kTrackEvent = {kTrackEventIndices,
kTrackEventComplexMessages};
@@ -344,7 +353,7 @@ constexpr MessageInfo kTrackDescriptor = {kTrackDescriptorIndices,
kTrackDescriptorComplexMessages};
// Proto Message: TracePacket
-// EDIT: Manually whitelisted: 3 (trusted_uid).
+// EDIT: Manually allowlisted: 3 (trusted_uid).
constexpr int kTracePacketIndices[] = {3, 6, 8, 10, 11, 12, 13, 35, 36, 41,
42, 43, 44, 51, 54, 56, 58, 59, 60, -1};
constexpr MessageInfo const* kTracePacketComplexMessages[] = {
diff --git a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
index 1e660c1a21f..f217e6d0103 100644
--- a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
+++ b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
@@ -933,5 +933,84 @@ TEST_F(SystemPerfettoTest, RespectsFeatureList) {
->IsDummySystemProducerForTesting());
}
}
+
+#if defined(OS_ANDROID)
+TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
+ if (base::android::BuildInfo::GetInstance()->sdk_int() >=
+ base::android::SDK_VERSION_P) {
+ return;
+ }
+
+ auto run_test = [this](bool enable_feature) {
+ PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
+
+ base::test::ScopedFeatureList feature_list;
+ if (enable_feature) {
+ feature_list.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
+ } else {
+ feature_list.InitAndDisableFeature(
+ features::kEnablePerfettoSystemTracing);
+ }
+ PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
+
+ std::string data_source_name = "temp_name";
+
+ base::RunLoop data_source_started_runloop;
+ std::unique_ptr<TestDataSource> data_source =
+ TestDataSource::CreateAndRegisterDataSource(data_source_name, 1);
+ data_source->set_start_tracing_callback(
+ data_source_started_runloop.QuitClosure());
+
+ auto system_service = CreateMockSystemService();
+
+ base::RunLoop system_no_more_packets_runloop;
+ MockConsumer system_consumer(
+ {data_source_name}, system_service->GetService(),
+ [&system_no_more_packets_runloop](bool has_more) {
+ if (!has_more) {
+ system_no_more_packets_runloop.Quit();
+ }
+ });
+
+ base::RunLoop system_data_source_enabled_runloop;
+ base::RunLoop system_data_source_disabled_runloop;
+ auto system_producer = CreateMockPosixSystemProducer(
+ system_service.get(),
+ /* num_data_sources = */ 1, &system_data_source_enabled_runloop,
+ &system_data_source_disabled_runloop, /* check_sdk_level = */ true);
+ PerfettoTracedProcess::GetTaskRunner()->PostTask(
+ [&system_producer]() { system_producer->ConnectToSystemService(); });
+
+ if (enable_feature) {
+ system_data_source_enabled_runloop.Run();
+ data_source_started_runloop.Run();
+ system_consumer.WaitForAllDataSourcesStarted();
+ }
+
+ // Post the task to ensure that the data will have been written and
+ // committed if any tracing is being done.
+ base::RunLoop stop_tracing;
+ PerfettoTracedProcess::GetTaskRunner()->PostTask(
+ [&system_consumer, &stop_tracing]() {
+ system_consumer.StopTracing();
+ stop_tracing.Quit();
+ });
+ stop_tracing.Run();
+
+ if (enable_feature) {
+ system_data_source_disabled_runloop.Run();
+ system_consumer.WaitForAllDataSourcesStopped();
+ }
+ system_no_more_packets_runloop.Run();
+
+ PerfettoProducer::DeleteSoonForTesting(std::move(system_producer));
+ return system_consumer.received_test_packets();
+ };
+
+ EXPECT_EQ(1u, run_test(/* enable_feature = */ true));
+ EXPECT_EQ(0u, run_test(/* enable_feature = */ false));
+}
+#endif // defined(OS_ANDROID)
+
} // namespace
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/BUILD.gn b/chromium/services/tracing/public/cpp/BUILD.gn
index f94537ea640..1cd4d42da6e 100644
--- a/chromium/services/tracing/public/cpp/BUILD.gn
+++ b/chromium/services/tracing/public/cpp/BUILD.gn
@@ -2,10 +2,10 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//base/trace_event/features.gni")
import("//build/buildflag_header.gni")
import("//build/config/chromecast_build.gni")
import("//build/config/compiler/compiler.gni")
+import("//build_overrides/build.gni")
import("//services/tracing/public/cpp/stack_sampling/loader_lock_sampling.gni")
buildflag_header("buildflags") {
@@ -40,8 +40,9 @@ if (!is_nacl && !is_ios) {
target(tracing_lib_type, "cpp") {
sources = [
+ "perfetto/flow_event_utils.cc",
+ "perfetto/flow_event_utils.h",
"perfetto/macros.h",
- "perfetto/macros_internal.h",
]
defines = [ "IS_TRACING_CPP_IMPL" ]
@@ -49,14 +50,11 @@ target(tracing_lib_type, "cpp") {
configs += [ "//build/config/compiler:wexit_time_destructors" ]
- public_deps = [
- "//base",
- "//third_party/perfetto:libperfetto",
- ]
+ public_deps = [ "//base" ]
deps = [ "//third_party/perfetto/include/perfetto/protozero" ]
- all_dependent_configs = [ "//third_party/perfetto/gn:public_config" ]
+ all_dependent_configs = []
if (!is_nacl && !is_ios) {
sources += [
@@ -64,8 +62,6 @@ target(tracing_lib_type, "cpp") {
"base_agent.h",
"perfetto/dummy_producer.cc",
"perfetto/dummy_producer.h",
- "perfetto/flow_event_utils.cc",
- "perfetto/flow_event_utils.h",
"perfetto/interning_index.h",
"perfetto/java_heap_profiler/hprof_buffer_android.cc",
"perfetto/java_heap_profiler/hprof_buffer_android.h",
@@ -76,7 +72,6 @@ target(tracing_lib_type, "cpp") {
"perfetto/java_heap_profiler/hprof_parser_android.h",
"perfetto/java_heap_profiler/java_heap_profiler_android.cc",
"perfetto/java_heap_profiler/java_heap_profiler_android.h",
- "perfetto/macros_internal.cc",
"perfetto/perfetto_config.cc",
"perfetto/perfetto_config.h",
"perfetto/perfetto_producer.cc",
@@ -100,12 +95,14 @@ target(tracing_lib_type, "cpp") {
"perfetto/traced_value_proto_writer.h",
"perfetto/track_event_thread_local_event_sink.cc",
"perfetto/track_event_thread_local_event_sink.h",
+ "stack_sampling/reached_code_data_source_android.cc",
+ "stack_sampling/reached_code_data_source_android.h",
"stack_sampling/tracing_sampler_profiler.cc",
"stack_sampling/tracing_sampler_profiler.h",
"trace_event_agent.cc",
"trace_event_agent.h",
- "trace_event_args_whitelist.cc",
- "trace_event_args_whitelist.h",
+ "trace_event_args_allowlist.cc",
+ "trace_event_args_allowlist.h",
"trace_startup.cc",
"trace_startup.h",
"traced_process_impl.cc",
@@ -141,10 +138,6 @@ target(tracing_lib_type, "cpp") {
]
}
- if (is_linux && !is_fuchsia) {
- deps += [ "//components/crash/core/app:app" ]
- }
-
if (is_android && can_unwind_with_cfi_table && is_official_build) {
sources += [
"stack_sampling/stack_sampler_android.cc",
diff --git a/chromium/services/tracing/public/cpp/perfetto/macros.h b/chromium/services/tracing/public/cpp/perfetto/macros.h
index c7c461a27a1..ade79860aa4 100644
--- a/chromium/services/tracing/public/cpp/perfetto/macros.h
+++ b/chromium/services/tracing/public/cpp/perfetto/macros.h
@@ -5,76 +5,7 @@
#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_H_
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_H_
-#include "base/trace_event/trace_event.h"
-#include "services/tracing/public/cpp/perfetto/macros_internal.h"
-
-// Needed not for this file but for every user of the TRACE_EVENT macros for the
-// lambda definition. So included here for convenience.
-#include "third_party/perfetto/include/perfetto/tracing/event_context.h"
-#include "third_party/perfetto/protos/perfetto/trace/track_event/track_event.pbzero.h"
-
-#if defined(TRACE_EVENT_BEGIN)
-#error "Another copy of perfetto tracing macros have been included"
-#endif
-
-// TODO(nuskos): This whole file should be removed and migrated to using the
-// Perfetto client library macros. However currently chromium isn't set up to
-// use the client library so in the meantime we've added support for features we
-// want sooner.
-
-namespace tracing {
-// The perfetto client library does not use event names for
-// TRACE_EVENT_PHASE_END. However currently Chrome expects all TraceEvents to
-// have event names. So until we move over to the client library we will use
-// this for all TRACE_EVENT_PHASE_END typed arguments.
-//
-// TODO(nuskos): remove this constant.
-constexpr char kTraceEventEndName[] = "";
-} // namespace tracing
-
-// Begin a thread-scoped slice under |category| with the title |name|. Both
-// strings must be static constants. The track event is only recorded if
-// |category| is enabled for a tracing session.
-//
-// Rest of parameters can contain: a perfetto::Track object for asynchronous
-// events and a lambda used to fill typed event. Should be passed in that exact
-// order when both are used.
-//
-// When lambda is passed as an argument, it is executed synchronously.
-//
-// TODO(nuskos): Give a simple example once we have a typed event that doesn't
-// need interning.
-// TRACE_EVENT_BEGIN("log", "LogMessage",
-// [](perfetto::EventContext ctx) {
-// auto* event = ctx.event();
-// // Fill in some field in track_event.
-// });
-#define TRACE_EVENT_BEGIN(category, name, ...) \
- TRACING_INTERNAL_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_BEGIN, category, name, \
- TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__)
-
-// End a thread-scoped slice under |category|.
-#define TRACE_EVENT_END(category, ...) \
- TRACING_INTERNAL_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_END, category, \
- tracing::kTraceEventEndName, \
- TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__)
-
-// Begin a thread-scoped slice which gets automatically closed when going out
-// of scope.
-//
-// BEWARE: similarly to TRACE_EVENT_BEGIN, this macro does accept a track, but
-// it does not work properly and should not be used.
-// TODO(b/154583431): figure out how to fix or disallow that and update the
-// comment.
-//
-// Similarly to TRACE_EVENT_BEGIN, when lambda is passed as an argument, it is
-// executed synchronously.
-#define TRACE_EVENT(category, name, ...) \
- TRACING_INTERNAL_SCOPED_ADD_TRACE_EVENT(category, name, ##__VA_ARGS__)
-
-// Emit a single event called "name" immediately, with zero duration.
-#define TRACE_EVENT_INSTANT(category, name, scope, ...) \
- TRACING_INTERNAL_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_INSTANT, category, name, \
- scope, ##__VA_ARGS__)
+// TODO(eseckler): Replace this header with the version from base.
+#include "base/trace_event/typed_macros.h"
#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/macros_internal.cc b/chromium/services/tracing/public/cpp/perfetto/macros_internal.cc
deleted file mode 100644
index 8efeeda4476..00000000000
--- a/chromium/services/tracing/public/cpp/perfetto/macros_internal.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright 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 "services/tracing/public/cpp/perfetto/macros_internal.h"
-
-#include "base/trace_event/thread_instruction_count.h"
-
-namespace tracing {
-namespace internal {
-namespace {
-
-base::ThreadTicks ThreadNow() {
- return base::ThreadTicks::IsSupported()
- ? base::subtle::ThreadTicksNowIgnoringOverride()
- : base::ThreadTicks();
-}
-
-base::trace_event::ThreadInstructionCount ThreadInstructionNow() {
- return base::trace_event::ThreadInstructionCount::IsSupported()
- ? base::trace_event::ThreadInstructionCount::Now()
- : base::trace_event::ThreadInstructionCount();
-}
-
-} // namespace
-
-base::Optional<base::trace_event::TraceEvent> CreateTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- base::TimeTicks ts = base::TimeTicks()) {
- DCHECK(phase == TRACE_EVENT_PHASE_BEGIN || phase == TRACE_EVENT_PHASE_END ||
- phase == TRACE_EVENT_PHASE_INSTANT);
- DCHECK(category_group_enabled);
- const int thread_id = static_cast<int>(base::PlatformThread::CurrentId());
- auto* trace_log = base::trace_event::TraceLog::GetInstance();
- DCHECK(trace_log);
- if (!trace_log->ShouldAddAfterUpdatingState(phase, category_group_enabled,
- name, trace_event_internal::kNoId,
- thread_id, nullptr)) {
- return base::nullopt;
- }
-
- if (ts.is_null()) {
- ts = TRACE_TIME_TICKS_NOW();
- } else {
- flags |= TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP;
- }
- base::ThreadTicks thread_now = ThreadNow();
- base::trace_event::ThreadInstructionCount thread_instruction_now =
- ThreadInstructionNow();
-
- return base::trace_event::TraceEvent(
- thread_id, ts, thread_now, thread_instruction_now, phase,
- category_group_enabled, name, trace_event_internal::kGlobalScope,
- trace_event_internal::kNoId, trace_event_internal::kNoId, nullptr, flags);
-}
-
-} // namespace internal
-} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/macros_internal.h b/chromium/services/tracing/public/cpp/perfetto/macros_internal.h
deleted file mode 100644
index f2401f51eb9..00000000000
--- a/chromium/services/tracing/public/cpp/perfetto/macros_internal.h
+++ /dev/null
@@ -1,213 +0,0 @@
-// Copyright 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.
-
-#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
-#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
-
-#include "build/build_config.h"
-#include "third_party/perfetto/include/perfetto/tracing/event_context.h"
-#include "third_party/perfetto/include/perfetto/tracing/track.h"
-
-// Copy of function with the same name from Perfetto client library.
-template <typename T>
-static constexpr bool IsValidTraceLambdaImpl(
- typename std::enable_if<static_cast<bool>(
- sizeof(std::declval<T>()(std::declval<perfetto::EventContext>()),
- 0))>::type* = nullptr) {
- return true;
-}
-
-template <typename T>
-static constexpr bool IsValidTraceLambdaImpl(...) {
- return false;
-}
-
-template <typename T>
-static constexpr bool IsValidTraceLambda() {
- return IsValidTraceLambdaImpl<T>(nullptr);
-}
-
-#if !defined(OS_IOS) && !defined(OS_NACL)
-
-#include "base/component_export.h"
-#include "base/trace_event/trace_event.h"
-#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
-
-namespace tracing {
-namespace internal {
-base::Optional<base::trace_event::TraceEvent> COMPONENT_EXPORT(TRACING_CPP)
- CreateTraceEvent(char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- base::TimeTicks timestamp);
-
-template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext),
- typename ArgumentFunctionCheck = typename std::enable_if<
- IsValidTraceLambda<TrackEventArgumentFunction>()>::type>
-static inline base::trace_event::TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- const perfetto::Track& track,
- base::TimeTicks timestamp,
- TrackEventArgumentFunction argument_func) {
- base::trace_event::TraceEventHandle handle = {0, 0, 0};
- auto maybe_event =
- CreateTraceEvent(phase, category_group_enabled, name, flags, timestamp);
- if (!maybe_event) {
- return handle;
- }
- TraceEventDataSource::OnAddTraceEvent(&maybe_event.value(),
- /* thread_will_flush = */ false,
- nullptr, track,
- std::move(argument_func));
- return handle;
-}
-
-} // namespace internal
-} // namespace tracing
-
-// These macros should not be called directly. They are intended to be used by
-// macros in //services/tracing/perfetto/macros.h only.
-
-#define TRACING_INTERNAL_CONCAT2(a, b) a##b
-#define TRACING_INTERNAL_CONCAT(a, b) TRACING_INTERNAL_CONCAT2(a, b)
-#define TRACING_INTERNAL_UID(prefix) TRACING_INTERNAL_CONCAT(prefix, __LINE__)
-
-#define TRACING_INTERNAL_ADD_TRACE_EVENT(phase, category, name, flags, ...) \
- do { \
- INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
- if (INTERNAL_TRACE_EVENT_CATEGORY_GROUP_ENABLED()) { \
- tracing::internal::AddTraceEvent( \
- phase, INTERNAL_TRACE_EVENT_UID(category_group_enabled), name, \
- flags, ##__VA_ARGS__); \
- } \
- } while (false)
-
-#define TRACING_INTERNAL_SCOPED_ADD_TRACE_EVENT(category, name, ...) \
- struct { \
- struct ScopedTraceEvent { \
- /* The parameter is an implementation detail. It allows the */ \
- /* anonymous struct to use aggregate initialization to invoke the */ \
- /* lambda to emit the begin event with the proper reference capture */ \
- /* for any TrackEventArgumentFunction in |__VA_ARGS__|. This is */ \
- /* required so that the scoped event is exactly ONE line and can't */ \
- /* escape the scope if used in a single line if statement. */ \
- ScopedTraceEvent(...) {} \
- ~ScopedTraceEvent() { \
- /* TODO(nuskos): Remove the empty string passed as the |name| */ \
- /* field. As described in macros.h we shouldn't need it in our */ \
- /* end state. */ \
- TRACING_INTERNAL_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_END, category, "", \
- TRACE_EVENT_FLAG_NONE, \
- [](perfetto::EventContext) {}); \
- } \
- } event; \
- } TRACING_INTERNAL_UID(scoped_event){[&]() { \
- TRACING_INTERNAL_ADD_TRACE_EVENT(TRACE_EVENT_PHASE_BEGIN, category, name, \
- TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
- return 0; \
- }()};
-
-#else // !defined(OS_IOS) && !defined(OS_NACL)
-
-// Tracing isn't supported on IOS or NACL so we just black hole all the
-// parameters into a function that doesn't do anything. This ensures that no
-// warnings about unused parameters are generated.
-
-namespace tracing {
-namespace internal {
-template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
-static inline base::trace_event::TraceEventHandle AddTraceEvent(
- char,
- const unsigned char*,
- const char*,
- unsigned int,
- const perfetto::Track&,
- base::TimeTicks,
- TrackEventArgumentFunction) {
- return {0, 0, 0};
-}
-
-} // namespace internal
-} // namespace tracing
-
-#define TRACING_INTERNAL_ADD_TRACE_EVENT(phase, category, name, flags, ...) \
- tracing::internal::AddTraceEvent(phase, nullptr, name, flags, ##__VA_ARGS__);
-
-#define TRACING_INTERNAL_SCOPED_ADD_TRACE_EVENT(category, name, ...) \
- TRACING_INTERNAL_ADD_TRACE_EVENT('B', category, name, TRACE_EVENT_FLAG_NONE, \
- ##__VA_ARGS__);
-#endif // else of !defined(OS_IOS) && !defined(OS_NACL)
-
-namespace tracing {
-namespace internal {
-
-template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext),
- typename ArgumentFunctionCheck = typename std::enable_if<
- IsValidTraceLambda<TrackEventArgumentFunction>()>::type,
- typename TrackType,
- typename TrackTypeCheck = typename std::enable_if<
- std::is_convertible<TrackType, perfetto::Track>::value>::type>
-static inline base::trace_event::TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- const TrackType& track,
- TrackEventArgumentFunction argument_func) {
- return AddTraceEvent(phase, category_group_enabled, name, flags, track,
- base::TimeTicks(), argument_func);
-}
-
-template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext),
- typename ArgumentFunctionCheck = typename std::enable_if<
- IsValidTraceLambda<TrackEventArgumentFunction>()>::type>
-static inline base::trace_event::TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- TrackEventArgumentFunction argument_func) {
- return AddTraceEvent(phase, category_group_enabled, name, flags,
- perfetto::Track(), base::TimeTicks(), argument_func);
-}
-
-template <typename TrackType,
- typename TrackTypeCheck = typename std::enable_if<
- std::is_convertible<TrackType, perfetto::Track>::value>::type>
-inline base::trace_event::TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- const TrackType& track) {
- return AddTraceEvent(phase, category_group_enabled, name, flags, track,
- base::TimeTicks(), [](perfetto::EventContext ctx) {});
-}
-
-template <typename TrackType,
- typename TrackTypeCheck = typename std::enable_if<
- std::is_convertible<TrackType, perfetto::Track>::value>::type>
-inline base::trace_event::TraceEventHandle AddTraceEvent(
- char phase,
- const unsigned char* category_group_enabled,
- const char* name,
- unsigned int flags,
- const TrackType& track,
- base::TimeTicks timestamp) {
- return AddTraceEvent(phase, category_group_enabled, name, flags, track,
- timestamp, [](perfetto::EventContext ctx) {});
-}
-
-} // namespace internal
-} // namespace tracing
-
-#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_MACROS_INTERNAL_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
index 8f0cce3e2c9..94edd835823 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -13,6 +13,7 @@
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
+#include "services/tracing/public/cpp/perfetto/trace_time.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
namespace tracing {
@@ -34,11 +35,98 @@ perfetto::TraceConfig::DataSource* AddDataSourceConfig(
return data_source;
}
+void AddDataSourceConfigs(
+ perfetto::TraceConfig* perfetto_config,
+ const base::trace_event::TraceConfig::ProcessFilterConfig& process_filters,
+ const base::trace_event::TraceConfig& stripped_config,
+ const std::set<std::string>& source_names,
+ bool privacy_filtering_enabled) {
+ const std::string chrome_config_string = stripped_config.ToString();
+
+ // Capture actual trace events.
+ if (source_names.empty() ||
+ source_names.count(tracing::mojom::kTraceEventDataSourceName) == 1) {
+ auto* trace_event_data_source = AddDataSourceConfig(
+ perfetto_config, tracing::mojom::kTraceEventDataSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ for (auto& enabled_pid : process_filters.included_process_ids()) {
+ *trace_event_data_source->add_producer_name_filter() = base::StrCat(
+ {mojom::kPerfettoProducerNamePrefix,
+ base::NumberToString(static_cast<uint32_t>(enabled_pid))});
+ }
+ }
+
+ // Capture system trace events if supported and enabled. The datasources will
+ // only emit events if system tracing is enabled in |chrome_config|.
+ if (!privacy_filtering_enabled) {
+#if defined(OS_CHROMEOS) || (BUILDFLAG(IS_CHROMECAST) && defined(OS_LINUX))
+ if (source_names.empty() ||
+ source_names.count(tracing::mojom::kSystemTraceDataSourceName) == 1) {
+ AddDataSourceConfig(perfetto_config,
+ tracing::mojom::kSystemTraceDataSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+#endif
+
+#if defined(OS_CHROMEOS)
+ if (source_names.empty() ||
+ source_names.count(tracing::mojom::kArcTraceDataSourceName) == 1) {
+ AddDataSourceConfig(perfetto_config,
+ tracing::mojom::kArcTraceDataSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+#endif
+ }
+
+ // Also capture global metadata.
+ if (source_names.empty() ||
+ source_names.count(tracing::mojom::kMetaDataSourceName) == 1) {
+ AddDataSourceConfig(perfetto_config, tracing::mojom::kMetaDataSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+
+ if (stripped_config.IsCategoryGroupEnabled(
+ TRACE_DISABLED_BY_DEFAULT("cpu_profiler"))) {
+ DCHECK_EQ(
+ 1u, source_names.empty() ||
+ source_names.count(tracing::mojom::kSamplerProfilerSourceName));
+ AddDataSourceConfig(perfetto_config,
+ tracing::mojom::kSamplerProfilerSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+
+ if (stripped_config.IsCategoryGroupEnabled(
+ TRACE_DISABLED_BY_DEFAULT("java-heap-profiler"))) {
+ DCHECK_EQ(1u, source_names.empty() ||
+ source_names.count(
+ tracing::mojom::kJavaHeapProfilerSourceName));
+ AddDataSourceConfig(perfetto_config,
+ tracing::mojom::kJavaHeapProfilerSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+
+ if (source_names.empty() ||
+ source_names.count(tracing::mojom::kReachedCodeProfilerSourceName) == 1) {
+ AddDataSourceConfig(perfetto_config,
+ tracing::mojom::kReachedCodeProfilerSourceName,
+ chrome_config_string, privacy_filtering_enabled);
+ }
+}
+
} // namespace
perfetto::TraceConfig GetDefaultPerfettoConfig(
const base::trace_event::TraceConfig& chrome_config,
bool privacy_filtering_enabled) {
+ return GetPerfettoConfigWithDataSources(chrome_config, {},
+ privacy_filtering_enabled);
+}
+
+perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP)
+ GetPerfettoConfigWithDataSources(
+ const base::trace_event::TraceConfig& chrome_config,
+ const std::set<std::string>& source_names,
+ bool privacy_filtering_enabled) {
perfetto::TraceConfig perfetto_config;
size_t size_limit = chrome_config.GetTraceBufferSizeInKb();
@@ -65,9 +153,18 @@ perfetto::TraceConfig GetDefaultPerfettoConfig(
break;
}
- // Perfetto uses clock_gettime for its internal snapshotting, which gets
- // blocked by the sandboxed and isn't needed for Chrome regardless.
auto* builtin_data_sources = perfetto_config.mutable_builtin_data_sources();
+
+ // Chrome uses CLOCK_MONOTONIC as its trace clock on Posix. To avoid that
+ // trace processor converts Chrome's event timestamps into CLOCK_BOOTTIME
+ // during import, we set the trace clock here (the service will emit it into
+ // the trace's ClockSnapshots). See also crbug.com/1060400, where the
+ // conversion to BOOTTIME caused CrOS and chromecast system data source data
+ // to be misaligned.
+ builtin_data_sources->set_primary_trace_clock(
+ static_cast<perfetto::protos::gen::BuiltinClock>(kTraceClockId));
+
+ // Chrome emits system / trace config metadata itself.
builtin_data_sources->set_disable_trace_config(privacy_filtering_enabled);
builtin_data_sources->set_disable_system_info(privacy_filtering_enabled);
builtin_data_sources->set_disable_service_events(privacy_filtering_enabled);
@@ -88,52 +185,10 @@ perfetto::TraceConfig GetDefaultPerfettoConfig(
base::trace_event::TraceConfig::ProcessFilterConfig());
stripped_config.SetTraceBufferSizeInKb(0);
stripped_config.SetTraceBufferSizeInEvents(0);
- std::string chrome_config_string = stripped_config.ToString();
-
- // Capture actual trace events.
- auto* trace_event_data_source = AddDataSourceConfig(
- &perfetto_config, tracing::mojom::kTraceEventDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
- for (auto& enabled_pid :
- chrome_config.process_filter_config().included_process_ids()) {
- *trace_event_data_source->add_producer_name_filter() = base::StrCat(
- {mojom::kPerfettoProducerNamePrefix,
- base::NumberToString(static_cast<uint32_t>(enabled_pid))});
- }
-
-// Capture system trace events if supported and enabled. The datasources will
-// only emit events if system tracing is enabled in |chrome_config|.
- if (!privacy_filtering_enabled) {
-#if defined(OS_CHROMEOS) || (BUILDFLAG(IS_CHROMECAST) && defined(OS_LINUX))
- AddDataSourceConfig(&perfetto_config,
- tracing::mojom::kSystemTraceDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
-#endif
-
-#if defined(OS_CHROMEOS)
- AddDataSourceConfig(&perfetto_config,
- tracing::mojom::kArcTraceDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
-#endif
- }
- // Also capture global metadata.
- AddDataSourceConfig(&perfetto_config, tracing::mojom::kMetaDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
-
- if (chrome_config.IsCategoryGroupEnabled(
- TRACE_DISABLED_BY_DEFAULT("cpu_profiler"))) {
- AddDataSourceConfig(&perfetto_config,
- tracing::mojom::kSamplerProfilerSourceName,
- chrome_config_string, privacy_filtering_enabled);
- }
-
- if (chrome_config.IsCategoryGroupEnabled(
- TRACE_DISABLED_BY_DEFAULT("java-heap-profiler"))) {
- AddDataSourceConfig(&perfetto_config,
- tracing::mojom::kJavaHeapProfilerSourceName,
- chrome_config_string, privacy_filtering_enabled);
- }
+ AddDataSourceConfigs(&perfetto_config, chrome_config.process_filter_config(),
+ stripped_config, source_names,
+ privacy_filtering_enabled);
return perfetto_config;
}
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h
index b4616787278..27d33a982c4 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h
@@ -5,6 +5,9 @@
#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_
+#include <set>
+#include <string>
+
#include "base/component_export.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
@@ -20,6 +23,16 @@ perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP) GetDefaultPerfettoConfig(
const base::trace_event::TraceConfig& chrome_config,
bool privacy_filtering_enabled = false);
+// Creates a perfetto trace config with only the data sources included in
+// |source_names| and enabled by |trace_config|. Passing empty set will add all
+// data sources based on trace config. The list of possible names are listed in
+// services/tracing/public/mojom/perfetto_service.mojom.
+perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP)
+ GetPerfettoConfigWithDataSources(
+ const base::trace_event::TraceConfig& chrome_config,
+ const std::set<std::string>& source_names,
+ bool privacy_filtering_enabled = false);
+
} // namespace tracing
#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_CONFIG_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.cc b/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.cc
index a782ff7748b..0f144724150 100644
--- a/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/posix_system_producer.cc
@@ -14,6 +14,7 @@
#include "services/tracing/public/cpp/perfetto/shared_memory.h"
#include "services/tracing/public/cpp/trace_startup.h"
#include "services/tracing/public/cpp/traced_process_impl.h"
+#include "services/tracing/public/cpp/tracing_features.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
@@ -135,6 +136,13 @@ void PosixSystemProducer::ConnectToSystemService() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
CHECK(IsTracingInitialized());
DCHECK(state_ == State::kDisconnected);
+
+ // Some Telemetry tests use sideloaded Perfetto library on pre-Pie devices.
+ // We allow those tests to use system tracing by setting the
+ // EnablePerfettoSystemTracing feature.
+ disallow_pre_android_pie_ =
+ !base::FeatureList::IsEnabled(features::kEnablePerfettoSystemTracing);
+
Connect();
}
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
index f8f3a133b42..edbda2af892 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -25,30 +25,7 @@
#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h"
#include "third_party/perfetto/protos/perfetto/common/track_event_descriptor.pbzero.h"
-#if defined(OS_LINUX)
-#include "components/crash/core/app/crashpad.h" // nogncheck
-#endif
-
namespace {
-#if defined(OS_LINUX)
-constexpr char kCrashHandlerMetricName[] =
- "CrashReport.DumpWithoutCrashingHandler.FromInitSharedMemoryIfNeeded";
-// Crash handler that might handle base::debug::DumpWithoutCrashing.
-// TODO(crbug.com/1074115): Remove once crbug.com/1074115 is resolved.
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class CrashHandler {
- kCrashpad = 0,
- kBreakpad = 1,
- kMaxValue = kBreakpad,
-};
-#endif
-
-// UMA that records the return value of base::debug::DumpWithoutCrashing.
-// TODO(crbug.com/1074115): Remove once crbug.com/1074115 is resolved.
-constexpr char kDumpWithoutCrashingResultMetricName[] =
- "CrashReport.DumpWithoutCrashingResult.FromInitSharedMemoryIfNeeded";
-
// Result for getting the shared buffer in InitSharedMemoryIfNeeded.
constexpr char kSharedBufferIsValidMetricName[] = "Tracing.SharedBufferIsValid";
} // namespace
@@ -421,18 +398,17 @@ bool ProducerClient::InitSharedMemoryIfNeeded() {
base::UmaHistogramBoolean(kSharedBufferIsValidMetricName, valid);
if (!valid) {
-#if defined(OS_LINUX)
// TODO(crbug.com/1074115): Investigate why Breakpad doesn't seem to
// generate reports on some ChromeOS boards.
- CrashHandler handler = crash_reporter::IsCrashpadEnabled()
- ? CrashHandler::kCrashpad
- : CrashHandler::kBreakpad;
- base::UmaHistogramEnumeration(kCrashHandlerMetricName, handler);
-#endif
+ if (pre_dump_error_callback_) {
+ pre_dump_error_callback_.Run();
+ }
bool dump_with_crashing_result = base::debug::DumpWithoutCrashing();
- base::UmaHistogramBoolean(kDumpWithoutCrashingResultMetricName,
- dump_with_crashing_result);
+
+ if (post_dump_error_callback_) {
+ post_dump_error_callback_.Run(dump_with_crashing_result);
+ }
LOG(ERROR) << "Failed to create tracing SMB";
shared_memory_.reset();
@@ -493,4 +469,12 @@ void ProducerClient::NotifyDataSourceFlushComplete(
}
}
+void ProducerClient::SetBufferAllocationFailureCallbacks(
+ base::Closure pre_dump_error_callback,
+ base::Callback<void(bool dump_result)> post_dump_error_callback) {
+ base::AutoLock lock(lock_);
+ pre_dump_error_callback_ = std::move(pre_dump_error_callback);
+ post_dump_error_callback_ = std::move(post_dump_error_callback);
+}
+
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_client.h b/chromium/services/tracing/public/cpp/perfetto/producer_client.h
index d831ca81145..63a010f43ac 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.h
@@ -12,6 +12,7 @@
#include <vector>
#include "base/atomicops.h"
+#include "base/callback_forward.h"
#include "base/component_export.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -108,6 +109,13 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient
mojo::PendingRemote<mojom::ProducerHost>);
perfetto::SharedMemory* shared_memory_for_testing();
+ // Callbacks that are triggered if this class cannot allocate its shared
+ // buffer. For error reporting. The second callback is called after
+ // DumpWithoutCrashing is called, and includes the result of that call.
+ void SetBufferAllocationFailureCallbacks(
+ base::Closure pre_dump_error_callback,
+ base::Callback<void(bool dump_result)> post_dump_error_callback);
+
protected:
// Protected for testing. Returns false if SMB creation failed.
bool InitSharedMemoryIfNeeded();
@@ -142,6 +150,12 @@ class COMPONENT_EXPORT(TRACING_CPP) ProducerClient
std::unique_ptr<perfetto::SharedMemoryArbiter> shared_memory_arbiter_
GUARDED_BY(lock_);
+ // See ProducerClient::SetBufferAllocationFailureCallbacks for details of
+ // what these callbacks mean.
+ base::Closure pre_dump_error_callback_ GUARDED_BY(lock_);
+ base::Callback<void(bool dump_without_crashing_result)>
+ post_dump_error_callback_ GUARDED_BY(lock_);
+
// NOTE: Weak pointers must be invalidated before all other member variables.
base::WeakPtrFactory<ProducerClient> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(ProducerClient);
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
new file mode 100644
index 00000000000..7ec9798e28a
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
@@ -0,0 +1,161 @@
+// Copyright 2020 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 "services/tracing/public/cpp/perfetto/producer_test_utils.h"
+
+#include <deque>
+#include <functional>
+#include <utility>
+
+#include "base/debug/leak_annotations.h"
+#include "base/optional.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/ext/base/utils.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
+
+namespace tracing {
+
+namespace {
+
+// For sequences/threads other than our own, we just want to ignore
+// any events coming in.
+class DummyTraceWriter : public perfetto::TraceWriter {
+ public:
+ DummyTraceWriter()
+ : delegate_(perfetto::base::kPageSize), stream_(&delegate_) {}
+
+ perfetto::TraceWriter::TracePacketHandle NewTracePacket() override {
+ stream_.Reset(delegate_.GetNewBuffer());
+ trace_packet_.Reset(&stream_);
+
+ return perfetto::TraceWriter::TracePacketHandle(&trace_packet_);
+ }
+
+ void Flush(std::function<void()> callback = {}) override {}
+
+ perfetto::WriterID writer_id() const override {
+ return perfetto::WriterID(0);
+ }
+
+ uint64_t written() const override { return 0u; }
+
+ private:
+ perfetto::protos::pbzero::TracePacket trace_packet_;
+ protozero::ScatteredStreamWriterNullDelegate delegate_;
+ protozero::ScatteredStreamWriter stream_;
+};
+
+} // namespace
+
+TestProducerClient::TestProducerClient(
+ std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner,
+ bool log_only_main_thread)
+ : ProducerClient(main_thread_task_runner.get()),
+ delegate_(perfetto::base::kPageSize),
+ stream_(&delegate_),
+ main_thread_task_runner_(std::move(main_thread_task_runner)),
+ log_only_main_thread_(log_only_main_thread) {
+ trace_packet_.Reset(&stream_);
+}
+
+TestProducerClient::~TestProducerClient() = default;
+
+std::unique_ptr<perfetto::TraceWriter> TestProducerClient::CreateTraceWriter(
+ perfetto::BufferID target_buffer,
+ perfetto::BufferExhaustedPolicy) {
+ // We attempt to destroy TraceWriters on thread shutdown in
+ // ThreadLocalStorage::Slot, by posting them to the ProducerClient taskrunner,
+ // but there's no guarantee that this will succeed if that taskrunner is also
+ // shut down.
+ ANNOTATE_SCOPED_MEMORY_LEAK;
+ if (!log_only_main_thread_ ||
+ main_thread_task_runner_->GetOrCreateTaskRunner()
+ ->RunsTasksInCurrentSequence()) {
+ return std::make_unique<TestTraceWriter>(this);
+ } else {
+ return std::make_unique<DummyTraceWriter>();
+ }
+}
+
+void TestProducerClient::FlushPacketIfPossible() {
+ // GetNewBuffer() in ScatteredStreamWriterNullDelegate doesn't
+ // actually return a new buffer, but rather lets us access the buffer
+ // buffer already used by protozero to write the TracePacket into.
+ protozero::ContiguousMemoryRange buffer = delegate_.GetNewBuffer();
+
+ uint32_t message_size = trace_packet_.Finalize();
+ if (message_size) {
+ EXPECT_GE(buffer.size(), message_size);
+
+ auto proto = std::make_unique<perfetto::protos::TracePacket>();
+ EXPECT_TRUE(proto->ParseFromArray(buffer.begin, message_size));
+ if (proto->has_chrome_events() &&
+ proto->chrome_events().metadata().size() > 0) {
+ legacy_metadata_packets_.push_back(std::move(proto));
+ } else if (proto->has_chrome_metadata()) {
+ proto_metadata_packets_.push_back(std::move(proto));
+ } else {
+ finalized_packets_.push_back(std::move(proto));
+ }
+ }
+
+ stream_.Reset(buffer);
+ trace_packet_.Reset(&stream_);
+}
+
+perfetto::protos::pbzero::TracePacket* TestProducerClient::NewTracePacket() {
+ FlushPacketIfPossible();
+
+ return &trace_packet_;
+}
+
+size_t TestProducerClient::GetFinalizedPacketCount() {
+ FlushPacketIfPossible();
+ return finalized_packets_.size();
+}
+
+const perfetto::protos::TracePacket* TestProducerClient::GetFinalizedPacket(
+ size_t packet_index) {
+ FlushPacketIfPossible();
+ EXPECT_GT(finalized_packets_.size(), packet_index);
+ return finalized_packets_[packet_index].get();
+}
+
+const google::protobuf::RepeatedPtrField<perfetto::protos::ChromeMetadata>*
+TestProducerClient::GetChromeMetadata(size_t packet_index) {
+ FlushPacketIfPossible();
+ if (legacy_metadata_packets_.empty()) {
+ return nullptr;
+ }
+ EXPECT_GT(legacy_metadata_packets_.size(), packet_index);
+
+ const auto& event_bundle =
+ legacy_metadata_packets_[packet_index]->chrome_events();
+ return &event_bundle.metadata();
+}
+
+const perfetto::protos::ChromeMetadataPacket*
+TestProducerClient::GetProtoChromeMetadata(size_t packet_index) {
+ FlushPacketIfPossible();
+ EXPECT_GT(proto_metadata_packets_.size(), packet_index);
+ return &proto_metadata_packets_[packet_index]->chrome_metadata();
+}
+
+TestTraceWriter::TestTraceWriter(TestProducerClient* producer_client)
+ : producer_client_(producer_client) {}
+
+perfetto::TraceWriter::TracePacketHandle TestTraceWriter::NewTracePacket() {
+ return perfetto::TraceWriter::TracePacketHandle(
+ producer_client_->NewTracePacket());
+}
+
+perfetto::WriterID TestTraceWriter::writer_id() const {
+ return perfetto::WriterID(0);
+}
+
+uint64_t TestTraceWriter::written() const {
+ return 0u;
+}
+
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
new file mode 100644
index 00000000000..bbab71f84da
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
@@ -0,0 +1,94 @@
+// Copyright 2020 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 SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_TEST_UTILS_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_TEST_UTILS_H_
+
+#include <memory>
+#include <vector>
+
+#include "base/callback_forward.h"
+#include "base/optional.h"
+#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/perfetto/task_runner.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
+#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h"
+#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_trace_event.pb.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace tracing {
+
+// Test producer client for data source tests.
+class TestProducerClient : public ProducerClient {
+ public:
+ explicit TestProducerClient(
+ std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner,
+ bool log_only_main_thread = true);
+ ~TestProducerClient() override;
+
+ // ProducerClient implementation:
+ std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
+ perfetto::BufferID target_buffer,
+ perfetto::BufferExhaustedPolicy =
+ perfetto::BufferExhaustedPolicy::kDefault) override;
+
+ void FlushPacketIfPossible();
+
+ perfetto::protos::pbzero::TracePacket* NewTracePacket();
+
+ size_t GetFinalizedPacketCount();
+
+ const perfetto::protos::TracePacket* GetFinalizedPacket(
+ size_t packet_index = 0);
+
+ const google::protobuf::RepeatedPtrField<perfetto::protos::ChromeMetadata>*
+ GetChromeMetadata(size_t packet_index = 0);
+
+ const perfetto::protos::ChromeMetadataPacket* GetProtoChromeMetadata(
+ size_t packet_index = 0);
+
+ const std::vector<std::unique_ptr<perfetto::protos::TracePacket>>&
+ finalized_packets() const {
+ return finalized_packets_;
+ }
+
+ TestProducerClient(TestProducerClient&&) = delete;
+ TestProducerClient& operator=(TestProducerClient&&) = delete;
+
+ private:
+ std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
+ finalized_packets_;
+ std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
+ legacy_metadata_packets_;
+ std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
+ proto_metadata_packets_;
+ perfetto::protos::pbzero::TracePacket trace_packet_;
+ protozero::ScatteredStreamWriterNullDelegate delegate_;
+ protozero::ScatteredStreamWriter stream_;
+ std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner_;
+ bool log_only_main_thread_;
+};
+
+class TestTraceWriter : public perfetto::TraceWriter {
+ public:
+ using TracePacketCallback = base::RepeatingCallback<void(
+ std::unique_ptr<perfetto::protos::TracePacket>)>;
+ explicit TestTraceWriter(TestProducerClient* producer_client);
+
+ perfetto::TraceWriter::TracePacketHandle NewTracePacket() override;
+ void Flush(std::function<void()> callback = {}) override {}
+ perfetto::WriterID writer_id() const override;
+ uint64_t written() const override;
+
+ TestTraceWriter(TestTraceWriter&&) = delete;
+ TestTraceWriter& operator=(TestTraceWriter&&) = delete;
+
+ private:
+ TestProducerClient* producer_client_;
+};
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PRODUCER_TEST_UTILS_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h b/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
index cdc96cffe61..c2f421e4b61 100644
--- a/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/system_trace_writer.h
@@ -8,8 +8,8 @@
#include <list>
#include "base/bind.h"
+#include "base/check.h"
#include "base/component_export.h"
-#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ref_counted_memory.h"
#include "base/memory/weak_ptr.h"
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
index 6b7435c631e..88506ec5207 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc
@@ -39,10 +39,11 @@
#include "services/tracing/public/cpp/perfetto/macros.h"
#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
+#include "services/tracing/public/cpp/perfetto/system_producer.h"
#include "services/tracing/public/cpp/perfetto/trace_time.h"
#include "services/tracing/public/cpp/perfetto/traced_value_proto_writer.h"
#include "services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h"
-#include "services/tracing/public/cpp/trace_event_args_whitelist.h"
+#include "services/tracing/public/cpp/trace_event_args_allowlist.h"
#include "services/tracing/public/cpp/trace_startup.h"
#include "services/tracing/public/mojom/constants.mojom.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h"
@@ -176,11 +177,11 @@ TraceEventMetadataSource::GenerateTraceConfigMetadataDict() {
auto metadata_dict = std::make_unique<base::DictionaryValue>();
// If argument filtering is enabled, we need to check if the trace config is
- // whitelisted before emitting it.
+ // allowlisted before emitting it.
// TODO(eseckler): Figure out a way to solve this without calling directly
- // into IsMetadataWhitelisted().
+ // into IsMetadataAllowlisted().
if (!parsed_chrome_config_->IsArgumentFilterEnabled() ||
- IsMetadataWhitelisted("trace-config")) {
+ IsMetadataAllowlisted("trace-config")) {
metadata_dict->SetString("trace-config", chrome_config_);
} else {
metadata_dict->SetString("trace-config", "__stripped__");
@@ -458,11 +459,13 @@ TraceEventDataSource::~TraceEventDataSource() = default;
void TraceEventDataSource::RegisterStartupHooks() {
RegisterTracedValueProtoWriter();
+ base::trace_event::EnableTypedTraceEvents(
+ &TraceEventDataSource::OnAddTypedTraceEvent);
}
void TraceEventDataSource::RegisterWithTraceLog() {
TraceLog::GetInstance()->SetAddTraceEventOverrides(
- &TraceEventDataSource::OnAddTraceEvent,
+ &TraceEventDataSource::OnAddLegacyTraceEvent,
&TraceEventDataSource::FlushCurrentThread,
&TraceEventDataSource::OnUpdateDuration);
base::AutoLock l(lock_);
@@ -498,8 +501,7 @@ void TraceEventDataSource::OnStopTracingDone() {
}
// static
-TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink(
- bool thread_will_flush) {
+TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink() {
// Avoid re-entrancy, which can happen during PostTasks (the taskqueue can
// emit trace events). We discard the events in this case, as any PostTasking
// to deal with these events later would break the event ordering that the
@@ -536,8 +538,7 @@ TrackEventThreadLocalEventSink* TraceEventDataSource::GetOrPrepareEventSink(
}
if (!thread_local_event_sink) {
- thread_local_event_sink =
- GetInstance()->CreateThreadLocalEventSink(thread_will_flush);
+ thread_local_event_sink = GetInstance()->CreateThreadLocalEventSink();
ThreadLocalEventSinkSlot()->Set(thread_local_event_sink);
}
@@ -869,7 +870,7 @@ void TraceEventDataSource::LogHistogram(base::HistogramBase* histogram) {
base::Base64Encode(
std::string(static_cast<const char*>(pickle.data()), pickle.size()),
&buckets);
- TRACE_EVENT_INSTANT2("benchmark", "UMAHistogramSamples",
+ TRACE_EVENT_INSTANT2("benchmark,uma", "UMAHistogramSamples",
TRACE_EVENT_SCOPE_PROCESS, "name",
histogram->histogram_name(), "buckets", buckets);
}
@@ -929,7 +930,7 @@ TraceEventDataSource::CreateTraceWriterLocked() {
}
TrackEventThreadLocalEventSink*
-TraceEventDataSource::CreateThreadLocalEventSink(bool thread_will_flush) {
+TraceEventDataSource::CreateThreadLocalEventSink() {
AutoLockWithDeferredTaskPosting lock(lock_);
uint32_t session_id =
session_flags_.load(std::memory_order_relaxed).session_id;
@@ -945,12 +946,27 @@ TraceEventDataSource::CreateThreadLocalEventSink(bool thread_will_flush) {
}
// static
-void TraceEventDataSource::OnAddTraceEvent(
+void TraceEventDataSource::OnAddLegacyTraceEvent(
TraceEvent* trace_event,
bool thread_will_flush,
base::trace_event::TraceEventHandle* handle) {
- OnAddTraceEvent(trace_event, thread_will_flush, handle, perfetto::Track(),
- [](perfetto::EventContext) {});
+ auto* thread_local_event_sink = GetOrPrepareEventSink();
+ if (thread_local_event_sink) {
+ AutoThreadLocalBoolean thread_is_in_trace_event(
+ GetThreadIsInTraceEventTLS());
+ thread_local_event_sink->AddLegacyTraceEvent(trace_event, handle);
+ }
+}
+
+// static
+base::trace_event::TrackEventHandle TraceEventDataSource::OnAddTypedTraceEvent(
+ base::trace_event::TraceEvent* trace_event) {
+ auto* thread_local_event_sink = GetOrPrepareEventSink();
+ if (thread_local_event_sink) {
+ // GetThreadIsInTraceEventTLS() is handled by the sink for typed events.
+ return thread_local_event_sink->AddTypedTraceEvent(trace_event);
+ }
+ return base::trace_event::TrackEventHandle();
}
// static
@@ -1109,6 +1125,23 @@ void TraceEventDataSource::EmitTrackDescriptor() {
chrome_process->set_process_type(process_type);
}
+#if defined(OS_ANDROID)
+ // Host app package name is only recorded if privacy filtering is disabled or
+ // this is a system trace.
+ if (!privacy_filtering_enabled_ ||
+ producer_ == PerfettoTracedProcess::Get()->system_producer()) {
+ // Host app package name is used to group information from different
+ // processes that "belong" to the same WebView app.
+ // TODO(b/161983088): only write this for WebView since this information is
+ // not useful in other cases.
+ if (process_type == ChromeProcessDescriptor::PROCESS_RENDERER ||
+ process_type == ChromeProcessDescriptor::PROCESS_BROWSER) {
+ chrome_process->set_host_app_package_name(
+ base::android::BuildInfo::GetInstance()->host_package_name());
+ }
+ }
+#endif // defined(OS_ANDROID)
+
// TODO(eseckler): Set other fields on |chrome_process|.
trace_packet = TracePacketHandle();
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h
index ce909395611..ad6943fb834 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h
@@ -20,6 +20,7 @@
#include "base/time/time.h"
#include "base/timer/timer.h"
#include "base/trace_event/trace_config.h"
+#include "base/trace_event/typed_macros.h"
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h"
#include "third_party/perfetto/protos/perfetto/trace/chrome/chrome_metadata.pbzero.h"
@@ -35,7 +36,6 @@ struct TraceEventHandle;
namespace perfetto {
class TraceWriter;
-class EventContext;
}
namespace tracing {
@@ -180,24 +180,6 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource
bool IsEnabled();
- static TrackEventThreadLocalEventSink* GetOrPrepareEventSink(
- bool thread_will_flush);
-
- template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
- static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event,
- bool thread_will_flush,
- base::trace_event::TraceEventHandle* handle,
- const perfetto::Track& track,
- TrackEventArgumentFunction func) {
- auto* thread_local_event_sink = GetOrPrepareEventSink(thread_will_flush);
- if (thread_local_event_sink) {
- AutoThreadLocalBoolean thread_is_in_trace_event(
- GetThreadIsInTraceEventTLS());
- thread_local_event_sink->AddTraceEvent(trace_event, handle, track, func);
- }
- }
-
// Registered with base::StatisticsRecorder to receive a callback on every
// histogram sample which gets added.
static void OnMetricsSampleCallback(const char* histogram_name,
@@ -226,13 +208,17 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource
void OnStopTracingDone();
std::unique_ptr<perfetto::TraceWriter> CreateTraceWriterLocked();
- TrackEventThreadLocalEventSink* CreateThreadLocalEventSink(
- bool thread_will_flush);
+ TrackEventThreadLocalEventSink* CreateThreadLocalEventSink();
+
+ static TrackEventThreadLocalEventSink* GetOrPrepareEventSink();
- // Callback from TraceLog, can be called from any thread.
- static void OnAddTraceEvent(base::trace_event::TraceEvent* trace_event,
- bool thread_will_flush,
- base::trace_event::TraceEventHandle* handle);
+ // Callback from TraceLog / typed macros, can be called from any thread.
+ static void OnAddLegacyTraceEvent(
+ base::trace_event::TraceEvent* trace_event,
+ bool thread_will_flush,
+ base::trace_event::TraceEventHandle* handle);
+ static base::trace_event::TrackEventHandle OnAddTypedTraceEvent(
+ base::trace_event::TraceEvent* trace_event);
static void OnUpdateDuration(
const unsigned char* category_group_enabled,
const char* name,
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
index 17067c8761d..83af5e52128 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_event_data_source_unittest.cc
@@ -6,13 +6,13 @@
#include <map>
#include <memory>
+#include <set>
#include <utility>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
-#include "base/debug/leak_annotations.h"
#include "base/json/json_reader.h"
#include "base/metrics/histogram_macros.h"
#include "base/metrics/metrics_hashes.h"
@@ -31,14 +31,10 @@
#include "base/trace_event/trace_log.h"
#include "components/tracing/common/tracing_switches.h"
#include "services/tracing/public/cpp/perfetto/macros.h"
-#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/perfetto/producer_test_utils.h"
#include "services/tracing/public/cpp/perfetto/trace_time.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/perfetto/include/perfetto/ext/base/utils.h"
-#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
-#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h"
-#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
#include "third_party/perfetto/protos/perfetto/trace/clock_snapshot.pb.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
@@ -64,173 +60,10 @@ constexpr const char kCategoryGroup[] = "foo";
constexpr uint32_t kClockIdAbsolute = 64;
constexpr uint32_t kClockIdIncremental = 65;
-class MockProducerClient : public ProducerClient {
- public:
- explicit MockProducerClient(
- std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner)
- : ProducerClient(main_thread_task_runner.get()),
- delegate_(perfetto::base::kPageSize),
- stream_(&delegate_),
- main_thread_task_runner_(std::move(main_thread_task_runner)) {
- trace_packet_.Reset(&stream_);
- }
-
- std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
- perfetto::BufferID target_buffer,
- perfetto::BufferExhaustedPolicy =
- perfetto::BufferExhaustedPolicy::kDefault) override;
-
- void FlushPacketIfPossible() {
- // GetNewBuffer() in ScatteredStreamWriterNullDelegate doesn't
- // actually return a new buffer, but rather lets us access the buffer
- // buffer already used by protozero to write the TracePacket into.
- protozero::ContiguousMemoryRange buffer = delegate_.GetNewBuffer();
-
- uint32_t message_size = trace_packet_.Finalize();
- if (message_size) {
- EXPECT_GE(buffer.size(), message_size);
-
- auto proto = std::make_unique<perfetto::protos::TracePacket>();
- EXPECT_TRUE(proto->ParseFromArray(buffer.begin, message_size));
- if (proto->has_chrome_events() &&
- proto->chrome_events().metadata().size() > 0) {
- legacy_metadata_packets_.push_back(std::move(proto));
- } else if (proto->has_chrome_metadata()) {
- proto_metadata_packets_.push_back(std::move(proto));
- } else {
- finalized_packets_.push_back(std::move(proto));
- }
- }
-
- stream_.Reset(buffer);
- trace_packet_.Reset(&stream_);
- }
-
- perfetto::protos::pbzero::TracePacket* NewTracePacket() {
- FlushPacketIfPossible();
-
- return &trace_packet_;
- }
-
- size_t GetFinalizedPacketCount() {
- FlushPacketIfPossible();
- return finalized_packets_.size();
- }
-
- const perfetto::protos::TracePacket* GetFinalizedPacket(
- size_t packet_index = 0) {
- FlushPacketIfPossible();
- EXPECT_GT(finalized_packets_.size(), packet_index);
- return finalized_packets_[packet_index].get();
- }
-
- const google::protobuf::RepeatedPtrField<perfetto::protos::ChromeMetadata>
- GetChromeMetadata(size_t packet_index = 0) {
- FlushPacketIfPossible();
- if (legacy_metadata_packets_.empty()) {
- return google::protobuf::RepeatedPtrField<
- perfetto::protos::ChromeMetadata>();
- }
- EXPECT_GT(legacy_metadata_packets_.size(), packet_index);
-
- auto event_bundle = legacy_metadata_packets_[packet_index]->chrome_events();
- return event_bundle.metadata();
- }
-
- const perfetto::protos::ChromeMetadataPacket* GetProtoChromeMetadata(
- size_t packet_index = 0) {
- FlushPacketIfPossible();
- EXPECT_GT(proto_metadata_packets_.size(), packet_index);
- return &proto_metadata_packets_[packet_index]->chrome_metadata();
- }
-
- const std::vector<std::unique_ptr<perfetto::protos::TracePacket>>&
- finalized_packets() {
- return finalized_packets_;
- }
-
- private:
- std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
- finalized_packets_;
- std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
- legacy_metadata_packets_;
- std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
- proto_metadata_packets_;
- perfetto::protos::pbzero::TracePacket trace_packet_;
- protozero::ScatteredStreamWriterNullDelegate delegate_;
- protozero::ScatteredStreamWriter stream_;
- std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner_;
-};
-
-// For sequences/threads other than our own, we just want to ignore
-// any events coming in.
-class DummyTraceWriter : public perfetto::TraceWriter {
- public:
- DummyTraceWriter()
- : delegate_(perfetto::base::kPageSize), stream_(&delegate_) {}
-
- perfetto::TraceWriter::TracePacketHandle NewTracePacket() override {
- stream_.Reset(delegate_.GetNewBuffer());
- trace_packet_.Reset(&stream_);
-
- return perfetto::TraceWriter::TracePacketHandle(&trace_packet_);
- }
-
- void Flush(std::function<void()> callback = {}) override {}
-
- perfetto::WriterID writer_id() const override {
- return perfetto::WriterID(0);
- }
-
- uint64_t written() const override { return 0u; }
-
- private:
- perfetto::protos::pbzero::TracePacket trace_packet_;
- protozero::ScatteredStreamWriterNullDelegate delegate_;
- protozero::ScatteredStreamWriter stream_;
-};
-
-class MockTraceWriter : public perfetto::TraceWriter {
- public:
- explicit MockTraceWriter(MockProducerClient* producer_client)
- : producer_client_(producer_client) {}
-
- perfetto::TraceWriter::TracePacketHandle NewTracePacket() override {
- return perfetto::TraceWriter::TracePacketHandle(
- producer_client_->NewTracePacket());
- }
-
- void Flush(std::function<void()> callback = {}) override {}
-
- perfetto::WriterID writer_id() const override {
- return perfetto::WriterID(0);
- }
-
- uint64_t written() const override { return 0u; }
-
- private:
- MockProducerClient* producer_client_;
-};
-
-std::unique_ptr<perfetto::TraceWriter> MockProducerClient::CreateTraceWriter(
- perfetto::BufferID target_buffer,
- perfetto::BufferExhaustedPolicy) {
- // We attempt to destroy TraceWriters on thread shutdown in
- // ThreadLocalStorage::Slot, by posting them to the ProducerClient taskrunner,
- // but there's no guarantee that this will succeed if that taskrunner is also
- // shut down.
- ANNOTATE_SCOPED_MEMORY_LEAK;
- if (main_thread_task_runner_->GetOrCreateTaskRunner()
- ->RunsTasksInCurrentSequence()) {
- return std::make_unique<MockTraceWriter>(this);
- } else {
- return std::make_unique<DummyTraceWriter>();
- }
-}
-
class TraceEventDataSourceTest : public testing::Test {
public:
void SetUp() override {
+ TraceEventDataSource::GetInstance()->RegisterStartupHooks();
// TODO(eseckler): Initialize the entire perfetto client library instead.
perfetto::internal::TrackRegistry::InitializeInstance();
@@ -247,7 +80,7 @@ class TraceEventDataSourceTest : public testing::Test {
auto perfetto_wrapper = std::make_unique<PerfettoTaskRunner>(
task_environment_.GetMainThreadTaskRunner());
producer_client_ =
- std::make_unique<MockProducerClient>(std::move(perfetto_wrapper));
+ std::make_unique<TestProducerClient>(std::move(perfetto_wrapper));
TraceEventMetadataSource::GetInstance()->ResetForTesting();
}
@@ -264,7 +97,7 @@ class TraceEventDataSourceTest : public testing::Test {
wait_for_tracelog_flush.Run();
}
- // As MockTraceWriter keeps a pointer to our MockProducerClient,
+ // As MockTraceWriter keeps a pointer to our TestProducerClient,
// we need to make sure to clean it up from TLS. The other sequences
// get DummyTraceWriters that we don't care about.
TraceEventDataSource::GetInstance()->FlushCurrentThread();
@@ -295,7 +128,7 @@ class TraceEventDataSourceTest : public testing::Test {
}
}
- MockProducerClient* producer_client() { return producer_client_.get(); }
+ TestProducerClient* producer_client() { return producer_client_.get(); }
void ExpectClockSnapshotAndDefaults(
const perfetto::protos::TracePacket* packet,
@@ -305,8 +138,7 @@ class TraceEventDataSourceTest : public testing::Test {
ASSERT_EQ(packet->clock_snapshot().clocks().size(), 3);
EXPECT_EQ(packet->clock_snapshot().clocks()[0].clock_id(),
- static_cast<uint32_t>(
- perfetto::protos::pbzero::ClockSnapshot::Clock::BOOTTIME));
+ static_cast<uint32_t>(kTraceClockId));
EXPECT_FALSE(packet->clock_snapshot().clocks()[0].has_unit_multiplier_ns());
EXPECT_FALSE(packet->clock_snapshot().clocks()[0].has_is_incremental());
@@ -540,9 +372,10 @@ class TraceEventDataSourceTest : public testing::Test {
} else {
EXPECT_EQ(packet->track_event().extra_counter_track_uuids_size(), 0);
if (packet->track_event().extra_counter_values_size()) {
- // If the event is for a different thread, then we shouldn't have thread
- // timestamps except for the explicit thread timestamps above.
+ // If the event is for a different thread or track, we shouldn't have
+ // thread timestamps except for the explicit thread timestamps above.
EXPECT_TRUE(tid_override == 0);
+ EXPECT_EQ(track.uuid, 0u);
int64_t thread_time_delta =
packet->track_event().extra_counter_values()[0];
EXPECT_LE(last_thread_time_ + thread_time_delta,
@@ -735,7 +568,7 @@ class TraceEventDataSourceTest : public testing::Test {
// Should be the first member.
base::test::TaskEnvironment task_environment_;
- std::unique_ptr<MockProducerClient> producer_client_;
+ std::unique_ptr<TestProducerClient> producer_client_;
uint64_t last_timestamp_ = 0;
int64_t last_thread_time_ = 0;
uint64_t default_track_uuid_ = 0u;
@@ -813,7 +646,7 @@ TEST_F(TraceEventDataSourceTest, MetadataGeneratorBeforeTracing) {
metadata_source->StopTracing(wait_for_stop.QuitClosure());
wait_for_stop.Run();
- auto metadata = producer_client()->GetChromeMetadata();
+ auto& metadata = *producer_client()->GetChromeMetadata();
EXPECT_EQ(4, metadata.size());
MetadataHasNamedValue(metadata, "foo_int", 42);
MetadataHasNamedValue(metadata, "foo_str", "bar");
@@ -836,7 +669,7 @@ TEST_F(TraceEventDataSourceTest, MetadataGeneratorWhileTracing) {
metadata_source->StopTracing(wait_for_stop.QuitClosure());
wait_for_stop.Run();
- auto metadata = producer_client()->GetChromeMetadata();
+ auto& metadata = *producer_client()->GetChromeMetadata();
EXPECT_EQ(4, metadata.size());
MetadataHasNamedValue(metadata, "foo_int", 42);
MetadataHasNamedValue(metadata, "foo_str", "bar");
@@ -864,7 +697,7 @@ TEST_F(TraceEventDataSourceTest, MultipleMetadataGenerators) {
metadata_source->StopTracing(wait_for_stop.QuitClosure());
wait_for_stop.Run();
- auto metadata = producer_client()->GetChromeMetadata();
+ auto& metadata = *producer_client()->GetChromeMetadata();
EXPECT_EQ(4, metadata.size());
MetadataHasNamedValue(metadata, "foo_int", 42);
MetadataHasNamedValue(metadata, "foo_str", "bar");
@@ -874,9 +707,9 @@ TEST_F(TraceEventDataSourceTest, MultipleMetadataGenerators) {
child_dict->SetString("child_str", "child_val");
MetadataHasNamedValue(metadata, "child_dict", *child_dict);
- metadata = producer_client()->GetChromeMetadata(1);
- EXPECT_EQ(1, metadata.size());
- MetadataHasNamedValue(metadata, "before_int", 42);
+ auto& metadata1 = *producer_client()->GetChromeMetadata(1);
+ EXPECT_EQ(1, metadata1.size());
+ MetadataHasNamedValue(metadata1, "before_int", 42);
}
TEST_F(TraceEventDataSourceTest, BasicTraceEvent) {
@@ -1686,8 +1519,7 @@ TEST_F(TraceEventDataSourceTest, FilteringMetadataSource) {
metadata_source->StopTracing(wait_for_stop.QuitClosure());
wait_for_stop.Run();
- auto metadata = producer_client()->GetChromeMetadata();
- EXPECT_EQ(0, metadata.size());
+ EXPECT_FALSE(producer_client()->GetChromeMetadata());
}
TEST_F(TraceEventDataSourceTest, ProtoMetadataSource) {
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_time.h b/chromium/services/tracing/public/cpp/perfetto/trace_time.h
index 4a13d74a316..34a60632258 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_time.h
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_time.h
@@ -6,21 +6,21 @@
#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_TIME_H_
#include "build/build_config.h"
-#include "third_party/perfetto/protos/perfetto/trace/clock_snapshot.pbzero.h"
+#include "third_party/perfetto/protos/perfetto/common/builtin_clock.pbzero.h"
namespace tracing {
#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
// Linux, Android, and Fuchsia all use CLOCK_MONOTONIC. See crbug.com/166153
// about efforts to unify base::TimeTicks across all platforms.
-constexpr perfetto::protos::pbzero::ClockSnapshot::Clock::BuiltinClocks
- kTraceClockId = perfetto::protos::pbzero::ClockSnapshot::Clock::MONOTONIC;
+constexpr perfetto::protos::pbzero::BuiltinClock kTraceClockId =
+ perfetto::protos::pbzero::BUILTIN_CLOCK_MONOTONIC;
#else
// Mac and Windows TimeTicks advance when sleeping, so are closest to BOOTTIME
// in behavior.
-// TODO(eseckler): Support specifying Mac/Win platform clocks in BuiltinClocks.
-constexpr perfetto::protos::pbzero::ClockSnapshot::Clock::BuiltinClocks
- kTraceClockId = perfetto::protos::pbzero::ClockSnapshot::Clock::BOOTTIME;
+// TODO(eseckler): Support specifying Mac/Win platform clocks in BuiltinClock.
+constexpr perfetto::protos::pbzero::BuiltinClock kTraceClockId =
+ perfetto::protos::pbzero::BUILTIN_CLOCK_BOOTTIME;
#endif
// Returns CLOCK_BOOTTIME on systems that support it, otherwise falls back to
diff --git a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
index 90d1696545a..28a678073fb 100644
--- a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.cc
@@ -233,6 +233,61 @@ void TrackEventThreadLocalEventSink::ClearIncrementalState() {
incremental_state_reset_id_.fetch_add(1u, std::memory_order_relaxed);
}
+void TrackEventThreadLocalEventSink::AddLegacyTraceEvent(
+ base::trace_event::TraceEvent* trace_event,
+ base::trace_event::TraceEventHandle* handle) {
+ DCHECK(!pending_trace_packet_);
+ UpdateIncrementalStateIfNeeded(trace_event);
+
+ auto trace_packet = trace_writer_->NewTracePacket();
+ PrepareTrackEvent(trace_event, handle, &trace_packet);
+
+ if (!pending_interning_updates_.empty()) {
+ EmitStoredInternedData(trace_packet->set_interned_data());
+ }
+}
+
+base::trace_event::TrackEventHandle
+TrackEventThreadLocalEventSink::AddTypedTraceEvent(
+ base::trace_event::TraceEvent* trace_event) {
+ DCHECK(!TraceEventDataSource::GetInstance()
+ ->GetThreadIsInTraceEventTLS()
+ ->Get());
+ // Cleared in OnTrackEventCompleted().
+ TraceEventDataSource::GetInstance()->GetThreadIsInTraceEventTLS()->Set(true);
+
+ DCHECK(!pending_trace_packet_);
+ UpdateIncrementalStateIfNeeded(trace_event);
+
+ pending_trace_packet_ = trace_writer_->NewTracePacket();
+
+ // Note: Since |track_event| is a protozero message under |trace_packet|, we
+ // can't modify |trace_packet| further until we're done with |track_event|.
+ // Thus, incremental state is buffered until the TrackEventHandle we return
+ // here is destroyed.
+ base::trace_event::TraceEventHandle base_handle{0, 0, 0};
+ auto* track_event =
+ PrepareTrackEvent(trace_event, &base_handle, &pending_trace_packet_);
+
+ // |pending_trace_packet_| will be finalized in OnTrackEventCompleted() after
+ // the code in //base ran the typed trace point's argument function.
+ return base::trace_event::TrackEventHandle(track_event, this);
+}
+
+void TrackEventThreadLocalEventSink::OnTrackEventCompleted() {
+ DCHECK(pending_trace_packet_);
+
+ if (!pending_interning_updates_.empty()) {
+ EmitStoredInternedData(pending_trace_packet_->set_interned_data());
+ }
+
+ pending_trace_packet_ = perfetto::TraceWriter::TracePacketHandle();
+
+ DCHECK(
+ TraceEventDataSource::GetInstance()->GetThreadIsInTraceEventTLS()->Get());
+ TraceEventDataSource::GetInstance()->GetThreadIsInTraceEventTLS()->Set(false);
+}
+
void TrackEventThreadLocalEventSink::UpdateIncrementalStateIfNeeded(
base::trace_event::TraceEvent* trace_event) {
bool explicit_timestamp =
@@ -785,9 +840,7 @@ void TrackEventThreadLocalEventSink::UpdateDuration(
trace_event_internal::kNoId /* bind_id */, nullptr,
explicit_timestamps ? TRACE_EVENT_FLAG_EXPLICIT_TIMESTAMP
: TRACE_EVENT_FLAG_NONE);
- perfetto::Track track{};
- AddTraceEvent(&new_trace_event, nullptr, track,
- [](perfetto::EventContext) {});
+ AddLegacyTraceEvent(&new_trace_event, nullptr);
}
void TrackEventThreadLocalEventSink::Flush() {
@@ -915,20 +968,10 @@ void TrackEventThreadLocalEventSink::DoResetIncrementalState(
}
ClockSnapshot* clocks = packet->set_clock_snapshot();
- // Always reference the boottime timestamps to help trace processor
- // translate the clocks to boottime more efficiently.
+ // Reference clock is in nanoseconds.
ClockSnapshot::Clock* clock_reference = clocks->add_clocks();
- clock_reference->set_clock_id(ClockSnapshot::Clock::BOOTTIME);
- if (kTraceClockId == ClockSnapshot::Clock::BOOTTIME) {
- clock_reference->set_timestamp(timestamp.since_origin().InNanoseconds());
- } else {
- int64_t current_boot_nanos = TraceBootTicksNow();
- int64_t current_monotonic_nanos =
- TRACE_TIME_TICKS_NOW().since_origin().InNanoseconds();
- int64_t diff = current_boot_nanos - current_monotonic_nanos;
- clock_reference->set_timestamp(timestamp.since_origin().InNanoseconds() +
- diff);
- }
+ clock_reference->set_clock_id(kTraceClockId);
+ clock_reference->set_timestamp(timestamp.since_origin().InNanoseconds());
// Absolute clock in micros.
ClockSnapshot::Clock* clock_absolute = clocks->add_clocks();
clock_absolute->set_clock_id(kClockIdAbsolute);
diff --git a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
index a3ff3bbb897..0b3095b72e8 100644
--- a/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
+++ b/chromium/services/tracing/public/cpp/perfetto/track_event_thread_local_event_sink.h
@@ -16,6 +16,8 @@
#include "base/threading/thread_id_name_manager.h"
#include "base/time/time.h"
#include "base/trace_event/thread_instruction_count.h"
+#include "base/trace_event/typed_macros.h"
+#include "base/trace_event/typed_macros_embedder_support.h"
#include "services/tracing/public/cpp/perfetto/interning_index.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
#include "third_party/perfetto/include/perfetto/protozero/message_handle.h"
@@ -29,7 +31,8 @@ namespace tracing {
// ThreadLocalEventSink that emits TrackEvent protos.
class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
- : public base::ThreadIdNameManager::Observer {
+ : public base::ThreadIdNameManager::Observer,
+ public base::trace_event::TrackEventHandle::CompletionListener {
public:
enum class IndexType {
kName = 0,
@@ -67,51 +70,11 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
// (e.g. interning index entries and a ThreadDescriptor) to be emitted again.
static void ClearIncrementalState();
- // Emit any necessary descriptors that we haven't emitted yet and, if
- // required, perform an incremental state reset.
- void UpdateIncrementalStateIfNeeded(
- base::trace_event::TraceEvent* trace_event);
-
- // Fills in all the fields in |trace_packet| that can be directly deduced from
- // |trace_event|. Also fills all updates needed to be emitted into the
- // |InternedData| field into |pending_interning_updates_|. Returns a pointer
- // to the prepared TrackEvent proto, on which the caller may set further
- // fields.
- perfetto::protos::pbzero::TrackEvent* PrepareTrackEvent(
- base::trace_event::TraceEvent* trace_event,
- base::trace_event::TraceEventHandle* handle,
- protozero::MessageHandle<perfetto::protos::pbzero::TracePacket>*
- trace_packet);
-
- // Given a list of updates to the indexes will fill in |interned_data| to
- // reflect them.
- void EmitStoredInternedData(
- perfetto::protos::pbzero::InternedData* interned_data);
-
- template <
- typename TrackEventArgumentFunction = void (*)(perfetto::EventContext)>
- void AddTraceEvent(base::trace_event::TraceEvent* trace_event,
- base::trace_event::TraceEventHandle* handle,
- const perfetto::Track& track,
- TrackEventArgumentFunction arg_func) {
- UpdateIncrementalStateIfNeeded(trace_event);
-
- auto trace_packet = trace_writer_->NewTracePacket();
-
- // Note: Since |track_event| is a protozero message under |trace_packet|, we
- // can't modify |trace_packet| further until we're done with |track_event|.
- auto* track_event = PrepareTrackEvent(trace_event, handle, &trace_packet);
-
- if (track) {
- track_event->set_track_uuid(track.uuid);
- }
-
- arg_func(perfetto::EventContext(track_event));
+ void AddLegacyTraceEvent(base::trace_event::TraceEvent* trace_event,
+ base::trace_event::TraceEventHandle* handle);
- if (!pending_interning_updates_.empty()) {
- EmitStoredInternedData(trace_packet->set_interned_data());
- }
- }
+ base::trace_event::TrackEventHandle AddTypedTraceEvent(
+ base::trace_event::TraceEvent* trace_event);
void UpdateDuration(
const unsigned char* category_group_enabled,
@@ -129,9 +92,33 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
// ThreadIdNameManager::Observer implementation:
void OnThreadNameChanged(const char* name) override;
+ // base::trace_event::TrackEventHandle::CompletionListener implementation:
+ void OnTrackEventCompleted() override;
+
private:
static constexpr size_t kMaxCompleteEventDepth = 30;
+ // Emit any necessary descriptors that we haven't emitted yet and, if
+ // required, perform an incremental state reset.
+ void UpdateIncrementalStateIfNeeded(
+ base::trace_event::TraceEvent* trace_event);
+
+ // Fills in all the fields in |trace_packet| that can be directly deduced from
+ // |trace_event|. Also fills all updates needed to be emitted into the
+ // |InternedData| field into |pending_interning_updates_|. Returns a pointer
+ // to the prepared TrackEvent proto, on which the caller may set further
+ // fields.
+ perfetto::protos::pbzero::TrackEvent* PrepareTrackEvent(
+ base::trace_event::TraceEvent* trace_event,
+ base::trace_event::TraceEventHandle* handle,
+ protozero::MessageHandle<perfetto::protos::pbzero::TracePacket>*
+ trace_packet);
+
+ // Given a list of updates to the indexes will fill in |interned_data| to
+ // reflect them.
+ void EmitStoredInternedData(
+ perfetto::protos::pbzero::InternedData* interned_data);
+
void EmitThreadTrackDescriptor(base::trace_event::TraceEvent* trace_event,
base::TimeTicks timestamp,
const char* maybe_new_name = nullptr);
@@ -186,6 +173,11 @@ class COMPONENT_EXPORT(TRACING_CPP) TrackEventThreadLocalEventSink
uint32_t session_id_;
bool disable_interning_;
uint32_t sink_id_;
+
+ // Stores the trace packet handle for a typed TrackEvent until the TrackEvent
+ // was finalized after the code in //base filled its typed argument fields.
+ perfetto::TraceWriter::TracePacketHandle pending_trace_packet_;
+
DISALLOW_COPY_AND_ASSIGN(TrackEventThreadLocalEventSink);
};
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.cc b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.cc
new file mode 100644
index 00000000000..8d423d93a89
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.cc
@@ -0,0 +1,71 @@
+// Copyright 2020 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 "services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h"
+
+#include <utility>
+#include <vector>
+
+#include "base/android/reached_addresses_bitset.h"
+#include "base/android/reached_code_profiler.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
+#include "third_party/perfetto/include/perfetto/tracing/data_source.h"
+#include "third_party/perfetto/protos/perfetto/trace/profiling/profile_packet.pbzero.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
+
+namespace tracing {
+
+// static
+ReachedCodeDataSource* ReachedCodeDataSource::Get() {
+ static base::NoDestructor<ReachedCodeDataSource> instance;
+ return instance.get();
+}
+
+ReachedCodeDataSource::ReachedCodeDataSource()
+ : DataSourceBase(mojom::kReachedCodeProfilerSourceName) {}
+
+ReachedCodeDataSource::~ReachedCodeDataSource() {
+ NOTREACHED();
+}
+
+void ReachedCodeDataSource::StartTracing(
+ PerfettoProducer* producer,
+ const perfetto::DataSourceConfig& data_source_config) {
+ trace_writer_ =
+ producer->CreateTraceWriter(data_source_config.target_buffer());
+}
+
+void ReachedCodeDataSource::StopTracing(
+ base::OnceClosure stop_complete_callback) {
+ if (!base::android::IsReachedCodeProfilerEnabled()) {
+ std::move(stop_complete_callback).Run();
+ return;
+ }
+ auto* bitset = base::android::ReachedAddressesBitset::GetTextBitset();
+ // |bitset| is null when the build does not support code ordering.
+ if (!bitset) {
+ return;
+ }
+ std::vector<uint32_t> offsets = bitset->GetReachedOffsets();
+ perfetto::TraceWriter::TracePacketHandle trace_packet =
+ trace_writer_->NewTracePacket();
+ // Delta encoded timestamps and interned data require incremental state.
+ auto* streaming_profile_packet = trace_packet->set_streaming_profile_packet();
+ for (uint32_t offset : offsets) {
+ // TODO(ssid): add a new packed field to the trace packet proto.
+ streaming_profile_packet->add_callstack_iid(offset);
+ }
+ trace_packet->Finalize();
+ trace_writer_.reset();
+ std::move(stop_complete_callback).Run();
+}
+
+void ReachedCodeDataSource::Flush(
+ base::RepeatingClosure flush_complete_callback) {
+ flush_complete_callback.Run();
+}
+
+void ReachedCodeDataSource::ClearIncrementalState() {}
+
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h
new file mode 100644
index 00000000000..73c615d94c8
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h
@@ -0,0 +1,42 @@
+// Copyright 2020 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 SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_REACHED_CODE_DATA_SOURCE_ANDROID_H_
+#define SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_REACHED_CODE_DATA_SOURCE_ANDROID_H_
+
+#include <memory>
+
+#include "base/component_export.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
+
+namespace tracing {
+
+class COMPONENT_EXPORT(TRACING_CPP) ReachedCodeDataSource
+ : public PerfettoTracedProcess::DataSourceBase {
+ public:
+ static ReachedCodeDataSource* Get();
+
+ ReachedCodeDataSource();
+ ~ReachedCodeDataSource() override;
+
+ // PerfettoTracedProcess::DataSourceBase implementation, called by
+ // ProducerClient.
+ void StartTracing(
+ PerfettoProducer* producer,
+ const perfetto::DataSourceConfig& data_source_config) override;
+ void StopTracing(base::OnceClosure stop_complete_callback) override;
+ void Flush(base::RepeatingClosure flush_complete_callback) override;
+ void ClearIncrementalState() override;
+
+ ReachedCodeDataSource(ReachedCodeDataSource&&) = delete;
+ ReachedCodeDataSource& operator=(ReachedCodeDataSource&&) = delete;
+
+ private:
+ std::unique_ptr<perfetto::TraceWriter> trace_writer_;
+};
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PUBLIC_CPP_STACK_SAMPLING_REACHED_CODE_DATA_SOURCE_ANDROID_H_
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc
new file mode 100644
index 00000000000..5cf87745ba6
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc
@@ -0,0 +1,104 @@
+// Copyright 2020 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 "services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h"
+
+#include <stdlib.h>
+
+#include <limits>
+#include <memory>
+#include <utility>
+
+#include "base/android/reached_code_profiler.h"
+#include "base/base_switches.h"
+#include "base/bind_helpers.h"
+#include "base/run_loop.h"
+#include "base/test/task_environment.h"
+#include "base/time/time.h"
+#include "services/tracing/public/cpp/perfetto/producer_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/tracing/core/forward_decls.h"
+
+namespace tracing {
+
+namespace {
+
+double BusyLoopFor(base::TimeDelta duration) {
+ // Do some floating point arithmetic, since uninterruptible waits cannot be
+ // profiled.
+ base::TimeTicks end = base::TimeTicks::Now() + duration;
+ double number = 1;
+ while (base::TimeTicks::Now() < end) {
+ for (int i = 0; i < 10000; ++i) {
+ number *= rand() / static_cast<double>(RAND_MAX) * 2;
+ }
+ }
+ return number;
+}
+
+class ReachedCodeDataSourceTest : public testing::Test {
+ public:
+ void SetUp() override {
+ PerfettoTracedProcess::ResetTaskRunnerForTesting();
+ PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner();
+
+ auto perfetto_wrapper = std::make_unique<PerfettoTaskRunner>(
+ task_environment_.GetMainThreadTaskRunner());
+
+ producer_ =
+ std::make_unique<TestProducerClient>(std::move(perfetto_wrapper));
+ }
+
+ void TearDown() override {
+ // Be sure there is no pending/running tasks.
+ task_environment_.RunUntilIdle();
+ }
+
+ void BeginTrace() {
+ ReachedCodeDataSource::Get()->StartTracingWithID(
+ /*data_source_id=*/1, producer_.get(), perfetto::DataSourceConfig());
+ }
+
+ void EndTracing() {
+ base::RunLoop wait_for_end;
+ ReachedCodeDataSource::Get()->StopTracing(wait_for_end.QuitClosure());
+ wait_for_end.Run();
+ }
+
+ TestProducerClient* producer() const { return producer_.get(); }
+
+ private:
+ base::test::TaskEnvironment task_environment_;
+
+ std::unique_ptr<TestProducerClient> producer_;
+};
+
+} // namespace
+
+TEST_F(ReachedCodeDataSourceTest, ProfilerDisabled) {
+ BeginTrace();
+ base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
+ EndTracing();
+ EXPECT_EQ(producer()->GetFinalizedPacketCount(), 0u);
+}
+
+TEST_F(ReachedCodeDataSourceTest, ProfilerOutput) {
+ if (!base::android::IsReachedCodeProfilerSupported())
+ return;
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableReachedCodeProfiler);
+ base::android::InitReachedCodeProfilerAtStartup(
+ base::android::PROCESS_BROWSER);
+ ASSERT_TRUE(base::android::IsReachedCodeProfilerEnabled());
+ BeginTrace();
+ BusyLoopFor(base::TimeDelta::FromSeconds(2));
+ EndTracing();
+ EXPECT_EQ(producer()->GetFinalizedPacketCount(), 1u);
+ const auto* packet = producer()->GetFinalizedPacket();
+ EXPECT_TRUE(packet->has_streaming_profile_packet());
+ // TODO: the profiler doesn't work in test because of ordering.
+ EXPECT_GT(packet->streaming_profile_packet().callstack_iid_size(), 0);
+}
+
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
index fc86e4f5009..b99bda52188 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc
@@ -652,10 +652,6 @@ void TracingSamplerProfiler::StartTracing(
base::StackSamplingProfiler::SamplingParams params;
params.samples_per_profile = std::numeric_limits<int>::max();
params.sampling_interval = base::TimeDelta::FromMilliseconds(50);
- // If the sampled thread is stopped for too long for sampling then it is ok to
- // get next sample at a later point of time. We do not want very accurate
- // metrics when looking at traces.
- params.keep_consistent_sampling_interval = false;
auto profile_builder = std::make_unique<TracingProfileBuilder>(
sampled_thread_token_.id, std::move(trace_writer),
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
index 0be58031175..f619fa85099 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
+++ b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc
@@ -8,25 +8,18 @@
#include "base/at_exit.h"
#include "base/bind.h"
-#include "base/bind_helpers.h"
#include "base/json/json_reader.h"
-#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
-#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
-#include "base/time/time.h"
#include "base/trace_event/trace_buffer.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/buildflags.h"
-#include "services/tracing/public/cpp/perfetto/producer_client.h"
+#include "services/tracing/public/cpp/perfetto/producer_test_utils.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/perfetto/include/perfetto/ext/base/utils.h"
-#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_null_delegate.h"
#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
-#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pbzero.h"
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
#include "base/test/trace_event_analyzer.h"
@@ -40,111 +33,6 @@ using base::trace_event::TraceLog;
using ::testing::Invoke;
using ::testing::Return;
-class MockTraceWriter : public perfetto::TraceWriter {
- public:
- MockTraceWriter(
- const base::RepeatingCallback<void(
- std::unique_ptr<perfetto::protos::TracePacket>)>& on_packet_callback)
- : delegate_(perfetto::base::kPageSize),
- stream_(&delegate_),
- on_packet_callback_(std::move(on_packet_callback)) {
- trace_packet_.Reset(&stream_);
- }
-
- void FlushPacketIfPossible() {
- // GetNewBuffer() in ScatteredStreamWriterNullDelegate doesn't
- // actually return a new buffer, but rather lets us access the buffer
- // buffer already used by protozero to write the TracePacket into.
- protozero::ContiguousMemoryRange buffer = delegate_.GetNewBuffer();
-
- uint32_t message_size = trace_packet_.Finalize();
- if (message_size) {
- EXPECT_GE(buffer.size(), message_size);
-
- auto proto = std::make_unique<perfetto::protos::TracePacket>();
- EXPECT_TRUE(proto->ParseFromArray(buffer.begin, message_size));
- on_packet_callback_.Run(std::move(proto));
- }
-
- stream_.Reset(buffer);
- trace_packet_.Reset(&stream_);
- }
-
- perfetto::TraceWriter::TracePacketHandle NewTracePacket() override {
- FlushPacketIfPossible();
-
- return perfetto::TraceWriter::TracePacketHandle(&trace_packet_);
- }
-
- void Flush(std::function<void()> callback = {}) override {}
-
- perfetto::WriterID writer_id() const override {
- return perfetto::WriterID(0);
- }
-
- uint64_t written() const override { return 0u; }
-
- private:
- perfetto::protos::pbzero::TracePacket trace_packet_;
- protozero::ScatteredStreamWriterNullDelegate delegate_;
- protozero::ScatteredStreamWriter stream_;
-
- base::RepeatingCallback<void(std::unique_ptr<perfetto::protos::TracePacket>)>
- on_packet_callback_;
-
- DISALLOW_COPY_AND_ASSIGN(MockTraceWriter);
-};
-
-class MockPerfettoProducer : public ProducerClient {
- public:
- explicit MockPerfettoProducer(std::unique_ptr<PerfettoTaskRunner> task_runner)
- : ProducerClient(task_runner.get()),
- task_runner_(std::move(task_runner)) {}
-
- std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
- perfetto::BufferID target_buffer,
- perfetto::BufferExhaustedPolicy =
- perfetto::BufferExhaustedPolicy::kDefault) override {
- auto packet_callback = base::BindRepeating(
- [](base::WeakPtr<MockPerfettoProducer> weak_self,
- scoped_refptr<base::SequencedTaskRunner> task_runner,
- std::unique_ptr<perfetto::protos::TracePacket> packet) {
- task_runner->PostTask(
- FROM_HERE, base::BindOnce(&MockPerfettoProducer::ReceivePacket,
- weak_self, std::move(packet)));
- },
- weak_ptr_factory_.GetWeakPtr(), base::SequencedTaskRunnerHandle::Get());
-
- return std::make_unique<MockTraceWriter>(packet_callback);
- }
-
- void ReceivePacket(std::unique_ptr<perfetto::protos::TracePacket> packet) {
- base::AutoLock lock(lock_);
- finalized_packets_.push_back(std::move(packet));
- }
-
- const perfetto::protos::TracePacket* GetFinalizedPacket(
- size_t packet_index = 0) {
- base::AutoLock lock(lock_);
- EXPECT_GT(finalized_packets_.size(), packet_index);
- return finalized_packets_[packet_index].get();
- }
-
- const std::vector<std::unique_ptr<perfetto::protos::TracePacket>>&
- finalized_packets() const {
- return finalized_packets_;
- }
-
- private:
- base::Lock lock_; // protects finalized_packets_
- std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
- finalized_packets_;
-
- std::unique_ptr<PerfettoTaskRunner> task_runner_;
- base::WeakPtrFactory<MockPerfettoProducer> weak_ptr_factory_{this};
- DISALLOW_COPY_AND_ASSIGN(MockPerfettoProducer);
-};
-
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
class MockLoaderLockSampler : public TracingSamplerProfiler::LoaderLockSampler {
@@ -189,7 +77,8 @@ class TracingSampleProfilerTest : public testing::Test {
task_environment_.GetMainThreadTaskRunner());
producer_ =
- std::make_unique<MockPerfettoProducer>(std::move(perfetto_wrapper));
+ std::make_unique<TestProducerClient>(std::move(perfetto_wrapper),
+ /*log_only_main_thread=*/false);
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
ON_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
@@ -249,7 +138,7 @@ class TracingSampleProfilerTest : public testing::Test {
return profile_sequence_id;
}
- const MockPerfettoProducer* producer() const { return producer_.get(); }
+ const TestProducerClient* producer() const { return producer_.get(); }
protected:
base::test::TaskEnvironment task_environment_;
@@ -258,7 +147,7 @@ class TracingSampleProfilerTest : public testing::Test {
base::ShadowingAtExitManager at_exit_manager_;
base::trace_event::TraceResultBuffer trace_buffer_;
- std::unique_ptr<MockPerfettoProducer> producer_;
+ std::unique_ptr<TestProducerClient> producer_;
// Number of stack sampling events received.
size_t events_stack_received_count_ = 0;
@@ -501,50 +390,70 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockWithoutMock) {
#endif // BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
-TEST(TracingProfileBuilderTest, ValidModule) {
+class TracingProfileBuilderTest : public testing::Test {
+ public:
+ void SetUp() override {
+ auto perfetto_wrapper = std::make_unique<PerfettoTaskRunner>(
+ task_environment_.GetMainThreadTaskRunner());
+ producer_client_ = std::make_unique<TestProducerClient>(
+ std::move(perfetto_wrapper), /*log_only_main_thread=*/false);
+ }
+
+ void TearDown() override { producer_client_.reset(); }
+
+ TestProducerClient* producer() { return producer_client_.get(); }
+
+ private:
+ // Should be the first member.
+ base::test::TaskEnvironment task_environment_;
+
+ std::unique_ptr<TestProducerClient> producer_client_;
+};
+
+TEST_F(TracingProfileBuilderTest, ValidModule) {
TestModule module;
TracingSamplerProfiler::TracingProfileBuilder profile_builder(
- base::PlatformThreadId(),
- std::make_unique<MockTraceWriter>(base::DoNothing()), false);
+ base::PlatformThreadId(), std::make_unique<TestTraceWriter>(producer()),
+ false);
profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)},
base::TimeTicks());
}
-TEST(TracingProfileBuilderTest, InvalidModule) {
+TEST_F(TracingProfileBuilderTest, InvalidModule) {
TracingSamplerProfiler::TracingProfileBuilder profile_builder(
- base::PlatformThreadId(),
- std::make_unique<MockTraceWriter>(base::DoNothing()), false);
+ base::PlatformThreadId(), std::make_unique<TestTraceWriter>(producer()),
+ false);
profile_builder.OnSampleCompleted({base::Frame(0x1010, nullptr)},
base::TimeTicks());
}
#if defined(OS_ANDROID) || defined(OS_LINUX)
-TEST(TracingProfileBuilderTest, MangleELFModuleID) {
+TEST_F(TracingProfileBuilderTest, MangleELFModuleID) {
TestModule module;
// See explanation for the module_id mangling in
// TracingSamplerProfiler::TracingProfileBuilder::GetCallstackIDAndMaybeEmit.
module.set_id("7F0715C286F8B16C10E4AD349CDA3B9B56C7A773");
- bool found_build_id = false;
- auto on_packet_callback = base::BindLambdaForTesting(
- [&found_build_id](std::unique_ptr<perfetto::protos::TracePacket> packet) {
- if (!packet->has_interned_data() ||
- packet->interned_data().build_ids_size() == 0) {
- return;
- }
-
- found_build_id = true;
- EXPECT_EQ(packet->interned_data().build_ids(0).str(),
- "C215077FF8866CB110E4AD349CDA3B9B0");
- });
-
- auto trace_writer = std::make_unique<MockTraceWriter>(on_packet_callback);
- auto* raw_trace_writer = trace_writer.get();
TracingSamplerProfiler::TracingProfileBuilder profile_builder(
- base::PlatformThreadId(), std::move(trace_writer), false);
+ base::PlatformThreadId(), std::make_unique<TestTraceWriter>(producer()),
+ false);
profile_builder.OnSampleCompleted({base::Frame(0x1010, &module)},
base::TimeTicks());
- raw_trace_writer->FlushPacketIfPossible();
+ producer()->FlushPacketIfPossible();
+
+ bool found_build_id = false;
+ for (unsigned i = 0; i < producer()->GetFinalizedPacketCount(); ++i) {
+ const perfetto::protos::TracePacket* packet =
+ producer()->GetFinalizedPacket(i);
+ if (!packet->has_interned_data() ||
+ packet->interned_data().build_ids_size() == 0) {
+ return;
+ }
+
+ found_build_id = true;
+ EXPECT_EQ(packet->interned_data().build_ids(0).str(),
+ "C215077FF8866CB110E4AD349CDA3B9B0");
+ }
EXPECT_TRUE(found_build_id);
}
#endif
diff --git a/chromium/services/tracing/public/cpp/trace_event_agent.cc b/chromium/services/tracing/public/cpp/trace_event_agent.cc
index 6427c8b5ccd..bd7ed5c242d 100644
--- a/chromium/services/tracing/public/cpp/trace_event_agent.cc
+++ b/chromium/services/tracing/public/cpp/trace_event_agent.cc
@@ -21,9 +21,13 @@
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h"
-#include "services/tracing/public/cpp/trace_event_args_whitelist.h"
+#include "services/tracing/public/cpp/trace_event_args_allowlist.h"
#include "services/tracing/public/cpp/tracing_features.h"
+#if defined(OS_ANDROID)
+#include "services/tracing/public/cpp/stack_sampling/reached_code_data_source_android.h"
+#endif
+
namespace tracing {
// static
@@ -41,14 +45,17 @@ TraceEventAgent::TraceEventAgent() {
->GetArgumentFilterPredicate()
.is_null()) {
base::trace_event::TraceLog::GetInstance()->SetArgumentFilterPredicate(
- base::BindRepeating(&IsTraceEventArgsWhitelisted));
+ base::BindRepeating(&IsTraceEventArgsAllowlisted));
base::trace_event::TraceLog::GetInstance()->SetMetadataFilterPredicate(
- base::BindRepeating(&IsMetadataWhitelisted));
+ base::BindRepeating(&IsMetadataAllowlisted));
}
PerfettoTracedProcess::Get()->AddDataSource(
TraceEventDataSource::GetInstance());
TracingSamplerProfiler::RegisterDataSource();
+#if defined(OS_ANDROID)
+ PerfettoTracedProcess::Get()->AddDataSource(ReachedCodeDataSource::Get());
+#endif
}
TraceEventAgent::~TraceEventAgent() = default;
diff --git a/chromium/services/tracing/public/cpp/trace_event_args_whitelist.cc b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc
index 7e5af23624b..23be6e65ff1 100644
--- a/chromium/services/tracing/public/cpp/trace_event_args_whitelist.cc
+++ b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "services/tracing/public/cpp/trace_event_args_whitelist.h"
+#include "services/tracing/public/cpp/trace_event_args_allowlist.h"
#include "base/bind.h"
#include "base/strings/pattern.h"
@@ -13,14 +13,14 @@
namespace tracing {
namespace {
-// Each whitelist entry is used to whitelist an array arguments for a
+// Each allowlist entry is used to allowlist an array arguments for a
// single or group of trace events.
-struct WhitelistEntry {
+struct AllowlistEntry {
// Category name of the interested trace event.
const char* category_name;
// Pattern to match the interested trace event name.
const char* event_name;
- // List of patterns that match the whitelisted arguments.
+ // List of patterns that match the allowlisted arguments.
const char* const* arg_name_filter;
};
@@ -38,15 +38,17 @@ const char* const kMemoryDumpAllowedArgs[] = {
const char* const kRendererHostAllowedArgs[] = {
"class", "line", "should_background", "has_pending_views",
"bytes_allocated", nullptr};
+const char* const kUIAllowedArgs[] = {"dpi", "message_id", nullptr};
const char* const kV8GCAllowedArgs[] = {"num_items", "num_tasks", nullptr};
const char* const kTopLevelFlowAllowedArgs[] = {"task_queue_name", nullptr};
const char* const kTopLevelIpcRunTaskAllowedArgs[] = {"ipc_hash", nullptr};
const char* const kLifecyclesTaskPostedAllowedArgs[] = {
"task_queue_name", "time_since_disabled_ms", "ipc_hash", "location",
nullptr};
-const char* const kMemoryPressureEventsAllowedArgs[] = {"level", nullptr};
+const char* const kMemoryPressureEventsAllowedArgs[] = {
+ "level", "listener_creation_info", nullptr};
-const WhitelistEntry kEventArgsWhitelist[] = {
+const AllowlistEntry kEventArgsAllowlist[] = {
{"__metadata", "thread_name", nullptr},
{"__metadata", "process_name", nullptr},
{"__metadata", "process_uptime_seconds", nullptr},
@@ -54,6 +56,8 @@ const WhitelistEntry kEventArgsWhitelist[] = {
{"__metadata", "chrome_library_module", nullptr},
{"__metadata", "stackFrames", nullptr},
{"__metadata", "typeNames", nullptr},
+ {"base", "MemoryPressureListener::Notify",
+ kMemoryPressureEventsAllowedArgs},
{"base", "MessagePumpForUI::ProcessNextWindowsMessage PeekMessage",
kPeekMessageAllowedArgs},
{"base", "MultiSourceMemoryPressureMonitor::OnMemoryPressureLevelChanged",
@@ -65,7 +69,7 @@ const WhitelistEntry kEventArgsWhitelist[] = {
{"base", "ScopedBlockingCall*", kScopedBlockingCallAllowedArgs},
{"base", "ScopedMayLoadLibraryAtBackgroundPriority",
kScopedBlockingCallAllowedArgs},
- {"benchmark", "TestWhitelist*", nullptr},
+ {"benchmark", "TestAllowlist*", nullptr},
{"blink", "MemoryPressureListenerRegistry::onMemoryPressure",
kMemoryPressureEventsAllowedArgs},
{"browser", "KeyedServiceFactory::GetServiceForContext", nullptr},
@@ -92,17 +96,18 @@ const WhitelistEntry kEventArgsWhitelist[] = {
{TRACE_DISABLED_BY_DEFAULT("memory-infra"), "*", kMemoryDumpAllowedArgs},
{TRACE_DISABLED_BY_DEFAULT("system_stats"), "*", nullptr},
{TRACE_DISABLED_BY_DEFAULT("v8.gc"), "*", kV8GCAllowedArgs},
+ {"ui", "HWNDMessageHandler::OnWndProc", kUIAllowedArgs},
+ {"ui", "HWNDMessageHandler::OnDwmCompositionChanged", kUIAllowedArgs},
{"ui", "RenderTextHarfBuzz::FallbackFont", kFallbackFontAllowedArgs},
{"ui", "RenderTextHarfBuzz::GetFallbackFonts",
kGetFallbackFontsAllowedArgs},
{TRACE_DISABLED_BY_DEFAULT("user_action_samples"), "UserAction", nullptr},
- {TRACE_DISABLED_BY_DEFAULT("toplevel.flow"), "SequenceManager::PostTask",
- kTopLevelFlowAllowedArgs},
+ {"toplevel.flow", "SequenceManager::PostTask", kTopLevelFlowAllowedArgs},
{TRACE_DISABLED_BY_DEFAULT("lifecycles"), "task_posted_to_disabled_queue",
kLifecyclesTaskPostedAllowedArgs},
{nullptr, nullptr, nullptr}};
-const char* kMetadataWhitelist[] = {"chrome-bitness",
+const char* kMetadataAllowlist[] = {"chrome-bitness",
"chrome-library-name",
"clock-domain",
"config",
@@ -124,7 +129,7 @@ const char* kMetadataWhitelist[] = {"chrome-bitness",
} // namespace
-bool IsTraceArgumentNameWhitelisted(const char* const* granular_filter,
+bool IsTraceArgumentNameAllowlisted(const char* const* granular_filter,
const char* arg_name) {
for (int i = 0; granular_filter[i] != nullptr; ++i) {
if (base::MatchPattern(arg_name, granular_filter[i]))
@@ -134,7 +139,7 @@ bool IsTraceArgumentNameWhitelisted(const char* const* granular_filter,
return false;
}
-bool IsTraceEventArgsWhitelisted(
+bool IsTraceEventArgsAllowlisted(
const char* category_group_name,
const char* event_name,
base::trace_event::ArgumentNameFilterPredicate* arg_name_filter) {
@@ -144,16 +149,16 @@ bool IsTraceEventArgsWhitelisted(
",");
while (category_group_tokens.GetNext()) {
const std::string& category_group_token = category_group_tokens.token();
- for (int i = 0; kEventArgsWhitelist[i].category_name != nullptr; ++i) {
- const WhitelistEntry& whitelist_entry = kEventArgsWhitelist[i];
- DCHECK(whitelist_entry.event_name);
+ for (int i = 0; kEventArgsAllowlist[i].category_name != nullptr; ++i) {
+ const AllowlistEntry& allowlist_entry = kEventArgsAllowlist[i];
+ DCHECK(allowlist_entry.event_name);
if (base::MatchPattern(category_group_token,
- whitelist_entry.category_name) &&
- base::MatchPattern(event_name, whitelist_entry.event_name)) {
- if (whitelist_entry.arg_name_filter) {
+ allowlist_entry.category_name) &&
+ base::MatchPattern(event_name, allowlist_entry.event_name)) {
+ if (allowlist_entry.arg_name_filter) {
*arg_name_filter = base::BindRepeating(
- &IsTraceArgumentNameWhitelisted, whitelist_entry.arg_name_filter);
+ &IsTraceArgumentNameAllowlisted, allowlist_entry.arg_name_filter);
}
return true;
}
@@ -163,9 +168,9 @@ bool IsTraceEventArgsWhitelisted(
return false;
}
-bool IsMetadataWhitelisted(const std::string& metadata_name) {
- for (size_t i = 0; kMetadataWhitelist[i] != nullptr; ++i) {
- if (base::MatchPattern(metadata_name, kMetadataWhitelist[i])) {
+bool IsMetadataAllowlisted(const std::string& metadata_name) {
+ for (size_t i = 0; kMetadataAllowlist[i] != nullptr; ++i) {
+ if (base::MatchPattern(metadata_name, kMetadataAllowlist[i])) {
return true;
}
}
diff --git a/chromium/services/tracing/public/cpp/trace_event_args_whitelist.h b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.h
index e3a19458ba6..c1eb42f4888 100644
--- a/chromium/services/tracing/public/cpp/trace_event_args_whitelist.h
+++ b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_WHITELIST_H_
-#define SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_WHITELIST_H_
+#ifndef SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_ALLOWLIST_H_
+#define SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_ALLOWLIST_H_
#include <string>
@@ -15,18 +15,18 @@ namespace tracing {
// TODO(ssid): This is a temporary argument filter that will be removed once
// slow reports moves to using proto completely.
-// Used to filter trace event arguments against a whitelist of events that
+// Used to filter trace event arguments against a allowlist of events that
// have been manually vetted to not include any PII.
-bool COMPONENT_EXPORT(TRACING_CPP) IsTraceEventArgsWhitelisted(
+bool COMPONENT_EXPORT(TRACING_CPP) IsTraceEventArgsAllowlisted(
const char* category_group_name,
const char* event_name,
base::trace_event::ArgumentNameFilterPredicate* arg_name_filter);
-// Used to filter metadata against a whitelist of metadata names that have been
+// Used to filter metadata against a allowlist of metadata names that have been
// manually vetted to not include any PII.
bool COMPONENT_EXPORT(TRACING_CPP)
- IsMetadataWhitelisted(const std::string& metadata_name);
+ IsMetadataAllowlisted(const std::string& metadata_name);
} // namespace tracing
-#endif // SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_WHITELIST_H_
+#endif // SERVICES_TRACING_PUBLIC_CPP_TRACE_EVENT_ARGS_ALLOWLIST_H_
diff --git a/chromium/services/tracing/public/cpp/trace_startup.cc b/chromium/services/tracing/public/cpp/trace_startup.cc
index 106002df61f..188d127cd43 100644
--- a/chromium/services/tracing/public/cpp/trace_startup.cc
+++ b/chromium/services/tracing/public/cpp/trace_startup.cc
@@ -15,7 +15,7 @@
#include "services/tracing/public/cpp/perfetto/system_producer.h"
#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
#include "services/tracing/public/cpp/trace_event_agent.h"
-#include "services/tracing/public/cpp/trace_event_args_whitelist.h"
+#include "services/tracing/public/cpp/trace_event_args_allowlist.h"
#include "services/tracing/public/cpp/tracing_features.h"
#include "third_party/perfetto/include/perfetto/tracing/track.h"
diff --git a/chromium/services/tracing/public/mojom/perfetto_service.mojom b/chromium/services/tracing/public/mojom/perfetto_service.mojom
index 170d6f26c1e..7af80cb0a1a 100644
--- a/chromium/services/tracing/public/mojom/perfetto_service.mojom
+++ b/chromium/services/tracing/public/mojom/perfetto_service.mojom
@@ -17,6 +17,8 @@ const string kSystemTraceDataSourceName = "org.chromium.trace_system";
const string kArcTraceDataSourceName = "org.chromium.trace_arc";
const string kSamplerProfilerSourceName = "org.chromium.sampler_profiler";
const string kJavaHeapProfilerSourceName = "org.chromium.java_heap_profiler";
+const string kReachedCodeProfilerSourceName =
+ "org.chromium.reached_code_profiler";
// Brief description of the flow: There's a per-process ProducerClient which
// connects to the central PerfettoService and establishes a two-way connection
diff --git a/chromium/services/video_capture/broadcasting_receiver_unittest.cc b/chromium/services/video_capture/broadcasting_receiver_unittest.cc
index a0caa62530f..aa3e34eb7b0 100644
--- a/chromium/services/video_capture/broadcasting_receiver_unittest.cc
+++ b/chromium/services/video_capture/broadcasting_receiver_unittest.cc
@@ -96,8 +96,6 @@ TEST_F(
access_permission.InitWithNewPipeAndPassReceiver());
media::mojom::VideoFrameInfoPtr frame_info =
media::mojom::VideoFrameInfo::New();
- media::VideoFrameMetadata frame_metadata;
- frame_info->metadata = frame_metadata.GetInternalValues().Clone();
broadcaster_.OnFrameReadyInBuffer(kArbiraryBufferId, kArbiraryFrameFeedbackId,
std::move(access_permission),
std::move(frame_info));
@@ -160,8 +158,6 @@ TEST_F(BroadcastingReceiverTest,
access_permission.InitWithNewPipeAndPassReceiver());
media::mojom::VideoFrameInfoPtr frame_info =
media::mojom::VideoFrameInfo::New();
- media::VideoFrameMetadata frame_metadata;
- frame_info->metadata = frame_metadata.GetInternalValues().Clone();
broadcaster_.OnFrameReadyInBuffer(kArbiraryBufferId, kArbiraryFrameFeedbackId,
std::move(access_permission),
std::move(frame_info));
diff --git a/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom b/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
index 6f0ab01e9dc..c7a8c1e6f02 100644
--- a/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -41,7 +41,8 @@ struct RootCompositorFrameSinkParams {
pending_associated_receiver<DisplayPrivate> display_private;
pending_remote<DisplayClient> display_client;
- associated ExternalBeginFrameController&? external_begin_frame_controller;
+ pending_associated_receiver<ExternalBeginFrameController>?
+ external_begin_frame_controller;
};
// The FrameSinkManager interface is a privileged interface that allows the
diff --git a/chromium/services/viz/privileged/mojom/gl/BUILD.gn b/chromium/services/viz/privileged/mojom/gl/BUILD.gn
index da48d0ac4db..bfa92f2b682 100644
--- a/chromium/services/viz/privileged/mojom/gl/BUILD.gn
+++ b/chromium/services/viz/privileged/mojom/gl/BUILD.gn
@@ -2,7 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/profiling/profiling.gni")
+import("//build/config/sanitizers/sanitizers.gni")
import("//mojo/public/tools/bindings/mojom.gni")
mojom("gl") {
@@ -36,8 +36,8 @@ mojom("gl") {
enabled_features += [ "is_not_android" ]
}
- if (use_clang_profiling) {
- enabled_features += [ "use_clang_profiling" ]
+ if (use_clang_profiling_inside_sandbox) {
+ enabled_features += [ "use_clang_profiling_inside_sandbox" ]
}
cpp_typemaps = [
diff --git a/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom b/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom
index efb330eb26a..9d40a960ab3 100644
--- a/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom
+++ b/chromium/services/viz/privileged/mojom/gl/gpu_host.mojom
@@ -41,6 +41,11 @@ interface GpuHost {
[EnableIf=is_win]
DidUpdateOverlayInfo(gpu.mojom.OverlayInfo overlay_info);
+ // Tells the GPU host that the HDR status has been updated in the GPU
+ // process.
+ [EnableIf=is_win]
+ DidUpdateHDRStatus(bool hdr_enabled);
+
// GPU process has decided to disable GPU compositing. Host process keeps
// track of this decision in case the GPU process crashes.
DisableGpuCompositing();
diff --git a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
index 0d1cc4af4a1..5d6701aaca3 100644
--- a/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
+++ b/chromium/services/viz/privileged/mojom/gl/gpu_service.mojom
@@ -153,7 +153,7 @@ interface GpuService {
// Write out the accumulated code profiling profile to the configured file.
// The callback is invoked once the profile has been flushed to disk.
- [EnableIf=use_clang_profiling]
+ [EnableIf=use_clang_profiling_inside_sandbox]
WriteClangProfilingProfile() => ();
Crash();
diff --git a/chromium/services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom b/chromium/services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom
index 4757b5ccbf7..c58d6f4a56b 100644
--- a/chromium/services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom
+++ b/chromium/services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom
@@ -14,15 +14,19 @@ interface InfoCollectionGpuService {
[EnableIf=is_win]
RequestDxDiagNodeInfo() => (gpu.mojom.DxDiagNode dx_diagnostics);
- // Requests Vulkan and DX12 supports and device performance info on Windows.
- // Returning whether Vulkan and DX12 are supported, and if yes, the
- // supported version/feature level, together with a few metrics related
- // to the device's performance for about:gpu and histogram recording
- // purpose.
+ // Requests DX12 version and device performance info on Windows.
+ // Returning whether DX12 are supported, and if yes, the supported feature
+ // level, together with a few metrics related to the device's performance for
+ // about:gpu and histogram recording purpose.
// TODO(crbug.com/1028263): histograms need to be recorded at browser process
// for now.
[EnableIf=is_win]
- GetGpuSupportedRuntimeVersionAndDevicePerfInfo()
- => (gpu.mojom.Dx12VulkanVersionInfo dx12_vulkan_version_info,
+ GetGpuSupportedDx12VersionAndDevicePerfInfo()
+ => (uint32 d3d12_feature_level,
gpu.mojom.DevicePerfInfo device_perf_info);
+
+ // Requests Vulkan version
+ [EnableIf=is_win]
+ GetGpuSupportedVulkanVersionInfo()
+ => (uint32 vulkan_version);
};
diff --git a/chromium/services/viz/public/cpp/BUILD.gn b/chromium/services/viz/public/cpp/BUILD.gn
new file mode 100644
index 00000000000..f58553703c2
--- /dev/null
+++ b/chromium/services/viz/public/cpp/BUILD.gn
@@ -0,0 +1,15 @@
+# Copyright 2020 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.
+
+source_set("crash_keys") {
+ sources = [
+ "crash_keys.cc",
+ "crash_keys.h",
+ ]
+
+ deps = [
+ "//base",
+ "//components/crash/core//common:crash_key",
+ ]
+}
diff --git a/chromium/services/viz/public/cpp/DEPS b/chromium/services/viz/public/cpp/DEPS
new file mode 100644
index 00000000000..90e574cf755
--- /dev/null
+++ b/chromium/services/viz/public/cpp/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+components/crash/core/common/crash_key.h",
+]
diff --git a/chromium/services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.cc
index 84a31fba2b8..b36230af3f6 100644
--- a/chromium/services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
namespace mojo {
@@ -64,8 +65,11 @@ bool StructTraits<viz::mojom::BeginFrameArgsDataView, viz::BeginFrameArgs>::
bool StructTraits<viz::mojom::BeginFrameAckDataView, viz::BeginFrameAck>::Read(
viz::mojom::BeginFrameAckDataView data,
viz::BeginFrameAck* out) {
- if (data.sequence_number() < viz::BeginFrameArgs::kStartingFrameNumber)
+ if (data.sequence_number() < viz::BeginFrameArgs::kStartingFrameNumber) {
+ viz::SetDeserializationCrashKeyString(
+ "Invalid begin frame ack sequence number");
return false;
+ }
out->frame_id.source_id = data.source_id();
out->frame_id.sequence_number = data.sequence_number();
out->trace_id = data.trace_id();
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
index 51a7f00f143..cb57ef4394f 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.cc
@@ -8,6 +8,7 @@
#include "services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.h"
#include "services/viz/public/cpp/compositing/selection_mojom_traits.h"
#include "services/viz/public/cpp/compositing/surface_id_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
#include "ui/gfx/mojom/display_color_spaces_mojom_traits.h"
#include "ui/gfx/mojom/selection_bound_mojom_traits.h"
#include "ui/latency/mojom/latency_info_mojom_traits.h"
@@ -19,11 +20,14 @@ bool StructTraits<viz::mojom::CompositorFrameMetadataDataView,
viz::CompositorFrameMetadata>::
Read(viz::mojom::CompositorFrameMetadataDataView data,
viz::CompositorFrameMetadata* out) {
- if (data.device_scale_factor() <= 0)
+ if (data.device_scale_factor() <= 0) {
+ viz::SetDeserializationCrashKeyString("Invalid device scale factor");
return false;
+ }
out->device_scale_factor = data.device_scale_factor();
- if (!data.ReadRootScrollOffset(&out->root_scroll_offset))
+ if (!data.ReadRootScrollOffset(&out->root_scroll_offset)) {
return false;
+ }
out->page_scale_factor = data.page_scale_factor();
if (!data.ReadScrollableViewportSize(&out->scrollable_viewport_size))
@@ -46,16 +50,23 @@ bool StructTraits<viz::mojom::CompositorFrameMetadataDataView,
data.top_controls_visible_height());
}
- return data.ReadLatencyInfo(&out->latency_info) &&
- data.ReadReferencedSurfaces(&out->referenced_surfaces) &&
- data.ReadDeadline(&out->deadline) &&
- data.ReadActivationDependencies(&out->activation_dependencies) &&
- data.ReadBeginFrameAck(&out->begin_frame_ack) &&
- data.ReadLocalSurfaceIdAllocationTime(
- &out->local_surface_id_allocation_time) &&
- !out->local_surface_id_allocation_time.is_null() &&
- data.ReadPreferredFrameInterval(&out->preferred_frame_interval) &&
- data.ReadDisplayTransformHint(&out->display_transform_hint);
+ if (!data.ReadLatencyInfo(&out->latency_info) ||
+ !data.ReadReferencedSurfaces(&out->referenced_surfaces) ||
+ !data.ReadDeadline(&out->deadline) ||
+ !data.ReadActivationDependencies(&out->activation_dependencies) ||
+ !data.ReadBeginFrameAck(&out->begin_frame_ack) ||
+ !data.ReadLocalSurfaceIdAllocationTime(
+ &out->local_surface_id_allocation_time)) {
+ return false;
+ }
+ if (out->local_surface_id_allocation_time.is_null()) {
+ viz::SetDeserializationCrashKeyString(
+ "Null local surface ID allocation time");
+ return false;
+ }
+ return data.ReadPreferredFrameInterval(&out->preferred_frame_interval) &&
+ data.ReadDisplayTransformHint(&out->display_transform_hint) &&
+ data.ReadDelegatedInkMetadata(&out->delegated_ink_metadata);
}
} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
index aa5464d8931..84f65fdb54e 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h
@@ -10,6 +10,7 @@
#include "build/build_config.h"
#include "components/viz/common/quads/compositor_frame_metadata.h"
#include "services/viz/public/cpp/compositing/begin_frame_args_mojom_traits.h"
+#include "services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h"
#include "services/viz/public/cpp/compositing/frame_deadline_mojom_traits.h"
#include "services/viz/public/cpp/compositing/surface_range_mojom_traits.h"
#include "services/viz/public/mojom/compositing/compositor_frame_metadata.mojom-shared.h"
@@ -126,6 +127,11 @@ struct StructTraits<viz::mojom::CompositorFrameMetadataDataView,
return metadata.display_transform_hint;
}
+ static const std::unique_ptr<viz::DelegatedInkMetadata>&
+ delegated_ink_metadata(const viz::CompositorFrameMetadata& metadata) {
+ return metadata.delegated_ink_metadata;
+ }
+
static bool Read(viz::mojom::CompositorFrameMetadataDataView data,
viz::CompositorFrameMetadata* out);
};
diff --git a/chromium/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc
index f3dc02f553f..20b9ad3d904 100644
--- a/chromium/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/compositor_frame_mojom_traits.cc
@@ -4,16 +4,37 @@
#include "services/viz/public/cpp/compositing/compositor_frame_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
+
namespace mojo {
// static
bool StructTraits<viz::mojom::CompositorFrameDataView, viz::CompositorFrame>::
Read(viz::mojom::CompositorFrameDataView data, viz::CompositorFrame* out) {
- return data.ReadPasses(&out->render_pass_list) &&
- !out->render_pass_list.empty() &&
- !out->render_pass_list.back()->output_rect.size().IsEmpty() &&
- data.ReadMetadata(&out->metadata) &&
- data.ReadResources(&out->resource_list);
+ if (!data.ReadPasses(&out->render_pass_list))
+ return false;
+
+ if (out->render_pass_list.empty()) {
+ viz::SetDeserializationCrashKeyString(
+ "CompositorFrame::render_pass_list empty");
+ return false;
+ }
+
+ if (out->render_pass_list.back()->output_rect.size().IsEmpty()) {
+ viz::SetDeserializationCrashKeyString("CompositorFrame empty");
+ return false;
+ }
+
+ if (!data.ReadMetadata(&out->metadata))
+ return false;
+
+ if (!data.ReadResources(&out->resource_list)) {
+ viz::SetDeserializationCrashKeyString(
+ "Failed read CompositorFrame::resource_list");
+ return false;
+ }
+
+ return true;
}
} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/copy_output_request_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/copy_output_request_mojom_traits.cc
index 34c5039e218..af1dd74b8b3 100644
--- a/chromium/services/viz/public/cpp/compositing/copy_output_request_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/copy_output_request_mojom_traits.cc
@@ -7,10 +7,13 @@
#include <utility>
#include "base/bind.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/viz/public/cpp/compositing/copy_output_result_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
namespace {
@@ -22,17 +25,21 @@ class CopyOutputResultSenderImpl : public viz::mojom::CopyOutputResultSender {
public:
CopyOutputResultSenderImpl(
viz::CopyOutputRequest::ResultFormat result_format,
- viz::CopyOutputRequest::CopyOutputRequestCallback result_callback)
+ viz::CopyOutputRequest::CopyOutputRequestCallback result_callback,
+ scoped_refptr<base::SequencedTaskRunner> callback_task_runner)
: result_format_(result_format),
- result_callback_(std::move(result_callback)) {
+ result_callback_(std::move(result_callback)),
+ result_callback_task_runner_(std::move(callback_task_runner)) {
DCHECK(result_callback_);
+ DCHECK(result_callback_task_runner_);
}
~CopyOutputResultSenderImpl() override {
if (result_callback_) {
- std::move(result_callback_)
- .Run(std::make_unique<viz::CopyOutputResult>(result_format_,
- gfx::Rect()));
+ result_callback_task_runner_->PostTask(
+ FROM_HERE, base::BindOnce(std::move(result_callback_),
+ std::make_unique<viz::CopyOutputResult>(
+ result_format_, gfx::Rect())));
}
}
@@ -41,12 +48,15 @@ class CopyOutputResultSenderImpl : public viz::mojom::CopyOutputResultSender {
TRACE_EVENT0("viz", "CopyOutputResultSenderImpl::SendResult");
if (!result_callback_)
return;
- std::move(result_callback_).Run(std::move(result));
+ result_callback_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(std::move(result_callback_), std::move(result)));
}
private:
const viz::CopyOutputRequest::ResultFormat result_format_;
viz::CopyOutputRequest::CopyOutputRequestCallback result_callback_;
+ scoped_refptr<base::SequencedTaskRunner> result_callback_task_runner_;
};
void SendResult(
@@ -68,10 +78,23 @@ StructTraits<viz::mojom::CopyOutputRequestDataView,
std::unique_ptr<viz::CopyOutputRequest>>::
result_sender(const std::unique_ptr<viz::CopyOutputRequest>& request) {
mojo::PendingRemote<viz::mojom::CopyOutputResultSender> result_sender;
+ auto pending_receiver = result_sender.InitWithNewPipeAndPassReceiver();
+ // Receiving the result requires an expensive deserialize operation, so by
+ // default we want the pipe to operate on the ThreadPool, and then it will
+ // PostTask back to the current sequence.
auto impl = std::make_unique<CopyOutputResultSenderImpl>(
- request->result_format(), std::move(request->result_callback_));
- MakeSelfOwnedReceiver(std::move(impl),
- result_sender.InitWithNewPipeAndPassReceiver());
+ request->result_format(), std::move(request->result_callback_),
+ base::SequencedTaskRunnerHandle::Get());
+ auto runner = base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
+ runner->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](std::unique_ptr<CopyOutputResultSenderImpl> impl,
+ mojo::PendingReceiver<viz::mojom::CopyOutputResultSender>
+ receiver) {
+ MakeSelfOwnedReceiver(std::move(impl), std::move(receiver));
+ },
+ std::move(impl), std::move(pending_receiver)));
return result_sender;
}
@@ -91,12 +114,25 @@ bool StructTraits<viz::mojom::CopyOutputRequestDataView,
result_format, base::BindOnce(SendResult, std::move(result_sender)));
gfx::Vector2d scale_from;
- if (!data.ReadScaleFrom(&scale_from) || scale_from.x() <= 0 ||
- scale_from.y() <= 0) {
+ if (!data.ReadScaleFrom(&scale_from))
+ return false;
+ if (scale_from.x() <= 0) {
+ viz::SetDeserializationCrashKeyString("Invalid readback scale from x");
+ return false;
+ }
+ if (scale_from.y() <= 0) {
+ viz::SetDeserializationCrashKeyString("Invalid readback scale from y");
return false;
}
gfx::Vector2d scale_to;
- if (!data.ReadScaleTo(&scale_to) || scale_to.x() <= 0 || scale_to.y() <= 0) {
+ if (!data.ReadScaleTo(&scale_to))
+ return false;
+ if (scale_to.x() <= 0) {
+ viz::SetDeserializationCrashKeyString("Invalid readback scale to x");
+ return false;
+ }
+ if (scale_to.y() <= 0) {
+ viz::SetDeserializationCrashKeyString("Invalid readback scale to y");
return false;
}
request->SetScaleRatio(scale_from, scale_to);
diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc
new file mode 100644
index 00000000000..61657009295
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc
@@ -0,0 +1,33 @@
+// Copyright 2020 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 "services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<viz::mojom::DelegatedInkMetadataDataView,
+ std::unique_ptr<viz::DelegatedInkMetadata>>::
+ Read(viz::mojom::DelegatedInkMetadataDataView data,
+ std::unique_ptr<viz::DelegatedInkMetadata>* out) {
+ // Diameter isn't expected to ever be below 0, so stop here if it is in order
+ // to avoid unexpected calculations in viz.
+ if (data.diameter() < 0)
+ return false;
+
+ gfx::PointF point;
+ base::TimeTicks timestamp;
+ gfx::RectF presentation_area;
+ SkColor color;
+ if (!data.ReadPoint(&point) || !data.ReadTimestamp(&timestamp) ||
+ !data.ReadPresentationArea(&presentation_area) ||
+ !data.ReadColor(&color)) {
+ return false;
+ }
+ *out = std::make_unique<viz::DelegatedInkMetadata>(
+ point, data.diameter(), color, timestamp, presentation_area);
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h
new file mode 100644
index 00000000000..bb452750ee3
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h
@@ -0,0 +1,58 @@
+// Copyright 2020 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 SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_
+
+#include "components/viz/common/delegated_ink_metadata.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "services/viz/public/mojom/compositing/delegated_ink_metadata.mojom-shared.h"
+#include "skia/public/mojom/skcolor_mojom_traits.h"
+#include "ui/gfx/mojom/rrect_f_mojom_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<viz::mojom::DelegatedInkMetadataDataView,
+ std::unique_ptr<viz::DelegatedInkMetadata>> {
+ static bool IsNull(const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return !input;
+ }
+
+ static void SetToNull(std::unique_ptr<viz::DelegatedInkMetadata>* input) {
+ input->reset();
+ }
+
+ static gfx::PointF point(
+ const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return input->point();
+ }
+
+ static double diameter(
+ const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return input->diameter();
+ }
+
+ static SkColor color(
+ const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return input->color();
+ }
+
+ static base::TimeTicks timestamp(
+ const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return input->timestamp();
+ }
+
+ static gfx::RectF presentation_area(
+ const std::unique_ptr<viz::DelegatedInkMetadata>& input) {
+ return input->presentation_area();
+ }
+
+ static bool Read(viz::mojom::DelegatedInkMetadataDataView data,
+ std::unique_ptr<viz::DelegatedInkMetadata>* out);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_METADATA_MOJOM_TRAITS_H_
diff --git a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc
index 80f7b3cc82c..c99d11f218a 100644
--- a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc
@@ -4,6 +4,7 @@
#include "services/viz/public/cpp/compositing/quads_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
#include "ui/gfx/mojom/color_space_mojom_traits.h"
#include "ui/gfx/mojom/transform_mojom_traits.h"
@@ -74,8 +75,10 @@ bool StructTraits<viz::mojom::RenderPassQuadStateDataView, viz::DrawQuad>::Read(
quad->resources.count = data.mask_resource_id() ? 1 : 0;
quad->render_pass_id = data.render_pass_id();
// RenderPass ids are never zero.
- if (!quad->render_pass_id)
+ if (!quad->render_pass_id) {
+ viz::SetDeserializationCrashKeyString("Draw quad invalid render pass ID");
return false;
+ }
if (!data.ReadMaskUvRect(&quad->mask_uv_rect) ||
!data.ReadMaskTextureSize(&quad->mask_texture_size) ||
!data.ReadFiltersScale(&quad->filters_scale) ||
@@ -213,8 +216,12 @@ bool StructTraits<viz::mojom::YUVVideoQuadStateDataView, viz::DrawQuad>::Read(
quad->resource_offset = data.resource_offset();
quad->resource_multiplier = data.resource_multiplier();
quad->bits_per_channel = data.bits_per_channel();
- if (quad->bits_per_channel < viz::YUVVideoDrawQuad::kMinBitsPerChannel ||
- quad->bits_per_channel > viz::YUVVideoDrawQuad::kMaxBitsPerChannel) {
+ if (quad->bits_per_channel < viz::YUVVideoDrawQuad::kMinBitsPerChannel) {
+ viz::SetDeserializationCrashKeyString("Bits per channel too small");
+ return false;
+ }
+ if (quad->bits_per_channel > viz::YUVVideoDrawQuad::kMaxBitsPerChannel) {
+ viz::SetDeserializationCrashKeyString("Bits per channel too big");
return false;
}
return true;
@@ -227,11 +234,10 @@ bool StructTraits<viz::mojom::DrawQuadDataView, viz::DrawQuad>::Read(
if (!data.ReadRect(&out->rect) || !data.ReadVisibleRect(&out->visible_rect)) {
return false;
}
- // Reject quads with areas larger than int32.
- if (!out->rect.size().GetCheckedArea().IsValid())
- return false;
- if (!out->rect.Contains(out->visible_rect))
+ if (!out->rect.Contains(out->visible_rect)) {
+ viz::SetDeserializationCrashKeyString("Rect does not contain visible rect");
return false;
+ }
out->needs_blending = data.needs_blending();
return data.ReadDrawQuadState(out);
diff --git a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
index ea4d147a266..a690016318a 100644
--- a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -5,8 +5,9 @@
#ifndef SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_QUADS_MOJOM_TRAITS_H_
#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_QUADS_MOJOM_TRAITS_H_
+#include "base/check.h"
#include "base/containers/span.h"
-#include "base/logging.h"
+#include "base/notreached.h"
#include "base/unguessable_token.h"
#include "components/viz/common/quads/debug_border_draw_quad.h"
#include "components/viz/common/quads/picture_draw_quad.h"
@@ -197,7 +198,7 @@ struct StructTraits<viz::mojom::DebugBorderQuadStateDataView, viz::DrawQuad> {
template <>
struct StructTraits<viz::mojom::RenderPassQuadStateDataView, viz::DrawQuad> {
- static int32_t render_pass_id(const viz::DrawQuad& input) {
+ static uint64_t render_pass_id(const viz::DrawQuad& input) {
const viz::RenderPassDrawQuad* quad =
viz::RenderPassDrawQuad::MaterialCast(&input);
DCHECK(quad->render_pass_id);
diff --git a/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc
index dc84c9b20fa..e704ba1005d 100644
--- a/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "services/viz/public/cpp/compositing/render_pass_mojom_traits.h"
#include "base/numerics/safe_conversions.h"
+#include "services/viz/public/cpp/crash_keys.h"
#include "ui/gfx/mojom/display_color_spaces_mojom_traits.h"
namespace mojo {
@@ -27,8 +28,10 @@ bool StructTraits<viz::mojom::RenderPassDataView,
}
(*out)->id = data.id();
// RenderPass ids are never zero.
- if (!(*out)->id)
+ if (!(*out)->id) {
+ viz::SetDeserializationCrashKeyString("Invalid render pass ID");
return false;
+ }
(*out)->has_transparent_background = data.has_transparent_background();
(*out)->cache_render_pass = data.cache_render_pass();
(*out)->has_damage_from_contributing_content =
@@ -46,8 +49,10 @@ bool StructTraits<viz::mojom::RenderPassDataView,
viz::DrawQuad* quad =
AllocateAndConstruct(quad_state_data_view.tag(), &(*out)->quad_list);
- if (!quad)
+ if (!quad) {
+ viz::SetDeserializationCrashKeyString("AllocateAndConstruct quad failed");
return false;
+ }
if (!quads.Read(i, quad))
return false;
@@ -62,8 +67,10 @@ bool StructTraits<viz::mojom::RenderPassDataView,
return false;
}
quad->shared_quad_state = last_sqs;
- if (!quad->shared_quad_state)
+ if (!quad->shared_quad_state) {
+ viz::SetDeserializationCrashKeyString("No shared quad state");
return false;
+ }
}
return true;
}
diff --git a/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.h
index bd707618ccf..5284cff3816 100644
--- a/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.h
@@ -6,8 +6,9 @@
#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RENDER_PASS_MOJOM_TRAITS_H_
#include <memory>
+#include <vector>
-#include "base/logging.h"
+#include "base/check.h"
#include "components/viz/common/quads/render_pass.h"
#include "services/viz/public/cpp/compositing/copy_output_request_mojom_traits.h"
#include "services/viz/public/cpp/compositing/quads_mojom_traits.h"
diff --git a/chromium/services/viz/public/cpp/crash_keys.cc b/chromium/services/viz/public/cpp/crash_keys.cc
new file mode 100644
index 00000000000..ab79ea1928c
--- /dev/null
+++ b/chromium/services/viz/public/cpp/crash_keys.cc
@@ -0,0 +1,16 @@
+// Copyright 2020 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 "services/viz/public/cpp/crash_keys.h"
+
+#include "components/crash/core/common/crash_key.h"
+
+namespace viz {
+
+void SetDeserializationCrashKeyString(base::StringPiece str) {
+ static crash_reporter::CrashKeyString<128> key("viz_deserialization");
+ key.Set(str);
+}
+
+} // namespace viz
diff --git a/chromium/services/viz/public/cpp/crash_keys.h b/chromium/services/viz/public/cpp/crash_keys.h
new file mode 100644
index 00000000000..55288103303
--- /dev/null
+++ b/chromium/services/viz/public/cpp/crash_keys.h
@@ -0,0 +1,18 @@
+// Copyright 2020 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 SERVICES_VIZ_PUBLIC_CPP_CRASH_KEYS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_CRASH_KEYS_H_
+
+#include "base/strings/string_piece.h"
+
+namespace viz {
+
+// Sets a crash key to indicate what structure triggered a deserialization error
+// in viz mojom code.
+void SetDeserializationCrashKeyString(base::StringPiece str);
+
+} // namespace viz
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_CRASH_KEYS_H_
diff --git a/chromium/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc b/chromium/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc
index a15ba4b4490..74a0fe44ebf 100644
--- a/chromium/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc
@@ -4,18 +4,28 @@
#include "services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.h"
+#include "services/viz/public/cpp/crash_keys.h"
+
namespace mojo {
// static
bool StructTraits<viz::mojom::HitTestRegionDataView, viz::HitTestRegion>::Read(
viz::mojom::HitTestRegionDataView data,
viz::HitTestRegion* out) {
- if (!data.ReadFrameSinkId(&out->frame_sink_id))
+ if (!data.ReadFrameSinkId(&out->frame_sink_id)) {
+ viz::SetDeserializationCrashKeyString(
+ "Failed read HitTestRegion::frame_sink_id");
return false;
- if (!data.ReadRect(&out->rect))
+ }
+ if (!data.ReadRect(&out->rect)) {
+ viz::SetDeserializationCrashKeyString("Failed read HitTestRegion::rect");
return false;
- if (!data.ReadTransform(&out->transform))
+ }
+ if (!data.ReadTransform(&out->transform)) {
+ viz::SetDeserializationCrashKeyString(
+ "Failed read HitTestRegion::transform");
return false;
+ }
out->flags = data.flags();
out->async_hit_test_reasons = data.async_hit_test_reasons();
return true;
@@ -28,10 +38,16 @@ bool StructTraits<
viz::HitTestRegionList* out) {
if (!data.ReadRegions(&out->regions))
return false;
- if (!data.ReadBounds(&out->bounds))
+ if (!data.ReadBounds(&out->bounds)) {
+ viz::SetDeserializationCrashKeyString(
+ "Failed read HitTestRegionList::bounds");
return false;
- if (!data.ReadTransform(&out->transform))
+ }
+ if (!data.ReadTransform(&out->transform)) {
+ viz::SetDeserializationCrashKeyString(
+ "Failed read HitTestRegionList::transform");
return false;
+ }
out->flags = data.flags();
out->async_hit_test_reasons = data.async_hit_test_reasons();
return true;
diff --git a/chromium/services/viz/public/mojom/BUILD.gn b/chromium/services/viz/public/mojom/BUILD.gn
index 75ef138eab8..d6d676deaba 100644
--- a/chromium/services/viz/public/mojom/BUILD.gn
+++ b/chromium/services/viz/public/mojom/BUILD.gn
@@ -15,6 +15,7 @@ mojom("mojom") {
"compositing/compositor_frame_sink.mojom",
"compositing/copy_output_request.mojom",
"compositing/copy_output_result.mojom",
+ "compositing/delegated_ink_metadata.mojom",
"compositing/filter_operation.mojom",
"compositing/filter_operations.mojom",
"compositing/frame_deadline.mojom",
@@ -178,7 +179,10 @@ mojom("mojom") {
traits_private_headers = [
"//services/viz/public/cpp/compositing/compositor_frame_mojom_traits.h",
]
- traits_public_deps = [ "//components/viz/common" ]
+ traits_public_deps = [
+ "//components/viz/common",
+ "//services/viz/public/cpp:crash_keys",
+ ]
},
{
types = [
@@ -223,6 +227,19 @@ mojom("mojom") {
{
types = [
{
+ mojom = "viz.mojom.DelegatedInkMetadata"
+ cpp = "::std::unique_ptr<::viz::DelegatedInkMetadata>"
+ move_only = true
+ nullable_is_same_type = true
+ },
+ ]
+ traits_sources = [ "//services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.cc" ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/delegated_ink_metadata_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
mojom = "viz.mojom.FilterOperation"
cpp = "::cc::FilterOperation"
},
@@ -285,6 +302,7 @@ mojom("mojom") {
traits_sources = [ "//services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.cc" ]
traits_public_deps = [
"//components/viz/common",
+ "//services/viz/public/cpp:crash_keys",
"//ui/gfx/geometry/mojom",
]
},
@@ -435,6 +453,46 @@ mojom("mojom") {
{
types = [
{
+ mojom = "viz.mojom.HitTestRegion"
+ cpp = "::viz::HitTestRegion"
+ },
+ {
+ mojom = "viz.mojom.HitTestRegionList"
+ cpp = "::viz::HitTestRegionList"
+ move_only = true
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/hit_test/hit_test_region_list_mojom_traits.h" ]
+ traits_public_deps = [
+ "//components/viz/common",
+ "//services/viz/public/cpp:crash_keys",
+ "//ui/gfx/geometry/mojom",
+ ]
+ },
+ {
+ types = [
+ {
+ mojom = "viz.mojom.CompositorFrameMetadata"
+ cpp = "::viz::CompositorFrameMetadata"
+ move_only = true
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/compositor_frame_metadata_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
+ mojom = "viz.mojom.FrameTimingDetails"
+ cpp = "::viz::FrameTimingDetails"
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/frame_timing_details_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
mojom = "viz.mojom.CompositorFrame"
cpp = "::viz::CompositorFrame"
move_only = true
diff --git a/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom b/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
index 244e8225160..3f3e203607e 100644
--- a/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
+++ b/chromium/services/viz/public/mojom/compositing/compositor_frame_metadata.mojom
@@ -6,6 +6,7 @@ module viz.mojom;
import "mojo/public/mojom/base/time.mojom";
import "services/viz/public/mojom/compositing/begin_frame_args.mojom";
+import "services/viz/public/mojom/compositing/delegated_ink_metadata.mojom";
import "services/viz/public/mojom/compositing/frame_deadline.mojom";
import "services/viz/public/mojom/compositing/selection.mojom";
import "services/viz/public/mojom/compositing/surface_id.mojom";
@@ -16,6 +17,8 @@ import "ui/gfx/mojom/overlay_transform.mojom";
import "ui/latency/mojom/latency_info.mojom";
// See components/viz/service/quads/compositor_frame_metadata.h.
+// This is sent from viz clients such as the browser and renderer to the viz
+// compositor in the GPU process.
struct CompositorFrameMetadata {
float device_scale_factor;
gfx.mojom.Vector2dF root_scroll_offset;
@@ -47,4 +50,17 @@ struct CompositorFrameMetadata {
mojo_base.mojom.TimeDelta? preferred_frame_interval;
gfx.mojom.OverlayTransform display_transform_hint;
+
+ // Contains the metadata required for drawing a delegated ink trail onto the
+ // end of a rendered ink stroke. This should only be present when two
+ // conditions are met:
+ // 1. The JS API |updateInkTrailStartPoint| is used - This gathers the
+ // metadata and puts it onto a compositor frame to be sent to viz.
+ // 2. This frame will not be submitted to the root surface - The browser UI
+ // does not use this, and the frame must be contained within a
+ // SurfaceDrawQuad.
+ // The ink trail created with this metadata will only last for a single frame
+ // before it disappears, regardless of whether or not the next frame contains
+ // delegated ink metadata.
+ DelegatedInkMetadata? delegated_ink_metadata;
};
diff --git a/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom b/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom
new file mode 100644
index 00000000000..89843b27ddb
--- /dev/null
+++ b/chromium/services/viz/public/mojom/compositing/delegated_ink_metadata.mojom
@@ -0,0 +1,18 @@
+// Copyright 2020 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.
+
+module viz.mojom;
+
+import "mojo/public/mojom/base/time.mojom";
+import "skia/public/mojom/skcolor.mojom";
+import "ui/gfx/geometry/mojom/geometry.mojom";
+
+// See components/viz/common/delegated_ink_metadata.h.
+struct DelegatedInkMetadata {
+ gfx.mojom.PointF point;
+ double diameter;
+ skia.mojom.SkColor color;
+ mojo_base.mojom.TimeTicks timestamp;
+ gfx.mojom.RectF presentation_area;
+};