summaryrefslogtreecommitdiff
path: root/chromium/services
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2020-10-29 10:46:47 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2020-11-02 12:02:10 +0000
commit99677208ff3b216fdfec551fbe548da5520cd6fb (patch)
tree476a4865c10320249360e859d8fdd3e01833b03a /chromium/services
parentc30a6232df03e1efbd9f3b226777b07e087a1122 (diff)
downloadqtwebengine-chromium-99677208ff3b216fdfec551fbe548da5520cd6fb.tar.gz
BASELINE: Update Chromium to 86.0.4240.124
Change-Id: Ide0ff151e94cd665ae6521a446995d34a9d1d644 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/services')
-rw-r--r--chromium/services/BUILD.gn4
-rw-r--r--chromium/services/audio/BUILD.gn15
-rw-r--r--chromium/services/audio/DEPS1
-rw-r--r--chromium/services/audio/OWNERS1
-rw-r--r--chromium/services/audio/audio_sandbox_hook_linux.cc6
-rw-r--r--chromium/services/audio/audio_sandbox_hook_linux.h4
-rw-r--r--chromium/services/audio/audio_sandbox_win.cc58
-rw-r--r--chromium/services/audio/audio_sandbox_win.h25
-rw-r--r--chromium/services/audio/loopback_stream_unittest.cc3
-rw-r--r--chromium/services/audio/service.cc4
-rw-r--r--chromium/services/audio/service.h2
-rw-r--r--chromium/services/audio/snooper_node_unittest.cc7
-rw-r--r--chromium/services/audio/sync_reader.cc2
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/BUILD.gn3
-rw-r--r--chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc1
-rw-r--r--chromium/services/data_decoder/BUILD.gn21
-rw-r--r--chromium/services/data_decoder/DEPS2
-rw-r--r--chromium/services/data_decoder/data_decoder_service.cc10
-rw-r--r--chromium/services/data_decoder/data_decoder_service.h12
-rw-r--r--chromium/services/data_decoder/image_decoder_impl.cc1
-rw-r--r--chromium/services/data_decoder/public/cpp/BUILD.gn4
-rw-r--r--chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.cc44
-rw-r--r--chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.h42
-rw-r--r--chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc71
-rw-r--r--chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.cc149
-rw-r--r--chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.h80
-rw-r--r--chromium/services/data_decoder/public/mojom/BUILD.gn2
-rw-r--r--chromium/services/data_decoder/public/mojom/data_decoder_service.mojom4
-rw-r--r--chromium/services/data_decoder/public/mojom/web_bundle_parser.mojom133
-rw-r--r--chromium/services/data_decoder/web_bundle_parser.cc1349
-rw-r--r--chromium/services/data_decoder/web_bundle_parser.h71
-rw-r--r--chromium/services/data_decoder/web_bundle_parser_factory.cc79
-rw-r--r--chromium/services/data_decoder/web_bundle_parser_factory.h40
-rw-r--r--chromium/services/data_decoder/web_bundle_parser_factory_unittest.cc190
-rw-r--r--chromium/services/data_decoder/web_bundle_parser_fuzzer.cc131
-rw-r--r--chromium/services/data_decoder/web_bundle_parser_unittest.cc700
-rw-r--r--chromium/services/device/BUILD.gn14
-rw-r--r--chromium/services/device/README.md2
-rw-r--r--chromium/services/device/battery/BUILD.gn2
-rw-r--r--chromium/services/device/battery/android/BUILD.gn1
-rw-r--r--chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java41
-rw-r--r--chromium/services/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java16
-rw-r--r--chromium/services/device/battery/battery_status_manager_win.cc2
-rw-r--r--chromium/services/device/bluetooth/bluetooth_system.cc4
-rw-r--r--chromium/services/device/device_service.cc18
-rw-r--r--chromium/services/device/device_service.h8
-rw-r--r--chromium/services/device/generic_sensor/BUILD.gn2
-rw-r--r--chromium/services/device/generic_sensor/android/java/src/org/chromium/device/sensors/PlatformSensor.java10
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_and_provider_unittest_linux.cc2
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_provider.cc4
-rw-r--r--chromium/services/device/generic_sensor/platform_sensor_reader_win.cc8
-rw-r--r--chromium/services/device/geolocation/BUILD.gn5
-rw-r--r--chromium/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java3
-rw-r--r--chromium/services/device/geolocation/geolocation_provider_impl.cc2
-rw-r--r--chromium/services/device/geolocation/location_arbitrator.cc2
-rw-r--r--chromium/services/device/geolocation/network_location_provider_unittest.cc2
-rw-r--r--chromium/services/device/hid/BUILD.gn2
-rw-r--r--chromium/services/device/hid/hid_connection_impl_unittest.cc2
-rw-r--r--chromium/services/device/hid/hid_device_info.h4
-rw-r--r--chromium/services/device/hid/hid_manager_unittest.cc2
-rw-r--r--chromium/services/device/hid/hid_service.cc8
-rw-r--r--chromium/services/device/hid/hid_service_win.cc23
-rw-r--r--chromium/services/device/hid/hid_service_win.h8
-rw-r--r--chromium/services/device/nfc/android/BUILD.gn1
-rw-r--r--chromium/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java4
-rw-r--r--chromium/services/device/public/cpp/bluetooth/BUILD.gn1
-rw-r--r--chromium/services/device/public/cpp/bluetooth/bluetooth_utils.cc7
-rw-r--r--chromium/services/device/public/cpp/bluetooth/bluetooth_utils.h4
-rw-r--r--chromium/services/device/public/cpp/hid/hid_device_filter_unittest.cc2
-rw-r--r--chromium/services/device/public/cpp/serial/BUILD.gn10
-rw-r--r--chromium/services/device/public/cpp/serial/serial_switches.cc13
-rw-r--r--chromium/services/device/public/cpp/serial/serial_switches.h14
-rw-r--r--chromium/services/device/public/cpp/usb/usb_utils.cc8
-rw-r--r--chromium/services/device/public/cpp/usb/usb_utils_unittest.cc61
-rw-r--r--chromium/services/device/public/mojom/BUILD.gn2
-rw-r--r--chromium/services/device/public/mojom/hid.mojom122
-rw-r--r--chromium/services/device/public/mojom/serial.mojom33
-rw-r--r--chromium/services/device/screen_orientation/screen_orientation_listener_android.cc4
-rw-r--r--chromium/services/device/serial/BUILD.gn12
-rw-r--r--chromium/services/device/serial/bluetooth_serial_device_enumerator.cc68
-rw-r--r--chromium/services/device/serial/bluetooth_serial_device_enumerator.h43
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl.cc382
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl.h107
-rw-r--r--chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc353
-rw-r--r--chromium/services/device/serial/serial_device_enumerator.cc12
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_linux.cc23
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_linux.h6
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_linux_unittest.cc79
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_win.cc34
-rw-r--r--chromium/services/device/serial/serial_device_enumerator_win.h10
-rw-r--r--chromium/services/device/serial/serial_io_handler.cc2
-rw-r--r--chromium/services/device/serial/serial_io_handler.h5
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix.cc66
-rw-r--r--chromium/services/device/serial/serial_io_handler_posix.h3
-rw-r--r--chromium/services/device/serial/serial_io_handler_win.cc247
-rw-r--r--chromium/services/device/serial/serial_io_handler_win.h17
-rw-r--r--chromium/services/device/serial/serial_port_impl.cc101
-rw-r--r--chromium/services/device/serial/serial_port_impl.h19
-rw-r--r--chromium/services/device/serial/serial_port_impl_unittest.cc182
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.cc30
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl.h5
-rw-r--r--chromium/services/device/serial/serial_port_manager_impl_unittest.cc114
-rw-r--r--chromium/services/device/time_zone_monitor/BUILD.gn2
-rw-r--r--chromium/services/device/usb/BUILD.gn6
-rw-r--r--chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java3
-rw-r--r--chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java15
-rw-r--r--chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java3
-rw-r--r--chromium/services/device/usb/mojo/device_impl.cc6
-rw-r--r--chromium/services/device/usb/mojo/device_impl.h4
-rw-r--r--chromium/services/device/usb/mojo/device_impl_unittest.cc61
-rw-r--r--chromium/services/device/usb/mojo/device_manager_impl_unittest.cc1
-rw-r--r--chromium/services/device/usb/usb_descriptors.cc8
-rw-r--r--chromium/services/device/usb/usb_descriptors.h2
-rw-r--r--chromium/services/device/usb/usb_device.cc2
-rw-r--r--chromium/services/device/usb/usb_device.h2
-rw-r--r--chromium/services/device/usb/usb_device_android.cc72
-rw-r--r--chromium/services/device/usb/usb_device_handle_mac.cc925
-rw-r--r--chromium/services/device/usb/usb_device_handle_mac.h146
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.cc6
-rw-r--r--chromium/services/device/usb/usb_device_handle_win.h8
-rw-r--r--chromium/services/device/usb/usb_device_impl.cc2
-rw-r--r--chromium/services/device/usb/usb_device_mac.cc87
-rw-r--r--chromium/services/device/usb/usb_device_mac.h32
-rw-r--r--chromium/services/device/usb/usb_device_win.cc12
-rw-r--r--chromium/services/device/usb/usb_device_win.h20
-rw-r--r--chromium/services/device/usb/usb_interface_android.cc9
-rw-r--r--chromium/services/device/usb/usb_service.cc13
-rw-r--r--chromium/services/device/usb/usb_service_impl.cc12
-rw-r--r--chromium/services/device/usb/usb_service_impl.h6
-rw-r--r--chromium/services/device/usb/usb_service_linux.cc5
-rw-r--r--chromium/services/device/usb/usb_service_mac.cc326
-rw-r--r--chromium/services/device/usb/usb_service_mac.h55
-rw-r--r--chromium/services/device/usb/usb_service_win.cc92
-rw-r--r--chromium/services/device/usb/usb_service_win.h14
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/BUILD.gn9
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/DEPS1
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_linux.cc19
-rw-r--r--chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc2
-rw-r--r--chromium/services/device/wake_lock/wake_lock_provider.h1
-rw-r--r--chromium/services/device/wake_lock/wake_lock_unittest.cc1
-rw-r--r--chromium/services/image_annotation/public/cpp/image_processor.cc1
-rw-r--r--chromium/services/media_session/audio_focus_request.cc9
-rw-r--r--chromium/services/media_session/media_controller.cc7
-rw-r--r--chromium/services/media_session/media_controller.h1
-rw-r--r--chromium/services/media_session/public/cpp/OWNERS2
-rw-r--r--chromium/services/media_session/public/cpp/android/BUILD.gn5
-rw-r--r--chromium/services/media_session/public/cpp/media_session.typemap30
-rw-r--r--chromium/services/media_session/public/cpp/media_session_mojom_traits.cc1
-rw-r--r--chromium/services/media_session/public/cpp/media_session_mojom_traits.h8
-rw-r--r--chromium/services/media_session/public/cpp/mojom_traits_unittest.cc1
-rw-r--r--chromium/services/media_session/public/cpp/typemaps.gni5
-rw-r--r--chromium/services/media_session/public/mojom/BUILD.gn38
-rw-r--r--chromium/services/media_session/public/mojom/media_controller.mojom4
-rw-r--r--chromium/services/media_session/public/mojom/media_session.mojom13
-rw-r--r--chromium/services/metrics/public/cpp/ukm_source.cc2
-rw-r--r--chromium/services/network/BUILD.gn28
-rw-r--r--chromium/services/network/DEPS1
-rw-r--r--chromium/services/network/OWNERS1
-rw-r--r--chromium/services/network/README.md1
-rw-r--r--chromium/services/network/chunked_data_pipe_upload_data_stream.cc11
-rw-r--r--chromium/services/network/cookie_manager_unittest.cc117
-rw-r--r--chromium/services/network/cookie_settings.cc7
-rw-r--r--chromium/services/network/cookie_settings.h5
-rw-r--r--chromium/services/network/cors/cors_url_loader.cc59
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.cc83
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory.h4
-rw-r--r--chromium/services/network/cors/cors_url_loader_factory_unittest.cc2
-rw-r--r--chromium/services/network/cors/cors_url_loader_unittest.cc292
-rw-r--r--chromium/services/network/cors/preflight_controller.cc45
-rw-r--r--chromium/services/network/cors/preflight_controller.h15
-rw-r--r--chromium/services/network/cors/preflight_controller_unittest.cc13
-rw-r--r--chromium/services/network/crash_keys.cc4
-rw-r--r--chromium/services/network/crash_keys.h2
-rw-r--r--chromium/services/network/cross_origin_read_blocking_exception_for_plugin.cc43
-rw-r--r--chromium/services/network/cross_origin_read_blocking_exception_for_plugin.h38
-rw-r--r--chromium/services/network/cross_origin_read_blocking_explainer.md4
-rw-r--r--chromium/services/network/expect_ct_reporter.h2
-rw-r--r--chromium/services/network/expect_ct_reporter_unittest.cc12
-rw-r--r--chromium/services/network/host_resolver.cc1
-rw-r--r--chromium/services/network/host_resolver_unittest.cc1
-rw-r--r--chromium/services/network/ignore_errors_cert_verifier.h2
-rw-r--r--chromium/services/network/net_log_exporter.cc17
-rw-r--r--chromium/services/network/network_context.cc139
-rw-r--r--chromium/services/network/network_context.h27
-rw-r--r--chromium/services/network/network_context_unittest.cc190
-rw-r--r--chromium/services/network/network_sandbox_hook_linux.cc6
-rw-r--r--chromium/services/network/network_sandbox_hook_linux.h4
-rw-r--r--chromium/services/network/network_sandbox_win.cc28
-rw-r--r--chromium/services/network/network_sandbox_win.h27
-rw-r--r--chromium/services/network/network_service.cc23
-rw-r--r--chromium/services/network/network_service.h14
-rw-r--r--chromium/services/network/network_service_network_delegate.cc3
-rw-r--r--chromium/services/network/network_service_proxy_delegate_unittest.cc9
-rw-r--r--chromium/services/network/network_service_unittest.cc2
-rw-r--r--chromium/services/network/proxy_resolving_client_socket_factory.cc2
-rw-r--r--chromium/services/network/public/cpp/BUILD.gn28
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.cc4
-rw-r--r--chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo_unittest.cc6
-rw-r--r--chromium/services/network/public/cpp/client_hints.cc10
-rw-r--r--chromium/services/network/public/cpp/client_hints.h5
-rw-r--r--chromium/services/network/public/cpp/client_hints_unittest.cc8
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.cc700
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy.h21
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc446
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source.cc127
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source.h6
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc44
-rw-r--r--chromium/services/network/public/cpp/content_security_policy/csp_source_unittest.cc195
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc47
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits.h40
-rw-r--r--chromium/services/network/public/cpp/cookie_manager_mojom_traits_unittest.cc97
-rw-r--r--chromium/services/network/public/cpp/cors/cors.cc16
-rw-r--r--chromium/services/network/public/cpp/cors/cors.h8
-rw-r--r--chromium/services/network/public/cpp/cors/cors_legacy.h4
-rw-r--r--chromium/services/network/public/cpp/cors/origin_access_list.h2
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_result.cc6
-rw-r--r--chromium/services/network/public/cpp/cors/preflight_result.h4
-rw-r--r--chromium/services/network/public/cpp/cross_origin_opener_policy.cc13
-rw-r--r--chromium/services/network/public/cpp/cross_origin_opener_policy.h3
-rw-r--r--chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc19
-rw-r--r--chromium/services/network/public/cpp/cross_origin_opener_policy_parser.h4
-rw-r--r--chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc168
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking.cc (renamed from chromium/services/network/cross_origin_read_blocking.cc)53
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking.h (renamed from chromium/services/network/cross_origin_read_blocking.h)31
-rw-r--r--chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc (renamed from chromium/services/network/cross_origin_read_blocking_unittest.cc)8
-rw-r--r--chromium/services/network/public/cpp/cross_origin_resource_policy.cc22
-rw-r--r--chromium/services/network/public/cpp/cross_origin_resource_policy.h6
-rw-r--r--chromium/services/network/public/cpp/data_element.cc16
-rw-r--r--chromium/services/network/public/cpp/data_element.h4
-rw-r--r--chromium/services/network/public/cpp/empty_url_loader_client.cc16
-rw-r--r--chromium/services/network/public/cpp/empty_url_loader_client.h8
-rw-r--r--chromium/services/network/public/cpp/features.cc51
-rw-r--r--chromium/services/network/public/cpp/features.h11
-rw-r--r--chromium/services/network/public/cpp/host_resolver_mojom_traits.cc8
-rw-r--r--chromium/services/network/public/cpp/host_resolver_mojom_traits.h2
-rw-r--r--chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc1
-rw-r--r--chromium/services/network/public/cpp/initiator_lock_compatibility.cc43
-rw-r--r--chromium/services/network/public/cpp/initiator_lock_compatibility.h30
-rw-r--r--chromium/services/network/public/cpp/initiator_lock_compatibility_unittest.cc21
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.cc44
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util.h41
-rw-r--r--chromium/services/network/public/cpp/ip_address_space_util_unittest.cc97
-rw-r--r--chromium/services/network/public/cpp/load_info_util.cc1
-rw-r--r--chromium/services/network/public/cpp/net_ipc_param_traits.h10
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.cc2
-rw-r--r--chromium/services/network/public/cpp/network_ipc_param_traits.h1
-rw-r--r--chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc37
-rw-r--r--chromium/services/network/public/cpp/not_implemented_url_loader_factory.h46
-rw-r--r--chromium/services/network/public/cpp/optional_trust_token_params_unittest.cc2
-rw-r--r--chromium/services/network/public/cpp/parsed_headers.cc12
-rw-r--r--chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc4
-rw-r--r--chromium/services/network/public/cpp/resource_request.cc24
-rw-r--r--chromium/services/network/public/cpp/resource_request.h7
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.cc31
-rw-r--r--chromium/services/network/public/cpp/resource_request_body.h6
-rw-r--r--chromium/services/network/public/cpp/session_cookie_delete_predicate.h23
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader.cc2
-rw-r--r--chromium/services/network/public/cpp/simple_url_loader_unittest.cc3
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.cc52
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits.h14
-rw-r--r--chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc34
-rw-r--r--chromium/services/network/public/mojom/BUILD.gn26
-rw-r--r--chromium/services/network/public/mojom/content_security_policy.mojom58
-rw-r--r--chromium/services/network/public/mojom/cookie_access_observer.mojom2
-rw-r--r--chromium/services/network/public/mojom/cookie_manager.mojom17
-rw-r--r--chromium/services/network/public/mojom/cross_origin_opener_policy.mojom35
-rw-r--r--chromium/services/network/public/mojom/host_resolver.mojom4
-rw-r--r--chromium/services/network/public/mojom/network_context.mojom64
-rw-r--r--chromium/services/network/public/mojom/network_service.mojom8
-rw-r--r--chromium/services/network/public/mojom/network_service_test.mojom5
-rw-r--r--chromium/services/network/public/mojom/parsed_headers.mojom7
-rw-r--r--chromium/services/network/public/mojom/referrer_policy.mojom1
-rw-r--r--chromium/services/network/public/mojom/ssl_config.mojom6
-rw-r--r--chromium/services/network/public/mojom/trust_tokens.mojom2
-rw-r--r--chromium/services/network/public/mojom/url_loader.mojom5
-rw-r--r--chromium/services/network/public/mojom/url_loader_factory.mojom21
-rw-r--r--chromium/services/network/quic_transport.cc14
-rw-r--r--chromium/services/network/resource_scheduler/OWNERS2
-rw-r--r--chromium/services/network/restricted_cookie_manager.cc78
-rw-r--r--chromium/services/network/restricted_cookie_manager.h13
-rw-r--r--chromium/services/network/restricted_cookie_manager_unittest.cc85
-rw-r--r--chromium/services/network/sct_auditing_cache.cc100
-rw-r--r--chromium/services/network/sct_auditing_cache.h87
-rw-r--r--chromium/services/network/sct_auditing_cache_unittest.cc272
-rw-r--r--chromium/services/network/sec_header_helpers.cc2
-rw-r--r--chromium/services/network/session_cleanup_cookie_store.h11
-rw-r--r--chromium/services/network/ssl_config_service_mojo.cc4
-rw-r--r--chromium/services/network/ssl_config_service_mojo_unittest.cc10
-rw-r--r--chromium/services/network/ssl_config_type_converter.cc2
-rw-r--r--chromium/services/network/tcp_bound_socket_unittest.cc8
-rw-r--r--chromium/services/network/tcp_socket_unittest.cc4
-rw-r--r--chromium/services/network/throttling/throttling_network_interceptor.cc13
-rw-r--r--chromium/services/network/throttling/throttling_network_transaction.cc9
-rw-r--r--chromium/services/network/throttling/throttling_network_transaction.h3
-rw-r--r--chromium/services/network/tls_socket_factory.cc6
-rw-r--r--chromium/services/network/trust_tokens/BUILD.gn1
-rw-r--r--chromium/services/network/trust_tokens/sqlite_trust_token_persister_unittest.cc2
-rw-r--r--chromium/services/network/trust_tokens/trust_token_key_commitments.cc4
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory.cc27
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_helper_factory_unittest.cc13
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc3
-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.cc3
-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.cc253
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper.h59
-rw-r--r--chromium/services/network/trust_tokens/trust_token_request_signing_helper_unittest.cc224
-rw-r--r--chromium/services/network/udp_socket_test_util.cc202
-rw-r--r--chromium/services/network/udp_socket_test_util.h88
-rw-r--r--chromium/services/network/udp_socket_unittest.cc2
-rw-r--r--chromium/services/network/url_loader.cc206
-rw-r--r--chromium/services/network/url_loader.h31
-rw-r--r--chromium/services/network/url_loader_factory.cc16
-rw-r--r--chromium/services/network/url_loader_unittest.cc507
-rw-r--r--chromium/services/network/websocket.cc14
-rw-r--r--chromium/services/network/websocket.h14
-rw-r--r--chromium/services/network/websocket_factory.cc7
-rw-r--r--chromium/services/network/websocket_factory.h2
-rw-r--r--chromium/services/network/websocket_throttler.cc8
-rw-r--r--chromium/services/network/websocket_throttler.h9
-rw-r--r--chromium/services/network/websocket_throttler_unittest.cc21
-rw-r--r--chromium/services/preferences/tracked/BUILD.gn2
-rw-r--r--chromium/services/preferences/tracked/device_id_unittest.cc2
-rw-r--r--chromium/services/proxy_resolver/public/cpp/OWNERS6
-rw-r--r--chromium/services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h2
-rw-r--r--chromium/services/proxy_resolver/public/cpp/proxy_resolver.typemap27
-rw-r--r--chromium/services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h2
-rw-r--r--chromium/services/proxy_resolver/public/cpp/typemaps.gni5
-rw-r--r--chromium/services/proxy_resolver/public/mojom/BUILD.gn34
-rw-r--r--chromium/services/resource_coordinator/BUILD.gn3
-rw-r--r--chromium/services/resource_coordinator/DEPS1
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/OWNERS1
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc2
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc17
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.cc151
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h83
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter_unittest.cc86
-rw-r--r--chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc26
-rw-r--r--chromium/services/resource_coordinator/public/cpp/OWNERS6
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS3
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc3
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.typemap30
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc2
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h20
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc2
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h27
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc31
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc21
-rw-r--r--chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc2
-rw-r--r--chromium/services/resource_coordinator/public/cpp/typemaps.gni5
-rw-r--r--chromium/services/resource_coordinator/public/mojom/BUILD.gn49
-rw-r--r--chromium/services/service_manager/BUILD.gn4
-rw-r--r--chromium/services/service_manager/embedder/BUILD.gn6
-rw-r--r--chromium/services/service_manager/embedder/main.cc24
-rw-r--r--chromium/services/service_manager/embedder/main_delegate.h2
-rw-r--r--chromium/services/service_manager/embedder/set_process_title.cc31
-rw-r--r--chromium/services/service_manager/public/cpp/BUILD.gn4
-rw-r--r--chromium/services/service_manager/public/cpp/OWNERS2
-rw-r--r--chromium/services/service_manager/public/cpp/bind_source_info.typemap14
-rw-r--r--chromium/services/service_manager/public/cpp/bind_source_info_mojom_traits.h6
-rw-r--r--chromium/services/service_manager/public/cpp/identity.typemap14
-rw-r--r--chromium/services/service_manager/public/cpp/interface_provider_spec.typemap17
-rw-r--r--chromium/services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h8
-rw-r--r--chromium/services/service_manager/public/cpp/manifest.h9
-rw-r--r--chromium/services/service_manager/public/cpp/service.h2
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/BUILD.gn4
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/main.cc2
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc31
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h3
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/service_main.h3
-rw-r--r--chromium/services/service_manager/public/cpp/service_executable/switches.cc5
-rw-r--r--chromium/services/service_manager/public/cpp/service_filter.typemap14
-rw-r--r--chromium/services/service_manager/public/cpp/service_keepalive.cc12
-rw-r--r--chromium/services/service_manager/public/cpp/service_keepalive.h16
-rw-r--r--chromium/services/service_manager/public/cpp/service_receiver.cc (renamed from chromium/services/service_manager/public/cpp/service_binding.cc)34
-rw-r--r--chromium/services/service_manager/public/cpp/service_receiver.h (renamed from chromium/services/service_manager/public/cpp/service_binding.h)61
-rw-r--r--chromium/services/service_manager/public/cpp/typemaps.gni6
-rw-r--r--chromium/services/service_manager/public/mojom/BUILD.gn66
-rw-r--r--chromium/services/service_manager/sandbox/BUILD.gn144
-rw-r--r--chromium/services/service_manager/sandbox/DEPS4
-rw-r--r--chromium/services/service_manager/sandbox/OWNERS4
-rw-r--r--chromium/services/service_manager/sandbox/export.h29
-rw-r--r--chromium/services/service_manager/sandbox/features.cc52
-rw-r--r--chromium/services/service_manager/sandbox/features.h39
-rw-r--r--chromium/services/service_manager/sandbox/fuchsia/OWNERS1
-rw-r--r--chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc284
-rw-r--r--chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h62
-rw-r--r--chromium/services/service_manager/sandbox/linux/OWNERS2
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.cc138
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.cc55
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.h46
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.cc149
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.h35
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.cc56
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.cc70
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h30
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.cc67
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h33
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.cc93
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.cc49
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.h27
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.cc44
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.h29
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.cc49
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.cc54
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc111
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.cc45
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.h29
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.cc47
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.h31
-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/bpf_utility_policy_linux.cc55
-rw-r--r--chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.h28
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.cc79
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h26
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_linux.cc563
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_linux.h297
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc282
-rw-r--r--chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h78
-rw-r--r--chromium/services/service_manager/sandbox/mac/BUILD.gn34
-rw-r--r--chromium/services/service_manager/sandbox/mac/DEPS3
-rw-r--r--chromium/services/service_manager/sandbox/mac/OWNERS2
-rw-r--r--chromium/services/service_manager/sandbox/mac/audio.sb67
-rw-r--r--chromium/services/service_manager/sandbox/mac/cdm.sb16
-rw-r--r--chromium/services/service_manager/sandbox/mac/common.sb298
-rw-r--r--chromium/services/service_manager/sandbox/mac/gpu.sb99
-rw-r--r--chromium/services/service_manager/sandbox/mac/gpu_v2.sb116
-rw-r--r--chromium/services/service_manager/sandbox/mac/nacl_loader.sb45
-rw-r--r--chromium/services/service_manager/sandbox/mac/network.sb124
-rwxr-xr-xchromium/services/service_manager/sandbox/mac/package_sb_file.py64
-rw-r--r--chromium/services/service_manager/sandbox/mac/ppapi.sb49
-rw-r--r--chromium/services/service_manager/sandbox/mac/print_compositor.sb33
-rw-r--r--chromium/services/service_manager/sandbox/mac/renderer.sb193
-rw-r--r--chromium/services/service_manager/sandbox/mac/sandbox_mac.h72
-rw-r--r--chromium/services/service_manager/sandbox/mac/sandbox_mac.mm272
-rw-r--r--chromium/services/service_manager/sandbox/mac/utility.sb26
-rw-r--r--chromium/services/service_manager/sandbox/sandbox.cc126
-rw-r--r--chromium/services/service_manager/sandbox/sandbox.h73
-rw-r--r--chromium/services/service_manager/sandbox/sandbox_delegate.h47
-rw-r--r--chromium/services/service_manager/sandbox/sandbox_type.cc329
-rw-r--r--chromium/services/service_manager/sandbox/sandbox_type.h121
-rw-r--r--chromium/services/service_manager/sandbox/switches.cc139
-rw-r--r--chromium/services/service_manager/sandbox/switches.h93
-rw-r--r--chromium/services/service_manager/sandbox/win/OWNERS2
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_diagnostics.cc69
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h48
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_win.cc1138
-rw-r--r--chromium/services/service_manager/sandbox/win/sandbox_win.h102
-rw-r--r--chromium/services/service_manager/service_instance.cc3
-rw-r--r--chromium/services/service_manager/service_instance.h4
-rw-r--r--chromium/services/service_manager/service_manager.cc33
-rw-r--r--chromium/services/service_manager/service_manager.h6
-rw-r--r--chromium/services/service_manager/service_process_host.h4
-rw-r--r--chromium/services/service_manager/service_process_launcher.cc18
-rw-r--r--chromium/services/service_manager/service_process_launcher.h9
-rw-r--r--chromium/services/service_manager/tests/BUILD.gn7
-rw-r--r--chromium/services/service_manager/tests/sandbox/BUILD.gn24
-rw-r--r--chromium/services/shape_detection/BUILD.gn4
-rw-r--r--chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java2
-rw-r--r--chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java2
-rw-r--r--chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java2
-rw-r--r--chromium/services/shape_detection/face_detection_impl_mac_unittest.mm3
-rw-r--r--chromium/services/shape_detection/shape_detection_service.cc10
-rw-r--r--chromium/services/shape_detection/shape_detection_service.h2
-rw-r--r--chromium/services/tracing/BUILD.gn1
-rw-r--r--chromium/services/tracing/perfetto/consumer_host.cc53
-rw-r--r--chromium/services/tracing/perfetto/consumer_host.h7
-rw-r--r--chromium/services/tracing/perfetto/perfetto_integration_unittest.cc44
-rw-r--r--chromium/services/tracing/perfetto/perfetto_service.cc9
-rw-r--r--chromium/services/tracing/perfetto/perfetto_service.h1
-rw-r--r--chromium/services/tracing/perfetto/producer_host.cc4
-rw-r--r--chromium/services/tracing/perfetto/system_perfetto_unittest.cc77
-rw-r--r--chromium/services/tracing/perfetto/test_utils.cc21
-rw-r--r--chromium/services/tracing/perfetto/test_utils.h25
-rw-r--r--chromium/services/tracing/public/cpp/BUILD.gn8
-rw-r--r--chromium/services/tracing/public/cpp/base_agent.h1
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc42
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_config.h6
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_platform.cc57
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_platform.h44
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h4
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_session.cc35
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_session.h31
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc140
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h57
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc654
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h67
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.cc21
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_client.h13
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.cc43
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_event_data_source.h2
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc99
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h78
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer_unittest.cc143
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_time.cc3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/trace_time.h3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc3
-rw-r--r--chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc13
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/reached_code_data_source_android_unittest.cc9
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.cc39
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h19
-rw-r--r--chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler_unittest.cc40
-rw-r--r--chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc1
-rw-r--r--chromium/services/tracing/public/cpp/trace_startup.cc14
-rw-r--r--chromium/services/tracing/public/cpp/traced_process_impl.cc2
-rw-r--r--chromium/services/tracing/public/cpp/tracing_features.cc12
-rw-r--r--chromium/services/tracing/public/cpp/tracing_features.h3
-rw-r--r--chromium/services/tracing/public/mojom/BUILD.gn77
-rw-r--r--chromium/services/tracing/public/mojom/OWNERS2
-rw-r--r--chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h2
-rw-r--r--chromium/services/tracing/public/mojom/commit_data_request_mojom_traits.h2
-rw-r--r--chromium/services/tracing/public/mojom/data_source_config_mojom_traits.h2
-rw-r--r--chromium/services/tracing/public/mojom/data_source_descriptor_mojom_traits.h2
-rw-r--r--chromium/services/tracing/public/mojom/perfetto_service.typemap43
-rw-r--r--chromium/services/tracing/public/mojom/trace_config_mojom_traits.h2
-rw-r--r--chromium/services/tracing/public/mojom/typemaps.gni1
-rw-r--r--chromium/services/tracing/tracing_service.cc37
-rw-r--r--chromium/services/tracing/tracing_service.h5
-rw-r--r--chromium/services/tracing/tracing_service_unittest.cc311
-rw-r--r--chromium/services/video_capture/public/uma/video_capture_service_event.cc2
-rw-r--r--chromium/services/video_capture/public/uma/video_capture_service_event.h4
-rw-r--r--chromium/services/video_capture/texture_virtual_device_mojo_adapter.cc1
-rw-r--r--chromium/services/video_capture/video_capture_service_impl.cc24
-rw-r--r--chromium/services/viz/PRESUBMIT.py4
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/BUILD.gn8
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/DEPS1
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/display_private.mojom6
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom20
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/renderer_settings.mojom11
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc20
-rw-r--r--chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h40
-rw-r--r--chromium/services/viz/privileged/mojom/mojom_traits_unittest.cc21
-rw-r--r--chromium/services/viz/privileged/mojom/viz_main.mojom3
-rw-r--r--chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.cc17
-rw-r--r--chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.h32
-rw-r--r--chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc39
-rw-r--r--chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc17
-rw-r--r--chromium/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc6
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.cc16
-rw-r--r--chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h8
-rw-r--r--chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.cc25
-rw-r--r--chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h23
-rw-r--r--chromium/services/viz/public/cpp/compositing/render_pass_mojom_traits.cc6
-rw-r--r--chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h9
-rw-r--r--chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc4
-rw-r--r--chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h2
-rw-r--r--chromium/services/viz/public/mojom/BUILD.gn47
-rw-r--r--chromium/services/viz/public/mojom/compositing/delegated_ink_point.mojom25
-rw-r--r--chromium/services/viz/public/mojom/compositing/quads.mojom4
-rw-r--r--chromium/services/viz/public/mojom/compositing/render_pass.mojom3
-rw-r--r--chromium/services/viz/public/mojom/compositing/render_pass_id.mojom9
-rw-r--r--chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom5
561 files changed, 12086 insertions, 13977 deletions
diff --git a/chromium/services/BUILD.gn b/chromium/services/BUILD.gn
index cab26e2e9fe..847c1f82650 100644
--- a/chromium/services/BUILD.gn
+++ b/chromium/services/BUILD.gn
@@ -94,7 +94,7 @@ if (!is_ios) {
}
if (is_android) {
- junit_binary("service_junit_tests") {
+ junit_binary("services_junit_tests") {
sources = [
"device/generic_sensor/android/junit/src/org/chromium/device/sensors/PlatformSensorAndProviderTest.java",
"device/geolocation/android/junit/src/org/chromium/device/geolocation/LocationProviderTest.java",
@@ -127,7 +127,7 @@ if (is_android) {
]
}
- android_library("service_javatests") {
+ android_library("services_javatests") {
testonly = true
sources = [
"shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java",
diff --git a/chromium/services/audio/BUILD.gn b/chromium/services/audio/BUILD.gn
index dd4911729ab..84b197a67f2 100644
--- a/chromium/services/audio/BUILD.gn
+++ b/chromium/services/audio/BUILD.gn
@@ -71,24 +71,19 @@ source_set("audio") {
"//media",
"//media/webrtc",
"//services/audio/public/mojom",
- "//services/service_manager/sandbox",
]
- if (is_linux) {
+ if (is_linux || is_chromeos) {
sources += [
"audio_sandbox_hook_linux.cc",
"audio_sandbox_hook_linux.h",
]
- public_deps += [ "//sandbox/linux:sandbox_services" ]
- }
-
- if (is_win) {
- sources += [
- "audio_sandbox_win.cc",
- "audio_sandbox_win.h",
+ public_deps += [
+ "//sandbox/linux:sandbox_services",
+ "//sandbox/policy",
]
- public_deps += [ "//sandbox/win:sandbox" ]
}
+
configs += [
"//build/config/compiler:wexit_time_destructors",
"//media:media_config",
diff --git a/chromium/services/audio/DEPS b/chromium/services/audio/DEPS
index 5c8ac88773d..4e45e6d00ae 100644
--- a/chromium/services/audio/DEPS
+++ b/chromium/services/audio/DEPS
@@ -5,5 +5,4 @@ include_rules = [
"+media/webrtc",
"+sandbox",
"+services/audio/public",
- "+services/service_manager/sandbox",
]
diff --git a/chromium/services/audio/OWNERS b/chromium/services/audio/OWNERS
index e0dbf0d3868..dfd776de26d 100644
--- a/chromium/services/audio/OWNERS
+++ b/chromium/services/audio/OWNERS
@@ -3,6 +3,5 @@ dalecurtis@chromium.org
miu@chromium.org
per-file audio_sandbox_hook_linux.*=file://sandbox/linux/OWNERS
-per-file audio_sandbox_win.*=file://sandbox/win/OWNERS
# COMPONENT: Internals>Media>Audio
diff --git a/chromium/services/audio/audio_sandbox_hook_linux.cc b/chromium/services/audio/audio_sandbox_hook_linux.cc
index dad4537c4c6..e7928a96372 100644
--- a/chromium/services/audio/audio_sandbox_hook_linux.cc
+++ b/chromium/services/audio/audio_sandbox_hook_linux.cc
@@ -174,9 +174,9 @@ void LoadAudioLibraries() {
} // namespace
-bool AudioPreSandboxHook(service_manager::SandboxLinux::Options options) {
+bool AudioPreSandboxHook(sandbox::policy::SandboxLinux::Options options) {
LoadAudioLibraries();
- auto* instance = service_manager::SandboxLinux::GetInstance();
+ auto* instance = sandbox::policy::SandboxLinux::GetInstance();
instance->StartBrokerProcess(MakeBrokerCommandSet({
sandbox::syscall_broker::COMMAND_ACCESS,
#if defined(USE_PULSEAUDIO)
@@ -188,7 +188,7 @@ bool AudioPreSandboxHook(service_manager::SandboxLinux::Options options) {
sandbox::syscall_broker::COMMAND_UNLINK,
}),
GetAudioFilePermissions(),
- service_manager::SandboxLinux::PreSandboxHook(),
+ sandbox::policy::SandboxLinux::PreSandboxHook(),
options);
// TODO(https://crbug.com/850878) enable namespace sandbox. Currently, if
diff --git a/chromium/services/audio/audio_sandbox_hook_linux.h b/chromium/services/audio/audio_sandbox_hook_linux.h
index 528ceaa0790..65a17ccf09e 100644
--- a/chromium/services/audio/audio_sandbox_hook_linux.h
+++ b/chromium/services/audio/audio_sandbox_hook_linux.h
@@ -5,13 +5,13 @@
#ifndef SERVICES_AUDIO_AUDIO_SANDBOX_HOOK_LINUX_H_
#define SERVICES_AUDIO_AUDIO_SANDBOX_HOOK_LINUX_H_
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "sandbox/policy/linux/sandbox_linux.h"
namespace audio {
// Load audio shared libraries and setup allowed commands and filesystem
// permissions for audio service sandboxed process.
-bool AudioPreSandboxHook(service_manager::SandboxLinux::Options options);
+bool AudioPreSandboxHook(sandbox::policy::SandboxLinux::Options options);
} // namespace audio
diff --git a/chromium/services/audio/audio_sandbox_win.cc b/chromium/services/audio/audio_sandbox_win.cc
deleted file mode 100644
index c6f1c552383..00000000000
--- a/chromium/services/audio/audio_sandbox_win.cc
+++ /dev/null
@@ -1,58 +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.
-
-#include "services/audio/audio_sandbox_win.h"
-
-#include "sandbox/win/src/sandbox_policy.h"
-
-// NOTE: changes to this code need to be reviewed by the security team.
-
-namespace audio {
-
-//------------------------------------------------------------------------------
-// Public audio service sandbox configuration extension functions.
-//------------------------------------------------------------------------------
-//
-// Default policy:
-//
-// lockdown_level_(sandbox::USER_LOCKDOWN),
-// initial_level_(sandbox::USER_RESTRICTED_SAME_ACCESS),
-//
-// job_level_(sandbox::JOB_LOCKDOWN),
-//
-// integrity_level_(sandbox::INTEGRITY_LEVEL_LOW),
-// delayed_integrity_level_(sandbox::INTEGRITY_LEVEL_UNTRUSTED),
-
-bool AudioPreSpawnTarget(sandbox::TargetPolicy* policy) {
- // Audio process privilege requirements:
- // - Lockdown level of USER_NON_ADMIN
- // - Delayed integrity level of INTEGRITY_LEVEL_LOW
- //
- // For audio streams to create shared memory regions, lockdown level must be
- // at least USER_LIMITED and delayed integrity level INTEGRITY_LEVEL_LOW,
- // otherwise CreateFileMapping() will fail with error code ERROR_ACCESS_DENIED
- // (0x5).
- //
- // For audio input streams to use ISimpleAudioVolume interface, lockdown
- // level must be set to USER_NON_ADMIN, otherwise
- // WASAPIAudioInputStream::Open() will fail with error code E_ACCESSDENIED
- // (0x80070005) when trying to get a reference to ISimpleAudioVolume
- // interface. See
- // https://cs.chromium.org/chromium/src/media/audio/win/audio_low_latency_input_win.cc
- // Use USER_RESTRICTED_NON_ADMIN over USER_NON_ADMIN to prevent failures when
- // AppLocker and similar application whitelisting solutions are in place.
- policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
- sandbox::USER_RESTRICTED_NON_ADMIN);
- policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
-
- // Custom default policy allowing audio drivers to read device properties
- // (https://crbug.com/883326).
- policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
- policy->SetLockdownDefaultDacl();
- policy->SetAlternateDesktop(true);
-
- return true;
-}
-
-} // namespace audio
diff --git a/chromium/services/audio/audio_sandbox_win.h b/chromium/services/audio/audio_sandbox_win.h
deleted file mode 100644
index 8ce8cb0c7e1..00000000000
--- a/chromium/services/audio/audio_sandbox_win.h
+++ /dev/null
@@ -1,25 +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.
-
-#ifndef SERVICES_AUDIO_AUDIO_SANDBOX_WIN_H_
-#define SERVICES_AUDIO_AUDIO_SANDBOX_WIN_H_
-
-namespace sandbox {
-class TargetPolicy;
-}
-
-// These sandbox-config extension functions should be called from
-// UtilitySandboxedProcessLauncherDelegate on Windows (or the appropriate
-// Delegate if SandboxType::kAudio is removed from SandboxType::kUtility).
-//
-// NOTE: changes to this code need to be reviewed by the security team.
-
-namespace audio {
-
-// PreSpawnTarget extension.
-bool AudioPreSpawnTarget(sandbox::TargetPolicy* policy);
-
-} // namespace audio
-
-#endif // SERVICES_AUDIO_AUDIO_SANDBOX_WIN_H_
diff --git a/chromium/services/audio/loopback_stream_unittest.cc b/chromium/services/audio/loopback_stream_unittest.cc
index e1e7d53b084..aa7ee9b38a2 100644
--- a/chromium/services/audio/loopback_stream_unittest.cc
+++ b/chromium/services/audio/loopback_stream_unittest.cc
@@ -152,8 +152,7 @@ class LoopbackStreamTest : public testing::Test {
sources_.emplace_back(std::make_unique<FakeLoopbackGroupMember>(
media::AudioParameters(media::AudioParameters::AUDIO_PCM_LOW_LATENCY,
media::GuessChannelLayout(channels), sample_rate,
- (sample_rate * kBufferDuration) /
- base::TimeDelta::FromSeconds(1))));
+ (sample_rate * kBufferDuration).InSeconds())));
coordinator_.RegisterMember(group_id_, sources_.back().get());
return sources_.back().get();
}
diff --git a/chromium/services/audio/service.cc b/chromium/services/audio/service.cc
index 23bb03023ac..5eacb4c74c0 100644
--- a/chromium/services/audio/service.cc
+++ b/chromium/services/audio/service.cc
@@ -24,7 +24,7 @@
#include "services/audio/service_metrics.h"
#include "services/audio/system_info.h"
-#if defined(OS_MACOSX)
+#if defined(OS_APPLE)
#include "media/audio/mac/audio_device_listener_mac.h"
#endif
@@ -158,7 +158,7 @@ void Service::BindTestingApi(
void Service::InitializeDeviceMonitor() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
-#if defined(OS_MACOSX)
+#if defined(OS_APPLE)
if (audio_device_listener_mac_)
return;
diff --git a/chromium/services/audio/service.h b/chromium/services/audio/service.h
index cf433ad39ed..0b8343bba04 100644
--- a/chromium/services/audio/service.h
+++ b/chromium/services/audio/service.h
@@ -115,7 +115,7 @@ class Service : public mojom::AudioService {
std::unique_ptr<AudioManagerAccessor> audio_manager_accessor_;
const bool enable_remote_client_support_;
std::unique_ptr<base::SystemMonitor> system_monitor_;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
std::unique_ptr<media::AudioDeviceListenerMac> audio_device_listener_mac_;
#endif
std::unique_ptr<SystemInfo> system_info_;
diff --git a/chromium/services/audio/snooper_node_unittest.cc b/chromium/services/audio/snooper_node_unittest.cc
index 63ac9c0aba9..31c606340f6 100644
--- a/chromium/services/audio/snooper_node_unittest.cc
+++ b/chromium/services/audio/snooper_node_unittest.cc
@@ -336,7 +336,8 @@ TEST_P(SnooperNodeTest, MAYBE_ContinuousAudioFlowAdaptsToSkew) {
(output_skew * output_delay().InSecondsF())) *
output_params().sample_rate();
const double frames_in_one_millisecond =
- output_params().sample_rate() / 1000.0;
+ output_params().sample_rate() /
+ double{base::Time::kMillisecondsPerSecond};
EXPECT_NEAR(expected_end_of_silence_position,
consumer()->FindEndOfSilence(0, 0),
frames_in_one_millisecond);
@@ -416,7 +417,7 @@ TEST_P(SnooperNodeTest, HandlesMissingInput) {
const int output_frames_in_one_second = output_params().sample_rate();
const int output_frames_in_a_quarter_second = output_frames_in_one_second / 4;
const int output_frames_in_20_milliseconds =
- output_frames_in_one_second * 20 / 1000;
+ output_frames_in_one_second * 20 / base::Time::kMillisecondsPerSecond;
int output_silence_position =
((kInputAdvanceTime + output_delay()).InSecondsF() + 1.0) *
output_params().sample_rate();
@@ -624,7 +625,7 @@ double MapTimeOffsetToATone(base::TimeDelta offset) {
constexpr double kMaxFrequency = 2000;
constexpr int kNumToneSteps = 10;
- const int64_t step_number = offset / (kTestDuration / kNumToneSteps);
+ const int64_t step_number = offset.IntDiv(kTestDuration / kNumToneSteps);
const double t = static_cast<double>(step_number) / kNumToneSteps;
return kMinFrequency + t * (kMaxFrequency - kMinFrequency);
}
diff --git a/chromium/services/audio/sync_reader.cc b/chromium/services/audio/sync_reader.cc
index fbd4b1dc4ab..3b7b5537f2c 100644
--- a/chromium/services/audio/sync_reader.cc
+++ b/chromium/services/audio/sync_reader.cc
@@ -54,7 +54,7 @@ SyncReader::SyncReader(
renderer_callback_count_(0),
renderer_missed_callback_count_(0),
trailing_renderer_missed_callback_count_(0),
-#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
+#if defined(OS_MAC) || defined(OS_CHROMEOS)
maximum_wait_time_(params.GetBufferDuration() / 2),
#else
// TODO(dalecurtis): Investigate if we can reduce this on all platforms.
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/BUILD.gn b/chromium/services/cert_verifier/cert_net_url_loader/BUILD.gn
index 009e8c23e52..3efdc1e8994 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/BUILD.gn
+++ b/chromium/services/cert_verifier/cert_net_url_loader/BUILD.gn
@@ -3,10 +3,9 @@
# found in the LICENSE file.
import("//build/config/crypto.gni")
-import("//build/config/jumbo.gni")
import("//testing/test.gni")
-jumbo_component("cert_net_url_loader") {
+component("cert_net_url_loader") {
sources = [
"cert_net_fetcher_url_loader.cc",
"cert_net_fetcher_url_loader.h",
diff --git a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc
index 86981803d23..264950e90d6 100644
--- a/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc
+++ b/chromium/services/cert_verifier/cert_net_url_loader/cert_net_fetcher_url_loader_unittest.cc
@@ -24,6 +24,7 @@
#include "net/test/gtest_util.h"
#include "net/test/test_with_task_environment.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/url_request.h"
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "services/cert_verifier/cert_net_url_loader/cert_net_fetcher_test.h"
diff --git a/chromium/services/data_decoder/BUILD.gn b/chromium/services/data_decoder/BUILD.gn
index fa455db7aa3..adb398ed3ca 100644
--- a/chromium/services/data_decoder/BUILD.gn
+++ b/chromium/services/data_decoder/BUILD.gn
@@ -10,10 +10,6 @@ source_set("lib") {
"data_decoder_service.h",
"json_parser_impl.cc",
"json_parser_impl.h",
- "web_bundle_parser.cc",
- "web_bundle_parser.h",
- "web_bundle_parser_factory.cc",
- "web_bundle_parser_factory.h",
"web_bundler.cc",
"web_bundler.h",
"xml_parser.cc",
@@ -31,7 +27,7 @@ source_set("lib") {
deps = [
"//base",
- "//components/cbor",
+ "//components/web_package",
"//mojo/public/cpp/bindings",
"//net",
"//skia",
@@ -60,8 +56,6 @@ source_set("tests") {
"public/cpp/json_sanitizer_unittest.cc",
"public/cpp/safe_web_bundle_parser_unittest.cc",
"public/cpp/safe_xml_parser_unittest.cc",
- "web_bundle_parser_factory_unittest.cc",
- "web_bundle_parser_unittest.cc",
"xml_parser_unittest.cc",
]
@@ -73,7 +67,6 @@ source_set("tests") {
":lib",
"//base",
"//base/test:test_support",
- "//components/cbor",
"//services/data_decoder/public/cpp",
"//services/data_decoder/public/cpp:test_support",
"//skia",
@@ -81,6 +74,8 @@ source_set("tests") {
"//ui/gfx",
]
+ data = [ "//components/test/data/web_package/" ]
+
if (!is_ios) {
sources += [ "image_decoder_impl_unittest.cc" ]
deps += [
@@ -96,16 +91,6 @@ source_set("tests") {
}
}
-fuzzer_test("web_bundle_parser_fuzzer") {
- sources = [ "web_bundle_parser_fuzzer.cc" ]
- deps = [
- ":lib",
- "//base",
- "//mojo/core/embedder",
- ]
- seed_corpus = "//services/test/data/web_bundle"
-}
-
fuzzer_test("xml_parser_fuzzer") {
sources = [ "xml_parser_fuzzer.cc" ]
deps = [
diff --git a/chromium/services/data_decoder/DEPS b/chromium/services/data_decoder/DEPS
index f8f08e37243..bd2835402c1 100644
--- a/chromium/services/data_decoder/DEPS
+++ b/chromium/services/data_decoder/DEPS
@@ -1,5 +1,5 @@
include_rules = [
- "+components/cbor",
+ "+components/web_package",
"+device/bluetooth/public",
"+gin",
"+net",
diff --git a/chromium/services/data_decoder/data_decoder_service.cc b/chromium/services/data_decoder/data_decoder_service.cc
index f841ce45bfa..96f6a3aeb85 100644
--- a/chromium/services/data_decoder/data_decoder_service.cc
+++ b/chromium/services/data_decoder/data_decoder_service.cc
@@ -11,11 +11,11 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
+#include "components/web_package/web_bundle_parser_factory.h"
#include "mojo/public/cpp/bindings/generic_pending_receiver.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/data_decoder/json_parser_impl.h"
#include "services/data_decoder/public/mojom/image_decoder.mojom.h"
-#include "services/data_decoder/web_bundle_parser_factory.h"
#include "services/data_decoder/web_bundler.h"
#include "services/data_decoder/xml_parser.h"
@@ -70,12 +70,14 @@ void DataDecoderService::BindXmlParser(
}
void DataDecoderService::BindWebBundleParserFactory(
- mojo::PendingReceiver<mojom::WebBundleParserFactory> receiver) {
+ mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>
+ receiver) {
if (web_bundle_parser_factory_binder_) {
web_bundle_parser_factory_binder_.Run(std::move(receiver));
} else {
- mojo::MakeSelfOwnedReceiver(std::make_unique<WebBundleParserFactory>(),
- std::move(receiver));
+ mojo::MakeSelfOwnedReceiver(
+ std::make_unique<web_package::WebBundleParserFactory>(),
+ std::move(receiver));
}
}
diff --git a/chromium/services/data_decoder/data_decoder_service.h b/chromium/services/data_decoder/data_decoder_service.h
index b3999002ffe..3e079b2a9f4 100644
--- a/chromium/services/data_decoder/data_decoder_service.h
+++ b/chromium/services/data_decoder/data_decoder_service.h
@@ -8,12 +8,12 @@
#include <memory>
#include "base/macros.h"
+#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "services/data_decoder/public/mojom/data_decoder_service.mojom.h"
#include "services/data_decoder/public/mojom/image_decoder.mojom.h"
#include "services/data_decoder/public/mojom/json_parser.mojom.h"
-#include "services/data_decoder/public/mojom/web_bundle_parser.mojom.h"
#include "services/data_decoder/public/mojom/web_bundler.mojom.h"
#include "services/data_decoder/public/mojom/xml_parser.mojom.h"
@@ -50,8 +50,9 @@ class DataDecoderService : public mojom::DataDecoderService {
// WebBundleParserFactory in subsequent
// BindWebBundleParserFactory() calls.
void SetWebBundleParserFactoryBinderForTesting(
- base::RepeatingCallback<
- void(mojo::PendingReceiver<mojom::WebBundleParserFactory>)> binder) {
+ base::RepeatingCallback<void(
+ mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>)>
+ binder) {
web_bundle_parser_factory_binder_ = binder;
}
@@ -71,7 +72,8 @@ class DataDecoderService : public mojom::DataDecoderService {
mojo::PendingReceiver<mojom::JsonParser> receiver) override;
void BindXmlParser(mojo::PendingReceiver<mojom::XmlParser> receiver) override;
void BindWebBundleParserFactory(
- mojo::PendingReceiver<mojom::WebBundleParserFactory> receiver) override;
+ mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>
+ receiver) override;
void BindWebBundler(
mojo::PendingReceiver<mojom::WebBundler> receiver) override;
@@ -87,7 +89,7 @@ class DataDecoderService : public mojom::DataDecoderService {
bool drop_image_decoders_ = false;
bool drop_json_parsers_ = false;
base::RepeatingCallback<void(
- mojo::PendingReceiver<mojom::WebBundleParserFactory>)>
+ mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>)>
web_bundle_parser_factory_binder_;
base::RepeatingCallback<void(mojo::PendingReceiver<mojom::WebBundler>)>
web_bundler_binder_;
diff --git a/chromium/services/data_decoder/image_decoder_impl.cc b/chromium/services/data_decoder/image_decoder_impl.cc
index 9ba119aa9fe..16677c88c0e 100644
--- a/chromium/services/data_decoder/image_decoder_impl.cc
+++ b/chromium/services/data_decoder/image_decoder_impl.cc
@@ -8,7 +8,6 @@
#include <utility>
-#include "mojo/public/cpp/bindings/strong_binding.h"
#include "skia/ext/image_operations.h"
#include "third_party/blink/public/platform/web_data.h"
#include "third_party/blink/public/platform/web_size.h"
diff --git a/chromium/services/data_decoder/public/cpp/BUILD.gn b/chromium/services/data_decoder/public/cpp/BUILD.gn
index 4dd89896df9..16ef9b7c14a 100644
--- a/chromium/services/data_decoder/public/cpp/BUILD.gn
+++ b/chromium/services/data_decoder/public/cpp/BUILD.gn
@@ -77,12 +77,8 @@ source_set("test_support") {
sources = [
"test_support/in_process_data_decoder.cc",
"test_support/in_process_data_decoder.h",
- "test_support/web_bundle_builder.cc",
- "test_support/web_bundle_builder.h",
]
- deps = [ "//components/cbor" ]
-
public_deps = [
":cpp",
"//base",
diff --git a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.cc b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.cc
index bd8c57d2809..ac1d849e668 100644
--- a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.cc
+++ b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.cc
@@ -34,7 +34,7 @@ base::File::Error SafeWebBundleParser::OpenFile(base::File file) {
}
void SafeWebBundleParser::OpenDataSource(
- mojo::PendingRemote<mojom::BundleDataSource> data_source) {
+ mojo::PendingRemote<web_package::mojom::BundleDataSource> data_source) {
DCHECK(disconnected_);
GetFactory()->GetParserForDataSource(parser_.BindNewPipeAndPassReceiver(),
std::move(data_source));
@@ -45,14 +45,15 @@ void SafeWebBundleParser::OpenDataSource(
}
void SafeWebBundleParser::ParseMetadata(
- mojom::WebBundleParser::ParseMetadataCallback callback) {
+ web_package::mojom::WebBundleParser::ParseMetadataCallback callback) {
// This method is designed to be called once. So, allowing only once
// simultaneous request is fine enough.
if (disconnected_ || !metadata_callback_.is_null()) {
std::move(callback).Run(
- nullptr, mojom::BundleMetadataParseError::New(
- mojom::BundleParseErrorType::kParserInternalError,
- GURL() /* fallback_url */, kConnectionError));
+ nullptr,
+ web_package::mojom::BundleMetadataParseError::New(
+ web_package::mojom::BundleParseErrorType::kParserInternalError,
+ GURL() /* fallback_url */, kConnectionError));
return;
}
metadata_callback_ = std::move(callback);
@@ -63,16 +64,17 @@ void SafeWebBundleParser::ParseMetadata(
void SafeWebBundleParser::ParseResponse(
uint64_t response_offset,
uint64_t response_length,
- mojom::WebBundleParser::ParseResponseCallback callback) {
+ web_package::mojom::WebBundleParser::ParseResponseCallback callback) {
// This method allows simultaneous multiple requests. But if the unique ID
// overflows, and the previous request that owns the same ID hasn't finished,
// we just make the new request fail with kConnectionError.
if (disconnected_ ||
response_callbacks_.contains(response_callback_next_id_)) {
std::move(callback).Run(
- nullptr, mojom::BundleResponseParseError::New(
- mojom::BundleParseErrorType::kParserInternalError,
- kConnectionError));
+ nullptr,
+ web_package::mojom::BundleResponseParseError::New(
+ web_package::mojom::BundleParseErrorType::kParserInternalError,
+ kConnectionError));
return;
}
size_t callback_id = response_callback_next_id_++;
@@ -82,7 +84,7 @@ void SafeWebBundleParser::ParseResponse(
base::Unretained(this), callback_id));
}
-mojom::WebBundleParserFactory* SafeWebBundleParser::GetFactory() {
+web_package::mojom::WebBundleParserFactory* SafeWebBundleParser::GetFactory() {
if (!factory_) {
data_decoder_.GetService()->BindWebBundleParserFactory(
factory_.BindNewPipeAndPassReceiver());
@@ -100,30 +102,32 @@ void SafeWebBundleParser::OnDisconnect() {
disconnected_ = true;
if (!metadata_callback_.is_null())
std::move(metadata_callback_)
- .Run(nullptr, mojom::BundleMetadataParseError::New(
- mojom::BundleParseErrorType::kParserInternalError,
- GURL() /* fallback_url */, kConnectionError));
+ .Run(nullptr,
+ web_package::mojom::BundleMetadataParseError::New(
+ web_package::mojom::BundleParseErrorType::kParserInternalError,
+ GURL() /* fallback_url */, kConnectionError));
for (auto& callback : response_callbacks_)
std::move(callback.second)
- .Run(nullptr, mojom::BundleResponseParseError::New(
- mojom::BundleParseErrorType::kParserInternalError,
- kConnectionError));
+ .Run(nullptr,
+ web_package::mojom::BundleResponseParseError::New(
+ web_package::mojom::BundleParseErrorType::kParserInternalError,
+ kConnectionError));
response_callbacks_.clear();
if (disconnect_callback_)
std::move(disconnect_callback_).Run();
}
void SafeWebBundleParser::OnMetadataParsed(
- mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error) {
+ web_package::mojom::BundleMetadataPtr metadata,
+ web_package::mojom::BundleMetadataParseErrorPtr error) {
DCHECK(!metadata_callback_.is_null());
std::move(metadata_callback_).Run(std::move(metadata), std::move(error));
}
void SafeWebBundleParser::OnResponseParsed(
size_t callback_id,
- mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error) {
+ web_package::mojom::BundleResponsePtr response,
+ web_package::mojom::BundleResponseParseErrorPtr error) {
auto it = response_callbacks_.find(callback_id);
DCHECK(it != response_callbacks_.end());
auto callback = std::move(it->second);
diff --git a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.h b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.h
index 2ef665c1bef..d2097aa1d2c 100644
--- a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.h
+++ b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser.h
@@ -10,16 +10,16 @@
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/optional.h"
+#include "components/web_package/mojom/web_bundle_parser.mojom.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/data_decoder/public/cpp/data_decoder.h"
-#include "services/data_decoder/public/mojom/web_bundle_parser.mojom.h"
namespace data_decoder {
-// A class to wrap remote mojom::WebBundleParserFactory and
-// mojom::WebBundleParser service.
+// A class to wrap remote web_package::mojom::WebBundleParserFactory and
+// web_package::mojom::WebBundleParser service.
class SafeWebBundleParser {
public:
SafeWebBundleParser();
@@ -31,37 +31,41 @@ class SafeWebBundleParser {
// Binds |this| instance to the given |data_source| for subsequent parse
// calls.
- void OpenDataSource(mojo::PendingRemote<mojom::BundleDataSource> data_source);
+ void OpenDataSource(
+ mojo::PendingRemote<web_package::mojom::BundleDataSource> data_source);
- // Parses metadata. See mojom::WebBundleParser::ParseMetadata for
+ // Parses metadata. See web_package::mojom::WebBundleParser::ParseMetadata for
// details. This method fails when it's called before the previous call
// finishes.
- void ParseMetadata(mojom::WebBundleParser::ParseMetadataCallback callback);
+ void ParseMetadata(
+ web_package::mojom::WebBundleParser::ParseMetadataCallback callback);
- // Parses response. See mojom::WebBundleParser::ParseResponse for
+ // Parses response. See web_package::mojom::WebBundleParser::ParseResponse for
// details.
- void ParseResponse(uint64_t response_offset,
- uint64_t response_length,
- mojom::WebBundleParser::ParseResponseCallback callback);
+ void ParseResponse(
+ uint64_t response_offset,
+ uint64_t response_length,
+ web_package::mojom::WebBundleParser::ParseResponseCallback callback);
// Sets a callback to be called when the data_decoder service connection is
// terminated.
void SetDisconnectCallback(base::OnceClosure callback);
private:
- mojom::WebBundleParserFactory* GetFactory();
+ web_package::mojom::WebBundleParserFactory* GetFactory();
void OnDisconnect();
- void OnMetadataParsed(mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error);
+ void OnMetadataParsed(web_package::mojom::BundleMetadataPtr metadata,
+ web_package::mojom::BundleMetadataParseErrorPtr error);
void OnResponseParsed(size_t callback_id,
- mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error);
+ web_package::mojom::BundleResponsePtr response,
+ web_package::mojom::BundleResponseParseErrorPtr error);
DataDecoder data_decoder_;
- mojo::Remote<mojom::WebBundleParserFactory> factory_;
- mojo::Remote<mojom::WebBundleParser> parser_;
- mojom::WebBundleParser::ParseMetadataCallback metadata_callback_;
- base::flat_map<size_t, mojom::WebBundleParser::ParseResponseCallback>
+ mojo::Remote<web_package::mojom::WebBundleParserFactory> factory_;
+ mojo::Remote<web_package::mojom::WebBundleParser> parser_;
+ web_package::mojom::WebBundleParser::ParseMetadataCallback metadata_callback_;
+ base::flat_map<size_t,
+ web_package::mojom::WebBundleParser::ParseResponseCallback>
response_callbacks_;
base::OnceClosure disconnect_callback_;
size_t response_callback_next_id_ = 0;
diff --git a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc
index 8709166d18b..c6877ede504 100644
--- a/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc
+++ b/chromium/services/data_decoder/public/cpp/safe_web_bundle_parser_unittest.cc
@@ -29,17 +29,18 @@ base::File OpenTestFile(const base::FilePath& path) {
base::FilePath test_data_dir;
base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir);
test_data_dir = test_data_dir.Append(
- base::FilePath(FILE_PATH_LITERAL("services/test/data/web_bundle")));
+ base::FilePath(FILE_PATH_LITERAL("components/test/data/web_package")));
test_data_dir = test_data_dir.Append(path);
return base::File(test_data_dir,
base::File::FLAG_OPEN | base::File::FLAG_READ);
}
-class MockFactory final : public mojom::WebBundleParserFactory {
+class MockFactory final : public web_package::mojom::WebBundleParserFactory {
public:
- class MockParser final : public mojom::WebBundleParser {
+ class MockParser final : public web_package::mojom::WebBundleParser {
public:
- MockParser(mojo::PendingReceiver<mojom::WebBundleParser> receiver)
+ explicit MockParser(
+ mojo::PendingReceiver<web_package::mojom::WebBundleParser> receiver)
: receiver_(this, std::move(receiver)) {}
bool IsParseMetadataCalled() { return !metadata_callback_.is_null(); }
@@ -48,7 +49,7 @@ class MockFactory final : public mojom::WebBundleParserFactory {
void Disconnect() { receiver_.reset(); }
private:
- // mojom::WebBundleParser implementation.
+ // web_package::mojom::WebBundleParser implementation.
void ParseMetadata(ParseMetadataCallback callback) override {
metadata_callback_ = std::move(callback);
}
@@ -60,14 +61,15 @@ class MockFactory final : public mojom::WebBundleParserFactory {
ParseMetadataCallback metadata_callback_;
ParseResponseCallback response_callback_;
- mojo::Receiver<mojom::WebBundleParser> receiver_;
+ mojo::Receiver<web_package::mojom::WebBundleParser> receiver_;
DISALLOW_COPY_AND_ASSIGN(MockParser);
};
MockFactory() {}
void AddReceiver(
- mojo::PendingReceiver<mojom::WebBundleParserFactory> receiver) {
+ mojo::PendingReceiver<web_package::mojom::WebBundleParserFactory>
+ receiver) {
receivers_.Add(this, std::move(receiver));
}
MockParser* GetCreatedParser() {
@@ -77,33 +79,36 @@ class MockFactory final : public mojom::WebBundleParserFactory {
void DeleteParser() { parser_.reset(); }
private:
- // mojom::WebBundleParserFactory implementation.
- void GetParserForFile(mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- base::File file) override {
+ // web_package::mojom::WebBundleParserFactory implementation.
+ void GetParserForFile(
+ mojo::PendingReceiver<web_package::mojom::WebBundleParser> receiver,
+ base::File file) override {
parser_ = std::make_unique<MockParser>(std::move(receiver));
}
void GetParserForDataSource(
- mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- mojo::PendingRemote<mojom::BundleDataSource> data_source) override {
+ mojo::PendingReceiver<web_package::mojom::WebBundleParser> receiver,
+ mojo::PendingRemote<web_package::mojom::BundleDataSource> data_source)
+ override {
parser_ = std::make_unique<MockParser>(std::move(receiver));
}
std::unique_ptr<MockParser> parser_;
- mojo::ReceiverSet<data_decoder::mojom::WebBundleParserFactory> receivers_;
+ mojo::ReceiverSet<web_package::mojom::WebBundleParserFactory> receivers_;
DISALLOW_COPY_AND_ASSIGN(MockFactory);
};
-class MockDataSource final : public mojom::BundleDataSource {
+class MockDataSource final : public web_package::mojom::BundleDataSource {
public:
- MockDataSource(mojo::PendingReceiver<mojom::BundleDataSource> receiver)
+ explicit MockDataSource(
+ mojo::PendingReceiver<web_package::mojom::BundleDataSource> receiver)
: receiver_(this, std::move(receiver)) {}
private:
- // Implements mojom::BundledDataSource.
+ // Implements web_package::mojom::BundledDataSource.
void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {}
- mojo::Receiver<mojom::BundleDataSource> receiver_;
+ mojo::Receiver<web_package::mojom::BundleDataSource> receiver_;
DISALLOW_COPY_AND_ASSIGN(MockDataSource);
};
@@ -135,14 +140,14 @@ TEST_F(SafeWebBundleParserTest, ParseGoldenFile) {
OpenTestFile(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
ASSERT_EQ(base::File::FILE_OK, parser.OpenFile(std::move(test_file)));
- mojom::BundleMetadataPtr metadata_result;
+ web_package::mojom::BundleMetadataPtr metadata_result;
{
base::RunLoop run_loop;
parser.ParseMetadata(base::BindOnce(
[](base::OnceClosure quit_closure,
- mojom::BundleMetadataPtr* metadata_result,
- mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error) {
+ web_package::mojom::BundleMetadataPtr* metadata_result,
+ web_package::mojom::BundleMetadataPtr metadata,
+ web_package::mojom::BundleMetadataParseErrorPtr error) {
EXPECT_TRUE(metadata);
EXPECT_FALSE(error);
if (metadata)
@@ -156,7 +161,7 @@ TEST_F(SafeWebBundleParserTest, ParseGoldenFile) {
const auto& requests = metadata_result->requests;
ASSERT_EQ(requests.size(), 4u);
- std::map<std::string, mojom::BundleResponsePtr> responses;
+ std::map<std::string, web_package::mojom::BundleResponsePtr> responses;
for (auto& entry : requests) {
base::RunLoop run_loop;
parser.ParseResponse(
@@ -164,9 +169,10 @@ TEST_F(SafeWebBundleParserTest, ParseGoldenFile) {
entry.second->response_locations[0]->length,
base::BindOnce(
[](base::OnceClosure quit_closure, const std::string url,
- std::map<std::string, mojom::BundleResponsePtr>* responses,
- mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error) {
+ std::map<std::string, web_package::mojom::BundleResponsePtr>*
+ responses,
+ web_package::mojom::BundleResponsePtr response,
+ web_package::mojom::BundleResponseParseErrorPtr error) {
EXPECT_TRUE(response);
EXPECT_FALSE(error);
if (response)
@@ -196,8 +202,8 @@ TEST_F(SafeWebBundleParserTest, CallWithoutOpen) {
SafeWebBundleParser parser;
bool metadata_parsed = false;
parser.ParseMetadata(base::BindOnce(
- [](bool* metadata_parsed, mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error) {
+ [](bool* metadata_parsed, web_package::mojom::BundleMetadataPtr metadata,
+ web_package::mojom::BundleMetadataParseErrorPtr error) {
EXPECT_FALSE(metadata);
EXPECT_TRUE(error);
if (error)
@@ -211,8 +217,9 @@ TEST_F(SafeWebBundleParserTest, CallWithoutOpen) {
parser.ParseResponse(
0u, 0u,
base::BindOnce(
- [](bool* response_parsed, mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error) {
+ [](bool* response_parsed,
+ web_package::mojom::BundleResponsePtr response,
+ web_package::mojom::BundleResponseParseErrorPtr error) {
EXPECT_FALSE(response);
EXPECT_TRUE(error);
if (error)
@@ -250,7 +257,7 @@ TEST_F(SafeWebBundleParserTest, ConnectionError) {
SafeWebBundleParser parser;
MockFactory* raw_factory = InitializeMockFactory();
- mojo::PendingRemote<mojom::BundleDataSource> remote_data_source;
+ mojo::PendingRemote<web_package::mojom::BundleDataSource> remote_data_source;
auto data_source = std::make_unique<MockDataSource>(
remote_data_source.InitWithNewPipeAndPassReceiver());
parser.OpenDataSource(std::move(remote_data_source));
@@ -260,8 +267,8 @@ TEST_F(SafeWebBundleParserTest, ConnectionError) {
bool parsed = false;
parser.ParseMetadata(base::BindOnce(
[](base::OnceClosure quit_closure, bool* parsed,
- mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error) {
+ web_package::mojom::BundleMetadataPtr metadata,
+ web_package::mojom::BundleMetadataParseErrorPtr error) {
EXPECT_FALSE(metadata);
EXPECT_TRUE(error);
if (error)
diff --git a/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.cc b/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.cc
deleted file mode 100644
index 8155e97d512..00000000000
--- a/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-// 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/data_decoder/public/cpp/test_support/web_bundle_builder.h"
-
-namespace data_decoder {
-namespace test {
-
-namespace {
-
-cbor::Value CreateByteString(base::StringPiece s) {
- return cbor::Value(base::as_bytes(base::make_span(s)));
-}
-
-cbor::Value CreateHeaderMap(const WebBundleBuilder::Headers& headers) {
- cbor::Value::MapValue map;
- for (const auto& pair : headers)
- map.insert({CreateByteString(pair.first), CreateByteString(pair.second)});
- return cbor::Value(std::move(map));
-}
-
-} // namespace
-
-WebBundleBuilder::WebBundleBuilder(const std::string& fallback_url,
- const std::string& manifest_url)
- : fallback_url_(fallback_url) {
- writer_config_.allow_invalid_utf8_for_testing = true;
- if (!manifest_url.empty()) {
- AddSection("manifest",
- cbor::Value::InvalidUTF8StringValueForTesting(manifest_url));
- }
-}
-
-WebBundleBuilder::~WebBundleBuilder() = default;
-
-void WebBundleBuilder::AddExchange(base::StringPiece url,
- const Headers& response_headers,
- base::StringPiece payload) {
- AddIndexEntry(url, "", {AddResponse(response_headers, payload)});
-}
-
-WebBundleBuilder::ResponseLocation WebBundleBuilder::AddResponse(
- const Headers& headers,
- base::StringPiece payload) {
- // We assume that the size of the CBOR header of the responses array is 1,
- // which is true only if the responses array has no more than 23 elements.
- DCHECK_LT(responses_.size(), 23u)
- << "WebBundleBuilder cannot create bundles with more than 23 responses";
-
- cbor::Value::ArrayValue response_array;
- response_array.emplace_back(Encode(CreateHeaderMap(headers)));
- response_array.emplace_back(CreateByteString(payload));
- cbor::Value response(response_array);
- int64_t response_length = EncodedLength(response);
- ResponseLocation result = {current_responses_offset_, response_length};
- current_responses_offset_ += response_length;
- responses_.emplace_back(std::move(response));
- return result;
-}
-
-void WebBundleBuilder::AddIndexEntry(
- base::StringPiece url,
- base::StringPiece variants_value,
- std::vector<ResponseLocation> response_locations) {
- cbor::Value::ArrayValue index_value_array;
- index_value_array.emplace_back(CreateByteString(variants_value));
- for (const auto& location : response_locations) {
- index_value_array.emplace_back(location.offset);
- index_value_array.emplace_back(location.length);
- }
- index_.insert({cbor::Value::InvalidUTF8StringValueForTesting(url),
- cbor::Value(index_value_array)});
-}
-
-void WebBundleBuilder::AddSection(base::StringPiece name, cbor::Value section) {
- section_lengths_.emplace_back(name);
- section_lengths_.emplace_back(EncodedLength(section));
- sections_.emplace_back(std::move(section));
-}
-
-void WebBundleBuilder::AddAuthority(cbor::Value::MapValue authority) {
- authorities_.emplace_back(std::move(authority));
-}
-
-void WebBundleBuilder::AddVouchedSubset(cbor::Value::MapValue vouched_subset) {
- vouched_subsets_.emplace_back(std::move(vouched_subset));
-}
-
-std::vector<uint8_t> WebBundleBuilder::CreateBundle() {
- AddSection("index", cbor::Value(index_));
- if (!authorities_.empty() || !vouched_subsets_.empty()) {
- cbor::Value::ArrayValue signatures_section;
- signatures_section.emplace_back(std::move(authorities_));
- signatures_section.emplace_back(std::move(vouched_subsets_));
- AddSection("signatures", cbor::Value(std::move(signatures_section)));
- }
- AddSection("responses", cbor::Value(responses_));
- return Encode(CreateTopLevel());
-}
-
-cbor::Value WebBundleBuilder::CreateEncodedSigned(
- base::StringPiece validity_url,
- base::StringPiece auth_sha256,
- int64_t date,
- int64_t expires,
- base::StringPiece url,
- base::StringPiece header_sha256,
- base::StringPiece payload_integrity_header) {
- cbor::Value::ArrayValue subset_hash_value;
- subset_hash_value.emplace_back(CreateByteString("")); // variants-value
- subset_hash_value.emplace_back(CreateByteString(header_sha256));
- subset_hash_value.emplace_back(payload_integrity_header);
-
- cbor::Value::MapValue subset_hashes;
- subset_hashes.emplace(url, std::move(subset_hash_value));
-
- cbor::Value::MapValue signed_subset;
- signed_subset.emplace("validity-url", validity_url);
- signed_subset.emplace("auth-sha256", CreateByteString(auth_sha256));
- signed_subset.emplace("date", date);
- signed_subset.emplace("expires", expires);
- signed_subset.emplace("subset-hashes", std::move(subset_hashes));
- return cbor::Value(Encode(cbor::Value(signed_subset)));
-}
-
-cbor::Value WebBundleBuilder::CreateTopLevel() {
- cbor::Value::ArrayValue toplevel_array;
- toplevel_array.emplace_back(
- CreateByteString(u8"\U0001F310\U0001F4E6")); // "🌐📦"
- toplevel_array.emplace_back(CreateByteString(base::StringPiece("b1\0\0", 4)));
- toplevel_array.emplace_back(
- cbor::Value::InvalidUTF8StringValueForTesting(fallback_url_));
- toplevel_array.emplace_back(Encode(cbor::Value(section_lengths_)));
- toplevel_array.emplace_back(sections_);
- toplevel_array.emplace_back(CreateByteString("")); // length (ignored)
- return cbor::Value(toplevel_array);
-}
-
-std::vector<uint8_t> WebBundleBuilder::Encode(const cbor::Value& value) {
- return *cbor::Writer::Write(value, writer_config_);
-}
-
-int64_t WebBundleBuilder::EncodedLength(const cbor::Value& value) {
- return Encode(value).size();
-}
-
-} // namespace test
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.h b/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.h
deleted file mode 100644
index 71267ac3ec7..00000000000
--- a/chromium/services/data_decoder/public/cpp/test_support/web_bundle_builder.h
+++ /dev/null
@@ -1,80 +0,0 @@
-// 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_DATA_DECODER_PUBLIC_CPP_TEST_SUPPORT_WEB_BUNDLE_BUILDER_H_
-#define SERVICES_DATA_DECODER_PUBLIC_CPP_TEST_SUPPORT_WEB_BUNDLE_BUILDER_H_
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/strings/string_piece.h"
-#include "components/cbor/writer.h"
-
-namespace data_decoder {
-namespace test {
-
-// This class can be used to create a Web Bundle binary in tests.
-class WebBundleBuilder {
- public:
- using Headers = std::vector<std::pair<std::string, std::string>>;
- struct ResponseLocation {
- // /components/cbor uses int64_t for integer types.
- int64_t offset;
- int64_t length;
- };
-
- WebBundleBuilder(const std::string& fallback_url,
- const std::string& manifest_url);
- ~WebBundleBuilder();
-
- void AddExchange(base::StringPiece url,
- const Headers& response_headers,
- base::StringPiece payload);
-
- ResponseLocation AddResponse(const Headers& headers,
- base::StringPiece payload);
-
- void AddIndexEntry(base::StringPiece url,
- base::StringPiece variants_value,
- std::vector<ResponseLocation> response_locations);
- void AddSection(base::StringPiece name, cbor::Value section);
- void AddAuthority(cbor::Value::MapValue authority);
- void AddVouchedSubset(cbor::Value::MapValue vouched_subset);
-
- std::vector<uint8_t> CreateBundle();
-
- // Creates a signed-subset structure with single subset-hashes entry,
- // and returns it as a CBOR bytestring.
- cbor::Value CreateEncodedSigned(base::StringPiece validity_url,
- base::StringPiece auth_sha256,
- int64_t date,
- int64_t expires,
- base::StringPiece url,
- base::StringPiece header_sha256,
- base::StringPiece payload_integrity_header);
-
- private:
- cbor::Value CreateTopLevel();
- std::vector<uint8_t> Encode(const cbor::Value& value);
-
- int64_t EncodedLength(const cbor::Value& value);
-
- cbor::Writer::Config writer_config_;
- std::string fallback_url_;
- cbor::Value::ArrayValue section_lengths_;
- cbor::Value::ArrayValue sections_;
- cbor::Value::MapValue index_;
- cbor::Value::ArrayValue responses_;
- cbor::Value::ArrayValue authorities_;
- cbor::Value::ArrayValue vouched_subsets_;
-
- // 1 for the CBOR header byte. See the comment at the top of AddResponse().
- int64_t current_responses_offset_ = 1;
-};
-
-} // namespace test
-} // namespace data_decoder
-
-#endif // SERVICES_DATA_DECODER_PUBLIC_CPP_TEST_SUPPORT_WEB_BUNDLE_BUILDER_H_
diff --git a/chromium/services/data_decoder/public/mojom/BUILD.gn b/chromium/services/data_decoder/public/mojom/BUILD.gn
index ee6240f24a1..59dac08b913 100644
--- a/chromium/services/data_decoder/public/mojom/BUILD.gn
+++ b/chromium/services/data_decoder/public/mojom/BUILD.gn
@@ -9,13 +9,13 @@ mojom("mojom") {
"data_decoder_service.mojom",
"image_decoder.mojom",
"json_parser.mojom",
- "web_bundle_parser.mojom",
"web_bundler.mojom",
"xml_parser.mojom",
]
public_deps = [
":mojom_resource_snapshot_for_web_bundle",
+ "//components/web_package/mojom",
"//mojo/public/mojom/base",
"//skia/public/mojom",
"//ui/gfx/geometry/mojom",
diff --git a/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom b/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom
index 120ba37e7d4..77f2f1d421e 100644
--- a/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom
+++ b/chromium/services/data_decoder/public/mojom/data_decoder_service.mojom
@@ -4,10 +4,10 @@
module data_decoder.mojom;
+import "components/web_package/mojom/web_bundle_parser.mojom";
import "services/data_decoder/public/mojom/image_decoder.mojom";
import "services/data_decoder/public/mojom/json_parser.mojom";
import "services/data_decoder/public/mojom/web_bundler.mojom";
-import "services/data_decoder/public/mojom/web_bundle_parser.mojom";
import "services/data_decoder/public/mojom/xml_parser.mojom";
[EnableIf=is_chromeos]
@@ -26,7 +26,7 @@ interface DataDecoderService {
// Binds an interface which can be used to parse Web Bundles.
BindWebBundleParserFactory(
- pending_receiver<WebBundleParserFactory> receiver);
+ pending_receiver<web_package.mojom.WebBundleParserFactory> receiver);
// Binds an interface which can be used to generate a Web Bundle.
BindWebBundler(pending_receiver<WebBundler> receiver);
diff --git a/chromium/services/data_decoder/public/mojom/web_bundle_parser.mojom b/chromium/services/data_decoder/public/mojom/web_bundle_parser.mojom
deleted file mode 100644
index ca4c1be70a5..00000000000
--- a/chromium/services/data_decoder/public/mojom/web_bundle_parser.mojom
+++ /dev/null
@@ -1,133 +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.
-
-module data_decoder.mojom;
-
-import "mojo/public/mojom/base/file.mojom";
-import "url/mojom/url.mojom";
-
-// Factory interface to create WebBundleParser for the passed |file|
-// or |data_source| that provides application/webbundle data.
-interface WebBundleParserFactory {
- // Constructs a parser for the passed |file|.
- GetParserForFile(pending_receiver<WebBundleParser> receiver,
- mojo_base.mojom.File file);
-
- // Constructs a parser for the passed |data_source|.
- GetParserForDataSource(pending_receiver<WebBundleParser> receiver,
- pending_remote<BundleDataSource> data_source);
-};
-
-// Parser interface to obtain metadata and multiple responses from the bound
-// application/webbundle data provided on the construction at the factory above.
-interface WebBundleParser {
- // Parses bundle's metadata.
- ParseMetadata() => (BundleMetadata? Result, BundleMetadataParseError? error);
-
- // Parses a response from the range
- // |[response_offset, response_offset + response_length)|.
- ParseResponse(uint64 response_offset,
- uint64 response_length)
- => (BundleResponse? Result, BundleResponseParseError? error);
-};
-
-// Data source that provides application/webbundle data to the parser.
-interface BundleDataSource {
- // Reads up to |length| bytes starting with |offset|. Returns a non-null
- // buffer shorter than |length| iff the end of the stream is reached.
- Read(uint64 offset, uint64 length) => (array<uint8>? buffer);
-};
-
-enum BundleParseErrorType {
- kParserInternalError,
- kFormatError,
- kVersionError,
-};
-
-struct BundleMetadataParseError {
- BundleParseErrorType type;
- url.mojom.Url fallback_url;
- string message;
-};
-
-struct BundleResponseParseError {
- BundleParseErrorType type;
- string message;
-};
-
-// Corresponds to "bundle's metadata".
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#semantics-load-metadata
-struct BundleMetadata {
- url.mojom.Url primary_url;
- map<url.mojom.Url, BundleIndexValue> requests;
- url.mojom.Url manifest_url;
- array<AugmentedCertificate> authorities;
- array<VouchedSubset> vouched_subsets;
-};
-
-// Corresponds to the value type of "index" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#index-section
-struct BundleIndexValue {
- string variants_value;
- array<BundleResponseLocation> response_locations;
-};
-
-// Offset (within the webbundle file) and length of a response.
-struct BundleResponseLocation {
- uint64 offset;
- uint64 length;
-};
-
-// Corresponds to "augmented-certificate" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
-struct AugmentedCertificate {
- array<uint8> cert;
- array<uint8>? ocsp;
- array<uint8>? sct;
-};
-
-// Corresponds to the item type of "vouched-subsets" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
-struct VouchedSubset {
- uint64 authority; // An index in BundleMetadata::authorities.
- array<uint8> sig;
- array<uint8> raw_signed;
-
- SignedSubset parsed_signed; // Clients must verify |sig| before using this.
-};
-
-// Corresponds to "signed-subset" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
-struct SignedSubset {
- url.mojom.Url validity_url;
- array<uint8> auth_sha256;
- uint64 date;
- uint64 expires;
- map<url.mojom.Url, SubsetHashesValue> subset_hashes;
-};
-
-// Corresponds to the value type of "subset-hashes" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
-struct SubsetHashesValue {
- string variants_value;
- array<ResourceIntegrity> resource_integrities;
-};
-
-// Corresponds to "resource-integrity" in the spec CDDL.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
-struct ResourceIntegrity {
- array<uint8> header_sha256;
- string payload_integrity_header;
-};
-
-// Contains response headers and payload location.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-response
-struct BundleResponse {
- int32 response_code;
- map<string, string> response_headers;
-
- // Payload offset and length within the webbundle file.
- uint64 payload_offset;
- uint64 payload_length;
-};
diff --git a/chromium/services/data_decoder/web_bundle_parser.cc b/chromium/services/data_decoder/web_bundle_parser.cc
deleted file mode 100644
index e354823ca31..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser.cc
+++ /dev/null
@@ -1,1349 +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/data_decoder/web_bundle_parser.h"
-
-#include <algorithm>
-
-#include "base/big_endian.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/containers/span.h"
-#include "base/memory/weak_ptr.h"
-#include "base/numerics/checked_math.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_util.h"
-#include "components/cbor/reader.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "net/http/http_util.h"
-
-namespace data_decoder {
-
-namespace {
-
-// The maximum length of the CBOR item header (type and argument).
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#parse-type-argument
-constexpr uint64_t kMaxCBORItemHeaderSize = 9;
-
-// The maximum size of the section-lengths CBOR item.
-constexpr uint64_t kMaxSectionLengthsCBORSize = 8192;
-
-// The maximum size of a metadata section allowed in this implementation.
-constexpr uint64_t kMaxMetadataSectionSize = 1 * 1024 * 1024;
-
-// The maximum size of the response header CBOR.
-constexpr uint64_t kMaxResponseHeaderLength = 512 * 1024;
-
-// The initial buffer size for reading an item from the response section.
-constexpr uint64_t kInitialBufferSizeForResponse = 4096;
-
-// Step 2. of
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
-const uint8_t kBundleMagicBytes[] = {
- 0x86, 0x48, 0xF0, 0x9F, 0x8C, 0x90, 0xF0, 0x9F, 0x93, 0xA6,
-};
-
-// Step 7. of
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
-// We use an implementation-specific version string "b1\0\0".
-const uint8_t kVersionB1MagicBytes[] = {
- 0x44, 0x62, 0x31, 0x00, 0x00,
-};
-
-// Section names.
-constexpr char kCriticalSection[] = "critical";
-constexpr char kIndexSection[] = "index";
-constexpr char kManifestSection[] = "manifest";
-constexpr char kResponsesSection[] = "responses";
-constexpr char kSignaturesSection[] = "signatures";
-
-// https://tools.ietf.org/html/draft-ietf-cbor-7049bis-05#section-3.1
-enum class CBORType {
- kByteString = 2,
- kTextString = 3,
- kArray = 4,
-};
-
-// A list of (section-name, length) pairs.
-using SectionLengths = std::vector<std::pair<std::string, uint64_t>>;
-
-// A map from section name to (offset, length) pair.
-using SectionOffsets = std::map<std::string, std::pair<uint64_t, uint64_t>>;
-
-bool IsMetadataSection(const std::string& name) {
- return (name == kCriticalSection || name == kIndexSection ||
- name == kManifestSection || name == kSignaturesSection);
-}
-
-// Parses a `section-lengths` CBOR item.
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
-base::Optional<SectionLengths> ParseSectionLengths(
- base::span<const uint8_t> data) {
- cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> value = cbor::Reader::Read(data, &error);
- if (!value.has_value() || !value->is_array())
- return base::nullopt;
-
- const cbor::Value::ArrayValue& array = value->GetArray();
- if (array.size() % 2 != 0)
- return base::nullopt;
-
- SectionLengths result;
- for (size_t i = 0; i < array.size(); i += 2) {
- if (!array[i].is_string() || !array[i + 1].is_unsigned())
- return base::nullopt;
- result.emplace_back(array[i].GetString(), array[i + 1].GetUnsigned());
- }
- return result;
-}
-
-struct ParsedHeaders {
- base::flat_map<std::string, std::string> headers;
- base::flat_map<std::string, std::string> pseudos;
-};
-
-// https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#cbor-headers
-base::Optional<ParsedHeaders> ConvertCBORValueToHeaders(
- const cbor::Value& headers_value) {
- // Step 1. If item doesn’t match the headers rule in the above CDDL, return
- // an error.
- if (!headers_value.is_map())
- return base::nullopt;
-
- // Step 2. Let headers be a new header list ([FETCH]).
- // Step 3. Let pseudos be an empty map ([INFRA]).
- ParsedHeaders result;
-
- // Step 4. For each pair (name, value) in item:
- for (const auto& item : headers_value.GetMap()) {
- if (!item.first.is_bytestring() || !item.second.is_bytestring())
- return base::nullopt;
- base::StringPiece name = item.first.GetBytestringAsString();
- base::StringPiece value = item.second.GetBytestringAsString();
-
- // Step 4.1. If name contains any upper-case or non-ASCII characters, return
- // an error. This matches the requirement in Section 8.1.2 of [RFC7540].
- if (!base::IsStringASCII(name) ||
- std::any_of(name.begin(), name.end(), base::IsAsciiUpper<char>))
- return base::nullopt;
-
- // Step 4.2. If name starts with a ‘:’:
- if (!name.empty() && name[0] == ':') {
- // Step 4.2.1. Assert: pseudos[name] does not exist, because CBOR maps
- // cannot contain duplicate keys.
- // This is ensured by cbor::Reader.
- DCHECK(!result.pseudos.contains(name));
- // Step 4.2.2. Set pseudos[name] to value.
- result.pseudos.insert(
- std::make_pair(name.as_string(), value.as_string()));
- // Step 4.3.3. Continue.
- continue;
- }
-
- // Step 4.3. If name or value doesn’t satisfy the requirements for a header
- // in [FETCH], return an error.
- if (!net::HttpUtil::IsValidHeaderName(name) ||
- !net::HttpUtil::IsValidHeaderValue(value))
- return base::nullopt;
-
- // Step 4.4. Assert: headers does not contain ([FETCH]) name, because CBOR
- // maps cannot contain duplicate keys and an earlier step rejected
- // upper-case bytes.
- // This is ensured by cbor::Reader.
- DCHECK(!result.headers.contains(name));
-
- // Step 4.5. Append (name, value) to headers.
- result.headers.insert(std::make_pair(name.as_string(), value.as_string()));
- }
-
- // Step 5. Return (headers, pseudos).
- return result;
-}
-
-// A utility class for reading various values from input buffer.
-class InputReader {
- public:
- explicit InputReader(base::span<const uint8_t> buf) : buf_(buf) {}
-
- uint64_t CurrentOffset() const { return current_offset_; }
- size_t Size() const { return buf_.size(); }
-
- base::Optional<uint8_t> ReadByte() {
- if (buf_.empty())
- return base::nullopt;
- uint8_t byte = buf_[0];
- Advance(1);
- return byte;
- }
-
- template <typename T>
- bool ReadBigEndian(T* out) {
- auto bytes = ReadBytes(sizeof(T));
- if (!bytes)
- return false;
- base::ReadBigEndian(reinterpret_cast<const char*>(bytes->data()), out);
- return true;
- }
-
- base::Optional<base::span<const uint8_t>> ReadBytes(size_t n) {
- if (buf_.size() < n)
- return base::nullopt;
- auto result = buf_.subspan(0, n);
- Advance(n);
- return result;
- }
-
- base::Optional<base::StringPiece> ReadString(size_t n) {
- auto bytes = ReadBytes(n);
- if (!bytes)
- return base::nullopt;
- base::StringPiece str(reinterpret_cast<const char*>(bytes->data()),
- bytes->size());
- if (!base::IsStringUTF8(str))
- return base::nullopt;
- return str;
- }
-
- // Parses the type and argument of a CBOR item from the input head. If parsed
- // successfully and the type matches |expected_type|, returns the argument.
- // Otherwise returns nullopt.
- base::Optional<uint64_t> ReadCBORHeader(CBORType expected_type) {
- auto pair = ReadTypeAndArgument();
- if (!pair || pair->first != expected_type)
- return base::nullopt;
- return pair->second;
- }
-
- private:
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#parse-type-argument
- base::Optional<std::pair<CBORType, uint64_t>> ReadTypeAndArgument() {
- base::Optional<uint8_t> first_byte = ReadByte();
- if (!first_byte)
- return base::nullopt;
-
- CBORType type = static_cast<CBORType>((*first_byte & 0xE0) / 0x20);
- uint8_t b = *first_byte & 0x1F;
-
- if (b <= 23)
- return std::make_pair(type, b);
- if (b == 24) {
- auto content = ReadByte();
- if (!content || *content < 24)
- return base::nullopt;
- return std::make_pair(type, *content);
- }
- if (b == 25) {
- uint16_t content;
- if (!ReadBigEndian(&content) || content >> 8 == 0)
- return base::nullopt;
- return std::make_pair(type, content);
- }
- if (b == 26) {
- uint32_t content;
- if (!ReadBigEndian(&content) || content >> 16 == 0)
- return base::nullopt;
- return std::make_pair(type, content);
- }
- if (b == 27) {
- uint64_t content;
- if (!ReadBigEndian(&content) || content >> 32 == 0)
- return base::nullopt;
- return std::make_pair(type, content);
- }
- return base::nullopt;
- }
-
- void Advance(size_t n) {
- DCHECK_LE(n, buf_.size());
- buf_ = buf_.subspan(n);
- current_offset_ += n;
- }
-
- base::span<const uint8_t> buf_;
- uint64_t current_offset_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(InputReader);
-};
-
-GURL ParseExchangeURL(base::StringPiece str) {
- if (!base::IsStringUTF8(str))
- return GURL();
-
- GURL url(str);
- if (!url.is_valid())
- return GURL();
-
- // Exchange URL must not have a fragment or credentials.
- if (url.has_ref() || url.has_username() || url.has_password())
- return GURL();
-
- // For now, we allow only http: and https: schemes in Web Bundle URLs.
- // TODO(crbug.com/966753): Revisit this once
- // https://github.com/WICG/webpackage/issues/468 is resolved.
- if (!url.SchemeIsHTTPOrHTTPS())
- return GURL();
-
- return url;
-}
-
-} // namespace
-
-class WebBundleParser::SharedBundleDataSource::Observer {
- public:
- Observer() {}
- virtual ~Observer() {}
- virtual void OnDisconnect() = 0;
-
- DISALLOW_COPY_AND_ASSIGN(Observer);
-};
-
-// A parser for bundle's metadata. This class owns itself and will self destruct
-// after calling the ParseMetadataCallback.
-class WebBundleParser::MetadataParser
- : WebBundleParser::SharedBundleDataSource::Observer {
- public:
- MetadataParser(scoped_refptr<SharedBundleDataSource> data_source,
- ParseMetadataCallback callback)
- : data_source_(data_source), callback_(std::move(callback)) {
- data_source_->AddObserver(this);
- }
- ~MetadataParser() override { data_source_->RemoveObserver(this); }
-
- void Start() {
- // First, we will parse `magic`, `version`, and the CBOR header of
- // `primary-url`.
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#top-level
- const uint64_t length = sizeof(kBundleMagicBytes) +
- sizeof(kVersionB1MagicBytes) +
- kMaxCBORItemHeaderSize;
- data_source_->Read(0, length,
- base::BindOnce(&MetadataParser::ParseMagicBytes,
- weak_factory_.GetWeakPtr()));
- }
-
- private:
- // Step 1-4 of
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
- void ParseMagicBytes(const base::Optional<std::vector<uint8_t>>& data) {
- if (!data) {
- RunErrorCallbackAndDestroy("Error reading bundle magic bytes.");
- return;
- }
-
- // Step 1. "Seek to offset 0 in stream. Assert: this operation doesn't
- // fail."
- InputReader input(*data);
-
- // Step 2. "If reading 10 bytes from stream returns an error or doesn't
- // return the bytes with hex encoding "86 48 F0 9F 8C 90 F0 9F 93 A6"
- // (the CBOR encoding of the 6-item array initial byte and 8-byte bytestring
- // initial byte, followed by 🌐📦 in UTF-8), return a "format error"."
- const auto magic = input.ReadBytes(sizeof(kBundleMagicBytes));
- if (!magic ||
- !std::equal(magic->begin(), magic->end(), std::begin(kBundleMagicBytes),
- std::end(kBundleMagicBytes))) {
- RunErrorCallbackAndDestroy("Wrong magic bytes.");
- return;
- }
-
- // Step 3. "Let version be the result of reading 5 bytes from stream. If
- // this is an error, return a "format error"."
- const auto version = input.ReadBytes(sizeof(kVersionB1MagicBytes));
- if (!version) {
- RunErrorCallbackAndDestroy("Cannot read version bytes.");
- return;
- }
- if (!std::equal(version->begin(), version->end(),
- std::begin(kVersionB1MagicBytes),
- std::end(kVersionB1MagicBytes))) {
- version_mismatch_ = true;
- // Continue parsing until Step 7 where we get a fallback URL, and
- // then return "version error" with the fallback URL.
- }
-
- // Step 4. "Let urlType and urlLength be the result of reading the type and
- // argument of a CBOR item from stream (Section 3.5.3). If this is an error
- // or urlType is not 3 (a CBOR text string), return a "format error"."
- const auto url_length = input.ReadCBORHeader(CBORType::kTextString);
- if (!url_length) {
- RunErrorCallbackAndDestroy("Cannot parse the size of fallback URL.");
- return;
- }
-
- // In the next step, we will parse the content of `primary-url`,
- // `section-lengths`, and the CBOR header of `sections`.
- const uint64_t length =
- *url_length + kMaxSectionLengthsCBORSize + kMaxCBORItemHeaderSize * 2;
- data_source_->Read(input.CurrentOffset(), length,
- base::BindOnce(&MetadataParser::ParseBundleHeader,
- weak_factory_.GetWeakPtr(), *url_length,
- input.CurrentOffset()));
- }
-
- // Step 5-21 of
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
- void ParseBundleHeader(uint64_t url_length,
- uint64_t offset_in_stream,
- const base::Optional<std::vector<uint8_t>>& data) {
- if (!data) {
- RunErrorCallbackAndDestroy("Error reading bundle header.");
- return;
- }
- InputReader input(*data);
-
- // Step 5. "Let fallbackUrlBytes be the result of reading urlLength bytes
- // from stream. If this is an error, return a "format error"."
- const auto fallback_url_string = input.ReadString(url_length);
- if (!fallback_url_string) {
- RunErrorCallbackAndDestroy("Cannot read fallback URL.");
- return;
- }
-
- // Step 6. "Let fallbackUrl be the result of parsing ([URL]) the UTF-8
- // decoding of fallbackUrlBytes with no base URL. If either the UTF-8
- // decoding or parsing fails, return a "format error"."
- // For now, we enforce the same restriction as exchages' request URL.
- // TODO(crbug.com/966753): Revisit URL requirements here once
- // https://github.com/WICG/webpackage/issues/469 is resolved.
- GURL fallback_url = ParseExchangeURL(*fallback_url_string);
- if (!fallback_url.is_valid()) {
- RunErrorCallbackAndDestroy("Cannot parse fallback URL.");
- return;
- }
-
- // "Note: From this point forward, errors also include the fallback URL to
- // help clients recover."
- fallback_url_ = std::move(fallback_url);
-
- // Step 7. "If version does not have the hex encoding "44 31 00 00 00" (the
- // CBOR encoding of a 4-byte byte string holding an ASCII "1" followed by
- // three 0 bytes), return a "version error" with fallbackUrl. "
- // Note: We use an implementation-specific version string
- // kVersionB1MagicBytes.
- if (version_mismatch_) {
- RunErrorCallbackAndDestroy(
- "Version error: this implementation only supports "
- "bundle format of version b1.",
- mojom::BundleParseErrorType::kVersionError);
- return;
- }
-
- // Step 8. "Let sectionLengthsLength be the result of getting the length of
- // the CBOR bytestring header from stream (Section 3.5.2). If this is an
- // error, return a "format error" with fallbackUrl."
- const auto section_lengths_length =
- input.ReadCBORHeader(CBORType::kByteString);
- if (!section_lengths_length) {
- RunErrorCallbackAndDestroy("Cannot parse the size of section-lengths.");
- return;
- }
- // Step 9. "If sectionLengthsLength is 8192 (8*1024) or greater, return a
- // "format error" with fallbackUrl."
- if (*section_lengths_length >= kMaxSectionLengthsCBORSize) {
- RunErrorCallbackAndDestroy(
- "The section-lengths CBOR must be smaller than 8192 bytes.");
- return;
- }
-
- // Step 10. "Let sectionLengthsBytes be the result of reading
- // sectionLengthsLength bytes from stream. If sectionLengthsBytes is an
- // error, return a "format error" with fallbackUrl."
- const auto section_lengths_bytes = input.ReadBytes(*section_lengths_length);
- if (!section_lengths_bytes) {
- RunErrorCallbackAndDestroy("Cannot read section-lengths.");
- return;
- }
-
- // Step 11. "Let sectionLengths be the result of parsing one CBOR item
- // (Section 3.5) from sectionLengthsBytes, matching the section-lengths
- // rule in the CDDL ([I-D.ietf-cbor-cddl]) above. If sectionLengths is an
- // error, return a "format error" with fallbackUrl."
- const auto section_lengths = ParseSectionLengths(*section_lengths_bytes);
- if (!section_lengths) {
- RunErrorCallbackAndDestroy("Cannot parse section-lengths.");
- return;
- }
-
- // Step 12. "Let (sectionsType, numSections) be the result of parsing the
- // type and argument of a CBOR item from stream (Section 3.5.3)."
- const auto num_sections = input.ReadCBORHeader(CBORType::kArray);
- if (!num_sections) {
- RunErrorCallbackAndDestroy("Cannot parse the number of sections.");
- return;
- }
-
- // Step 13. "If sectionsType is not 4 (a CBOR array) or numSections is not
- // half of the length of sectionLengths, return a "format error" with
- // fallbackUrl."
- if (*num_sections != section_lengths->size()) {
- RunErrorCallbackAndDestroy("Unexpected number of sections.");
- return;
- }
-
- // Step 14. "Let sectionsStart be the current offset within stream."
- // Note: This doesn't exceed |size_|.
- const uint64_t sections_start = offset_in_stream + input.CurrentOffset();
-
- // Step 15. "Let knownSections be the subset of the Section 6.2 that this
- // client has implemented."
- // Step 16. "Let ignoredSections be an empty set."
-
- // This implementation doesn't use knownSections nor ignoredSections.
-
- // Step 17. "Let sectionOffsets be an empty map ([INFRA]) from section names
- // to (offset, length) pairs. These offsets are relative to the start of
- // stream."
-
- // |section_offsets_| is defined as a class member field.
-
- // Step 18. "Let currentOffset be sectionsStart."
- uint64_t current_offset = sections_start;
-
- // Step 19. "For each ("name", length) pair of adjacent elements in
- // sectionLengths:"
- for (const auto& pair : *section_lengths) {
- const std::string& name = pair.first;
- const uint64_t length = pair.second;
- // Step 19.1. "If "name"'s specification in knownSections says not to
- // process other sections, add those sections' names to ignoredSections."
-
- // There're no such sections at the moment.
-
- // Step 19.2. "If sectionOffsets["name"] exists, return a "format error"
- // with fallbackUrl. That is, duplicate sections are forbidden."
- // Step 19.3. "Set sectionOffsets["name"] to (currentOffset, length)."
- bool added = section_offsets_
- .insert(std::make_pair(
- name, std::make_pair(current_offset, length)))
- .second;
- if (!added) {
- RunErrorCallbackAndDestroy("Duplicated section.");
- return;
- }
-
- // Step 19.4. "Set currentOffset to currentOffset + length."
- if (!base::CheckAdd(current_offset, length)
- .AssignIfValid(&current_offset)) {
- RunErrorCallbackAndDestroy(
- "Integer overflow calculating section offsets.");
- return;
- }
- }
-
- // Step 20. "If the "responses" section is not last in sectionLengths,
- // return a "format error" with fallbackUrl. This allows a streaming parser
- // to assume that it'll know the requests by the time their responses
- // arrive."
- if (section_lengths->empty() ||
- section_lengths->back().first != kResponsesSection) {
- RunErrorCallbackAndDestroy(
- "Responses section is not the last in section-lengths.");
- return;
- }
-
- // Step 21. "Let metadata be a map ([INFRA]) initially containing the single
- // key/value pair "primaryUrl"/fallbackUrl."
- metadata_ = mojom::BundleMetadata::New();
- metadata_->primary_url = fallback_url_;
-
- ReadMetadataSections(section_offsets_.begin());
- }
-
- // Step 22-25 of
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-metadata
- void ReadMetadataSections(SectionOffsets::const_iterator section_iter) {
- // Step 22. "For each "name" -> (offset, length) triple in sectionOffsets:"
- for (; section_iter != section_offsets_.end(); ++section_iter) {
- const auto& name = section_iter->first;
- // Step 22.1. "If "name" isn't in knownSections, continue to the next
- // triple."
- // Step 22.2. "If "name"'s Metadata field (Section 6.2) is "No", continue
- // to the next triple."
- if (!IsMetadataSection(name))
- continue;
-
- // Step 22.3. "If "name" is in ignoredSections, continue to the next
- // triple."
- // In the current spec, ignoredSections is always empty.
-
- const uint64_t section_offset = section_iter->second.first;
- const uint64_t section_length = section_iter->second.second;
- if (section_length > kMaxMetadataSectionSize) {
- RunErrorCallbackAndDestroy(
- "Metadata sections larger than 1MB are not supported.");
- return;
- }
-
- data_source_->Read(section_offset, section_length,
- base::BindOnce(&MetadataParser::ParseMetadataSection,
- weak_factory_.GetWeakPtr(),
- section_iter, section_length));
- // This loop will be resumed by ParseMetadataSection().
- return;
- }
-
- // Step 23. "Assert: metadata has an entry with the key "primaryUrl"."
- DCHECK(!metadata_->primary_url.is_empty());
-
- // Step 24. "If metadata doesn't have an entry with the key "requests",
- // return a "format error" with fallbackUrl."
- if (metadata_->requests.empty()) {
- RunErrorCallbackAndDestroy("Bundle must have an index section.");
- return;
- }
-
- // Step 25. "Return metadata."
- RunSuccessCallbackAndDestroy();
- }
-
- void ParseMetadataSection(SectionOffsets::const_iterator section_iter,
- uint64_t expected_data_length,
- const base::Optional<std::vector<uint8_t>>& data) {
- if (!data || data->size() != expected_data_length) {
- RunErrorCallbackAndDestroy("Error reading section content.");
- return;
- }
-
- // Parse the section contents as a CBOR item.
- cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> section_value =
- cbor::Reader::Read(*data, &error);
- if (!section_value) {
- RunErrorCallbackAndDestroy(
- std::string("Error parsing section contents as CBOR: ") +
- cbor::Reader::ErrorCodeToString(error));
- return;
- }
-
- // Step 22.6. "Follow "name"'s specification from knownSections to process
- // the section, passing sectionContents, stream, sectionOffsets, and
- // metadata. If this returns an error, return a "format error" with
- // fallbackUrl."
- const auto& name = section_iter->first;
- // Note: Parse*Section() delete |this| on failure.
- if (name == kIndexSection) {
- if (!ParseIndexSection(*section_value))
- return;
- } else if (name == kManifestSection) {
- if (!ParseManifestSection(*section_value))
- return;
- } else if (name == kSignaturesSection) {
- if (!ParseSignaturesSection(*section_value))
- return;
- } else if (name == kCriticalSection) {
- if (!ParseCriticalSection(*section_value))
- return;
- } else {
- NOTREACHED();
- }
- // Resume the loop of Step 22.
- ReadMetadataSections(++section_iter);
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#index-section
- bool ParseIndexSection(const cbor::Value& section_value) {
- // Step 1. "Let index be the result of parsing sectionContents as a CBOR
- // item matching the index rule in the above CDDL (Section 3.5). If index is
- // an error, return an error."
- if (!section_value.is_map()) {
- RunErrorCallbackAndDestroy("Index section must be a map.");
- return false;
- }
-
- // Step 2. "Let requests be an initially-empty map ([INFRA]) from URLs to
- // response descriptions, each of which is either a single
- // location-in-stream value or a pair of a Variants header field value
- // ([I-D.ietf-httpbis-variants]) and a map from that value's possible
- // Variant-Keys to location-in-stream values, as described in Section 2.2."
- base::flat_map<GURL, mojom::BundleIndexValuePtr> requests;
-
- // Step 3. "Let MakeRelativeToStream be a function that takes a
- // location-in-responses value (offset, length) and returns a
- // ResponseMetadata struct or error by running the following
- // sub-steps:"
- // The logic of MakeRelativeToStream is inlined at the callsite below.
- auto responses_section = section_offsets_.find(kResponsesSection);
- DCHECK(responses_section != section_offsets_.end());
- const uint64_t responses_section_offset = responses_section->second.first;
- const uint64_t responses_section_length = responses_section->second.second;
-
- // Step 4. "For each (url, responses) entry in the index map:"
- for (const auto& item : section_value.GetMap()) {
- if (!item.first.is_string()) {
- RunErrorCallbackAndDestroy("Index section: key must be a string.");
- return false;
- }
- if (!item.second.is_array()) {
- RunErrorCallbackAndDestroy("Index section: value must be an array.");
- return false;
- }
- const std::string& url = item.first.GetString();
- const cbor::Value::ArrayValue& responses_array = item.second.GetArray();
-
- // Step 4.1. "Let parsedUrl be the result of parsing ([URL]) url with no
- // base URL."
- GURL parsed_url = ParseExchangeURL(url);
-
- // Step 4.2. "If parsedUrl is a failure, its fragment is not null, or it
- // includes credentials, return an error."
- if (!parsed_url.is_valid()) {
- RunErrorCallbackAndDestroy("Index section: exchange URL is not valid.");
- return false;
- }
-
- // Step 4.3. "If the first element of responses is the empty string:"
- if (responses_array.empty() || !responses_array[0].is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "Index section: the first element of responses array must be a "
- "bytestring.");
- return false;
- }
- base::StringPiece variants_value =
- responses_array[0].GetBytestringAsString();
- if (variants_value.empty()) {
- // Step 4.3.1. "If the length of responses is not 3 (i.e. there is more
- // than one location-in-responses in responses), return an error."
- if (responses_array.size() != 3) {
- RunErrorCallbackAndDestroy(
- "Index section: unexpected size of responses array.");
- return false;
- }
- } else {
- // Step 4.4. "Otherwise:"
- // TODO(crbug.com/969596): Parse variants_value to compute the number of
- // variantKeys, and check that responses_array has
- // (2 * #variantKeys + 1) elements.
- if (responses_array.size() < 3 || responses_array.size() % 2 != 1) {
- RunErrorCallbackAndDestroy(
- "Index section: unexpected size of responses array.");
- return false;
- }
- }
- // Instead of constructing a map from Variant-Keys to location-in-stream,
- // this implementation just returns the responses array's structure as
- // a BundleIndexValue.
- std::vector<mojom::BundleResponseLocationPtr> response_locations;
- for (size_t i = 1; i < responses_array.size(); i += 2) {
- if (!responses_array[i].is_unsigned() ||
- !responses_array[i + 1].is_unsigned()) {
- RunErrorCallbackAndDestroy(
- "Index section: offset and length values must be unsigned.");
- return false;
- }
- uint64_t offset = responses_array[i].GetUnsigned();
- uint64_t length = responses_array[i + 1].GetUnsigned();
-
- // MakeRelativeToStream (Step 3.) is inlined here.
- // Step 3.1. "If offset + length is larger than
- // sectionOffsets["responses"].length, return an error."
- uint64_t response_end;
- if (!base::CheckAdd(offset, length).AssignIfValid(&response_end) ||
- response_end > responses_section_length) {
- RunErrorCallbackAndDestroy("Index section: response out of range.");
- return false;
- }
- // Step 3.2. "Otherwise, return a ResponseMetadata struct whose offset
- // is sectionOffsets["responses"].offset + offset and whose length is
- // length."
-
- // This doesn't wrap because (offset <= responses_section_length) and
- // (responses_section_offset + responses_section_length) doesn't wrap.
- uint64_t offset_within_stream = responses_section_offset + offset;
-
- response_locations.push_back(
- mojom::BundleResponseLocation::New(offset_within_stream, length));
- }
- requests.insert(std::make_pair(
- parsed_url,
- mojom::BundleIndexValue::New(variants_value.as_string(),
- std::move(response_locations))));
- }
-
- // Step 5. "Set metadata["requests"] to requests."
- metadata_->requests = std::move(requests);
- return true;
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#manifest-section
- bool ParseManifestSection(const cbor::Value& section_value) {
- // Step 1. "Let urlString be the result of parsing sectionContents as a CBOR
- // item matching the above manifest rule (Section 3.5). If urlString is an
- // error, return that error."
- if (!section_value.is_string()) {
- RunErrorCallbackAndDestroy("Manifest section must be a string.");
- return false;
- }
- // Step 2. "Let url be the result of parsing ([URL]) urlString with no base
- // URL."
- GURL parsed_url = ParseExchangeURL(section_value.GetString());
-
- // Step 3. "If url is a failure, its fragment is not null, or it includes
- // credentials, return an error."
- if (!parsed_url.is_valid()) {
- RunErrorCallbackAndDestroy("Manifest URL is not a valid exchange URL.");
- return false;
- }
- // Step 4. "Set metadata["manifest"] to url."
- metadata_->manifest_url = std::move(parsed_url);
- return true;
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
- bool ParseSignaturesSection(const cbor::Value& section_value) {
- // Step 1. "Let signatures be the result of parsing sectionContents as a
- // CBOR item matching the signatures rule in the above CDDL (Section 3.5)."
- if (!section_value.is_array() || section_value.GetArray().size() != 2) {
- RunErrorCallbackAndDestroy(
- "Signatures section must be an array of size 2.");
- return false;
- }
- const cbor::Value& authorities_value = section_value.GetArray()[0];
- const cbor::Value& vouched_subsets_value = section_value.GetArray()[1];
-
- if (!authorities_value.is_array()) {
- RunErrorCallbackAndDestroy("Authorities must be an array.");
- return false;
- }
- std::vector<mojom::AugmentedCertificatePtr> authorities;
- for (const cbor::Value& value : authorities_value.GetArray()) {
- // ParseAugmentedCertificate deletes |this| on failure.
- auto authority = ParseAugmentedCertificate(value);
- if (!authority)
- return false;
- authorities.push_back(std::move(authority));
- }
-
- if (!vouched_subsets_value.is_array()) {
- RunErrorCallbackAndDestroy("Vouched-subsets must be an array.");
- return false;
- }
- std::vector<mojom::VouchedSubsetPtr> vouched_subsets;
- for (const cbor::Value& value : vouched_subsets_value.GetArray()) {
- if (!value.is_map()) {
- RunErrorCallbackAndDestroy(
- "An element of vouched-subsets must be a map.");
- return false;
- }
- const cbor::Value::MapValue& item_map = value.GetMap();
-
- auto* authority_value = Lookup(item_map, "authority");
- if (!authority_value || !authority_value->is_unsigned()) {
- RunErrorCallbackAndDestroy(
- "authority is not found in vouched-subsets map, or not an "
- "unsigned.");
- return false;
- }
- int64_t authority = authority_value->GetUnsigned();
-
- auto* sig_value = Lookup(item_map, "sig");
- if (!sig_value || !sig_value->is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "sig is not found in vouched-subsets map, or not a bytestring.");
- return false;
- }
- const cbor::Value::BinaryValue& sig = sig_value->GetBytestring();
-
- auto* signed_value = Lookup(item_map, "signed");
- if (!signed_value || !signed_value->is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "signed is not found in vouched-subsets map, or not a bytestring.");
- return false;
- }
- const cbor::Value::BinaryValue& raw_signed =
- signed_value->GetBytestring();
-
- // ParseSignedSubset deletes |this| on failure.
- auto parsed_signed = ParseSignedSubset(raw_signed);
- if (!parsed_signed)
- return false;
-
- vouched_subsets.push_back(mojom::VouchedSubset::New(
- authority, sig, raw_signed, std::move(parsed_signed)));
- }
-
- // Step 2. "Set metadata["authorities"] to the list of authorities in the
- // first element of the signatures array."
- metadata_->authorities = std::move(authorities);
-
- // Step 3. "Set metadata["vouched-subsets"] to the second element of the
- // signatures array."
- metadata_->vouched_subsets = std::move(vouched_subsets);
-
- return true;
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#critical-section
- bool ParseCriticalSection(const cbor::Value& section_value) {
- // Step 1. "Let critical be the result of parsing sectionContents as a CBOR
- // item matching the above critical rule (Section 3.5). If critical is an
- // error, return that error."
- if (!section_value.is_array()) {
- RunErrorCallbackAndDestroy("Critical section must be an array.");
- return false;
- }
- // Step 2. "For each value sectionName in the critical list, if the client
- // has not implemented sections named sectionName, return an error."
- for (const cbor::Value& elem : section_value.GetArray()) {
- if (!elem.is_string()) {
- RunErrorCallbackAndDestroy(
- "Non-string element in the critical section.");
- return false;
- }
- const auto& section_name = elem.GetString();
- if (!IsMetadataSection(section_name) &&
- section_name != kResponsesSection) {
- RunErrorCallbackAndDestroy("Unknown critical section.");
- return false;
- }
- }
- return true;
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-http-origin-signed-responses.html#cert-chain-format
- mojom::AugmentedCertificatePtr ParseAugmentedCertificate(
- const cbor::Value& value) {
- if (!value.is_map()) {
- RunErrorCallbackAndDestroy("augmented-certificate must be a map.");
- return nullptr;
- }
- const cbor::Value::MapValue& item_map = value.GetMap();
- mojom::AugmentedCertificatePtr authority =
- mojom::AugmentedCertificate::New();
-
- auto* cert_value = Lookup(item_map, "cert");
- if (!cert_value || !cert_value->is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "cert is not found in augmented-certificate, or not a bytestring.");
- return nullptr;
- }
- authority->cert = cert_value->GetBytestring();
-
- if (auto* ocsp_value = Lookup(item_map, "ocsp")) {
- if (!ocsp_value->is_bytestring()) {
- RunErrorCallbackAndDestroy("ocsp is not a bytestring.");
- return nullptr;
- }
- authority->ocsp = ocsp_value->GetBytestring();
- }
-
- if (auto* sct_value = Lookup(item_map, "sct")) {
- if (!sct_value->is_bytestring()) {
- RunErrorCallbackAndDestroy("sct is not a bytestring.");
- return nullptr;
- }
- authority->sct = sct_value->GetBytestring();
- }
- return authority;
- }
-
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#signatures-section
- mojom::SignedSubsetPtr ParseSignedSubset(
- const cbor::Value::BinaryValue& signed_bytes) {
- // Parse |signed_bytes| as a CBOR item.
- cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> value =
- cbor::Reader::Read(signed_bytes, &error);
- if (!value) {
- RunErrorCallbackAndDestroy(
- std::string("Error parsing signed bytes as CBOR: ") +
- cbor::Reader::ErrorCodeToString(error));
- return nullptr;
- }
-
- if (!value->is_map()) {
- RunErrorCallbackAndDestroy("signed-subset must be a CBOR map");
- return nullptr;
- }
- const cbor::Value::MapValue& value_map = value->GetMap();
-
- auto* validity_url_value = Lookup(value_map, "validity-url");
- if (!validity_url_value || !validity_url_value->is_string()) {
- RunErrorCallbackAndDestroy(
- "validity-url is not found in signed-subset, or not a string.");
- return nullptr;
- }
- // TODO(crbug.com/966753): Revisit this once requirements for validity URL
- // are speced.
- GURL validity_url(validity_url_value->GetString());
- if (!validity_url.is_valid()) {
- RunErrorCallbackAndDestroy("Cannot parse validity-url.");
- return nullptr;
- }
-
- auto* auth_sha256_value = Lookup(value_map, "auth-sha256");
- if (!auth_sha256_value || !auth_sha256_value->is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "auth-sha256 is not found in signed-subset, or not a bytestring.");
- return nullptr;
- }
- auto auth_sha256 = auth_sha256_value->GetBytestring();
-
- auto* date_value = Lookup(value_map, "date");
- if (!date_value || !date_value->is_unsigned()) {
- RunErrorCallbackAndDestroy(
- "date is not found in signed-subset, or not an unsigned.");
- return nullptr;
- }
- auto date = date_value->GetUnsigned();
-
- auto* expires_value = Lookup(value_map, "expires");
- if (!expires_value || !expires_value->is_unsigned()) {
- RunErrorCallbackAndDestroy(
- "expires is not found in signed-subset, or not an unsigned.");
- return nullptr;
- }
- auto expires = expires_value->GetUnsigned();
-
- auto* subset_hashes_value = Lookup(value_map, "subset-hashes");
- if (!subset_hashes_value || !subset_hashes_value->is_map()) {
- RunErrorCallbackAndDestroy(
- "subset-hashes is not found in signed-subset, or not a map.");
- return nullptr;
- }
- base::flat_map<GURL, mojom::SubsetHashesValuePtr> subset_hashes;
-
- for (const auto& item : subset_hashes_value->GetMap()) {
- if (!item.first.is_string()) {
- RunErrorCallbackAndDestroy("subset-hashes: key must be a string.");
- return nullptr;
- }
- if (!item.second.is_array()) {
- RunErrorCallbackAndDestroy("subset-hashes: value must be an array.");
- return nullptr;
- }
- const std::string& url = item.first.GetString();
- const cbor::Value::ArrayValue& value_array = item.second.GetArray();
-
- GURL parsed_url = ParseExchangeURL(url);
- if (!parsed_url.is_valid()) {
- RunErrorCallbackAndDestroy("subset-hashes: exchange URL is not valid.");
- return nullptr;
- }
-
- if (value_array.empty() || !value_array[0].is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "subset-hashes: the first element of array must be a bytestring.");
- return nullptr;
- }
- base::StringPiece variants_value = value_array[0].GetBytestringAsString();
- if (value_array.size() < 3 || value_array.size() % 2 != 1) {
- RunErrorCallbackAndDestroy(
- "subset-hashes: unexpected size of value array.");
- return nullptr;
- }
- std::vector<mojom::ResourceIntegrityPtr> resource_integrities;
- for (size_t i = 1; i < value_array.size(); i += 2) {
- if (!value_array[i].is_bytestring()) {
- RunErrorCallbackAndDestroy(
- "subset-hashes: header-sha256 must be a byte string.");
- return nullptr;
- }
- if (!value_array[i + 1].is_string()) {
- RunErrorCallbackAndDestroy(
- "subset-hashes: payload-integrity-header must be a string.");
- return nullptr;
- }
- resource_integrities.push_back(mojom::ResourceIntegrity::New(
- value_array[i].GetBytestring(), value_array[i + 1].GetString()));
- }
- subset_hashes.insert(std::make_pair(
- parsed_url,
- mojom::SubsetHashesValue::New(variants_value.as_string(),
- std::move(resource_integrities))));
- }
-
- return mojom::SignedSubset::New(validity_url, auth_sha256, date, expires,
- std::move(subset_hashes));
- }
-
- // Returns nullptr if |key| is not in |map|.
- const cbor::Value* Lookup(const cbor::Value::MapValue& map, const char* key) {
- auto iter = map.find(cbor::Value(key));
- if (iter == map.end())
- return nullptr;
- return &iter->second;
- }
-
- void RunSuccessCallbackAndDestroy() {
- std::move(callback_).Run(std::move(metadata_), nullptr);
- delete this;
- }
-
- void RunErrorCallbackAndDestroy(
- const std::string& message,
- mojom::BundleParseErrorType error_type =
- mojom::BundleParseErrorType::kFormatError) {
- mojom::BundleMetadataParseErrorPtr err =
- mojom::BundleMetadataParseError::New(error_type, fallback_url_,
- message);
- std::move(callback_).Run(nullptr, std::move(err));
- delete this;
- }
-
- // Implements SharedBundleDataSource::Observer.
- void OnDisconnect() override {
- RunErrorCallbackAndDestroy("Data source disconnected.");
- }
-
- scoped_refptr<SharedBundleDataSource> data_source_;
- ParseMetadataCallback callback_;
- bool version_mismatch_ = false;
- GURL fallback_url_;
- SectionOffsets section_offsets_;
- mojom::BundleMetadataPtr metadata_;
-
- base::WeakPtrFactory<MetadataParser> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(MetadataParser);
-};
-
-// A parser for reading single item from the responses section. This class owns
-// itself and will self destruct after calling the ParseResponseCallback.
-class WebBundleParser::ResponseParser
- : public WebBundleParser::SharedBundleDataSource::Observer {
- public:
- ResponseParser(scoped_refptr<SharedBundleDataSource> data_source,
- uint64_t response_offset,
- uint64_t response_length,
- WebBundleParser::ParseResponseCallback callback)
- : data_source_(data_source),
- response_offset_(response_offset),
- response_length_(response_length),
- callback_(std::move(callback)) {
- data_source_->AddObserver(this);
- }
- ~ResponseParser() override { data_source_->RemoveObserver(this); }
-
- void Start(uint64_t buffer_size = kInitialBufferSizeForResponse) {
- const uint64_t length = std::min(response_length_, buffer_size);
- data_source_->Read(response_offset_, length,
- base::BindOnce(&ResponseParser::ParseResponseHeader,
- weak_factory_.GetWeakPtr(), length));
- }
-
- private:
- // https://wicg.github.io/webpackage/draft-yasskin-wpack-bundled-exchanges.html#load-response
- void ParseResponseHeader(uint64_t expected_data_length,
- const base::Optional<std::vector<uint8_t>>& data) {
- // Step 1. "Seek to offset requestMetadata.offset in stream. If this fails,
- // return an error."
- if (!data || data->size() != expected_data_length) {
- RunErrorCallbackAndDestroy("Error reading response header.");
- return;
- }
- InputReader input(*data);
-
- // Step 2. "Read 1 byte from stream. If this is an error or isn't 0x82,
- // return an error."
- auto num_elements = input.ReadCBORHeader(CBORType::kArray);
- if (!num_elements || *num_elements != 2) {
- RunErrorCallbackAndDestroy("Array size of response must be 2.");
- return;
- }
-
- // Step 3. "Let headerLength be the result of getting the length of a CBOR
- // bytestring header from stream (Section 3.5.2). If headerLength is an
- // error, return that error."
- auto header_length = input.ReadCBORHeader(CBORType::kByteString);
- if (!header_length) {
- RunErrorCallbackAndDestroy("Cannot parse response header length.");
- return;
- }
-
- // Step 4. "If headerLength is 524288 (512*1024) or greater, return an
- // error."
- if (*header_length >= kMaxResponseHeaderLength) {
- RunErrorCallbackAndDestroy("Response header is too big.");
- return;
- }
-
- // If we don't have enough data for the headers and the CBOR header of the
- // payload, re-read with a larger buffer size.
- const uint64_t required_buffer_size = std::min(
- input.CurrentOffset() + *header_length + kMaxCBORItemHeaderSize,
- response_length_);
- if (data->size() < required_buffer_size) {
- DVLOG(1) << "Re-reading response header with a buffer of size "
- << required_buffer_size;
- Start(required_buffer_size);
- return;
- }
-
- // Step 5. "Let headerCbor be the result of reading headerLength bytes from
- // stream and parsing a CBOR item from them matching the headers CDDL rule.
- // If either the read or parse returns an error, return that error."
- auto headers_bytes = input.ReadBytes(*header_length);
- if (!headers_bytes) {
- RunErrorCallbackAndDestroy("Cannot read response headers.");
- return;
- }
- cbor::Reader::DecoderError error;
- base::Optional<cbor::Value> headers_value =
- cbor::Reader::Read(*headers_bytes, &error);
- if (!headers_value) {
- RunErrorCallbackAndDestroy("Cannot parse response headers.");
- return;
- }
-
- // Step 6. "Let (headers, pseudos) be the result of converting headerCbor
- // to a header list and pseudoheaders using the algorithm in Section 3.6.
- // If this returns an error, return that error."
- auto parsed_headers = ConvertCBORValueToHeaders(*headers_value);
- if (!parsed_headers) {
- RunErrorCallbackAndDestroy("Cannot parse response headers.");
- return;
- }
-
- // Step 7. "If pseudos does not have a key named ':status' or its size
- // isn't 1, return an error."
- const auto pseudo_status = parsed_headers->pseudos.find(":status");
- if (parsed_headers->pseudos.size() != 1 ||
- pseudo_status == parsed_headers->pseudos.end()) {
- RunErrorCallbackAndDestroy(
- "Response headers map must have exactly one pseudo-header, :status.");
- return;
- }
-
- // Step 8. "If pseudos[':status'] isn't exactly 3 ASCII decimal digits,
- // return an error."
- int status;
- const auto& status_str = pseudo_status->second;
- if (status_str.size() != 3 ||
- !std::all_of(status_str.begin(), status_str.end(),
- base::IsAsciiDigit<char>) ||
- !base::StringToInt(status_str, &status)) {
- RunErrorCallbackAndDestroy(":status must be 3 ASCII decimal digits.");
- return;
- }
-
- // Step 9. "Let payloadLength be the result of getting the length of a CBOR
- // bytestring header from stream (Section 3.5.2). If payloadLength is an
- // error, return that error."
- auto payload_length = input.ReadCBORHeader(CBORType::kByteString);
- if (!payload_length) {
- RunErrorCallbackAndDestroy("Cannot parse response payload length.");
- return;
- }
-
- // Step 10. "If payloadLength is greater than 0 and headers does not contain
- // a Content-Type header, return an error."
- if (*payload_length > 0 &&
- !parsed_headers->headers.contains("content-type")) {
- RunErrorCallbackAndDestroy(
- "Non-empty response must have a content-type header.");
- return;
- }
-
- // Step 11. "If stream.currentOffset + payloadLength !=
- // requestMetadata.offset + requestMetadata.length, return an error."
- if (input.CurrentOffset() + *payload_length != response_length_) {
- RunErrorCallbackAndDestroy("Unexpected payload length.");
- return;
- }
-
- // Step 12. "Let body be a new body ([FETCH]) whose stream is a tee'd copy
- // of stream starting at the current offset and ending after payloadLength
- // bytes."
-
- // Step 13. "Let response be a new response ([FETCH]) whose:
- // - Url list is request's url list,
- // - status is pseudos[':status'],
- // - header list is headers, and
- // - body is body."
- mojom::BundleResponsePtr response = mojom::BundleResponse::New();
- response->response_code = status;
- response->response_headers = std::move(parsed_headers->headers);
- response->payload_offset = response_offset_ + input.CurrentOffset();
- response->payload_length = *payload_length;
- RunSuccessCallbackAndDestroy(std::move(response));
- }
-
- void RunSuccessCallbackAndDestroy(mojom::BundleResponsePtr response) {
- std::move(callback_).Run(std::move(response), nullptr);
- delete this;
- }
-
- void RunErrorCallbackAndDestroy(
- const std::string& message,
- mojom::BundleParseErrorType error_type =
- mojom::BundleParseErrorType::kFormatError) {
- std::move(callback_).Run(
- nullptr, mojom::BundleResponseParseError::New(error_type, message));
- delete this;
- }
-
- // Implements SharedBundleDataSource::Observer.
- void OnDisconnect() override {
- RunErrorCallbackAndDestroy("Data source disconnected.");
- }
-
- scoped_refptr<SharedBundleDataSource> data_source_;
- uint64_t response_offset_;
- uint64_t response_length_;
- ParseResponseCallback callback_;
-
- base::WeakPtrFactory<ResponseParser> weak_factory_{this};
-
- DISALLOW_COPY_AND_ASSIGN(ResponseParser);
-};
-
-WebBundleParser::SharedBundleDataSource::SharedBundleDataSource(
- mojo::PendingRemote<mojom::BundleDataSource> pending_data_source)
- : data_source_(std::move(pending_data_source)) {
- data_source_.set_disconnect_handler(base::BindOnce(
- &SharedBundleDataSource::OnDisconnect, base::Unretained(this)));
-}
-
-void WebBundleParser::SharedBundleDataSource::AddObserver(Observer* observer) {
- DCHECK(observers_.end() == observers_.find(observer));
- observers_.insert(observer);
-}
-
-void WebBundleParser::SharedBundleDataSource::RemoveObserver(
- Observer* observer) {
- auto it = observers_.find(observer);
- DCHECK(observers_.end() != it);
- observers_.erase(it);
-}
-
-WebBundleParser::SharedBundleDataSource::~SharedBundleDataSource() = default;
-
-void WebBundleParser::SharedBundleDataSource::OnDisconnect() {
- for (auto* observer : observers_)
- observer->OnDisconnect();
-}
-
-void WebBundleParser::SharedBundleDataSource::Read(uint64_t offset,
- uint64_t length,
- ReadCallback callback) {
- data_source_->Read(offset, length, std::move(callback));
-}
-
-WebBundleParser::WebBundleParser(
- mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- mojo::PendingRemote<mojom::BundleDataSource> data_source)
- : receiver_(this, std::move(receiver)),
- data_source_(base::MakeRefCounted<SharedBundleDataSource>(
- std::move(data_source))) {
- receiver_.set_disconnect_handler(base::BindOnce(
- &base::DeletePointer<WebBundleParser>, base::Unretained(this)));
-}
-
-WebBundleParser::~WebBundleParser() = default;
-
-void WebBundleParser::ParseMetadata(ParseMetadataCallback callback) {
- MetadataParser* parser =
- new MetadataParser(data_source_, std::move(callback));
- parser->Start();
-}
-
-void WebBundleParser::ParseResponse(uint64_t response_offset,
- uint64_t response_length,
- ParseResponseCallback callback) {
- ResponseParser* parser = new ResponseParser(
- data_source_, response_offset, response_length, std::move(callback));
- parser->Start();
-}
-
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/web_bundle_parser.h b/chromium/services/data_decoder/web_bundle_parser.h
deleted file mode 100644
index 81fe780badc..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser.h
+++ /dev/null
@@ -1,71 +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_DATA_DECODER_WEB_BUNDLE_PARSER_H_
-#define SERVICES_DATA_DECODER_WEB_BUNDLE_PARSER_H_
-
-#include <memory>
-
-#include "base/containers/flat_set.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/data_decoder/public/mojom/web_bundle_parser.mojom.h"
-
-namespace data_decoder {
-
-class WebBundleParser : public mojom::WebBundleParser {
- public:
- WebBundleParser(mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- mojo::PendingRemote<mojom::BundleDataSource> data_source);
- ~WebBundleParser() override;
-
- private:
- class MetadataParser;
- class ResponseParser;
-
- class SharedBundleDataSource
- : public base::RefCounted<SharedBundleDataSource>,
- public mojom::BundleDataSource {
- public:
- class Observer;
-
- explicit SharedBundleDataSource(
- mojo::PendingRemote<mojom::BundleDataSource> pending_data_source);
-
- void AddObserver(Observer* observer);
- void RemoveObserver(Observer* observer);
-
- // Implements mojom::BundleDataSource.
- void Read(uint64_t offset, uint64_t length, ReadCallback callback) override;
-
- private:
- friend class base::RefCounted<SharedBundleDataSource>;
-
- ~SharedBundleDataSource() override;
-
- void OnDisconnect();
-
- mojo::Remote<mojom::BundleDataSource> data_source_;
- base::flat_set<Observer*> observers_;
-
- DISALLOW_COPY_AND_ASSIGN(SharedBundleDataSource);
- };
-
- // mojom::WebBundleParser implementation.
- void ParseMetadata(ParseMetadataCallback callback) override;
- void ParseResponse(uint64_t response_offset,
- uint64_t response_length,
- ParseResponseCallback callback) override;
-
- mojo::Receiver<mojom::WebBundleParser> receiver_;
- scoped_refptr<SharedBundleDataSource> data_source_;
-
- DISALLOW_COPY_AND_ASSIGN(WebBundleParser);
-};
-
-} // namespace data_decoder
-
-#endif // SERVICES_DATA_DECODER_WEB_BUNDLE_PARSER_H_
diff --git a/chromium/services/data_decoder/web_bundle_parser_factory.cc b/chromium/services/data_decoder/web_bundle_parser_factory.cc
deleted file mode 100644
index 1ead65ea90c..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser_factory.cc
+++ /dev/null
@@ -1,79 +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/data_decoder/web_bundle_parser_factory.h"
-
-#include "base/bind_helpers.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "net/http/http_util.h"
-#include "services/data_decoder/web_bundle_parser.h"
-
-namespace data_decoder {
-
-namespace {
-
-class FileDataSource final : public mojom::BundleDataSource {
- public:
- FileDataSource(mojo::PendingReceiver<mojom::BundleDataSource> receiver,
- base::File file)
- : receiver_(this, std::move(receiver)), file_(std::move(file)) {
- receiver_.set_disconnect_handler(base::BindOnce(
- &base::DeletePointer<FileDataSource>, base::Unretained(this)));
- }
-
- private:
- // Implements mojom::BundleDataSource.
- void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
- std::vector<uint8_t> buf(length);
- int bytes = file_.Read(offset, reinterpret_cast<char*>(buf.data()), length);
- if (bytes > 0) {
- buf.resize(bytes);
- std::move(callback).Run(std::move(buf));
- } else {
- std::move(callback).Run(base::nullopt);
- }
- }
-
- mojo::Receiver<mojom::BundleDataSource> receiver_;
- base::File file_;
-
- DISALLOW_COPY_AND_ASSIGN(FileDataSource);
-};
-
-} // namespace
-
-WebBundleParserFactory::WebBundleParserFactory() = default;
-
-WebBundleParserFactory::~WebBundleParserFactory() = default;
-
-std::unique_ptr<mojom::BundleDataSource>
-WebBundleParserFactory::CreateFileDataSourceForTesting(
- mojo::PendingReceiver<mojom::BundleDataSource> receiver,
- base::File file) {
- return std::make_unique<FileDataSource>(std::move(receiver), std::move(file));
-}
-
-void WebBundleParserFactory::GetParserForFile(
- mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- base::File file) {
- mojo::PendingRemote<mojom::BundleDataSource> remote_data_source;
- auto data_source = std::make_unique<FileDataSource>(
- remote_data_source.InitWithNewPipeAndPassReceiver(), std::move(file));
- GetParserForDataSource(std::move(receiver), std::move(remote_data_source));
-
- // |data_source| will be destructed on |remote_data_source| destruction.
- data_source.release();
-}
-
-void WebBundleParserFactory::GetParserForDataSource(
- mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- mojo::PendingRemote<mojom::BundleDataSource> data_source) {
- auto parser = std::make_unique<WebBundleParser>(std::move(receiver),
- std::move(data_source));
-
- // |parser| will be destructed on remote mojo ends' disconnection.
- parser.release();
-}
-
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/web_bundle_parser_factory.h b/chromium/services/data_decoder/web_bundle_parser_factory.h
deleted file mode 100644
index 5430b5b92f0..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser_factory.h
+++ /dev/null
@@ -1,40 +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_DATA_DECODER_WEB_BUNDLE_PARSER_FACTORY_H_
-#define SERVICES_DATA_DECODER_WEB_BUNDLE_PARSER_FACTORY_H_
-
-#include <memory>
-
-#include "base/files/file.h"
-#include "base/macros.h"
-#include "mojo/public/cpp/bindings/receiver.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "services/data_decoder/public/mojom/web_bundle_parser.mojom.h"
-
-namespace data_decoder {
-
-class WebBundleParserFactory : public mojom::WebBundleParserFactory {
- public:
- WebBundleParserFactory();
- ~WebBundleParserFactory() override;
-
- std::unique_ptr<mojom::BundleDataSource> CreateFileDataSourceForTesting(
- mojo::PendingReceiver<mojom::BundleDataSource> receiver,
- base::File file);
-
- private:
- // mojom::WebBundleParserFactory implementation.
- void GetParserForFile(mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- base::File file) override;
- void GetParserForDataSource(
- mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- mojo::PendingRemote<mojom::BundleDataSource> data_source) override;
-
- DISALLOW_COPY_AND_ASSIGN(WebBundleParserFactory);
-};
-
-} // namespace data_decoder
-
-#endif // SERVICES_DATA_DECODER_WEB_BUNDLE_PARSER_FACTORY_H_
diff --git a/chromium/services/data_decoder/web_bundle_parser_factory_unittest.cc b/chromium/services/data_decoder/web_bundle_parser_factory_unittest.cc
deleted file mode 100644
index c6cecfa12f1..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser_factory_unittest.cc
+++ /dev/null
@@ -1,190 +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/data_decoder/web_bundle_parser_factory.h"
-
-#include "base/files/file.h"
-#include "base/files/file_path.h"
-#include "base/optional.h"
-#include "base/path_service.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_receiver.h"
-#include "mojo/public/cpp/bindings/pending_remote.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace data_decoder {
-
-namespace {
-
-base::FilePath GetTestFilePath(const base::FilePath& path) {
- base::FilePath test_path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &test_path);
- test_path = test_path.Append(
- base::FilePath(FILE_PATH_LITERAL("services/test/data/web_bundle")));
- return test_path.Append(path);
-}
-
-} // namespace
-
-class WebBundleParserFactoryTest : public testing::Test {
- public:
- WebBundleParserFactoryTest()
- : factory_(std::make_unique<WebBundleParserFactory>()) {}
-
- std::unique_ptr<mojom::BundleDataSource> CreateFileDataSource(
- mojo::PendingReceiver<mojom::BundleDataSource> receiver,
- base::File file) {
- return factory_->CreateFileDataSourceForTesting(std::move(receiver),
- std::move(file));
- }
-
- void GetParserForFile(mojo::PendingReceiver<mojom::WebBundleParser> receiver,
- base::File file) {
- mojom::WebBundleParserFactory* factory = factory_.get();
- return factory->GetParserForFile(std::move(receiver), std::move(file));
- }
-
- private:
- std::unique_ptr<WebBundleParserFactory> factory_;
- base::test::TaskEnvironment task_environment_;
-};
-
-TEST_F(WebBundleParserFactoryTest, FileDataSource) {
- base::FilePath test_file =
- GetTestFilePath(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
-
- base::File file(test_file, base::File::FLAG_OPEN | base::File::FLAG_READ);
- ASSERT_TRUE(file.IsValid());
- int64_t file_length = file.GetLength();
- constexpr int64_t test_length = 16;
- ASSERT_LE(test_length, file_length);
- std::vector<uint8_t> first16b(test_length);
- ASSERT_EQ(test_length, file.Read(0, reinterpret_cast<char*>(first16b.data()),
- first16b.size()));
- std::vector<uint8_t> last16b(test_length);
- ASSERT_EQ(test_length,
- file.Read(file_length - test_length,
- reinterpret_cast<char*>(last16b.data()), last16b.size()));
-
- mojo::PendingRemote<mojom::BundleDataSource> remote;
- auto data_source = CreateFileDataSource(
- remote.InitWithNewPipeAndPassReceiver(), std::move(file));
-
- base::Optional<std::vector<uint8_t>> result_data;
- {
- base::RunLoop run_loop;
- data_source->Read(
- /*offset=*/0, test_length,
- base::BindLambdaForTesting(
- [&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
- result_data = data;
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_TRUE(result_data);
- EXPECT_EQ(first16b, *result_data);
-
- {
- base::RunLoop run_loop;
- data_source->Read(
- file_length - test_length, test_length,
- base::BindLambdaForTesting(
- [&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
- result_data = data;
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_TRUE(result_data);
- EXPECT_EQ(last16b, *result_data);
-
- {
- base::RunLoop run_loop;
- data_source->Read(
- file_length - test_length, test_length + 1,
- base::BindLambdaForTesting(
- [&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
- result_data = data;
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_TRUE(result_data);
- EXPECT_EQ(last16b, *result_data);
-
- {
- base::RunLoop run_loop;
- data_source->Read(
- file_length + 1, test_length,
- base::BindLambdaForTesting(
- [&result_data,
- &run_loop](const base::Optional<std::vector<uint8_t>>& data) {
- result_data = data;
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_FALSE(result_data);
-}
-
-TEST_F(WebBundleParserFactoryTest, GetParserForFile) {
- base::File file(
- GetTestFilePath(base::FilePath(FILE_PATH_LITERAL("hello.wbn"))),
- base::File::FLAG_OPEN | base::File::FLAG_READ);
- ASSERT_TRUE(file.IsValid());
-
- mojo::Remote<mojom::WebBundleParser> parser;
- GetParserForFile(parser.BindNewPipeAndPassReceiver(), std::move(file));
-
- mojom::BundleMetadataPtr metadata;
- {
- base::RunLoop run_loop;
- parser->ParseMetadata(base::BindLambdaForTesting(
- [&metadata, &run_loop](mojom::BundleMetadataPtr parsed_metadata,
- mojom::BundleMetadataParseErrorPtr error) {
- metadata = std::move(parsed_metadata);
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_TRUE(metadata);
- ASSERT_EQ(metadata->requests.size(), 4u);
-
- std::map<std::string, mojom::BundleResponsePtr> responses;
- for (const auto& item : metadata->requests) {
- ASSERT_TRUE(item.second->variants_value.empty());
- ASSERT_EQ(item.second->response_locations.size(), 1u);
- base::RunLoop run_loop;
- parser->ParseResponse(item.second->response_locations[0]->offset,
- item.second->response_locations[0]->length,
- base::BindLambdaForTesting(
- [&item, &responses, &run_loop](
- mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error) {
- ASSERT_TRUE(response);
- ASSERT_FALSE(error);
- responses[item.first.spec()] =
- std::move(response);
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- }
- ASSERT_TRUE(responses["https://test.example.org/"]);
- EXPECT_EQ(responses["https://test.example.org/"]->response_code, 200);
- EXPECT_EQ(
- responses["https://test.example.org/"]->response_headers["content-type"],
- "text/html; charset=utf-8");
- EXPECT_TRUE(responses["https://test.example.org/index.html"]);
- EXPECT_TRUE(responses["https://test.example.org/manifest.webmanifest"]);
- EXPECT_TRUE(responses["https://test.example.org/script.js"]);
-}
-
-} // namespace data_decoder
diff --git a/chromium/services/data_decoder/web_bundle_parser_fuzzer.cc b/chromium/services/data_decoder/web_bundle_parser_fuzzer.cc
deleted file mode 100644
index df56a878f86..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser_fuzzer.cc
+++ /dev/null
@@ -1,131 +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 <stddef.h>
-#include <stdint.h>
-
-#include <string>
-
-#include "base/at_exit.h"
-#include "base/bind.h"
-#include "base/i18n/icu_util.h"
-#include "base/run_loop.h"
-#include "base/task/single_thread_task_executor.h"
-#include "mojo/core/embedder/embedder.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/data_decoder/web_bundle_parser.h"
-#include "services/data_decoder/web_bundle_parser_factory.h"
-
-namespace {
-
-class DataSource : public data_decoder::mojom::BundleDataSource {
- public:
- DataSource(const uint8_t* data, size_t size) : data_(data), size_(size) {}
-
- void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
- if (offset >= size_) {
- std::move(callback).Run(base::nullopt);
- return;
- }
- const uint8_t* start = data_ + offset;
- length = std::min(length, size_ - offset);
- std::move(callback).Run(std::vector<uint8_t>(start, start + length));
- }
-
- void AddReceiver(
- mojo::PendingReceiver<data_decoder::mojom::BundleDataSource> receiver) {
- receivers_.Add(this, std::move(receiver));
- }
-
- private:
- const uint8_t* data_;
- size_t size_;
- mojo::ReceiverSet<data_decoder::mojom::BundleDataSource> receivers_;
-};
-
-class WebBundleParserFuzzer {
- public:
- WebBundleParserFuzzer(const uint8_t* data, size_t size)
- : data_source_(data, size) {}
-
- void FuzzBundle(base::RunLoop* run_loop) {
- mojo::PendingRemote<data_decoder::mojom::BundleDataSource>
- data_source_remote;
- data_source_.AddReceiver(
- data_source_remote.InitWithNewPipeAndPassReceiver());
-
- data_decoder::WebBundleParserFactory factory_impl;
- data_decoder::mojom::WebBundleParserFactory& factory = factory_impl;
- factory.GetParserForDataSource(parser_.BindNewPipeAndPassReceiver(),
- std::move(data_source_remote));
-
- quit_loop_ = run_loop->QuitClosure();
- parser_->ParseMetadata(base::BindOnce(
- &WebBundleParserFuzzer::OnParseMetadata, base::Unretained(this)));
- }
-
- void OnParseMetadata(data_decoder::mojom::BundleMetadataPtr metadata,
- data_decoder::mojom::BundleMetadataParseErrorPtr error) {
- if (!metadata) {
- std::move(quit_loop_).Run();
- return;
- }
- for (const auto& item : metadata->requests) {
- for (auto& resp_location : item.second->response_locations)
- locations_.push_back(std::move(resp_location));
- }
- ParseResponses(0);
- }
-
- void ParseResponses(size_t index) {
- if (index >= locations_.size()) {
- std::move(quit_loop_).Run();
- return;
- }
-
- parser_->ParseResponse(
- locations_[index]->offset, locations_[index]->length,
- base::BindOnce(&WebBundleParserFuzzer::OnParseResponse,
- base::Unretained(this), index));
- }
-
- void OnParseResponse(size_t index,
- data_decoder::mojom::BundleResponsePtr response,
- data_decoder::mojom::BundleResponseParseErrorPtr error) {
- ParseResponses(index + 1);
- }
-
- private:
- mojo::Remote<data_decoder::mojom::WebBundleParser> parser_;
- DataSource data_source_;
- base::OnceClosure quit_loop_;
- std::vector<data_decoder::mojom::BundleResponseLocationPtr> locations_;
-};
-
-struct Environment {
- Environment() {
- mojo::core::Init();
- CHECK(base::i18n::InitializeICU());
- }
-
- // Used by ICU integration.
- base::AtExitManager at_exit_manager;
- base::SingleThreadTaskExecutor task_executor;
-};
-
-} // namespace
-
-// Entry point for LibFuzzer.
-extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
- static Environment* env = new Environment();
-
- WebBundleParserFuzzer fuzzer(data, size);
- base::RunLoop run_loop;
- env->task_executor.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&WebBundleParserFuzzer::FuzzBundle,
- base::Unretained(&fuzzer), &run_loop));
- run_loop.Run();
-
- return 0;
-}
diff --git a/chromium/services/data_decoder/web_bundle_parser_unittest.cc b/chromium/services/data_decoder/web_bundle_parser_unittest.cc
deleted file mode 100644
index eb637bacf9e..00000000000
--- a/chromium/services/data_decoder/web_bundle_parser_unittest.cc
+++ /dev/null
@@ -1,700 +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/data_decoder/web_bundle_parser.h"
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/optional.h"
-#include "base/path_service.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/task_environment.h"
-#include "components/cbor/writer.h"
-#include "mojo/public/cpp/bindings/receiver_set.h"
-#include "services/data_decoder/public/cpp/test_support/web_bundle_builder.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace data_decoder {
-
-namespace {
-
-constexpr char kFallbackUrl[] = "https://test.example.com/";
-constexpr char kManifestUrl[] = "https://test.example.com/manifest";
-constexpr char kValidityUrl[] =
- "https://test.example.org/resource.validity.msg";
-const uint64_t kSignatureDate = 1564272000; // 2019-07-28T00:00:00Z
-const uint64_t kSignatureDuration = 7 * 24 * 60 * 60;
-
-std::string GetTestFileContents(const base::FilePath& path) {
- base::FilePath test_data_dir;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir);
- test_data_dir = test_data_dir.Append(
- base::FilePath(FILE_PATH_LITERAL("services/test/data/web_bundle")));
-
- std::string contents;
- EXPECT_TRUE(base::ReadFileToString(test_data_dir.Append(path), &contents));
- return contents;
-}
-
-class TestDataSource : public mojom::BundleDataSource {
- public:
- explicit TestDataSource(const base::FilePath& path)
- : data_(GetTestFileContents(path)) {}
- explicit TestDataSource(const std::vector<uint8_t>& data)
- : data_(reinterpret_cast<const char*>(data.data()), data.size()) {}
-
- void Read(uint64_t offset, uint64_t length, ReadCallback callback) override {
- if (offset >= data_.size())
- std::move(callback).Run(base::nullopt);
- const uint8_t* start =
- reinterpret_cast<const uint8_t*>(data_.data()) + offset;
- uint64_t available_length = std::min(length, data_.size() - offset);
- std::move(callback).Run(
- std::vector<uint8_t>(start, start + available_length));
- }
-
- base::StringPiece GetPayload(const mojom::BundleResponsePtr& response) {
- return base::StringPiece(data_).substr(response->payload_offset,
- response->payload_length);
- }
-
- void AddReceiver(mojo::PendingReceiver<mojom::BundleDataSource> receiver) {
- receivers_.Add(this, std::move(receiver));
- }
-
- private:
- std::string data_;
- mojo::ReceiverSet<mojom::BundleDataSource> receivers_;
-};
-
-using ParseBundleResult =
- std::pair<mojom::BundleMetadataPtr, mojom::BundleMetadataParseErrorPtr>;
-
-ParseBundleResult ParseBundle(TestDataSource* data_source) {
- mojo::PendingRemote<mojom::BundleDataSource> source_remote;
- data_source->AddReceiver(source_remote.InitWithNewPipeAndPassReceiver());
-
- mojo::PendingRemote<mojom::WebBundleParser> parser_remote;
- WebBundleParser parser_impl(parser_remote.InitWithNewPipeAndPassReceiver(),
- std::move(source_remote));
- data_decoder::mojom::WebBundleParser& parser = parser_impl;
-
- base::RunLoop run_loop;
- ParseBundleResult result;
- parser.ParseMetadata(base::BindLambdaForTesting(
- [&result, &run_loop](mojom::BundleMetadataPtr metadata,
- mojom::BundleMetadataParseErrorPtr error) {
- result = std::make_pair(std::move(metadata), std::move(error));
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- EXPECT_TRUE((result.first && !result.second) ||
- (!result.first && result.second));
- return result;
-}
-
-void ExpectFormatErrorWithFallbackURL(ParseBundleResult result) {
- ASSERT_TRUE(result.second);
- EXPECT_EQ(result.second->type, mojom::BundleParseErrorType::kFormatError);
- EXPECT_EQ(result.second->fallback_url, kFallbackUrl);
-}
-
-// Finds the only response for |url|. The index entry for |url| must not have
-// variants-value.
-mojom::BundleResponseLocationPtr FindResponse(
- const mojom::BundleMetadataPtr& metadata,
- const GURL& url) {
- const auto item = metadata->requests.find(url);
- if (item == metadata->requests.end())
- return nullptr;
-
- const mojom::BundleIndexValuePtr& index_value = item->second;
- EXPECT_TRUE(index_value->variants_value.empty());
- EXPECT_EQ(index_value->response_locations.size(), 1u);
- if (index_value->response_locations.empty())
- return nullptr;
- return index_value->response_locations[0].Clone();
-}
-
-mojom::BundleResponsePtr ParseResponse(
- TestDataSource* data_source,
- const mojom::BundleResponseLocationPtr& location) {
- mojo::PendingRemote<mojom::BundleDataSource> source_remote;
- data_source->AddReceiver(source_remote.InitWithNewPipeAndPassReceiver());
-
- mojo::PendingRemote<mojom::WebBundleParser> parser_remote;
- WebBundleParser parser_impl(parser_remote.InitWithNewPipeAndPassReceiver(),
- std::move(source_remote));
- data_decoder::mojom::WebBundleParser& parser = parser_impl;
-
- base::RunLoop run_loop;
- mojom::BundleResponsePtr result;
- parser.ParseResponse(
- location->offset, location->length,
- base::BindLambdaForTesting(
- [&result, &run_loop](mojom::BundleResponsePtr response,
- mojom::BundleResponseParseErrorPtr error) {
- result = std::move(response);
- run_loop.QuitClosure().Run();
- }));
- run_loop.Run();
- return result;
-}
-
-cbor::Value CreateByteString(base::StringPiece s) {
- return cbor::Value(base::as_bytes(base::make_span(s)));
-}
-
-std::string AsString(const std::vector<uint8_t>& data) {
- return std::string(reinterpret_cast<const char*>(data.data()), data.size());
-}
-
-} // namespace
-
-class WebBundleParserTest : public testing::Test {
- private:
- base::test::TaskEnvironment task_environment_;
-};
-
-TEST_F(WebBundleParserTest, WrongMagic) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- std::vector<uint8_t> bundle = builder.CreateBundle();
- bundle[3] ^= 1;
- TestDataSource data_source(bundle);
-
- mojom::BundleMetadataParseErrorPtr error = ParseBundle(&data_source).second;
- ASSERT_TRUE(error);
- EXPECT_EQ(error->type, mojom::BundleParseErrorType::kFormatError);
- EXPECT_TRUE(error->fallback_url.is_empty());
-}
-
-TEST_F(WebBundleParserTest, UnknownVersion) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- std::vector<uint8_t> bundle = builder.CreateBundle();
- // Modify the version string from "b1\0\0" to "q1\0\0".
- ASSERT_EQ(bundle[11], 'b');
- bundle[11] = 'q';
- TestDataSource data_source(bundle);
-
- mojom::BundleMetadataParseErrorPtr error = ParseBundle(&data_source).second;
- ASSERT_TRUE(error);
- EXPECT_EQ(error->type, mojom::BundleParseErrorType::kVersionError);
- EXPECT_EQ(error->fallback_url, kFallbackUrl);
-}
-
-TEST_F(WebBundleParserTest, FallbackURLIsNotUTF8) {
- test::WebBundleBuilder builder("https://test.example.com/\xcc", kManifestUrl);
- std::vector<uint8_t> bundle = builder.CreateBundle();
- TestDataSource data_source(bundle);
-
- mojom::BundleMetadataParseErrorPtr error = ParseBundle(&data_source).second;
- ASSERT_TRUE(error);
- EXPECT_EQ(error->type, mojom::BundleParseErrorType::kFormatError);
- EXPECT_TRUE(error->fallback_url.is_empty());
-}
-
-TEST_F(WebBundleParserTest, FallbackURLHasFragment) {
- test::WebBundleBuilder builder("https://test.example.com/#fragment",
- kManifestUrl);
- std::vector<uint8_t> bundle = builder.CreateBundle();
- TestDataSource data_source(bundle);
-
- mojom::BundleMetadataParseErrorPtr error = ParseBundle(&data_source).second;
- ASSERT_TRUE(error);
- EXPECT_EQ(error->type, mojom::BundleParseErrorType::kFormatError);
- EXPECT_TRUE(error->fallback_url.is_empty());
-}
-
-TEST_F(WebBundleParserTest, SectionLengthsTooLarge) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- std::string too_long_section_name(8192, 'x');
- builder.AddSection(too_long_section_name, cbor::Value(0));
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, DuplicateSectionName) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddSection("foo", cbor::Value(0));
- builder.AddSection("foo", cbor::Value(0));
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, SingleEntry) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- ASSERT_EQ(metadata->requests.size(), 1u);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- auto response = ParseResponse(&data_source, location);
- ASSERT_TRUE(response);
- EXPECT_EQ(response->response_code, 200);
- EXPECT_EQ(response->response_headers.size(), 1u);
- EXPECT_EQ(response->response_headers["content-type"], "text/plain");
- EXPECT_EQ(data_source.GetPayload(response), "payload");
-}
-
-TEST_F(WebBundleParserTest, InvalidRequestURL) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("", {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, RequestURLIsNotUTF8) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/\xcc",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, RequestURLHasBadScheme) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("file:///tmp/foo",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, RequestURLHasCredentials) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://user:passwd@test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, RequestURLHasFragment) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/#fragment",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, NoStatusInResponseHeaders) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{"content-type", "text/plain"}},
- "payload"); // ":status" is missing.
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, InvalidResponseStatus) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "0200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, ExtraPseudoInResponseHeaders) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange(
- "https://test.example.com/",
- {{":status", "200"}, {":foo", ""}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, UpperCaseCharacterInHeaderName) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"Content-Type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, InvalidHeaderValue) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "\n"}}, "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, NoContentTypeWithNonEmptyContent) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/", {{":status", "200"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_FALSE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, NoContentTypeWithEmptyContent) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/", {{":status", "301"}}, "");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- auto location = FindResponse(metadata, GURL("https://test.example.com/"));
- ASSERT_TRUE(location);
- ASSERT_TRUE(ParseResponse(&data_source, location));
-}
-
-TEST_F(WebBundleParserTest, Variants) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- auto location1 = builder.AddResponse(
- {{":status", "200"}, {"content-type", "text/html"}}, "payload1");
- auto location2 = builder.AddResponse(
- {{":status", "200"}, {"content-type", "text/plain"}}, "payload2");
- builder.AddIndexEntry("https://test.example.com/",
- "Accept;text/html;text/plain", {location1, location2});
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- const auto& found =
- metadata->requests.find(GURL("https://test.example.com/"));
- ASSERT_NE(found, metadata->requests.end());
- const mojom::BundleIndexValuePtr& index_entry = found->second;
- EXPECT_EQ(index_entry->variants_value, "Accept;text/html;text/plain");
- ASSERT_EQ(index_entry->response_locations.size(), 2u);
-
- auto response1 =
- ParseResponse(&data_source, index_entry->response_locations[0]);
- ASSERT_TRUE(response1);
- EXPECT_EQ(data_source.GetPayload(response1), "payload1");
- auto response2 =
- ParseResponse(&data_source, index_entry->response_locations[1]);
- ASSERT_TRUE(response2);
- EXPECT_EQ(data_source.GetPayload(response2), "payload2");
-}
-
-TEST_F(WebBundleParserTest, EmptyIndexEntry) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddIndexEntry("https://test.example.com/", "", {});
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, EmptyIndexEntryWithVariants) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddIndexEntry("https://test.example.com/",
- "Accept;text/html;text/plain", {});
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, MultipleResponsesWithoutVariantsValue) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- auto location1 = builder.AddResponse(
- {{":status", "200"}, {"content-type", "text/html"}}, "payload1");
- auto location2 = builder.AddResponse(
- {{":status", "200"}, {"content-type", "text/plain"}}, "payload2");
- builder.AddIndexEntry("https://test.example.com/", "",
- {location1, location2});
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, AllKnownSectionInCritical) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- cbor::Value::ArrayValue critical_section;
- critical_section.emplace_back("manifest");
- critical_section.emplace_back("index");
- critical_section.emplace_back("critical");
- critical_section.emplace_back("responses");
- builder.AddSection("critical", cbor::Value(critical_section));
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
-}
-
-TEST_F(WebBundleParserTest, UnknownSectionInCritical) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- cbor::Value::ArrayValue critical_section;
- critical_section.emplace_back("unknown_section_name");
- builder.AddSection("critical", cbor::Value(critical_section));
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, NoManifest) {
- test::WebBundleBuilder builder(kFallbackUrl, std::string());
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
-}
-
-TEST_F(WebBundleParserTest, InvalidManifestURL) {
- test::WebBundleBuilder builder(kFallbackUrl, "not-an-absolute-url");
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- TestDataSource data_source(builder.CreateBundle());
-
- ExpectFormatErrorWithFallbackURL(ParseBundle(&data_source));
-}
-
-TEST_F(WebBundleParserTest, EmptySignaturesSection) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
- // test::WebBundleBuilder omits signatures section if empty, so create it
- // ourselves.
- cbor::Value::ArrayValue signatures_section;
- signatures_section.emplace_back(cbor::Value::ArrayValue()); // authorities
- signatures_section.emplace_back(
- cbor::Value::ArrayValue()); // vouched-subsets
- builder.AddSection("signatures", cbor::Value(signatures_section));
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- EXPECT_TRUE(metadata->authorities.empty());
- EXPECT_TRUE(metadata->vouched_subsets.empty());
-}
-
-TEST_F(WebBundleParserTest, SignaturesSection) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
-
- // Create a signatures section with some dummy data.
- cbor::Value::MapValue authority;
- authority.emplace("cert", CreateByteString("[cert]"));
- authority.emplace("ocsp", CreateByteString("[ocsp]"));
- authority.emplace("sct", CreateByteString("[sct]"));
- builder.AddAuthority(std::move(authority));
-
- cbor::Value signed_bytes = builder.CreateEncodedSigned(
- kValidityUrl, "[auth-sha256]", kSignatureDate,
- kSignatureDate + kSignatureDuration, "https://test.example.com/",
- "[header-sha256]", "[payload-integrity]");
- cbor::Value::MapValue vouched_subset;
- vouched_subset.emplace("authority", 0);
- vouched_subset.emplace("sig", CreateByteString("[sig]"));
- vouched_subset.emplace("signed", signed_bytes.Clone());
- builder.AddVouchedSubset(std::move(vouched_subset));
-
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
-
- ASSERT_EQ(metadata->authorities.size(), 1u);
- EXPECT_EQ(AsString(metadata->authorities[0]->cert), "[cert]");
- ASSERT_TRUE(metadata->authorities[0]->ocsp.has_value());
- EXPECT_EQ(AsString(*metadata->authorities[0]->ocsp), "[ocsp]");
- ASSERT_TRUE(metadata->authorities[0]->sct.has_value());
- EXPECT_EQ(AsString(*metadata->authorities[0]->sct), "[sct]");
-
- ASSERT_EQ(metadata->vouched_subsets.size(), 1u);
- EXPECT_EQ(metadata->vouched_subsets[0]->authority, 0u);
- EXPECT_EQ(AsString(metadata->vouched_subsets[0]->sig), "[sig]");
- EXPECT_EQ(AsString(metadata->vouched_subsets[0]->raw_signed),
- signed_bytes.GetBytestringAsString());
-
- const auto& parsed_signed = metadata->vouched_subsets[0]->parsed_signed;
- EXPECT_EQ(parsed_signed->validity_url, kValidityUrl);
- EXPECT_EQ(AsString(parsed_signed->auth_sha256), "[auth-sha256]");
- EXPECT_EQ(parsed_signed->date, kSignatureDate);
- EXPECT_EQ(parsed_signed->expires, kSignatureDate + kSignatureDuration);
-
- EXPECT_EQ(parsed_signed->subset_hashes.size(), 1u);
- const auto& hashes =
- parsed_signed->subset_hashes[GURL("https://test.example.com/")];
- ASSERT_TRUE(hashes);
- EXPECT_EQ(hashes->variants_value, "");
- ASSERT_EQ(hashes->resource_integrities.size(), 1u);
- EXPECT_EQ(AsString(hashes->resource_integrities[0]->header_sha256),
- "[header-sha256]");
- EXPECT_EQ(hashes->resource_integrities[0]->payload_integrity_header,
- "[payload-integrity]");
-}
-
-TEST_F(WebBundleParserTest, MultipleSignatures) {
- test::WebBundleBuilder builder(kFallbackUrl, kManifestUrl);
- builder.AddExchange("https://test.example.com/",
- {{":status", "200"}, {"content-type", "text/plain"}},
- "payload");
-
- // Create a signatures section with some dummy data.
- cbor::Value::MapValue authority1;
- authority1.emplace("cert", CreateByteString("[cert1]"));
- authority1.emplace("ocsp", CreateByteString("[ocsp]"));
- authority1.emplace("sct", CreateByteString("[sct]"));
- builder.AddAuthority(std::move(authority1));
- cbor::Value::MapValue authority2;
- authority2.emplace("cert", CreateByteString("[cert2]"));
- builder.AddAuthority(std::move(authority2));
-
- cbor::Value signed_bytes1 = builder.CreateEncodedSigned(
- kValidityUrl, "[auth-sha256]", kSignatureDate,
- kSignatureDate + kSignatureDuration, "https://test.example.com/",
- "[header-sha256]", "[payload-integrity]");
- cbor::Value::MapValue vouched_subset1;
- vouched_subset1.emplace("authority", 0);
- vouched_subset1.emplace("sig", CreateByteString("[sig1]"));
- vouched_subset1.emplace("signed", signed_bytes1.Clone());
- builder.AddVouchedSubset(std::move(vouched_subset1));
-
- cbor::Value signed_bytes2 = builder.CreateEncodedSigned(
- kValidityUrl, "[auth-sha256-2]", kSignatureDate,
- kSignatureDate + kSignatureDuration, "https://test.example.org/",
- "[header-sha256-2]", "[payload-integrity-2]");
- cbor::Value::MapValue vouched_subset2;
- vouched_subset2.emplace("authority", 1);
- vouched_subset2.emplace("sig", CreateByteString("[sig2]"));
- vouched_subset2.emplace("signed", signed_bytes2.Clone());
- builder.AddVouchedSubset(std::move(vouched_subset2));
-
- TestDataSource data_source(builder.CreateBundle());
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
-
- ASSERT_EQ(metadata->authorities.size(), 2u);
- EXPECT_EQ(AsString(metadata->authorities[0]->cert), "[cert1]");
- EXPECT_TRUE(metadata->authorities[0]->ocsp.has_value());
- EXPECT_TRUE(metadata->authorities[0]->sct.has_value());
- EXPECT_EQ(AsString(metadata->authorities[1]->cert), "[cert2]");
- EXPECT_FALSE(metadata->authorities[1]->ocsp.has_value());
- EXPECT_FALSE(metadata->authorities[1]->sct.has_value());
-
- ASSERT_EQ(metadata->vouched_subsets.size(), 2u);
- EXPECT_EQ(metadata->vouched_subsets[0]->authority, 0u);
- EXPECT_EQ(AsString(metadata->vouched_subsets[0]->sig), "[sig1]");
- EXPECT_EQ(AsString(metadata->vouched_subsets[0]->raw_signed),
- signed_bytes1.GetBytestringAsString());
- EXPECT_EQ(metadata->vouched_subsets[1]->authority, 1u);
- EXPECT_EQ(AsString(metadata->vouched_subsets[1]->sig), "[sig2]");
- EXPECT_EQ(AsString(metadata->vouched_subsets[1]->raw_signed),
- signed_bytes2.GetBytestringAsString());
-}
-
-TEST_F(WebBundleParserTest, ParseGoldenFile) {
- TestDataSource data_source(base::FilePath(FILE_PATH_LITERAL("hello.wbn")));
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- ASSERT_EQ(metadata->requests.size(), 4u);
- EXPECT_EQ(metadata->manifest_url,
- "https://test.example.org/manifest.webmanifest");
-
- std::map<std::string, mojom::BundleResponsePtr> responses;
- for (const auto& item : metadata->requests) {
- auto location = FindResponse(metadata, item.first);
- ASSERT_TRUE(location);
- auto resp = ParseResponse(&data_source, location);
- ASSERT_TRUE(resp);
- responses[item.first.spec()] = std::move(resp);
- }
-
- ASSERT_TRUE(responses["https://test.example.org/"]);
- EXPECT_EQ(responses["https://test.example.org/"]->response_code, 200);
- EXPECT_EQ(
- responses["https://test.example.org/"]->response_headers["content-type"],
- "text/html; charset=utf-8");
- EXPECT_EQ(data_source.GetPayload(responses["https://test.example.org/"]),
- GetTestFileContents(
- base::FilePath(FILE_PATH_LITERAL("hello/index.html"))));
-
- EXPECT_TRUE(responses["https://test.example.org/index.html"]);
- EXPECT_TRUE(responses["https://test.example.org/manifest.webmanifest"]);
- EXPECT_TRUE(responses["https://test.example.org/script.js"]);
-}
-
-TEST_F(WebBundleParserTest, ParseSignedFile) {
- TestDataSource data_source(
- base::FilePath(FILE_PATH_LITERAL("hello_signed.wbn")));
-
- mojom::BundleMetadataPtr metadata = ParseBundle(&data_source).first;
- ASSERT_TRUE(metadata);
- EXPECT_EQ(metadata->authorities.size(), 1u);
- ASSERT_EQ(metadata->vouched_subsets.size(), 1u);
- EXPECT_EQ(metadata->vouched_subsets[0]->authority, 0u);
-
- const auto& parsed_signed = metadata->vouched_subsets[0]->parsed_signed;
- EXPECT_EQ(parsed_signed->validity_url, kValidityUrl);
- EXPECT_EQ(parsed_signed->date, kSignatureDate);
- EXPECT_EQ(parsed_signed->expires, kSignatureDate + kSignatureDuration);
-
- EXPECT_EQ(parsed_signed->subset_hashes.size(), metadata->requests.size());
- const auto& hashes =
- parsed_signed->subset_hashes[GURL("https://test.example.org/")];
- ASSERT_TRUE(hashes);
- EXPECT_EQ(hashes->variants_value, "");
- ASSERT_EQ(hashes->resource_integrities.size(), 1u);
- EXPECT_EQ(hashes->resource_integrities[0]->payload_integrity_header,
- "digest/mi-sha256-03");
-}
-
-// TODO(crbug.com/969596): Add a test case that loads a wbn file with variants,
-// once gen-bundle supports variants.
-
-} // namespace data_decoder
diff --git a/chromium/services/device/BUILD.gn b/chromium/services/device/BUILD.gn
index 05d4696dc52..62c53ee4ea5 100644
--- a/chromium/services/device/BUILD.gn
+++ b/chromium/services/device/BUILD.gn
@@ -8,7 +8,8 @@ if (is_android) {
import("//build/config/android/rules.gni")
}
-is_serial_enabled_platform = is_win || (is_linux && use_udev) || is_mac
+is_serial_enabled_platform =
+ is_win || ((is_linux || is_chromeos) && use_udev) || is_mac
source_set("lib") {
# This should be visible only to embedders of the Device Service, and the
@@ -92,7 +93,7 @@ component("binder_overrides") {
defines = [ "IS_DEVICE_SERVICE_BINDER_OVERRIDES_IMPL" ]
}
-is_linux_without_udev = is_linux && !use_udev
+is_linux_without_udev = (is_linux || is_chromeos) && !use_udev
source_set("perftests") {
testonly = true
@@ -247,6 +248,8 @@ source_set("tests") {
if (is_serial_enabled_platform) {
sources += [
+ "serial/bluetooth_serial_port_impl_unittest.cc",
+ "serial/serial_device_enumerator_linux_unittest.cc",
"serial/serial_device_enumerator_unittest.cc",
"serial/serial_port_impl_unittest.cc",
"serial/serial_port_manager_impl_unittest.cc",
@@ -256,7 +259,14 @@ source_set("tests") {
sources += [ "serial/serial_io_handler_posix_unittest.cc" ]
}
+ if (is_linux || is_chromeos) {
+ deps += [ "//device/udev_linux:test_support" ]
+ }
+
deps += [
+ "//device/bluetooth:mocks",
+ "//services/device/public/cpp/bluetooth:bluetooth",
+ "//services/device/public/cpp/serial:switches",
"//services/device/serial",
"//services/device/serial:test_support",
]
diff --git a/chromium/services/device/README.md b/chromium/services/device/README.md
new file mode 100644
index 00000000000..14c0f02ff68
--- /dev/null
+++ b/chromium/services/device/README.md
@@ -0,0 +1,2 @@
+Provides cross-platform public interfaces and per-platform backing
+implementations of various features related to the user's physical device.
diff --git a/chromium/services/device/battery/BUILD.gn b/chromium/services/device/battery/BUILD.gn
index 6c379e3b183..ea2a638a79b 100644
--- a/chromium/services/device/battery/BUILD.gn
+++ b/chromium/services/device/battery/BUILD.gn
@@ -61,7 +61,7 @@ if (!is_android) {
if (is_mac) {
sources -= [ "battery_status_manager_default.cc" ]
- libs = [
+ frameworks = [
"CoreFoundation.framework",
"IOKit.framework",
]
diff --git a/chromium/services/device/battery/android/BUILD.gn b/chromium/services/device/battery/android/BUILD.gn
index 70ecdb1d5da..8a2045a4c17 100644
--- a/chromium/services/device/battery/android/BUILD.gn
+++ b/chromium/services/device/battery/android/BUILD.gn
@@ -19,6 +19,7 @@ android_library("battery_monitor_java") {
"//mojo/public/java:system_java",
"//services/device/public/mojom:mojom_java",
"//services/service_manager/public/java:service_manager_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
"//third_party/android_deps:com_google_code_findbugs_jsr305_java",
]
}
diff --git a/chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java b/chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java
index 045f58aa007..44c2696c26f 100644
--- a/chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java
+++ b/chromium/services/device/battery/android/java/src/org/chromium/device/battery/BatteryStatusManager.java
@@ -4,13 +4,11 @@
package org.chromium.device.battery;
-import android.annotation.TargetApi;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.BatteryManager;
-import android.os.Build;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
@@ -39,13 +37,7 @@ class BatteryStatusManager {
BatteryStatusManager.this.onReceive(intent);
}
};
-
- // This is to workaround a Galaxy Nexus bug, see the comment in the constructor.
- private final boolean mIgnoreBatteryPresentState;
-
- // Only used in L (API level 21) and higher.
private AndroidBatteryManagerWrapper mAndroidBatteryManager;
-
private boolean mEnabled;
@VisibleForTesting
@@ -56,37 +48,31 @@ class BatteryStatusManager {
mBatteryManager = batteryManager;
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public int getIntProperty(int id) {
return mBatteryManager.getIntProperty(id);
}
}
- private BatteryStatusManager(BatteryStatusCallback callback, boolean ignoreBatteryPresentState,
- @Nullable AndroidBatteryManagerWrapper batteryManager) {
+ private BatteryStatusManager(
+ BatteryStatusCallback callback, @Nullable AndroidBatteryManagerWrapper batteryManager) {
mCallback = callback;
- mIgnoreBatteryPresentState = ignoreBatteryPresentState;
mAndroidBatteryManager = batteryManager;
}
BatteryStatusManager(BatteryStatusCallback callback) {
- // BatteryManager.EXTRA_PRESENT appears to be unreliable on Galaxy Nexus,
- // Android 4.2.1, it always reports false. See http://crbug.com/384348.
- this(callback, Build.MODEL.equals("Galaxy Nexus"),
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP
- ? new AndroidBatteryManagerWrapper(
- (BatteryManager) ContextUtils.getApplicationContext()
- .getSystemService(Context.BATTERY_SERVICE))
- : null);
+ this(callback,
+ new AndroidBatteryManagerWrapper(
+ (BatteryManager) ContextUtils.getApplicationContext().getSystemService(
+ Context.BATTERY_SERVICE)));
}
/**
* Creates a BatteryStatusManager without the Galaxy Nexus workaround for consistency in
* testing.
*/
- static BatteryStatusManager createBatteryStatusManagerForTesting(Context context,
+ static BatteryStatusManager createBatteryStatusManagerForTesting(
BatteryStatusCallback callback, @Nullable AndroidBatteryManagerWrapper batteryManager) {
- return new BatteryStatusManager(callback, false, batteryManager);
+ return new BatteryStatusManager(callback, batteryManager);
}
/**
@@ -120,9 +106,7 @@ class BatteryStatusManager {
return;
}
- boolean present = mIgnoreBatteryPresentState
- ? true
- : intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
+ boolean present = intent.getBooleanExtra(BatteryManager.EXTRA_PRESENT, false);
int pluggedStatus = intent.getIntExtra(BatteryManager.EXTRA_PLUGGED, -1);
if (!present || pluggedStatus == -1) {
@@ -156,16 +140,13 @@ class BatteryStatusManager {
batteryStatus.level = level;
if (mAndroidBatteryManager != null) {
- updateBatteryStatusForLollipop(batteryStatus);
+ updateBatteryStatus(batteryStatus);
}
mCallback.onBatteryStatusChanged(batteryStatus);
}
- private void updateBatteryStatusForLollipop(BatteryStatus batteryStatus) {
- assert mAndroidBatteryManager != null;
-
- // On Lollipop we can provide a better estimate for chargingTime and dischargingTime.
+ private void updateBatteryStatus(BatteryStatus batteryStatus) {
double remainingCapacityRatio =
mAndroidBatteryManager.getIntProperty(BatteryManager.BATTERY_PROPERTY_CAPACITY)
/ 100.0;
diff --git a/chromium/services/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java b/chromium/services/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java
index b489fd374db..7befccfbb8f 100644
--- a/chromium/services/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java
+++ b/chromium/services/device/battery/android/javatests/src/org/chromium/device/battery/BatteryStatusManagerTest.java
@@ -6,8 +6,6 @@ package org.chromium.device.battery;
import android.content.Intent;
import android.os.BatteryManager;
-import android.os.Build;
-import android.support.test.InstrumentationRegistry;
import androidx.test.filters.SmallTest;
@@ -99,7 +97,7 @@ public class BatteryStatusManagerTest {
public void initializeBatteryManager(FakeAndroidBatteryManager managerForTesting) {
mManager = BatteryStatusManager.createBatteryStatusManagerForTesting(
- InstrumentationRegistry.getContext(), mCallback, managerForTesting);
+ mCallback, managerForTesting);
}
@Test
@@ -188,9 +186,7 @@ public class BatteryStatusManagerTest {
@Test
@SmallTest
- public void testLollipopChargingTimeEstimate() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
+ public void testChargingTimeEstimate() {
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.putExtra(BatteryManager.EXTRA_PRESENT, true);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, BatteryManager.BATTERY_PLUGGED_USB);
@@ -209,9 +205,7 @@ public class BatteryStatusManagerTest {
@Test
@SmallTest
- public void testLollipopDischargingTimeEstimate() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
+ public void testDischargingTimeEstimate() {
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.putExtra(BatteryManager.EXTRA_PRESENT, true);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, 0);
@@ -231,9 +225,7 @@ public class BatteryStatusManagerTest {
@Test
@SmallTest
- public void testLollipopDischargingTimeEstimateRounding() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) return;
-
+ public void testDischargingTimeEstimateRounding() {
Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
intent.putExtra(BatteryManager.EXTRA_PRESENT, true);
intent.putExtra(BatteryManager.EXTRA_PLUGGED, 0);
diff --git a/chromium/services/device/battery/battery_status_manager_win.cc b/chromium/services/device/battery/battery_status_manager_win.cc
index 3e8ba408e51..2a27abb55b9 100644
--- a/chromium/services/device/battery/battery_status_manager_win.cc
+++ b/chromium/services/device/battery/battery_status_manager_win.cc
@@ -133,7 +133,7 @@ class BatteryStatusObserver {
if (!window_->CreateNamed(
base::BindRepeating(&BatteryStatusObserver::HandleMessage,
base::Unretained(this)),
- base::string16(kWindowClassName))) {
+ kWindowClassName)) {
LOG(ERROR) << "Failed to create message window: " << kWindowClassName;
window_.reset();
return false;
diff --git a/chromium/services/device/bluetooth/bluetooth_system.cc b/chromium/services/device/bluetooth/bluetooth_system.cc
index b63cd072365..7925dac8109 100644
--- a/chromium/services/device/bluetooth/bluetooth_system.cc
+++ b/chromium/services/device/bluetooth/bluetooth_system.cc
@@ -19,6 +19,7 @@
#include "device/bluetooth/dbus/bluetooth_adapter_client.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluez_dbus_manager.h"
+#include "device/bluetooth/public/cpp/bluetooth_address.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
namespace device {
@@ -209,8 +210,7 @@ void BluetoothSystem::GetAvailableDevices(
for (const auto& device_path : device_paths) {
auto* properties = GetBluetoothDeviceClient()->GetProperties(device_path);
std::array<uint8_t, 6> parsed_address;
- if (!BluetoothDevice::ParseAddress(properties->address.value(),
- parsed_address)) {
+ if (!ParseBluetoothAddress(properties->address.value(), parsed_address)) {
LOG(WARNING) << "Failed to parse device address '"
<< properties->address.value() << "' for "
<< device_path.value();
diff --git a/chromium/services/device/device_service.cc b/chromium/services/device/device_service.cc
index 7fe052a5553..bb284732ba8 100644
--- a/chromium/services/device/device_service.cc
+++ b/chromium/services/device/device_service.cc
@@ -43,7 +43,7 @@
#include "services/device/vibration/vibration_manager_impl.h"
#endif
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
#include "services/device/hid/input_service_linux.h"
#endif
@@ -125,11 +125,11 @@ DeviceService::DeviceService(
geolocation_api_key_(geolocation_api_key),
wake_lock_provider_(file_task_runner_, wake_lock_context_callback_) {
receivers_.Add(this, std::move(receiver));
-#if (defined(OS_LINUX) && defined(USE_UDEV)) || defined(OS_WIN) || \
- defined(OS_MACOSX)
+#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
+ defined(OS_WIN) || defined(OS_MAC)
serial_port_manager_ = std::make_unique<SerialPortManagerImpl>(
io_task_runner_, base::ThreadTaskRunnerHandle::Get());
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// On macOS the SerialDeviceEnumerator needs to run on the UI thread so that
// it has access to a CFRunLoop where it can register a notification source.
serial_port_manager_task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -155,8 +155,8 @@ DeviceService::~DeviceService() {
// it's not really important that this runs anyway.
device::BatteryStatusService::GetInstance()->Shutdown();
#endif
-#if (defined(OS_LINUX) && defined(USE_UDEV)) || defined(OS_WIN) || \
- defined(OS_MACOSX)
+#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
+ defined(OS_WIN) || defined(OS_MAC)
serial_port_manager_task_runner_->DeleteSoon(FROM_HERE,
std::move(serial_port_manager_));
#endif
@@ -230,7 +230,7 @@ void DeviceService::BindMtpManager(
}
#endif
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
void DeviceService::BindInputDeviceManager(
mojo::PendingReceiver<mojom::InputDeviceManager> receiver) {
file_task_runner_->PostTask(
@@ -311,8 +311,8 @@ void DeviceService::BindSensorProvider(
void DeviceService::BindSerialPortManager(
mojo::PendingReceiver<mojom::SerialPortManager> receiver) {
-#if (defined(OS_LINUX) && defined(USE_UDEV)) || defined(OS_WIN) || \
- defined(OS_MACOSX)
+#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
+ defined(OS_WIN) || defined(OS_MAC)
DCHECK(serial_port_manager_task_runner_);
serial_port_manager_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&SerialPortManagerImpl::Bind,
diff --git a/chromium/services/device/device_service.h b/chromium/services/device/device_service.h
index 43744315bf1..c5e950b095c 100644
--- a/chromium/services/device/device_service.h
+++ b/chromium/services/device/device_service.h
@@ -50,7 +50,7 @@
#include "services/device/public/mojom/bluetooth_system.mojom.h"
#endif
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
#include "services/device/public/mojom/input_service.mojom.h"
#endif
@@ -148,7 +148,7 @@ class DeviceService : public mojom::DeviceService {
void BindGeolocationControl(
mojo::PendingReceiver<mojom::GeolocationControl> receiver) override;
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
void BindInputDeviceManager(
mojo::PendingReceiver<mojom::InputDeviceManager> receiver) override;
#endif
@@ -234,8 +234,8 @@ class DeviceService : public mojom::DeviceService {
std::unique_ptr<HidManagerImpl> hid_manager_;
#endif
-#if (defined(OS_LINUX) && defined(USE_UDEV)) || defined(OS_WIN) || \
- defined(OS_MACOSX)
+#if ((defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)) || \
+ defined(OS_WIN) || defined(OS_MAC)
// Requests for the SerialPortManager interface must be bound to
// |serial_port_manager_| on |serial_port_manager_task_runner_| and it will
// be destroyed on that sequence.
diff --git a/chromium/services/device/generic_sensor/BUILD.gn b/chromium/services/device/generic_sensor/BUILD.gn
index b491d557fa2..6f969c000ae 100644
--- a/chromium/services/device/generic_sensor/BUILD.gn
+++ b/chromium/services/device/generic_sensor/BUILD.gn
@@ -84,7 +84,7 @@ source_set("generic_sensor") {
if (is_mac) {
deps += [ "//third_party/sudden_motion_sensor" ]
- libs = [
+ frameworks = [
"CoreFoundation.framework",
"IOKit.framework",
]
diff --git a/chromium/services/device/generic_sensor/android/java/src/org/chromium/device/sensors/PlatformSensor.java b/chromium/services/device/generic_sensor/android/java/src/org/chromium/device/sensors/PlatformSensor.java
index d16d43dd26c..43df6514a0e 100644
--- a/chromium/services/device/generic_sensor/android/java/src/org/chromium/device/sensors/PlatformSensor.java
+++ b/chromium/services/device/generic_sensor/android/java/src/org/chromium/device/sensors/PlatformSensor.java
@@ -7,7 +7,6 @@ package org.chromium.device.sensors;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
-import android.os.Build;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
@@ -109,12 +108,9 @@ public class PlatformSensor implements SensorEventListener {
*/
@CalledByNative
protected int getReportingMode() {
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
- return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS
- ? ReportingMode.CONTINUOUS
- : ReportingMode.ON_CHANGE;
- }
- return ReportingMode.CONTINUOUS;
+ return mSensor.getReportingMode() == Sensor.REPORTING_MODE_CONTINUOUS
+ ? ReportingMode.CONTINUOUS
+ : ReportingMode.ON_CHANGE;
}
/**
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 b43c55c56b8..7d33e74f4e0 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
@@ -313,7 +313,7 @@ class PlatformSensorAndProviderLinuxTest : public ::testing::Test {
void GenerateDeviceRemovedEvent(const base::FilePath& sensor_dir) {
{
base::ScopedAllowBlockingForTesting allow_blocking;
- EXPECT_TRUE(base::DeleteFileRecursively(sensor_dir));
+ EXPECT_TRUE(base::DeletePathRecursively(sensor_dir));
}
bool success = provider_->blocking_task_runner_->PostTask(
FROM_HERE,
diff --git a/chromium/services/device/generic_sensor/platform_sensor_provider.cc b/chromium/services/device/generic_sensor/platform_sensor_provider.cc
index f1f7159611e..6922319bf9d 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_provider.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_provider.cc
@@ -4,7 +4,7 @@
#include "services/device/generic_sensor/platform_sensor_provider.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include "services/device/generic_sensor/platform_sensor_provider_mac.h"
#elif defined(OS_ANDROID)
#include "services/device/generic_sensor/platform_sensor_provider_android.h"
@@ -23,7 +23,7 @@ namespace device {
// static
std::unique_ptr<PlatformSensorProvider> PlatformSensorProvider::Create() {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
return std::make_unique<PlatformSensorProviderMac>();
#elif defined(OS_ANDROID)
return std::make_unique<PlatformSensorProviderAndroid>();
diff --git a/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc b/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc
index 4111af1121a..63bd89b7b2d 100644
--- a/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc
+++ b/chromium/services/device/generic_sensor/platform_sensor_reader_win.cc
@@ -389,15 +389,15 @@ Microsoft::WRL::ComPtr<ISensor> PlatformSensorReaderWin32::GetSensorForType(
Microsoft::WRL::ComPtr<ISensorManager> sensor_manager) {
Microsoft::WRL::ComPtr<ISensor> sensor;
Microsoft::WRL::ComPtr<ISensorCollection> sensor_collection;
- HRESULT hr = sensor_manager->GetSensorsByType(
- sensor_type, sensor_collection.GetAddressOf());
+ HRESULT hr =
+ sensor_manager->GetSensorsByType(sensor_type, &sensor_collection);
if (FAILED(hr) || !sensor_collection)
return sensor;
ULONG count = 0;
hr = sensor_collection->GetCount(&count);
if (SUCCEEDED(hr) && count > 0)
- sensor_collection->GetAt(0, sensor.GetAddressOf());
+ sensor_collection->GetAt(0, &sensor);
return sensor;
}
@@ -484,7 +484,7 @@ bool PlatformSensorReaderWin32::SetReportingInterval(
return false;
Microsoft::WRL::ComPtr<IPortableDeviceValues> return_props;
- hr = sensor_->SetProperties(props.Get(), return_props.GetAddressOf());
+ hr = sensor_->SetProperties(props.Get(), &return_props);
return SUCCEEDED(hr);
}
diff --git a/chromium/services/device/geolocation/BUILD.gn b/chromium/services/device/geolocation/BUILD.gn
index bc366b81794..8b1beef4892 100644
--- a/chromium/services/device/geolocation/BUILD.gn
+++ b/chromium/services/device/geolocation/BUILD.gn
@@ -98,7 +98,7 @@ source_set("geolocation") {
if (is_chromeos || (is_linux && !use_dbus)) {
sources -= [ "wifi_data_provider_linux.cc" ]
}
- if (is_linux && use_dbus) {
+ if ((is_linux || is_chromeos) && use_dbus) {
sources -= [ "empty_wifi_data_provider.cc" ]
deps += [ "//dbus" ]
}
@@ -116,7 +116,7 @@ source_set("geolocation") {
}
if (is_mac) {
- libs = [
+ frameworks = [
"CoreWLAN.framework",
"Foundation.framework",
"CoreLocation.framework",
@@ -164,6 +164,7 @@ if (is_android) {
"//base:jni_java",
"//components/location/android:location_java",
"//services/device/public/java:geolocation_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
]
annotation_processor_deps = [ "//base/android/jni_generator:jni_processor" ]
}
diff --git a/chromium/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java b/chromium/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
index c3651e74a6b..ebdfcc7ab4a 100644
--- a/chromium/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
+++ b/chromium/services/device/geolocation/android/java/src/org/chromium/device/geolocation/LocationProviderAdapter.java
@@ -6,8 +6,6 @@ package org.chromium.device.geolocation;
import android.location.Location;
-import androidx.annotation.VisibleForTesting;
-
import org.chromium.base.Log;
import org.chromium.base.ThreadUtils;
import org.chromium.base.annotations.CalledByNative;
@@ -23,7 +21,6 @@ import java.util.concurrent.FutureTask;
* content/browser/geolocation/location_api_adapter_android.h.
* Based on android.webkit.GeolocationService.java
*/
-@VisibleForTesting
public class LocationProviderAdapter {
private static final String TAG = "LocationProvider";
diff --git a/chromium/services/device/geolocation/geolocation_provider_impl.cc b/chromium/services/device/geolocation/geolocation_provider_impl.cc
index 26edf4f9494..15dad9765c6 100644
--- a/chromium/services/device/geolocation/geolocation_provider_impl.cc
+++ b/chromium/services/device/geolocation/geolocation_provider_impl.cc
@@ -172,7 +172,7 @@ void GeolocationProviderImpl::OnClientsChanged() {
} else {
if (!IsRunning()) {
base::Thread::Options options;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
options.message_pump_type = base::MessagePumpType::NS_RUNLOOP;
#endif
StartWithOptions(options);
diff --git a/chromium/services/device/geolocation/location_arbitrator.cc b/chromium/services/device/geolocation/location_arbitrator.cc
index 394ec28bc4b..e5a1f312fdb 100644
--- a/chromium/services/device/geolocation/location_arbitrator.cc
+++ b/chromium/services/device/geolocation/location_arbitrator.cc
@@ -156,7 +156,7 @@ LocationArbitrator::NewNetworkLocationProvider(
std::unique_ptr<LocationProvider>
LocationArbitrator::NewSystemLocationProvider() {
-#if defined(OS_LINUX) || defined(OS_FUCHSIA)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_FUCHSIA)
return nullptr;
#else
return device::NewSystemLocationProvider();
diff --git a/chromium/services/device/geolocation/network_location_provider_unittest.cc b/chromium/services/device/geolocation/network_location_provider_unittest.cc
index 62b5157038f..59af9998dc7 100644
--- a/chromium/services/device/geolocation/network_location_provider_unittest.cc
+++ b/chromium/services/device/geolocation/network_location_provider_unittest.cc
@@ -319,7 +319,7 @@ TEST_F(GeolocationNetworkProviderTest, NonEmptyApiKey) {
const GURL& request_url =
test_url_loader_factory_.pending_requests()->back().request.url;
EXPECT_TRUE(request_url.has_query());
- EXPECT_TRUE(request_url.query_piece().starts_with("key="));
+ EXPECT_TRUE(base::StartsWith(request_url.query_piece(), "key="));
}
// Tests that, after StartProvider(), a TestURLFetcher can be extracted,
diff --git a/chromium/services/device/hid/BUILD.gn b/chromium/services/device/hid/BUILD.gn
index 494ecc11848..dbe29872689 100644
--- a/chromium/services/device/hid/BUILD.gn
+++ b/chromium/services/device/hid/BUILD.gn
@@ -41,7 +41,7 @@ source_set("hid") {
"//services/device/public/mojom",
]
- if (is_linux && use_udev) {
+ if ((is_linux || is_chromeos) && use_udev) {
sources += [
"hid_service_linux.cc",
"hid_service_linux.h",
diff --git a/chromium/services/device/hid/hid_connection_impl_unittest.cc b/chromium/services/device/hid/hid_connection_impl_unittest.cc
index cde9f8e444c..1a1b4613e00 100644
--- a/chromium/services/device/hid/hid_connection_impl_unittest.cc
+++ b/chromium/services/device/hid/hid_connection_impl_unittest.cc
@@ -18,7 +18,7 @@ namespace device {
namespace {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
const uint64_t kTestDeviceId = 123;
#elif defined(OS_WIN)
const wchar_t* kTestDeviceId = L"123";
diff --git a/chromium/services/device/hid/hid_device_info.h b/chromium/services/device/hid/hid_device_info.h
index eca93d9aa21..0c84e730f09 100644
--- a/chromium/services/device/hid/hid_device_info.h
+++ b/chromium/services/device/hid/hid_device_info.h
@@ -19,10 +19,10 @@
namespace device {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
typedef uint64_t HidPlatformDeviceId;
#elif defined(OS_WIN)
-typedef base::string16 HidPlatformDeviceId;
+typedef std::wstring HidPlatformDeviceId;
#else
typedef std::string HidPlatformDeviceId;
#endif
diff --git a/chromium/services/device/hid/hid_manager_unittest.cc b/chromium/services/device/hid/hid_manager_unittest.cc
index 7334f83a72c..6a5066d6b13 100644
--- a/chromium/services/device/hid/hid_manager_unittest.cc
+++ b/chromium/services/device/hid/hid_manager_unittest.cc
@@ -22,7 +22,7 @@ namespace device {
namespace {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
const uint64_t kTestDeviceIds[] = {0, 1, 2};
#elif defined(OS_WIN)
const wchar_t* const kTestDeviceIds[] = {L"0", L"1", L"2"};
diff --git a/chromium/services/device/hid/hid_service.cc b/chromium/services/device/hid/hid_service.cc
index f36737283e3..056c83b638d 100644
--- a/chromium/services/device/hid/hid_service.cc
+++ b/chromium/services/device/hid/hid_service.cc
@@ -14,9 +14,9 @@
#include "build/build_config.h"
#include "components/device_event_log/device_event_log.h"
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
#include "services/device/hid/hid_service_linux.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
#include "services/device/hid/hid_service_mac.h"
#elif defined(OS_WIN)
#include "services/device/hid/hid_service_win.h"
@@ -34,9 +34,9 @@ constexpr base::TaskTraits HidService::kBlockingTaskTraits;
// static
std::unique_ptr<HidService> HidService::Create() {
-#if defined(OS_LINUX) && defined(USE_UDEV)
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && defined(USE_UDEV)
return base::WrapUnique(new HidServiceLinux());
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
return base::WrapUnique(new HidServiceMac());
#elif defined(OS_WIN)
return base::WrapUnique(new HidServiceWin());
diff --git a/chromium/services/device/hid/hid_service_win.cc b/chromium/services/device/hid/hid_service_win.cc
index 80fff2d39a8..e9233de42b4 100644
--- a/chromium/services/device/hid/hid_service_win.cc
+++ b/chromium/services/device/hid/hid_service_win.cc
@@ -62,7 +62,7 @@ bool GetDeviceInfoAndPathFromInterface(
HDEVINFO device_info_set,
SP_DEVICE_INTERFACE_DATA& device_interface_data,
SP_DEVINFO_DATA* device_info_data,
- base::string16* device_path) {
+ std::wstring* device_path) {
// Get the required buffer size. When called with
// DeviceInterfaceDetailData == nullptr and DeviceInterfaceDetailSize == 0,
// SetupDiGetDeviceInterfaceDetail returns the required buffer size at
@@ -93,8 +93,7 @@ bool GetDeviceInfoAndPathFromInterface(
// 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);
+ std::wstring path = device_interface_detail_data->DevicePath;
DCHECK(base::IsStringASCII(path));
*device_path = base::ToLowerASCII(path);
return true;
@@ -104,7 +103,7 @@ bool GetDeviceInfoAndPathFromInterface(
// |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,
+ const std::wstring& device_path,
SP_DEVINFO_DATA* device_info_data) {
base::win::ScopedDevInfo device_info_set(SetupDiGetClassDevs(
&GUID_DEVINTERFACE_HID, /*Enumerator=*/nullptr,
@@ -119,7 +118,7 @@ base::win::ScopedDevInfo GetDeviceInfoFromPath(
return base::win::ScopedDevInfo();
}
- base::string16 intf_device_path;
+ std::wstring intf_device_path;
GetDeviceInfoAndPathFromInterface(device_info_set.get(),
device_interface_data, device_info_data,
&intf_device_path);
@@ -193,7 +192,7 @@ void HidServiceWin::EnumerateBlocking(
++device_index) {
SP_DEVINFO_DATA dev_info_data = {0};
dev_info_data.cbSize = sizeof(dev_info_data);
- base::string16 device_path;
+ std::wstring device_path;
if (!GetDeviceInfoAndPathFromInterface(dev_info.get(),
device_interface_data,
&dev_info_data, &device_path)) {
@@ -207,7 +206,7 @@ void HidServiceWin::EnumerateBlocking(
continue;
}
std::string physical_device_id =
- base::UTF16ToUTF8(base::win::String16FromGUID(container_id));
+ base::WideToUTF8(base::win::WStringFromGUID(container_id));
AddDeviceBlocking(service, task_runner, device_path, physical_device_id);
}
@@ -264,7 +263,7 @@ void HidServiceWin::CollectInfoFromValueCaps(
void HidServiceWin::AddDeviceBlocking(
base::WeakPtr<HidServiceWin> service,
scoped_refptr<base::SequencedTaskRunner> task_runner,
- const base::string16& device_path,
+ const std::wstring& device_path,
const std::string& physical_device_id) {
base::win::ScopedHandle device_handle(OpenDevice(device_path));
if (!device_handle.IsValid()) {
@@ -361,7 +360,7 @@ void HidServiceWin::AddDeviceBlocking(
}
void HidServiceWin::OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& 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);
@@ -374,7 +373,7 @@ void HidServiceWin::OnDeviceAdded(const GUID& class_guid,
return;
}
std::string physical_device_id =
- base::UTF16ToUTF8(base::win::String16FromGUID(container_id));
+ base::WideToUTF8(base::win::WStringFromGUID(container_id));
blocking_task_runner_->PostTask(
FROM_HERE, base::BindOnce(&HidServiceWin::AddDeviceBlocking,
@@ -383,7 +382,7 @@ void HidServiceWin::OnDeviceAdded(const GUID& class_guid,
}
void HidServiceWin::OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& device_path) {
// Execute a no-op closure on the file task runner to synchronize with any
// devices that are still being enumerated.
blocking_task_runner_->PostTaskAndReply(
@@ -394,7 +393,7 @@ void HidServiceWin::OnDeviceRemoved(const GUID& class_guid,
// static
base::win::ScopedHandle HidServiceWin::OpenDevice(
- const base::string16& device_path) {
+ const std::wstring& device_path) {
base::win::ScopedHandle file(
CreateFile(device_path.c_str(), GENERIC_WRITE | GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING,
diff --git a/chromium/services/device/hid/hid_service_win.h b/chromium/services/device/hid/hid_service_win.h
index ac6745f3aaf..54779511339 100644
--- a/chromium/services/device/hid/hid_service_win.h
+++ b/chromium/services/device/hid/hid_service_win.h
@@ -59,17 +59,17 @@ 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 std::wstring& device_path,
const std::string& physical_device_id);
// DeviceMonitorWin::Observer implementation:
void OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
void OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
// Tries to open the device read-write and falls back to read-only.
- static base::win::ScopedHandle OpenDevice(const base::string16& device_path);
+ static base::win::ScopedHandle OpenDevice(const std::wstring& device_path);
const scoped_refptr<base::SequencedTaskRunner> task_runner_;
const scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
diff --git a/chromium/services/device/nfc/android/BUILD.gn b/chromium/services/device/nfc/android/BUILD.gn
index 882201e1f05..c2107663e88 100644
--- a/chromium/services/device/nfc/android/BUILD.gn
+++ b/chromium/services/device/nfc/android/BUILD.gn
@@ -29,5 +29,6 @@ android_library("java") {
"//services/device/public/mojom:mojom_java",
"//services/service_manager/public/java:service_manager_java",
"//services/service_manager/public/mojom:mojom_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
]
}
diff --git a/chromium/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java b/chromium/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
index c5a5a35df7e..1fc5cd3430f 100644
--- a/chromium/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
+++ b/chromium/services/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
@@ -5,7 +5,6 @@
package org.chromium.device.nfc;
import android.Manifest;
-import android.annotation.TargetApi;
import android.app.Activity;
import android.content.Context;
import android.content.pm.PackageManager;
@@ -15,7 +14,6 @@ import android.nfc.NfcAdapter.ReaderCallback;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.nfc.TagLostException;
-import android.os.Build;
import android.os.Process;
import android.os.Vibrator;
import android.util.SparseArray;
@@ -413,7 +411,6 @@ public class NfcImpl implements Nfc {
* discovered, Tag object is delegated to mojo service implementation method
* NfcImpl.onTagDiscovered().
*/
- @TargetApi(Build.VERSION_CODES.KITKAT)
private static class ReaderCallbackHandler implements ReaderCallback {
private final NfcImpl mNfcImpl;
@@ -449,7 +446,6 @@ public class NfcImpl implements Nfc {
* Disables reader mode.
* @see android.nfc.NfcAdapter#disableReaderMode
*/
- @TargetApi(Build.VERSION_CODES.KITKAT)
private void disableReaderMode() {
// There is no API that could query whether reader mode is enabled for adapter.
// If mReaderCallbackHandler is null, reader mode is not enabled.
diff --git a/chromium/services/device/public/cpp/bluetooth/BUILD.gn b/chromium/services/device/public/cpp/bluetooth/BUILD.gn
index cef8c766f6f..9f748a14742 100644
--- a/chromium/services/device/public/cpp/bluetooth/BUILD.gn
+++ b/chromium/services/device/public/cpp/bluetooth/BUILD.gn
@@ -11,6 +11,7 @@ source_set("bluetooth") {
deps = [
"//base",
"//device/bluetooth",
+ "//device/bluetooth/public/cpp:cpp",
"//device/bluetooth/strings",
"//services/device/public/mojom",
"//ui/base",
diff --git a/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.cc b/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.cc
index d9fd4d260c0..5b85c093140 100644
--- a/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.cc
+++ b/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.cc
@@ -139,4 +139,11 @@ base::string16 GetBluetoothDeviceLabelForAccessibility(
name_utf16);
}
+const BluetoothUUID& GetSerialPortProfileUUID() {
+ // The Serial Port Profile (SPP) UUID is 1101.
+ // https://chromium-review.googlesource.com/c/chromium/src/+/2334682/17..19
+ static const BluetoothUUID kValue("1101");
+ return kValue;
+}
+
} // namespace device
diff --git a/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.h b/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.h
index adb92141431..2c882928867 100644
--- a/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.h
+++ b/chromium/services/device/public/cpp/bluetooth/bluetooth_utils.h
@@ -6,6 +6,7 @@
#define SERVICES_DEVICE_PUBLIC_CPP_BLUETOOTH_BLUETOOTH_UTILS_H_
#include "base/strings/string16.h"
+#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
#include "services/device/public/mojom/bluetooth_system.mojom.h"
namespace device {
@@ -25,6 +26,9 @@ base::string16 GetBluetoothDeviceNameForDisplay(
base::string16 GetBluetoothDeviceLabelForAccessibility(
const mojom::BluetoothDeviceInfoPtr& device_info);
+// Returns a BluetoothUUID for a Bluetooth SPP device.
+const BluetoothUUID& GetSerialPortProfileUUID();
+
} // namespace device
#endif // SERVICES_DEVICE_PUBLIC_CPP_BLUETOOTH_BLUETOOTH_UTILS_H_
diff --git a/chromium/services/device/public/cpp/hid/hid_device_filter_unittest.cc b/chromium/services/device/public/cpp/hid/hid_device_filter_unittest.cc
index 8fb23c78f8f..9ce84e03bea 100644
--- a/chromium/services/device/public/cpp/hid/hid_device_filter_unittest.cc
+++ b/chromium/services/device/public/cpp/hid/hid_device_filter_unittest.cc
@@ -15,7 +15,7 @@ namespace device {
namespace {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
const uint64_t kTestDeviceId = 42;
#elif defined(OS_WIN)
const wchar_t* kTestDeviceId = L"device1";
diff --git a/chromium/services/device/public/cpp/serial/BUILD.gn b/chromium/services/device/public/cpp/serial/BUILD.gn
new file mode 100644
index 00000000000..686c2eb8d81
--- /dev/null
+++ b/chromium/services/device/public/cpp/serial/BUILD.gn
@@ -0,0 +1,10 @@
+# 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.
+
+static_library("switches") {
+ sources = [
+ "serial_switches.cc",
+ "serial_switches.h",
+ ]
+}
diff --git a/chromium/services/device/public/cpp/serial/serial_switches.cc b/chromium/services/device/public/cpp/serial/serial_switches.cc
new file mode 100644
index 00000000000..d6405bc1d11
--- /dev/null
+++ b/chromium/services/device/public/cpp/serial/serial_switches.cc
@@ -0,0 +1,13 @@
+// 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/device/public/cpp/serial/serial_switches.h"
+
+namespace switches {
+
+// Enable serial communication for SPP devices.
+const char kEnableBluetoothSerialPortProfileInSerialApi[] =
+ "enable-bluetooth-spp-in-serial-api";
+
+} // namespace switches
diff --git a/chromium/services/device/public/cpp/serial/serial_switches.h b/chromium/services/device/public/cpp/serial/serial_switches.h
new file mode 100644
index 00000000000..76f1298a8e7
--- /dev/null
+++ b/chromium/services/device/public/cpp/serial/serial_switches.h
@@ -0,0 +1,14 @@
+// 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_DEVICE_PUBLIC_CPP_SERIAL_SERIAL_SWITCHES_H_
+#define SERVICES_DEVICE_PUBLIC_CPP_SERIAL_SERIAL_SWITCHES_H_
+
+namespace switches {
+
+extern const char kEnableBluetoothSerialPortProfileInSerialApi[];
+
+} // namespace switches
+
+#endif // SERVICES_DEVICE_PUBLIC_CPP_SERIAL_SERIAL_SWITCHES_H_
diff --git a/chromium/services/device/public/cpp/usb/usb_utils.cc b/chromium/services/device/public/cpp/usb/usb_utils.cc
index ef6f5199686..db364184fbf 100644
--- a/chromium/services/device/public/cpp/usb/usb_utils.cc
+++ b/chromium/services/device/public/cpp/usb/usb_utils.cc
@@ -26,6 +26,14 @@ bool UsbDeviceFilterMatches(const mojom::UsbDeviceFilter& filter,
}
if (filter.has_class_code) {
+ if (device_info.class_code == filter.class_code &&
+ (!filter.has_subclass_code ||
+ (device_info.subclass_code == filter.subclass_code &&
+ (!filter.has_protocol_code ||
+ device_info.protocol_code == filter.protocol_code)))) {
+ return true;
+ }
+
for (auto& config : device_info.configurations) {
for (auto& iface : config->interfaces) {
for (auto& alternate_info : iface->alternates) {
diff --git a/chromium/services/device/public/cpp/usb/usb_utils_unittest.cc b/chromium/services/device/public/cpp/usb/usb_utils_unittest.cc
index c79d56c51b7..a50ab515d54 100644
--- a/chromium/services/device/public/cpp/usb/usb_utils_unittest.cc
+++ b/chromium/services/device/public/cpp/usb/usb_utils_unittest.cc
@@ -168,6 +168,67 @@ TEST_F(UsbUtilsTest, MatchSerialNumber) {
EXPECT_FALSE(UsbDeviceFilterMatches(*filter, GetPhoneInfo()));
}
+TEST_F(UsbUtilsTest, MatchDeviceClass) {
+ auto device_info = mojom::UsbDeviceInfo::New();
+ device_info->class_code = 1;
+ device_info->subclass_code = 2;
+ device_info->protocol_code = 3;
+
+ auto matching_class_filter = mojom::UsbDeviceFilter::New();
+ matching_class_filter->has_class_code = true;
+ matching_class_filter->class_code = 1;
+ EXPECT_TRUE(UsbDeviceFilterMatches(*matching_class_filter, *device_info));
+
+ auto nonmatching_class_filter = mojom::UsbDeviceFilter::New();
+ nonmatching_class_filter->has_class_code = true;
+ nonmatching_class_filter->class_code = 2;
+ EXPECT_FALSE(UsbDeviceFilterMatches(*nonmatching_class_filter, *device_info));
+
+ auto matching_subclass_filter = mojom::UsbDeviceFilter::New();
+ matching_subclass_filter->has_class_code = true;
+ matching_subclass_filter->class_code = 1;
+ matching_subclass_filter->has_subclass_code = true;
+ matching_subclass_filter->subclass_code = 2;
+ EXPECT_TRUE(UsbDeviceFilterMatches(*matching_subclass_filter, *device_info));
+
+ auto nonmatching_subclass_filter = mojom::UsbDeviceFilter::New();
+ nonmatching_subclass_filter->has_class_code = true;
+ nonmatching_subclass_filter->class_code = 1;
+ nonmatching_subclass_filter->has_subclass_code = true;
+ nonmatching_subclass_filter->subclass_code = 3;
+ EXPECT_FALSE(
+ UsbDeviceFilterMatches(*nonmatching_subclass_filter, *device_info));
+
+ auto matching_protocol_filter = mojom::UsbDeviceFilter::New();
+ matching_protocol_filter->has_class_code = true;
+ matching_protocol_filter->class_code = 1;
+ matching_protocol_filter->has_subclass_code = true;
+ matching_protocol_filter->subclass_code = 2;
+ matching_protocol_filter->has_protocol_code = true;
+ matching_protocol_filter->protocol_code = 3;
+ EXPECT_TRUE(UsbDeviceFilterMatches(*matching_protocol_filter, *device_info));
+
+ auto nonmatching_protocol_filter = mojom::UsbDeviceFilter::New();
+ nonmatching_protocol_filter->has_class_code = true;
+ nonmatching_protocol_filter->class_code = 1;
+ nonmatching_protocol_filter->has_subclass_code = true;
+ nonmatching_protocol_filter->subclass_code = 2;
+ nonmatching_protocol_filter->has_protocol_code = true;
+ nonmatching_protocol_filter->protocol_code = 1;
+ EXPECT_FALSE(
+ UsbDeviceFilterMatches(*nonmatching_protocol_filter, *device_info));
+
+ // Without |has_subclass_code| set the |protocol_code| filter should be
+ // ignored.
+ auto invalid_matching_protocol_filter = mojom::UsbDeviceFilter::New();
+ invalid_matching_protocol_filter->has_class_code = true;
+ invalid_matching_protocol_filter->class_code = 1;
+ invalid_matching_protocol_filter->has_protocol_code = true;
+ invalid_matching_protocol_filter->protocol_code = 2;
+ EXPECT_TRUE(
+ UsbDeviceFilterMatches(*invalid_matching_protocol_filter, *device_info));
+}
+
TEST_F(UsbUtilsTest, MatchAnyEmptyList) {
std::vector<mojom::UsbDeviceFilterPtr> filters;
ASSERT_TRUE(UsbDeviceFilterMatchesAny(filters, GetPhoneInfo()));
diff --git a/chromium/services/device/public/mojom/BUILD.gn b/chromium/services/device/public/mojom/BUILD.gn
index 221576f2369..e7f0f733d41 100644
--- a/chromium/services/device/public/mojom/BUILD.gn
+++ b/chromium/services/device/public/mojom/BUILD.gn
@@ -86,7 +86,7 @@ mojom("device_service") {
disable_variants = true
enabled_features = []
- if (is_linux && use_udev) {
+ if ((is_linux || is_chromeos) && use_udev) {
enabled_features += [ "enable_input_device_manager" ]
}
diff --git a/chromium/services/device/public/mojom/hid.mojom b/chromium/services/device/public/mojom/hid.mojom
index 1631214c0f4..cc418d198ee 100644
--- a/chromium/services/device/public/mojom/hid.mojom
+++ b/chromium/services/device/public/mojom/hid.mojom
@@ -132,8 +132,8 @@ const uint32 kHIDCollectionTypeVendorMin = 0x80;
const uint32 kHIDCollectionTypeVendorMax = 0xff;
struct HidUsageAndPage {
- uint16 usage;
- uint16 usage_page;
+ uint16 usage@0;
+ uint16 usage_page@1;
};
// A HID report is a packet of data sent between a HID device and its host. The
@@ -149,50 +149,50 @@ struct HidUsageAndPage {
struct HidReportItem {
// True if the usages for this item are defined by |usage_minimum| and
// |usage_maximum|. False if the usages for this item are defined by |usages|.
- bool is_range;
+ bool is_range@0;
// Data associated with the Main item. See section 6.2.2.5 of the Device Class
// Definition for HID.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
- bool is_constant; // Constant (true) or Data (false).
- bool is_variable; // Variable (true) or Array (false).
- bool is_relative; // Relative (true) or Absolute (false).
- bool wrap; // Wrap (true) or No Wrap (false).
- bool is_non_linear; // Non Linear (true) or Linear (false).
- bool no_preferred_state; // No Preferred (true) or Preferred State (false).
- bool has_null_position; // Null state (true) or No Null position (false).
- bool is_volatile; // Volatile (true) or Non Volatile (false).
- bool is_buffered_bytes; // Buffered Bytes (true) or Bit Field (false).
+ bool is_constant@1; // Constant (true) or Data (false).
+ bool is_variable@2; // Variable (true) or Array (false).
+ bool is_relative@3; // Relative (true) or Absolute (false).
+ bool wrap@4; // Wrap (true) or No Wrap (false).
+ bool is_non_linear@5; // Non Linear (true) or Linear (false).
+ bool no_preferred_state@6; // No Preferred (true) or Preferred State (false).
+ bool has_null_position@7; // Null state (true) or No Null position (false).
+ bool is_volatile@8; // Volatile (true) or Non Volatile (false).
+ bool is_buffered_bytes@9; // Buffered Bytes (true) or Bit Field (false).
// Local items. See section 6.2.2.8 of the Device Class Definition for HID.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
// If |is_range| is false, usages for this item are listed in |usages| in the
// order they were encountered in the report descriptor.
- array<HidUsageAndPage> usages;
+ array<HidUsageAndPage> usages@10;
// If |is_range| is true, usages for this item are assigned from a range of
// usages starting at |usage_minimum| and incrementing until |usage_maximum|.
// If this item is a Variable and |report_count| is larger than the number of
// usages in this range, all remaining fields are also assigned
// |usage_maximum|.
- HidUsageAndPage usage_minimum;
- HidUsageAndPage usage_maximum;
+ HidUsageAndPage usage_minimum@11;
+ HidUsageAndPage usage_maximum@12;
// If this item has one or more entries in the Physical descriptor table,
// |designator_minimum| and |designator_maximum| are set to the minimum and
// maximum indices of these entries. If the item has no designators, both are
// set to zero. A designator describes the body part intended to be used with
// a particular control.
- uint32 designator_minimum;
- uint32 designator_maximum;
+ uint32 designator_minimum@13;
+ uint32 designator_maximum@14;
// If this item has one or more entries in the String descriptor table,
// |string_minimum| and |string_maximum| are set to the minimum and maximum
// indices of these entries. If the item has no strings, both are set to zero.
// The String descriptor contains a list of text strings for the device.
- uint32 string_minimum;
- uint32 string_maximum;
+ uint32 string_minimum@15;
+ uint32 string_maximum@16;
// Global items. See section 6.2.2.7 of the Device Class Definition for HID.
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
@@ -200,32 +200,32 @@ struct HidReportItem {
// |logical_minimum| and |logical_maximum| define the extent of valid data
// values for the item in logical units. If |has_null_position| is true,
// values outside this range are interpreted as null input.
- int32 logical_minimum;
- int32 logical_maximum;
+ int32 logical_minimum@17;
+ int32 logical_maximum@18;
// |physical_minimum| and |physical_maximum| define the extent of valid data
// values after applying units to the logical extents.
- int32 physical_minimum;
- int32 physical_maximum;
+ int32 physical_minimum@19;
+ int32 physical_maximum@20;
// The value of the unit exponent in base 10. Values between 0x0 and 0x7
// represent positive exponents 0 to 7, values between 0x8 and 0xF represent
// nevative exponents -8 to -1. Bits [4:31] are reserved and should be set to
// zero.
- uint32 unit_exponent;
+ uint32 unit_exponent@21;
// The units to apply to this item. The |unit| value is coded as seven 4-bit
// fields that define the unit system and the exponents on units of length,
// mass, time, temperature, current, and luminous intensity. Bits [28:31] are
// reserved and should be set to zero.
- uint32 unit;
+ uint32 unit@21;
// A single report item may define multiple same-sized fields within a report.
// |report_size| and |report_count| define the size of one field (in bits) and
// the number of fields within the item. The total size of this item in bits
// is equal to the product of these values.
- uint32 report_size;
- uint32 report_count;
+ uint32 report_size@22;
+ uint32 report_count@23;
};
// Contains information collected from the HID report descriptor regarding a
@@ -237,10 +237,10 @@ struct HidReportItem {
struct HidReportDescription {
// Report ID associated with this report, or zero if the device does not use
// report IDs.
- uint8 report_id;
+ uint8 report_id@0;
// The sequence of report items that describe this report.
- array<HidReportItem> items;
+ array<HidReportItem> items@1;
};
// Contains information collected from the HID report descriptor regarding a
@@ -254,26 +254,26 @@ struct HidReportDescription {
// https://www.usb.org/sites/default/files/documents/hid1_11.pdf
struct HidCollectionInfo {
// Collection's usage ID.
- HidUsageAndPage usage;
+ HidUsageAndPage usage@0;
// HID report IDs which belong to this collection or to its embedded
// collections, in the order they appear in the report descriptor.
- array<uint8> report_ids;
+ array<uint8> report_ids@1;
// Collection type.
- uint32 collection_type;
+ uint32 collection_type@2;
// Reports described in the report descriptor.
- array<HidReportDescription> input_reports;
- array<HidReportDescription> output_reports;
- array<HidReportDescription> feature_reports;
+ array<HidReportDescription> input_reports@3;
+ array<HidReportDescription> output_reports@4;
+ array<HidReportDescription> feature_reports@5;
// The children of this collection in the order they appear in the report
// descriptor. In child collections, the reports described in the
// |input_reports|, |output_reports|, and |feature_reports| members include
// only the subsequence of report items from the parent collection that appear
// within the child collection.
- array<HidCollectionInfo> children;
+ array<HidCollectionInfo> children@6;
};
// Contains information related to a single logical HID device. Note that a
@@ -284,65 +284,65 @@ struct HidDeviceInfo {
// A random GUID assigned to the device during enumeration. The device GUID is
// stable as long as the application is running and the device remains
// connected to the system.
- string guid;
+ string guid@0;
// A platform-specific string identifier for the physical device. When a
// single physical device exposes multiple logical devices, the logical
// devices will have the same value for |physical_device_id|.
- string physical_device_id;
+ string physical_device_id@1;
// The vendor ID value reported by the device. Vendor IDs are 16-bit values
// assigned by the USB-IF or Bluetooth SIG to manufacturers of USB and
// Bluetooth devices.
// TODO(mattreynolds): Indicate whether the vendor ID was assigned by USB-IF
// or Bluetooth SIG.
- uint16 vendor_id;
+ uint16 vendor_id@2;
// The product ID reported by the device. Product IDs are 16-bit values
// assigned by the manufacturer to identify a particular device model.
- uint16 product_id;
+ uint16 product_id@3;
// The product name string reported by the device, or an empty string if no
// product name is available.
- string product_name;
+ string product_name@4;
// The USB serial number string, or an empty string if the device is not a USB
// device or has no serial number.
- string serial_number;
+ string serial_number@5;
// The bus used to connect this device to the system.
- HidBusType bus_type;
+ HidBusType bus_type@6;
// An array of bytes representing the HID report descriptor reported by the
// device, or an empty array if the report descriptor could not be read.
- array<uint8> report_descriptor;
+ array<uint8> report_descriptor@7;
// A structured representation of the information contained in the HID report
// descriptor.
- array<HidCollectionInfo> collections;
+ array<HidCollectionInfo> collections@8;
// True if the device uses report IDs.
- bool has_report_id;
+ bool has_report_id@9;
// The maximum size in bytes of input, output, and feature reports supported
// by the device.
- uint64 max_input_report_size;
- uint64 max_output_report_size;
- uint64 max_feature_report_size;
+ uint64 max_input_report_size@10;
+ uint64 max_output_report_size@11;
+ uint64 max_feature_report_size@12;
// A platform-specific string identifier for the logical device.
- string device_node;
+ string device_node@13;
};
// A client interface for receiving a notification when HID devices are
// physically connected or disconnected.
interface HidManagerClient {
// Notifies the client that a device is added.
- DeviceAdded(HidDeviceInfo device_info);
+ DeviceAdded@0(HidDeviceInfo device_info);
// Notifies the client that a device is being removed; called before
// removing the device from HidService.
- DeviceRemoved(HidDeviceInfo device_info);
+ DeviceRemoved@1(HidDeviceInfo device_info);
};
// Provides an interface for enumerating available HID devices, registering for
@@ -352,11 +352,11 @@ interface HidManager {
// Enumerates available devices and set as a client of HidManager.
// The implementation of HidManager guarantees that the returned callback
// will always be posted earlier than DeviceAdded() and DeviceRemoved().
- GetDevicesAndSetClient(pending_associated_remote<HidManagerClient> client) =>
- (array<HidDeviceInfo> devices);
+ GetDevicesAndSetClient@0(pending_associated_remote<HidManagerClient> client)
+ => (array<HidDeviceInfo> devices);
// Enumerates available devices only.
- GetDevices() => (array<HidDeviceInfo> devices);
+ GetDevices@1() => (array<HidDeviceInfo> devices);
// Opens a connection to a device by given guid. The callback will be run
// with null on failure.
@@ -368,7 +368,7 @@ interface HidManager {
// open. When the HID connection is closed, the watcher is also closed. This
// is useful when the connection closure should be handled somewhere other
// than where the |connection| and |connection_client| are held.
- Connect(string device_guid,
+ Connect@2(string device_guid,
pending_remote<HidConnectionClient>? connection_client,
pending_remote<HidConnectionWatcher>? watcher)
=> (pending_remote<HidConnection>? connection);
@@ -381,18 +381,18 @@ interface HidManager {
interface HidConnection {
// A |report_id| of 0 is returned via callback if report IDs are not
// supported by the device.
- Read() => (bool success, uint8 report_id, array<uint8>? buffer);
+ Read@0() => (bool success, uint8 report_id, array<uint8>? buffer);
// Pass the |report_id| as 0 if not supported by the device.
- Write(uint8 report_id, array<uint8> buffer) => (bool success);
+ Write@1(uint8 report_id, array<uint8> buffer) => (bool success);
// The buffer will contain whatever report data was received from the device.
// This may include the report ID. The report ID is not stripped because a
// device may respond with other data in place of the report ID.
- GetFeatureReport(uint8 report_id) => (bool success, array<uint8>? buffer);
+ GetFeatureReport@2(uint8 report_id) => (bool success, array<uint8>? buffer);
// Pass the |report_id| as 0 if not supported by the device.
- SendFeatureReport(uint8 report_id, array<uint8> buffer) => (bool success);
+ SendFeatureReport@3(uint8 report_id, array<uint8> buffer) => (bool success);
};
// A client interface for receiving a notification when input reports are
@@ -400,7 +400,7 @@ interface HidConnection {
interface HidConnectionClient {
// Notifies the client that an input report was received. A |report_id| of 0
// is passed if report IDs are not used by the device.
- OnInputReport(uint8 report_id, array<uint8> buffer);
+ OnInputReport@0(uint8 report_id, array<uint8> buffer);
};
// A client interface for observing whether a HID connection is still active.
diff --git a/chromium/services/device/public/mojom/serial.mojom b/chromium/services/device/public/mojom/serial.mojom
index b24628c54ee..905ea45b9cc 100644
--- a/chromium/services/device/public/mojom/serial.mojom
+++ b/chromium/services/device/public/mojom/serial.mojom
@@ -16,6 +16,10 @@ struct SerialPortInfo {
mojo_base.mojom.FilePath path;
+ // This member is used to identify whether the SerialPortInfo object is
+ // converted from a Bluetooth serial device.
+ DeviceType type;
+
// 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
@@ -66,6 +70,27 @@ enum SerialStopBits {
TWO,
};
+enum SerialPortFlushMode {
+ // Flushes both receive and transmit buffers without discarding any bytes in
+ // the data pipes. This is for compatibility with chrome.serial.flush().
+ kReceiveAndTransmit,
+
+ // Flushes the receive buffers and discards data in the data_pipe_producer by
+ // closing it.
+ kReceive,
+
+ // Flushes the send buffers and discards data in the data_pipe_consumer by
+ // closing it.
+ kTransmit,
+};
+
+enum DeviceType {
+ // The SerialPortInfo object is created from a serial device.
+ PLATFORM_SERIAL,
+ // The SerialPortInfo object is created from a Bluetooth SPP device.
+ SPP_DEVICE,
+};
+
struct SerialConnectionOptions {
uint32 bitrate = 0;
SerialDataBits data_bits = NONE;
@@ -146,8 +171,12 @@ interface SerialPort {
// called on |client| to indicate an error.
StartReading(handle<data_pipe_producer> producer);
- // Flushes input and output buffers.
- Flush() => (bool success);
+ // Flushes buffers according to the selected |mode|.
+ Flush(SerialPortFlushMode mode) => ();
+
+ // Waits for the data_pipe_consumer passed to StartWriting() to be closed and
+ // all buffered data to be transmitted by the port.
+ Drain() => ();
// Reads current control signals (DCD, CTS, etc.).
GetControlSignals() => (SerialPortControlSignals signals);
diff --git a/chromium/services/device/screen_orientation/screen_orientation_listener_android.cc b/chromium/services/device/screen_orientation/screen_orientation_listener_android.cc
index 0b36405e97c..40b87982aa3 100644
--- a/chromium/services/device/screen_orientation/screen_orientation_listener_android.cc
+++ b/chromium/services/device/screen_orientation/screen_orientation_listener_android.cc
@@ -6,7 +6,7 @@
#include "base/android/jni_android.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
+#include "base/task/current_thread.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/device/screen_orientation/screen_orientation_jni_headers/ScreenOrientationListener_jni.h"
@@ -23,7 +23,7 @@ void ScreenOrientationListenerAndroid::Create(
ScreenOrientationListenerAndroid::ScreenOrientationListenerAndroid() = default;
ScreenOrientationListenerAndroid::~ScreenOrientationListenerAndroid() {
- DCHECK(base::MessageLoopCurrentForIO::IsSet());
+ DCHECK(base::CurrentIOThread::IsSet());
}
void ScreenOrientationListenerAndroid::IsAutoRotateEnabledByUser(
diff --git a/chromium/services/device/serial/BUILD.gn b/chromium/services/device/serial/BUILD.gn
index d75328bfb9b..77a58d170f6 100644
--- a/chromium/services/device/serial/BUILD.gn
+++ b/chromium/services/device/serial/BUILD.gn
@@ -4,7 +4,7 @@
import("//build/config/features.gni")
-if (is_win || (is_linux && use_udev) || is_mac) {
+if (is_win || ((is_linux || is_chromeos) && use_udev) || is_mac) {
config("platform_support") {
visibility = [ ":serial" ]
if (is_win) {
@@ -21,6 +21,10 @@ if (is_win || (is_linux && use_udev) || is_mac) {
]
sources = [
+ "bluetooth_serial_device_enumerator.cc",
+ "bluetooth_serial_device_enumerator.h",
+ "bluetooth_serial_port_impl.cc",
+ "bluetooth_serial_port_impl.h",
"buffer.cc",
"buffer.h",
"serial_device_enumerator.cc",
@@ -47,8 +51,12 @@ if (is_win || (is_linux && use_udev) || is_mac) {
deps = [
"//base",
+ "//device/bluetooth:bluetooth",
+ "//device/bluetooth/public/cpp",
"//mojo/public/cpp/bindings",
"//net",
+ "//services/device/public/cpp/bluetooth:bluetooth",
+ "//services/device/public/cpp/serial:switches",
]
if (is_posix) {
@@ -67,7 +75,7 @@ if (is_win || (is_linux && use_udev) || is_mac) {
}
if (is_mac) {
- libs = [
+ frameworks = [
"Foundation.framework",
"IOKit.framework",
]
diff --git a/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc b/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc
new file mode 100644
index 00000000000..07359674ce6
--- /dev/null
+++ b/chromium/services/device/serial/bluetooth_serial_device_enumerator.cc
@@ -0,0 +1,68 @@
+// 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/device/serial/bluetooth_serial_device_enumerator.h"
+
+#include "base/command_line.h"
+#include "base/unguessable_token.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "services/device/public/cpp/bluetooth/bluetooth_utils.h"
+#include "services/device/public/cpp/serial/serial_switches.h"
+#include "services/device/public/mojom/serial.mojom.h"
+
+namespace device {
+
+BluetoothSerialDeviceEnumerator::BluetoothSerialDeviceEnumerator() {
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi));
+ device::BluetoothAdapterFactory::Get()->GetClassicAdapter(
+ base::BindOnce(&BluetoothSerialDeviceEnumerator::OnGotClassicAdapter,
+ base::Unretained(this)));
+}
+
+BluetoothSerialDeviceEnumerator::~BluetoothSerialDeviceEnumerator() = default;
+
+void BluetoothSerialDeviceEnumerator::OnGotClassicAdapter(
+ scoped_refptr<device::BluetoothAdapter> adapter) {
+ DCHECK(adapter);
+ adapter_ = adapter;
+ adapter_->AddObserver(this);
+ BluetoothAdapter::DeviceList devices = adapter_->GetDevices();
+ for (auto* device : devices) {
+ BluetoothDevice::UUIDSet device_uuids = device->GetUUIDs();
+ if (base::Contains(device_uuids, GetSerialPortProfileUUID())) {
+ auto port = mojom::SerialPortInfo::New();
+ port->token = base::UnguessableToken::Create();
+ port->path = base::FilePath::FromUTF8Unsafe(device->GetIdentifier());
+ port->type = mojom::DeviceType::SPP_DEVICE;
+ bluetooth_ports_.insert(
+ std::make_pair(device->GetAddress(), port->token));
+ AddPort(std::move(port));
+ }
+ }
+}
+
+void BluetoothSerialDeviceEnumerator::DeviceAdded(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ BluetoothDevice::UUIDSet device_uuids = device->GetUUIDs();
+ if (base::Contains(device_uuids, GetSerialPortProfileUUID())) {
+ auto port = mojom::SerialPortInfo::New();
+ port->token = base::UnguessableToken::Create();
+ port->path = base::FilePath::FromUTF8Unsafe(device->GetIdentifier());
+ port->type = mojom::DeviceType::SPP_DEVICE;
+ bluetooth_ports_.insert(std::make_pair(device->GetAddress(), port->token));
+ AddPort(std::move(port));
+ }
+}
+
+void BluetoothSerialDeviceEnumerator::DeviceRemoved(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ auto it = bluetooth_ports_.find(device->GetAddress());
+ DCHECK(it != bluetooth_ports_.end());
+ base::UnguessableToken token = it->second;
+ bluetooth_ports_.erase(it);
+ RemovePort(token);
+}
+
+} // namespace device
diff --git a/chromium/services/device/serial/bluetooth_serial_device_enumerator.h b/chromium/services/device/serial/bluetooth_serial_device_enumerator.h
new file mode 100644
index 00000000000..fa3928b8fa4
--- /dev/null
+++ b/chromium/services/device/serial/bluetooth_serial_device_enumerator.h
@@ -0,0 +1,43 @@
+// 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_DEVICE_SERIAL_BLUETOOTH_SERIAL_DEVICE_ENUMERATOR_H_
+#define SERVICES_DEVICE_SERIAL_BLUETOOTH_SERIAL_DEVICE_ENUMERATOR_H_
+
+#include <map>
+
+#include "base/memory/scoped_refptr.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "services/device/public/mojom/serial.mojom-forward.h"
+#include "services/device/serial/serial_device_enumerator.h"
+
+namespace device {
+
+class BluetoothSerialDeviceEnumerator : public BluetoothAdapter::Observer,
+ public SerialDeviceEnumerator {
+ public:
+ BluetoothSerialDeviceEnumerator();
+ BluetoothSerialDeviceEnumerator(const BluetoothSerialDeviceEnumerator&) =
+ delete;
+ BluetoothSerialDeviceEnumerator& operator=(
+ const BluetoothSerialDeviceEnumerator&) = delete;
+ ~BluetoothSerialDeviceEnumerator() override;
+
+ // BluetoothAdapter::Observer methods:
+ void DeviceAdded(BluetoothAdapter* adapter, BluetoothDevice* device) override;
+ void DeviceRemoved(BluetoothAdapter* adapter,
+ BluetoothDevice* device) override;
+
+ protected:
+ scoped_refptr<BluetoothAdapter> adapter_;
+
+ private:
+ void OnGotClassicAdapter(scoped_refptr<device::BluetoothAdapter> adapter);
+
+ std::unordered_map<std::string, base::UnguessableToken> bluetooth_ports_;
+};
+
+} // namespace device
+
+#endif // SERVICES_DEVICE_SERIAL_BLUETOOTH_SERIAL_DEVICE_ENUMERATOR_H_
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.cc b/chromium/services/device/serial/bluetooth_serial_port_impl.cc
new file mode 100644
index 00000000000..346a44ae5b8
--- /dev/null
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl.cc
@@ -0,0 +1,382 @@
+// 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/device/serial/bluetooth_serial_port_impl.h"
+
+#include "base/command_line.h"
+#include "net/base/io_buffer.h"
+#include "services/device/public/cpp/bluetooth/bluetooth_utils.h"
+#include "services/device/public/cpp/serial/serial_switches.h"
+#include "services/device/serial/buffer.h"
+
+namespace device {
+
+// static
+void BluetoothSerialPortImpl::Create(
+ std::unique_ptr<BluetoothDevice> device,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) {
+ DCHECK(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi));
+
+ // This BluetoothSerialPortImpl is owned by |receiver| and |watcher|.
+ new BluetoothSerialPortImpl(std::move(device), std::move(receiver),
+ std::move(watcher));
+}
+
+BluetoothSerialPortImpl::BluetoothSerialPortImpl(
+ std::unique_ptr<BluetoothDevice> device,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher)
+ : receiver_(this, std::move(receiver)),
+ watcher_(std::move(watcher)),
+ in_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ out_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
+ bluetooth_device_(std::move(device)) {
+ receiver_.set_disconnect_handler(
+ base::BindOnce([](BluetoothSerialPortImpl* self) { delete self; },
+ base::Unretained(this)));
+ if (watcher_.is_bound()) {
+ watcher_.set_disconnect_handler(
+ base::BindOnce([](BluetoothSerialPortImpl* self) { delete self; },
+ base::Unretained(this)));
+ }
+}
+
+BluetoothSerialPortImpl::~BluetoothSerialPortImpl() {
+ if (bluetooth_socket_)
+ bluetooth_socket_->Close();
+}
+
+void BluetoothSerialPortImpl::Open(
+ mojom::SerialConnectionOptionsPtr options,
+ mojo::PendingRemote<mojom::SerialPortClient> client,
+ OpenCallback callback) {
+ if (client)
+ client_.Bind(std::move(client));
+
+ BluetoothDevice::UUIDSet device_uuids = bluetooth_device_->GetUUIDs();
+ if (base::Contains(device_uuids, GetSerialPortProfileUUID())) {
+ auto copyable_callback =
+ base::AdaptCallbackForRepeating(std::move(callback));
+ bluetooth_device_->ConnectToService(
+ GetSerialPortProfileUUID(),
+ base::BindOnce(&BluetoothSerialPortImpl::OnSocketConnected,
+ weak_ptr_factory_.GetWeakPtr(), copyable_callback),
+ base::BindOnce(&BluetoothSerialPortImpl::OnSocketConnectedError,
+ weak_ptr_factory_.GetWeakPtr(), copyable_callback));
+ return;
+ }
+ std::move(callback).Run(false);
+}
+
+void BluetoothSerialPortImpl::OnSocketConnected(
+ OpenCallback callback,
+ scoped_refptr<BluetoothSocket> socket) {
+ DCHECK(socket);
+ bluetooth_socket_ = std::move(socket);
+ std::move(callback).Run(true);
+}
+
+void BluetoothSerialPortImpl::OnSocketConnectedError(
+ OpenCallback callback,
+ const std::string& message) {
+ std::move(callback).Run(false);
+}
+
+void BluetoothSerialPortImpl::StartWriting(
+ mojo::ScopedDataPipeConsumerHandle consumer) {
+ DCHECK(!write_pending_);
+
+ if (in_stream_) {
+ mojo::ReportBadMessage("Data pipe consumer still open.");
+ return;
+ }
+
+ if (!bluetooth_socket_) {
+ mojo::ReportBadMessage("No Bluetooth socket.");
+ return;
+ }
+
+ in_stream_watcher_.Cancel();
+ in_stream_ = std::move(consumer);
+ in_stream_watcher_.Watch(
+ in_stream_.get(),
+ MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&BluetoothSerialPortImpl::WriteToSocket,
+ weak_ptr_factory_.GetWeakPtr()));
+ in_stream_watcher_.ArmOrNotify();
+}
+
+void BluetoothSerialPortImpl::StartReading(
+ mojo::ScopedDataPipeProducerHandle producer) {
+ if (out_stream_) {
+ mojo::ReportBadMessage("Data pipe producer still open.");
+ return;
+ }
+
+ if (!bluetooth_socket_) {
+ mojo::ReportBadMessage("No Bluetooth socket.");
+ return;
+ }
+
+ out_stream_watcher_.Cancel();
+ out_stream_ = std::move(producer);
+ out_stream_watcher_.Watch(
+ out_stream_.get(),
+ MOJO_HANDLE_SIGNAL_WRITABLE | MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindRepeating(&BluetoothSerialPortImpl::ReadFromSocketAndWriteOut,
+ weak_ptr_factory_.GetWeakPtr()));
+ out_stream_watcher_.ArmOrNotify();
+}
+
+void BluetoothSerialPortImpl::ReadFromSocketAndWriteOut(
+ MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ switch (result) {
+ case MOJO_RESULT_OK:
+ ReadMore();
+ break;
+ case MOJO_RESULT_SHOULD_WAIT:
+ // If there is no space to write, wait for more space.
+ out_stream_watcher_.ArmOrNotify();
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ case MOJO_RESULT_CANCELLED:
+ // The |out_stream_| has been closed.
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ break;
+ default:
+ NOTREACHED() << "Unexpected Mojo result: " << result;
+ }
+}
+
+void BluetoothSerialPortImpl::ReadMore() {
+ DCHECK(out_stream_.is_valid());
+
+ void* buffer = nullptr;
+
+ uint32_t buffer_max_size = 0;
+ // The |buffer| is owned by |out_stream_|.
+ MojoResult result = out_stream_->BeginWriteData(&buffer, &buffer_max_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ out_stream_watcher_.ArmOrNotify();
+ return;
+ }
+ if (result != MOJO_RESULT_OK) {
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ return;
+ }
+
+ if (!bluetooth_socket_) {
+ mojo::ReportBadMessage("No Bluetooth socket.");
+ return;
+ }
+
+ read_pending_ = true;
+ bluetooth_socket_->Receive(
+ buffer_max_size,
+ base::BindOnce(
+ &BluetoothSerialPortImpl::OnBluetoothSocketReceive,
+ weak_ptr_factory_.GetWeakPtr(),
+ base::make_span(reinterpret_cast<char*>(buffer), buffer_max_size)),
+ base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketReceiveError,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothSerialPortImpl::OnBluetoothSocketReceive(
+ base::span<char> pending_write_buffer,
+ int num_bytes_received,
+ scoped_refptr<net::IOBuffer> io_buffer) {
+ DCHECK_GT(num_bytes_received, 0);
+ DCHECK(io_buffer->data());
+ DCHECK(out_stream_.is_valid());
+
+ read_pending_ = false;
+ std::copy(io_buffer->data(), io_buffer->data() + num_bytes_received,
+ pending_write_buffer.data());
+ out_stream_->EndWriteData(static_cast<uint32_t>(num_bytes_received));
+
+ if (read_flush_callback_) {
+ std::move(read_flush_callback_).Run();
+ out_stream_->EndWriteData(0);
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ return;
+ }
+ ReadMore();
+}
+
+void BluetoothSerialPortImpl::OnBluetoothSocketReceiveError(
+ BluetoothSocket::ErrorReason error_reason,
+ const std::string& error_message) {
+ DCHECK(out_stream_.is_valid());
+ read_pending_ = false;
+ if (client_) {
+ DCHECK(error_reason != BluetoothSocket::ErrorReason::kIOPending);
+ switch (error_reason) {
+ case BluetoothSocket::ErrorReason::kDisconnected:
+ client_->OnReadError(mojom::SerialReceiveError::DISCONNECTED);
+ break;
+ case BluetoothSocket::ErrorReason::kIOPending:
+ NOTREACHED();
+ break;
+ case BluetoothSocket::ErrorReason::kSystemError:
+ client_->OnReadError(mojom::SerialReceiveError::SYSTEM_ERROR);
+ break;
+ }
+ }
+ if (read_flush_callback_)
+ std::move(read_flush_callback_).Run();
+ out_stream_->EndWriteData(0);
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+}
+
+void BluetoothSerialPortImpl::WriteToSocket(
+ MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ switch (result) {
+ case MOJO_RESULT_OK:
+ WriteMore();
+ break;
+ case MOJO_RESULT_SHOULD_WAIT:
+ // If there is no space to write, wait for more space.
+ in_stream_watcher_.ArmOrNotify();
+ break;
+ case MOJO_RESULT_FAILED_PRECONDITION:
+ case MOJO_RESULT_CANCELLED:
+ // The |in_stream_| has been closed.
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+
+ if (drain_callback_)
+ std::move(drain_callback_).Run();
+ break;
+ default:
+ NOTREACHED() << "Unexpected Mojo result: " << result;
+ }
+}
+
+void BluetoothSerialPortImpl::WriteMore() {
+ DCHECK(in_stream_.is_valid());
+
+ const void* buffer = nullptr;
+ uint32_t buffer_size = 0;
+ // |buffer| is owned by |in_stream_|.
+ MojoResult result = in_stream_->BeginReadData(&buffer, &buffer_size,
+ MOJO_WRITE_DATA_FLAG_NONE);
+ if (result == MOJO_RESULT_SHOULD_WAIT) {
+ in_stream_watcher_.ArmOrNotify();
+ return;
+ }
+ if (result != MOJO_RESULT_OK) {
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ return;
+ }
+
+ if (!bluetooth_socket_) {
+ mojo::ReportBadMessage("No Bluetooth socket.");
+ return;
+ }
+
+ write_pending_ = true;
+ bluetooth_socket_->Send(
+ base::MakeRefCounted<net::WrappedIOBuffer>(
+ reinterpret_cast<const char*>(buffer)),
+ buffer_size,
+ base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketSend,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::BindOnce(&BluetoothSerialPortImpl::OnBluetoothSocketSendError,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothSerialPortImpl::OnBluetoothSocketSend(int num_bytes_sent) {
+ DCHECK_GE(num_bytes_sent, 0);
+ DCHECK(in_stream_.is_valid());
+
+ write_pending_ = false;
+
+ in_stream_->EndReadData(static_cast<uint32_t>(num_bytes_sent));
+
+ if (write_flush_callback_) {
+ std::move(write_flush_callback_).Run();
+ in_stream_->EndReadData(0);
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ return;
+ }
+ WriteMore();
+}
+
+void BluetoothSerialPortImpl::OnBluetoothSocketSendError(
+ const std::string& error_message) {
+ DCHECK(in_stream_.is_valid());
+ write_pending_ = false;
+ if (client_)
+ client_->OnSendError(mojom::SerialSendError::SYSTEM_ERROR);
+ if (write_flush_callback_)
+ std::move(write_flush_callback_).Run();
+ in_stream_->EndReadData(0);
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+}
+
+void BluetoothSerialPortImpl::Flush(mojom::SerialPortFlushMode mode,
+ FlushCallback callback) {
+ NOTIMPLEMENTED();
+}
+
+void BluetoothSerialPortImpl::Drain(DrainCallback callback) {
+ if (!in_stream_) {
+ std::move(callback).Run();
+ return;
+ }
+
+ drain_callback_ = std::move(callback);
+}
+
+void BluetoothSerialPortImpl::GetControlSignals(
+ GetControlSignalsCallback callback) {
+ auto signals = mojom::SerialPortControlSignals::New();
+ std::move(callback).Run(std::move(signals));
+}
+
+void BluetoothSerialPortImpl::SetControlSignals(
+ mojom::SerialHostControlSignalsPtr signals,
+ SetControlSignalsCallback callback) {
+ std::move(callback).Run(true);
+}
+
+void BluetoothSerialPortImpl::ConfigurePort(
+ mojom::SerialConnectionOptionsPtr options,
+ ConfigurePortCallback callback) {
+ options_ = std::move(options);
+ std::move(callback).Run(true);
+}
+
+void BluetoothSerialPortImpl::GetPortInfo(GetPortInfoCallback callback) {
+ auto info = mojom::SerialConnectionInfo::New(
+ /*bitrate=*/options_->bitrate, /*data_bits=*/options_->data_bits,
+ /*parity_bit=*/options_->parity_bit, /*stop_bits=*/options_->stop_bits,
+ /*cts_flow_control=*/options_->cts_flow_control);
+ std::move(callback).Run(std::move(info));
+}
+
+void BluetoothSerialPortImpl::Close(CloseCallback callback) {
+ client_.reset();
+ if (bluetooth_socket_) {
+ bluetooth_socket_->Close();
+ bluetooth_socket_.reset();
+ }
+ std::move(callback).Run();
+}
+
+} // namespace device
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl.h b/chromium/services/device/serial/bluetooth_serial_port_impl.h
new file mode 100644
index 00000000000..107d3de93cb
--- /dev/null
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl.h
@@ -0,0 +1,107 @@
+// 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_DEVICE_SERIAL_BLUETOOTH_SERIAL_PORT_IMPL_H_
+#define SERVICES_DEVICE_SERIAL_BLUETOOTH_SERIAL_PORT_IMPL_H_
+
+#include "base/single_thread_task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/bluetooth_socket.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "services/device/public/mojom/serial.mojom.h"
+#include "services/device/serial/serial_io_handler.h"
+#include "services/device/serial/serial_port_impl.h"
+
+namespace device {
+
+// This class is intended to allow serial communication using a Bluetooth
+// SPP device. The Bluetooth device is used to create a Bluetooth socket
+// which is closed upon error in any of the interface functions.
+class BluetoothSerialPortImpl : public mojom::SerialPort {
+ public:
+ // Creates of instance of BluetoothSerialPortImpl using a Bluetooth
+ // device and a receiver/watcher to create a pipe. The receiver and
+ // watcher will own this object.
+ static void Create(
+ std::unique_ptr<BluetoothDevice> device,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher);
+
+ BluetoothSerialPortImpl(
+ std::unique_ptr<BluetoothDevice> device,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher);
+ BluetoothSerialPortImpl(const BluetoothSerialPortImpl&) = delete;
+ BluetoothSerialPortImpl& operator=(const BluetoothSerialPortImpl&) = delete;
+ ~BluetoothSerialPortImpl() override;
+
+ private:
+ // mojom::SerialPort methods:
+ void Open(mojom::SerialConnectionOptionsPtr options,
+ mojo::PendingRemote<mojom::SerialPortClient> client,
+ OpenCallback callback) override;
+ void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override;
+ void StartReading(mojo::ScopedDataPipeProducerHandle producer) override;
+ void Flush(mojom::SerialPortFlushMode mode, FlushCallback callback) override;
+ void Drain(DrainCallback callback) override;
+ void GetControlSignals(GetControlSignalsCallback callback) override;
+ void SetControlSignals(mojom::SerialHostControlSignalsPtr signals,
+ SetControlSignalsCallback callback) override;
+ void ConfigurePort(mojom::SerialConnectionOptionsPtr options,
+ ConfigurePortCallback callback) override;
+ void GetPortInfo(GetPortInfoCallback callback) override;
+ void Close(CloseCallback callback) override;
+
+ void WriteToSocket(MojoResult result, const mojo::HandleSignalsState& state);
+ void ReadFromSocketAndWriteOut(MojoResult result,
+ const mojo::HandleSignalsState& state);
+
+ void ReadMore();
+ void WriteMore();
+
+ void OnSocketConnected(OpenCallback callback,
+ scoped_refptr<BluetoothSocket> socket);
+ void OnSocketConnectedError(OpenCallback callback,
+ const std::string& message);
+
+ void OnBluetoothSocketReceive(base::span<char> pending_write_buffer,
+ int num_bytes_received,
+ scoped_refptr<net::IOBuffer> io_buffer);
+ void OnBluetoothSocketReceiveError(
+ device::BluetoothSocket::ErrorReason error_reason,
+ const std::string& error_message);
+ void OnBluetoothSocketSend(int num_bytes_sent);
+ void OnBluetoothSocketSendError(const std::string& error_message);
+
+ mojo::Receiver<mojom::SerialPort> receiver_;
+ mojo::Remote<mojom::SerialPortConnectionWatcher> watcher_;
+ mojo::Remote<mojom::SerialPortClient> client_;
+
+ // Data pipes for input and output.
+ mojo::ScopedDataPipeConsumerHandle in_stream_;
+ mojo::SimpleWatcher in_stream_watcher_;
+ mojo::ScopedDataPipeProducerHandle out_stream_;
+ mojo::SimpleWatcher out_stream_watcher_;
+
+ // Holds the callback for a flush or drain until pending operations have been
+ // completed.
+ FlushCallback read_flush_callback_;
+ FlushCallback write_flush_callback_;
+ DrainCallback drain_callback_;
+
+ scoped_refptr<device::BluetoothSocket> bluetooth_socket_;
+ std::unique_ptr<BluetoothDevice> bluetooth_device_;
+
+ bool read_pending_ = false;
+ bool write_pending_ = false;
+
+ mojom::SerialConnectionOptionsPtr options_;
+
+ base::WeakPtrFactory<BluetoothSerialPortImpl> weak_ptr_factory_{this};
+};
+
+} // namespace device
+
+#endif // SERVICES_DEVICE_SERIAL_BLUETOOTH_SERIAL_PORT_IMPL_H_
diff --git a/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc
new file mode 100644
index 00000000000..0067f97ebd7
--- /dev/null
+++ b/chromium/services/device/serial/bluetooth_serial_port_impl_unittest.cc
@@ -0,0 +1,353 @@
+// 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/device/serial/bluetooth_serial_port_impl.h"
+
+#include "base/command_line.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/gmock_callback_support.h"
+#include "base/test/task_environment.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/bluetooth_socket.h"
+#include "device/bluetooth/test/mock_bluetooth_adapter.h"
+#include "device/bluetooth/test/mock_bluetooth_device.h"
+#include "device/bluetooth/test/mock_bluetooth_socket.h"
+#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
+#include "net/base/io_buffer.h"
+#include "services/device/public/cpp/bluetooth/bluetooth_utils.h"
+#include "services/device/public/cpp/serial/serial_switches.h"
+#include "services/device/public/mojom/serial.mojom.h"
+#include "services/device/serial/buffer.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+namespace {
+
+using ::base::test::RunOnceCallback;
+using ::testing::_;
+using ::testing::Invoke;
+using ::testing::WithArgs;
+
+constexpr char kBuffer[] = "test";
+constexpr char kDeviceAddress[] = "00:00:00:00:00:00";
+constexpr uint32_t kElementNumBytes = 1;
+constexpr uint32_t kCapacityNumBytes = 64;
+
+class BluetoothSerialPortImplTest : public testing::Test {
+ public:
+ BluetoothSerialPortImplTest() {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi);
+ }
+ BluetoothSerialPortImplTest(const BluetoothSerialPortImplTest&) = delete;
+ BluetoothSerialPortImplTest& operator=(const BluetoothSerialPortImplTest&) =
+ delete;
+ ~BluetoothSerialPortImplTest() override = default;
+
+ void CreatePort(
+ mojo::Remote<mojom::SerialPort>* port,
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher>* watcher) {
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote;
+ *watcher = mojo::MakeSelfOwnedReceiver(
+ std::make_unique<mojom::SerialPortConnectionWatcher>(),
+ watcher_remote.InitWithNewPipeAndPassReceiver());
+
+ scoped_refptr<MockBluetoothAdapter> adapter =
+ base::MakeRefCounted<MockBluetoothAdapter>();
+ device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
+ auto mock_device = std::make_unique<MockBluetoothDevice>(
+ adapter.get(), 0, "Test Device", kDeviceAddress, false, false);
+ mock_device->AddUUID(GetSerialPortProfileUUID());
+
+ EXPECT_CALL(*mock_device,
+ ConnectToService(GetSerialPortProfileUUID(), _, _))
+ .WillOnce(RunOnceCallback<1>(mock_socket_));
+
+ BluetoothSerialPortImpl::Create(std::move(mock_device),
+ port->BindNewPipeAndPassReceiver(),
+ std::move(watcher_remote));
+ }
+
+ void CreatePortWithSocketError(
+ mojo::Remote<mojom::SerialPort>* port,
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher>* watcher) {
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote;
+ *watcher = mojo::MakeSelfOwnedReceiver(
+ std::make_unique<mojom::SerialPortConnectionWatcher>(),
+ watcher_remote.InitWithNewPipeAndPassReceiver());
+
+ scoped_refptr<MockBluetoothAdapter> adapter =
+ base::MakeRefCounted<MockBluetoothAdapter>();
+ device::BluetoothAdapterFactory::SetAdapterForTesting(adapter);
+ auto mock_device = std::make_unique<MockBluetoothDevice>(
+ adapter.get(), 0, "Test Device", kDeviceAddress, false, false);
+ mock_device->AddUUID(GetSerialPortProfileUUID());
+
+ EXPECT_CALL(*mock_device,
+ ConnectToService(GetSerialPortProfileUUID(), _, _))
+ .WillOnce(RunOnceCallback<2>("Error"));
+
+ BluetoothSerialPortImpl::Create(std::move(mock_device),
+ port->BindNewPipeAndPassReceiver(),
+ std::move(watcher_remote));
+ }
+
+ void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
+ mojo::ScopedDataPipeConsumerHandle* consumer) {
+ MojoCreateDataPipeOptions options;
+ options.struct_size = sizeof(options);
+ options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
+ options.element_num_bytes = kElementNumBytes;
+ options.capacity_num_bytes = kCapacityNumBytes;
+
+ MojoResult result = mojo::CreateDataPipe(&options, producer, consumer);
+ DCHECK_EQ(result, MOJO_RESULT_OK);
+ }
+
+ MockBluetoothSocket& mock_socket() { return *mock_socket_; }
+
+ private:
+ scoped_refptr<MockBluetoothSocket> mock_socket_ =
+ base::MakeRefCounted<MockBluetoothSocket>();
+
+ base::test::SingleThreadTaskEnvironment task_environment_;
+};
+
+class FakeSerialPortClient : public mojom::SerialPortClient {
+ public:
+ FakeSerialPortClient() = default;
+ FakeSerialPortClient(FakeSerialPortClient&) = delete;
+ FakeSerialPortClient& operator=(FakeSerialPortClient&) = delete;
+ ~FakeSerialPortClient() override = default;
+
+ void Bind(mojo::PendingReceiver<device::mojom::SerialPortClient> receiver) {
+ receiver_.Bind(std::move(receiver));
+ }
+
+ // mojom::SerialPortClient
+ void OnReadError(mojom::SerialReceiveError error) override {}
+ void OnSendError(mojom::SerialSendError error) override {}
+
+ private:
+ mojo::Receiver<mojom::SerialPortClient> receiver_{this};
+};
+
+} // namespace
+
+TEST_F(BluetoothSerialPortImplTest, NullSocketTest) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePortWithSocketError(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ auto options = mojom::SerialConnectionOptions::New();
+ mojo::PendingRemote<mojom::SerialPortClient> client;
+ FakeSerialPortClient serial_client;
+ serial_client.Bind(client.InitWithNewPipeAndPassReceiver());
+ base::RunLoop loop;
+ serial_port->Open(std::move(options), std::move(client),
+ base::BindLambdaForTesting([&loop](bool success) {
+ EXPECT_FALSE(success);
+ loop.Quit();
+ }));
+ loop.Run();
+
+ EXPECT_CALL(mock_socket(), Receive(_, _, _)).Times(0);
+ EXPECT_CALL(mock_socket(), Close()).Times(0);
+
+ serial_port->StartReading(std::move(producer));
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, StartWritingTest) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ auto options = mojom::SerialConnectionOptions::New();
+ mojo::PendingRemote<mojom::SerialPortClient> client;
+ FakeSerialPortClient serial_client;
+ serial_client.Bind(client.InitWithNewPipeAndPassReceiver());
+ base::RunLoop loop;
+ serial_port->Open(std::move(options), std::move(client),
+ base::BindLambdaForTesting([&loop](bool success) {
+ EXPECT_TRUE(success);
+ loop.Quit();
+ }));
+ loop.Run();
+
+ uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
+ auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
+
+ MojoResult result =
+ producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+
+ EXPECT_CALL(mock_socket(), Send)
+ .WillOnce(WithArgs<0, 1, 2>(Invoke(
+ [&](scoped_refptr<net::IOBuffer> buf, int buffer_size,
+ MockBluetoothSocket::SendCompletionCallback success_callback) {
+ ASSERT_EQ(buffer_size, int{bytes_read});
+ // EXPECT_EQ only does a shallow comparison, so it's necessary to
+ // iterate through both objects and compare each character.
+ for (int i = 0; i < buffer_size; i++) {
+ EXPECT_EQ(buf->data()[i], kBuffer[i])
+ << "buffer comparison failed at index " << i;
+ }
+ std::move(success_callback).Run(buffer_size);
+ })));
+
+ EXPECT_CALL(mock_socket(), Close());
+
+ serial_port->StartWriting(std::move(consumer));
+
+ EXPECT_EQ(write_buffer->size(), int{bytes_read});
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, StartReadingTest) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ auto options = mojom::SerialConnectionOptions::New();
+ mojo::PendingRemote<mojom::SerialPortClient> client;
+ FakeSerialPortClient serial_client;
+ serial_client.Bind(client.InitWithNewPipeAndPassReceiver());
+ base::RunLoop loop;
+ serial_port->Open(std::move(options), std::move(client),
+ base::BindLambdaForTesting([&loop](bool success) {
+ EXPECT_TRUE(success);
+ loop.Quit();
+ }));
+ loop.Run();
+
+ uint32_t bytes_read = std::char_traits<char>::length(kBuffer);
+ auto write_buffer = base::MakeRefCounted<net::StringIOBuffer>(kBuffer);
+
+ MojoResult result =
+ producer->WriteData(&kBuffer, &bytes_read, MOJO_WRITE_DATA_FLAG_NONE);
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+
+ EXPECT_CALL(mock_socket(), Receive(_, _, _))
+ .WillOnce(RunOnceCallback<1>(write_buffer->size(), write_buffer))
+ .WillOnce(RunOnceCallback<2>(BluetoothSocket::kSystemError, "Error"));
+ EXPECT_CALL(mock_socket(), Close());
+
+ serial_port->StartReading(std::move(producer));
+
+ ASSERT_EQ(write_buffer->size(), int{bytes_read});
+ int size = write_buffer->size();
+ // EXPECT_EQ only does a shallow comparison, so it's necessary to iterate
+ // through both objects and compare each character.
+ for (int i = 0; i < size; i++) {
+ EXPECT_EQ(write_buffer->data()[i], kBuffer[i])
+ << "buffer comparison failed at index " << i;
+ }
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, Drain) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ auto options = mojom::SerialConnectionOptions::New();
+ mojo::PendingRemote<mojom::SerialPortClient> client;
+ FakeSerialPortClient serial_client;
+ serial_client.Bind(client.InitWithNewPipeAndPassReceiver());
+ base::RunLoop loop;
+ serial_port->Open(std::move(options), std::move(client),
+ base::BindLambdaForTesting([&loop](bool success) {
+ EXPECT_TRUE(success);
+ loop.Quit();
+ }));
+ loop.Run();
+
+ serial_port->StartWriting(std::move(consumer));
+
+ producer.reset();
+
+ base::RunLoop drain_loop;
+ serial_port->Drain(drain_loop.QuitClosure());
+ drain_loop.Run();
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(disconnect_loop.QuitClosure());
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+TEST_F(BluetoothSerialPortImplTest, Close) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer;
+ mojo::ScopedDataPipeConsumerHandle consumer;
+ CreateDataPipe(&producer, &consumer);
+
+ auto options = mojom::SerialConnectionOptions::New();
+ mojo::PendingRemote<mojom::SerialPortClient> client;
+ FakeSerialPortClient serial_client;
+ serial_client.Bind(client.InitWithNewPipeAndPassReceiver());
+ base::RunLoop loop;
+ serial_port->Open(
+ std::move(options), std::move(client),
+ base::BindOnce([](base::RunLoop* loop, bool success) { loop->Quit(); },
+ &loop));
+ loop.Run();
+
+ EXPECT_CALL(mock_socket(), Close());
+
+ base::RunLoop close_loop;
+ serial_port->Close(close_loop.QuitClosure());
+ close_loop.Run();
+
+ base::RunLoop disconnect_loop;
+ watcher->set_connection_error_handler(
+ base::BindLambdaForTesting([&]() { disconnect_loop.Quit(); }));
+
+ serial_port.reset();
+ disconnect_loop.Run();
+}
+
+} // namespace device
diff --git a/chromium/services/device/serial/serial_device_enumerator.cc b/chromium/services/device/serial/serial_device_enumerator.cc
index 057efc7654a..9e0e851b3ca 100644
--- a/chromium/services/device/serial/serial_device_enumerator.cc
+++ b/chromium/services/device/serial/serial_device_enumerator.cc
@@ -9,9 +9,9 @@
#include "base/unguessable_token.h"
#include "build/build_config.h"
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "services/device/serial/serial_device_enumerator_linux.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
#include "services/device/serial/serial_device_enumerator_mac.h"
#elif defined(OS_WIN)
#include "services/device/serial/serial_device_enumerator_win.h"
@@ -22,9 +22,9 @@ namespace device {
// static
std::unique_ptr<SerialDeviceEnumerator> SerialDeviceEnumerator::Create(
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
-#if defined(OS_LINUX)
- return std::make_unique<SerialDeviceEnumeratorLinux>();
-#elif defined(OS_MACOSX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+ return SerialDeviceEnumeratorLinux::Create();
+#elif defined(OS_MAC)
return std::make_unique<SerialDeviceEnumeratorMac>();
#elif defined(OS_WIN)
return std::make_unique<SerialDeviceEnumeratorWin>(std::move(ui_task_runner));
@@ -66,7 +66,7 @@ base::Optional<base::FilePath> SerialDeviceEnumerator::GetPathFromToken(
if (it == ports_.end())
return base::nullopt;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
if (use_alternate_path)
return it->second->alternate_path;
#endif
diff --git a/chromium/services/device/serial/serial_device_enumerator_linux.cc b/chromium/services/device/serial/serial_device_enumerator_linux.cc
index a90aa6afded..e172a70fa56 100644
--- a/chromium/services/device/serial/serial_device_enumerator_linux.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_linux.cc
@@ -33,10 +33,9 @@ struct SerialDriverInfo {
int minor_end; // Inclusive.
};
-std::vector<SerialDriverInfo> ReadSerialDriverInfo() {
+std::vector<SerialDriverInfo> ReadSerialDriverInfo(const base::FilePath& path) {
std::string tty_drivers;
- if (!base::ReadFileToString(base::FilePath("/proc/tty/drivers"),
- &tty_drivers)) {
+ if (!base::ReadFileToString(path, &tty_drivers)) {
return {};
}
@@ -84,12 +83,22 @@ std::vector<SerialDriverInfo> ReadSerialDriverInfo() {
} // namespace
-SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux() {
+// static
+std::unique_ptr<SerialDeviceEnumeratorLinux>
+SerialDeviceEnumeratorLinux::Create() {
+ return std::make_unique<SerialDeviceEnumeratorLinux>(
+ base::FilePath("/proc/tty/drivers"));
+}
+
+SerialDeviceEnumeratorLinux::SerialDeviceEnumeratorLinux(
+ const base::FilePath& tty_driver_info_path)
+ : tty_driver_info_path_(tty_driver_info_path) {
DETACH_FROM_SEQUENCE(sequence_checker_);
watcher_ = UdevWatcher::StartWatching(
this, {UdevWatcher::Filter(kSubsystemTty, "")});
- watcher_->EnumerateExistingDevices();
+ if (watcher_)
+ watcher_->EnumerateExistingDevices();
}
SerialDeviceEnumeratorLinux::~SerialDeviceEnumeratorLinux() {
@@ -121,7 +130,7 @@ void SerialDeviceEnumeratorLinux::OnDeviceAdded(ScopedUdevDevicePtr device) {
return;
}
- for (const auto& driver : ReadSerialDriverInfo()) {
+ for (const auto& driver : ReadSerialDriverInfo(tty_driver_info_path_)) {
if (major == driver.major && minor >= driver.minor_start &&
minor <= driver.minor_end) {
CreatePort(std::move(device), syspath);
@@ -164,7 +173,7 @@ void SerialDeviceEnumeratorLinux::CreatePort(ScopedUdevDevicePtr device,
const char* vendor_id =
udev_device_get_property_value(device.get(), "ID_VENDOR_ID");
const char* product_id =
- udev_device_get_property_value(device.get(), "ID_PRODUCT_ID");
+ udev_device_get_property_value(device.get(), "ID_MODEL_ID");
const char* product_name_enc =
udev_device_get_property_value(device.get(), "ID_MODEL_ENC");
const char* serial_number =
diff --git a/chromium/services/device/serial/serial_device_enumerator_linux.h b/chromium/services/device/serial/serial_device_enumerator_linux.h
index 16ea3816656..17c02843f57 100644
--- a/chromium/services/device/serial/serial_device_enumerator_linux.h
+++ b/chromium/services/device/serial/serial_device_enumerator_linux.h
@@ -19,7 +19,10 @@ namespace device {
class SerialDeviceEnumeratorLinux : public SerialDeviceEnumerator,
public UdevWatcher::Observer {
public:
- SerialDeviceEnumeratorLinux();
+ static std::unique_ptr<SerialDeviceEnumeratorLinux> Create();
+
+ explicit SerialDeviceEnumeratorLinux(
+ const base::FilePath& tty_driver_info_path);
~SerialDeviceEnumeratorLinux() override;
// UdevWatcher::Observer
@@ -31,6 +34,7 @@ class SerialDeviceEnumeratorLinux : public SerialDeviceEnumerator,
void CreatePort(ScopedUdevDevicePtr device, const std::string& syspath);
std::unique_ptr<UdevWatcher> watcher_;
+ const base::FilePath tty_driver_info_path_;
std::map<std::string, base::UnguessableToken> paths_;
DISALLOW_COPY_AND_ASSIGN(SerialDeviceEnumeratorLinux);
diff --git a/chromium/services/device/serial/serial_device_enumerator_linux_unittest.cc b/chromium/services/device/serial/serial_device_enumerator_linux_unittest.cc
new file mode 100644
index 00000000000..94076f12de5
--- /dev/null
+++ b/chromium/services/device/serial/serial_device_enumerator_linux_unittest.cc
@@ -0,0 +1,79 @@
+// 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/device/serial/serial_device_enumerator_linux.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/files/scoped_temp_dir.h"
+#include "base/test/task_environment.h"
+#include "device/udev_linux/fake_udev_loader.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace device {
+
+constexpr char kSerialDriverInfo[] =
+ R"(/dev/tty /dev/tty 5 0 system:/dev/tty
+/dev/console /dev/console 5 1 system:console
+/dev/ptmx /dev/ptmx 5 2 system
+/dev/vc/0 /dev/vc/0 4 0 system:vtmaster
+acm /dev/ttyACM 166 0-255 serial
+ttyAMA /dev/ttyAMA 204 64-77 serial
+ttyprintk /dev/ttyprintk 5 3 console
+max310x /dev/ttyMAX 204 209-224 serial
+serial /dev/ttyS 4 64 serial
+pty_slave /dev/pts 136 0-1048575 pty:slave
+pty_master /dev/ptm 128 0-1048575 pty:master
+pty_slave /dev/ttyp 3 0-255 pty:slave
+pty_master /dev/pty 2 0-255 pty:master
+unknown /dev/tty 4 1-63 console)";
+
+class SerialDeviceEnumeratorLinuxTest : public testing::Test {
+ public:
+ void SetUp() override {
+ ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
+ drivers_file_ = temp_dir_.GetPath().Append("drivers");
+ ASSERT_TRUE(base::WriteFile(drivers_file_, kSerialDriverInfo));
+ }
+
+ std::unique_ptr<SerialDeviceEnumeratorLinux> CreateEnumerator() {
+ return std::make_unique<SerialDeviceEnumeratorLinux>(drivers_file_);
+ }
+
+ private:
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO};
+ base::ScopedTempDir temp_dir_;
+ base::FilePath drivers_file_;
+};
+
+TEST_F(SerialDeviceEnumeratorLinuxTest, Enumerate) {
+ testing::FakeUdevLoader fake_udev;
+ fake_udev.AddFakeDevice(/*name=*/"ttyACM0",
+ /*syspath=*/"/sys/class/tty/ttyACM0",
+ /*subsystem=*/"tty", /*sysattrs=*/{},
+ /*properties=*/
+ {
+ {"DEVNAME", "/dev/ttyACM0"},
+ {"MAJOR", "166"},
+ {"MINOR", "0"},
+ {"ID_VENDOR_ID", "2341"},
+ {"ID_MODEL_ID", "0043"},
+ {"ID_MODEL_ENC", "Arduino\\x20Uno"},
+ {"ID_SERIAL_SHORT", "000001"},
+ });
+
+ std::unique_ptr<SerialDeviceEnumeratorLinux> enumerator = CreateEnumerator();
+ std::vector<mojom::SerialPortInfoPtr> devices = enumerator->GetDevices();
+ ASSERT_EQ(devices.size(), 1u);
+ EXPECT_EQ(devices[0]->persistent_id, "2341-0043-000001");
+ EXPECT_EQ(devices[0]->path, base::FilePath("/dev/ttyACM0"));
+ EXPECT_TRUE(devices[0]->has_vendor_id);
+ EXPECT_EQ(devices[0]->vendor_id, 0x2341);
+ EXPECT_TRUE(devices[0]->has_product_id);
+ EXPECT_EQ(devices[0]->product_id, 0x0043);
+ EXPECT_EQ(devices[0]->display_name, "Arduino Uno");
+}
+
+} // namespace device
diff --git a/chromium/services/device/serial/serial_device_enumerator_win.cc b/chromium/services/device/serial/serial_device_enumerator_win.cc
index 931173b8f55..5adf77753d6 100644
--- a/chromium/services/device/serial/serial_device_enumerator_win.cc
+++ b/chromium/services/device/serial/serial_device_enumerator_win.cc
@@ -54,7 +54,7 @@ base::Optional<std::string> GetProperty(HDEVINFO dev_info,
return base::nullopt;
}
- base::string16 buffer;
+ std::wstring buffer;
if (!SetupDiGetDeviceProperty(
dev_info, dev_info_data, &property, &property_type,
reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
@@ -62,7 +62,7 @@ base::Optional<std::string> GetProperty(HDEVINFO dev_info,
return base::nullopt;
}
- return base::UTF16ToUTF8(buffer);
+ return base::WideToUTF8(buffer);
}
base::FilePath FixUpPortName(base::StringPiece port_name) {
@@ -74,6 +74,17 @@ base::FilePath FixUpPortName(base::StringPiece port_name) {
return base::FilePath::FromUTF8Unsafe(port_name);
}
+// Searches for the COM port in the device's friendly name and returns the
+// appropriate device path or nullopt if the input did not contain a valid
+// name.
+base::Optional<base::FilePath> GetPath(const std::string& friendly_name) {
+ std::string com_port;
+ if (!RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", &com_port))
+ return base::nullopt;
+
+ return FixUpPortName(com_port);
+}
+
// Searches for the display name in the device's friendly name, assigns its
// value to display_name, and returns whether the operation was successful.
bool GetDisplayName(const std::string friendly_name,
@@ -124,7 +135,7 @@ class SerialDeviceEnumeratorWin::UiThreadHelper
}
void OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) override {
+ const std::wstring& device_path) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&SerialDeviceEnumeratorWin::OnPathAdded,
@@ -132,7 +143,7 @@ class SerialDeviceEnumeratorWin::UiThreadHelper
}
void OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) override {
+ const std::wstring& device_path) override {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
task_runner_->PostTask(
FROM_HERE, base::BindOnce(&SerialDeviceEnumeratorWin::OnPathRemoved,
@@ -166,17 +177,7 @@ SerialDeviceEnumeratorWin::SerialDeviceEnumeratorWin(
SerialDeviceEnumeratorWin::~SerialDeviceEnumeratorWin() = default;
-// static
-base::Optional<base::FilePath> SerialDeviceEnumeratorWin::GetPath(
- const std::string& friendly_name) {
- std::string com_port;
- if (!RE2::PartialMatch(friendly_name, ".* \\((COM[0-9]+)\\)", &com_port))
- return base::nullopt;
-
- return FixUpPortName(com_port);
-}
-
-void SerialDeviceEnumeratorWin::OnPathAdded(const base::string16& device_path) {
+void SerialDeviceEnumeratorWin::OnPathAdded(const std::wstring& device_path) {
base::win::ScopedDevInfo dev_info(
SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid())
@@ -195,8 +196,7 @@ void SerialDeviceEnumeratorWin::OnPathAdded(const base::string16& device_path) {
EnumeratePort(dev_info.get(), &dev_info_data);
}
-void SerialDeviceEnumeratorWin::OnPathRemoved(
- const base::string16& device_path) {
+void SerialDeviceEnumeratorWin::OnPathRemoved(const std::wstring& device_path) {
base::win::ScopedDevInfo dev_info(
SetupDiCreateDeviceInfoList(nullptr, nullptr));
if (!dev_info.is_valid())
diff --git a/chromium/services/device/serial/serial_device_enumerator_win.h b/chromium/services/device/serial/serial_device_enumerator_win.h
index 553a73df2a1..a41d9b720ff 100644
--- a/chromium/services/device/serial/serial_device_enumerator_win.h
+++ b/chromium/services/device/serial/serial_device_enumerator_win.h
@@ -23,14 +23,8 @@ class SerialDeviceEnumeratorWin : public SerialDeviceEnumerator {
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
~SerialDeviceEnumeratorWin() override;
- // Searches for the COM port in the device's friendly name and returns the
- // appropriate device path or nullopt if the input did not contain a valid
- // name.
- static base::Optional<base::FilePath> GetPath(
- const std::string& friendly_name);
-
- void OnPathAdded(const base::string16& device_path);
- void OnPathRemoved(const base::string16& device_path);
+ void OnPathAdded(const std::wstring& device_path);
+ void OnPathRemoved(const std::wstring& device_path);
private:
class UiThreadHelper;
diff --git a/chromium/services/device/serial/serial_io_handler.cc b/chromium/services/device/serial/serial_io_handler.cc
index a68b67c5fb3..54e25511625 100644
--- a/chromium/services/device/serial/serial_io_handler.cc
+++ b/chromium/services/device/serial/serial_io_handler.cc
@@ -174,6 +174,8 @@ void SerialIoHandler::Close(base::OnceClosure callback) {
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::BindOnce(&SerialIoHandler::DoClose, std::move(file_)),
std::move(callback));
+ } else {
+ std::move(callback).Run();
}
}
diff --git a/chromium/services/device/serial/serial_io_handler.h b/chromium/services/device/serial/serial_io_handler.h
index b70906f7bca..cd49076f551 100644
--- a/chromium/services/device/serial/serial_io_handler.h
+++ b/chromium/services/device/serial/serial_io_handler.h
@@ -80,7 +80,10 @@ class SerialIoHandler : public base::RefCountedThreadSafe<SerialIoHandler> {
void CancelWrite(mojom::SerialSendError reason);
// Flushes input and output buffers.
- virtual bool Flush() const = 0;
+ virtual void Flush(mojom::SerialPortFlushMode mode) const = 0;
+
+ // Drains output buffers.
+ virtual void Drain() = 0;
// Reads current control signals (DCD, CTS, etc.) into an existing
// DeviceControlSignals structure. Returns |true| iff the signals were
diff --git a/chromium/services/device/serial/serial_io_handler_posix.cc b/chromium/services/device/serial/serial_io_handler_posix.cc
index 7f2a2c421b3..ad3ae505e15 100644
--- a/chromium/services/device/serial/serial_io_handler_posix.cc
+++ b/chromium/services/device/serial/serial_io_handler_posix.cc
@@ -15,7 +15,7 @@
#include "base/posix/eintr_wrapper.h"
#include "build/build_config.h"
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include <asm-generic/ioctls.h>
#include <linux/serial.h>
@@ -34,9 +34,9 @@ struct termios2 {
};
}
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include <IOKit/serial/ioss.h>
#endif
@@ -66,7 +66,7 @@ bool BitrateToSpeedConstant(int bitrate, speed_t* speed) {
BITRATE_TO_SPEED_CASE(9600)
BITRATE_TO_SPEED_CASE(19200)
BITRATE_TO_SPEED_CASE(38400)
-#if !defined(OS_MACOSX)
+#if !defined(OS_MAC)
BITRATE_TO_SPEED_CASE(57600)
BITRATE_TO_SPEED_CASE(115200)
BITRATE_TO_SPEED_CASE(230400)
@@ -80,7 +80,7 @@ bool BitrateToSpeedConstant(int bitrate, speed_t* speed) {
#undef BITRATE_TO_SPEED_CASE
}
-#if !defined(OS_LINUX)
+#if !defined(OS_LINUX) && !defined(OS_CHROMEOS)
// Convert a known nominal speed into an integral bitrate. Returns |true|
// if the conversion was successful and |false| otherwise.
bool SpeedConstantToBitrate(speed_t speed, int* bitrate) {
@@ -164,7 +164,7 @@ void SerialIoHandlerPosix::CancelWriteImpl() {
}
bool SerialIoHandlerPosix::ConfigurePortImpl() {
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
struct termios2 config;
if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) {
#else
@@ -187,11 +187,11 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() {
DCHECK(options().bitrate);
speed_t bitrate_opt = B0;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
bool need_iossiospeed = false;
#endif
if (BitrateToSpeedConstant(options().bitrate, &bitrate_opt)) {
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
config.c_cflag &= ~CBAUD;
config.c_cflag |= bitrate_opt;
#else
@@ -200,11 +200,11 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() {
#endif
} else {
// Attempt to set a custom speed.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
config.c_cflag &= ~CBAUD;
config.c_cflag |= CBAUDEX;
config.c_ispeed = config.c_ospeed = options().bitrate;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
// cfsetispeed and cfsetospeed sometimes work for custom baud rates on OS
// X but the IOSSIOSPEED ioctl is more reliable but has to be done after
// the rest of the port parameters are set or else it will be overwritten.
@@ -272,7 +272,7 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() {
config.c_cflag &= ~CRTSCTS;
}
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
if (ioctl(file().GetPlatformFile(), TCSETS2, &config) < 0) {
#else
if (tcsetattr(file().GetPlatformFile(), TCSANOW, &config) != 0) {
@@ -281,7 +281,7 @@ bool SerialIoHandlerPosix::ConfigurePortImpl() {
return false;
}
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
if (need_iossiospeed) {
speed_t bitrate = options().bitrate;
if (ioctl(file().GetPlatformFile(), IOSSIOSPEED, &bitrate) == -1) {
@@ -317,7 +317,6 @@ SerialIoHandlerPosix::~SerialIoHandlerPosix() = default;
void SerialIoHandlerPosix::AttemptRead(bool within_read) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
if (pending_read_buffer()) {
int bytes_read =
HANDLE_EINTR(read(file().GetPlatformFile(), pending_read_buffer(),
@@ -329,12 +328,15 @@ void SerialIoHandlerPosix::AttemptRead(bool within_read) {
} else if (errno == ENXIO) {
RunReadCompleted(within_read, 0,
mojom::SerialReceiveError::DEVICE_LOST);
+ StopWatchingFileRead();
} else {
+ VPLOG(1) << "Read failed";
RunReadCompleted(within_read, 0,
mojom::SerialReceiveError::SYSTEM_ERROR);
}
} else if (bytes_read == 0) {
RunReadCompleted(within_read, 0, mojom::SerialReceiveError::DEVICE_LOST);
+ StopWatchingFileRead();
} else {
bool break_detected = false;
bool parity_error_detected = false;
@@ -376,13 +378,18 @@ void SerialIoHandlerPosix::RunReadCompleted(bool within_read,
void SerialIoHandlerPosix::OnFileCanWriteWithoutBlocking() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
if (pending_write_buffer()) {
int bytes_written =
HANDLE_EINTR(write(file().GetPlatformFile(), pending_write_buffer(),
pending_write_buffer_len()));
if (bytes_written < 0) {
- WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
+ if (errno == ENXIO) {
+ WriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
+ StopWatchingFileWrite();
+ } else {
+ VPLOG(1) << "Write failed";
+ WriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
+ }
} else {
WriteCompleted(bytes_written, mojom::SerialSendError::NONE);
}
@@ -436,12 +443,27 @@ void SerialIoHandlerPosix::StopWatchingFileWrite() {
}
}
-bool SerialIoHandlerPosix::Flush() const {
- if (tcflush(file().GetPlatformFile(), TCIOFLUSH) != 0) {
- VPLOG(1) << "Failed to flush port";
- return false;
+void SerialIoHandlerPosix::Flush(mojom::SerialPortFlushMode mode) const {
+ int queue_selector;
+ switch (mode) {
+ case mojom::SerialPortFlushMode::kReceiveAndTransmit:
+ queue_selector = TCIOFLUSH;
+ break;
+ case mojom::SerialPortFlushMode::kReceive:
+ queue_selector = TCIFLUSH;
+ break;
+ case mojom::SerialPortFlushMode::kTransmit:
+ queue_selector = TCOFLUSH;
+ break;
}
- return true;
+
+ if (tcflush(file().GetPlatformFile(), queue_selector) != 0)
+ VPLOG(1) << "Failed to flush port";
+}
+
+void SerialIoHandlerPosix::Drain() {
+ if (tcdrain(file().GetPlatformFile()) != 0)
+ VPLOG(1) << "Failed to drain port";
}
mojom::SerialPortControlSignalsPtr SerialIoHandlerPosix::GetControlSignals()
@@ -510,7 +532,7 @@ bool SerialIoHandlerPosix::SetControlSignals(
}
mojom::SerialConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const {
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
struct termios2 config;
if (ioctl(file().GetPlatformFile(), TCGETS2, &config) < 0) {
#else
@@ -522,7 +544,7 @@ mojom::SerialConnectionInfoPtr SerialIoHandlerPosix::GetPortInfo() const {
}
auto info = mojom::SerialConnectionInfo::New();
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// Linux forces c_ospeed to contain the correct value, which is nice.
info->bitrate = config.c_ospeed;
#else
diff --git a/chromium/services/device/serial/serial_io_handler_posix.h b/chromium/services/device/serial/serial_io_handler_posix.h
index 3d69c6d04c4..51311d6abce 100644
--- a/chromium/services/device/serial/serial_io_handler_posix.h
+++ b/chromium/services/device/serial/serial_io_handler_posix.h
@@ -31,7 +31,8 @@ class SerialIoHandlerPosix : public SerialIoHandler {
bool ConfigurePortImpl() override;
bool PostOpen() override;
void PreClose() override;
- bool Flush() const override;
+ void Flush(mojom::SerialPortFlushMode mode) const override;
+ void Drain() override;
mojom::SerialPortControlSignalsPtr GetControlSignals() const override;
bool SetControlSignals(
const mojom::SerialHostControlSignals& control_signals) override;
diff --git a/chromium/services/device/serial/serial_io_handler_win.cc b/chromium/services/device/serial/serial_io_handler_win.cc
index 12d91e68ea9..ca90b1caed1 100644
--- a/chromium/services/device/serial/serial_io_handler_win.cc
+++ b/chromium/services/device/serial/serial_io_handler_win.cc
@@ -4,21 +4,13 @@
#include "services/device/serial/serial_io_handler_win.h"
-#define INITGUID
-#include <devpkey.h>
-#include <setupapi.h>
#include <windows.h>
#include <utility>
#include "base/bind.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/scoped_observer.h"
#include "base/sequence_checker.h"
-#include "device/base/device_info_query_win.h"
-#include "device/base/device_monitor_win.h"
-#include "services/device/serial/serial_device_enumerator_win.h"
+#include "base/task/current_thread.h"
namespace device {
@@ -153,108 +145,18 @@ scoped_refptr<SerialIoHandler> SerialIoHandler::Create(
return new SerialIoHandlerWin(port, std::move(ui_thread_task_runner));
}
-class SerialIoHandlerWin::UiThreadHelper final
- : public DeviceMonitorWin::Observer {
- public:
- UiThreadHelper(
- base::WeakPtr<SerialIoHandlerWin> io_handler,
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner)
- : device_observer_(this),
- io_handler_(io_handler),
- io_thread_task_runner_(io_thread_task_runner) {}
-
- ~UiThreadHelper() { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }
-
- static void Start(UiThreadHelper* self) {
- DETACH_FROM_THREAD(self->thread_checker_);
- DeviceMonitorWin* device_monitor = DeviceMonitorWin::GetForAllInterfaces();
- if (device_monitor)
- self->device_observer_.Add(device_monitor);
- }
-
- private:
- // DeviceMonitorWin::Observer
- void OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) override {
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- io_thread_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&SerialIoHandlerWin::OnDeviceRemoved,
- io_handler_, device_path));
- }
-
- THREAD_CHECKER(thread_checker_);
- ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_;
-
- // This weak pointer is only valid when checked on this task runner.
- base::WeakPtr<SerialIoHandlerWin> io_handler_;
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_;
-
- DISALLOW_COPY_AND_ASSIGN(UiThreadHelper);
-};
-
-void SerialIoHandlerWin::OnDeviceRemoved(const base::string16& device_path) {
- DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
-
- DeviceInfoQueryWin device_info_query;
- if (!device_info_query.device_info_list_valid()) {
- DVPLOG(1) << "Failed to create a device information set";
- return;
- }
-
- // This will add the device so we can query driver info.
- if (!device_info_query.AddDevice(device_path)) {
- DVPLOG(1) << "Failed to get device interface data for " << device_path;
- return;
- }
-
- if (!device_info_query.GetDeviceInfo()) {
- DVPLOG(1) << "Failed to get device info for " << device_path;
- return;
- }
-
- std::string friendly_name;
- if (!device_info_query.GetDeviceStringProperty(DEVPKEY_Device_FriendlyName,
- &friendly_name)) {
- DVPLOG(1) << "Failed to get device service property";
- return;
- }
-
- base::Optional<base::FilePath> path =
- SerialDeviceEnumeratorWin::GetPath(friendly_name);
- if (!path) {
- DVPLOG(1) << "Failed to get device path from \"" << friendly_name << "\".";
- return;
- }
-
- if (port() == *path)
- CancelRead(mojom::SerialReceiveError::DEVICE_LOST);
-}
-
bool SerialIoHandlerWin::PostOpen() {
- DCHECK(!comm_context_);
DCHECK(!read_context_);
DCHECK(!write_context_);
- base::MessageLoopCurrentForIO::Get()->RegisterIOHandler(
- file().GetPlatformFile(), this);
+ base::CurrentIOThread::Get()->RegisterIOHandler(file().GetPlatformFile(),
+ this);
- comm_context_.reset(new base::MessagePumpForIO::IOContext());
read_context_.reset(new base::MessagePumpForIO::IOContext());
write_context_.reset(new base::MessagePumpForIO::IOContext());
- scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner =
- base::ThreadTaskRunnerHandle::Get();
- helper_ =
- new UiThreadHelper(weak_factory_.GetWeakPtr(), io_thread_task_runner);
- ui_thread_task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&UiThreadHelper::Start, helper_));
-
- // A ReadIntervalTimeout of MAXDWORD will cause async reads to complete
- // immediately with any data that's available, even if there is none.
- // This is OK because we never issue a read request until WaitCommEvent
- // signals that data is available.
COMMTIMEOUTS timeouts = {0};
- timeouts.ReadIntervalTimeout = MAXDWORD;
+ timeouts.ReadIntervalTimeout = 1;
if (!::SetCommTimeouts(file().GetPlatformFile(), &timeouts)) {
VPLOG(1) << "Failed to set serial timeouts";
return false;
@@ -272,18 +174,16 @@ void SerialIoHandlerWin::ReadImpl() {
return;
}
- if (!SetCommMask(file().GetPlatformFile(), EV_RXCHAR)) {
- VPLOG(1) << "Failed to set serial event flags";
- }
+ ClearPendingError();
+ if (!IsReadPending())
+ return;
- event_mask_ = 0;
- BOOL ok = ::WaitCommEvent(file().GetPlatformFile(), &event_mask_,
- &comm_context_->overlapped);
- if (!ok && GetLastError() != ERROR_IO_PENDING) {
- VPLOG(1) << "Failed to receive serial event";
- QueueReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
+ if (!ReadFile(file().GetPlatformFile(), pending_read_buffer(),
+ pending_read_buffer_len(), nullptr,
+ &read_context_->overlapped) &&
+ GetLastError() != ERROR_IO_PENDING) {
+ OnIOCompleted(read_context_.get(), 0, GetLastError());
}
- is_comm_pending_ = true;
}
void SerialIoHandlerWin::WriteImpl() {
@@ -295,25 +195,27 @@ void SerialIoHandlerWin::WriteImpl() {
return;
}
- BOOL ok = ::WriteFile(file().GetPlatformFile(), pending_write_buffer(),
- pending_write_buffer_len(), NULL,
- &write_context_->overlapped);
- if (!ok && GetLastError() != ERROR_IO_PENDING) {
- VPLOG(1) << "Write failed";
- QueueWriteCompleted(0, mojom::SerialSendError::SYSTEM_ERROR);
+ if (!WriteFile(file().GetPlatformFile(), pending_write_buffer(),
+ pending_write_buffer_len(), nullptr,
+ &write_context_->overlapped) &&
+ GetLastError() != ERROR_IO_PENDING) {
+ OnIOCompleted(write_context_.get(), 0, GetLastError());
}
}
void SerialIoHandlerWin::CancelReadImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(file().IsValid());
- ::CancelIo(file().GetPlatformFile());
+
+ if (!PurgeComm(file().GetPlatformFile(), PURGE_RXABORT))
+ VPLOG(1) << "RX abort failed";
}
void SerialIoHandlerWin::CancelWriteImpl() {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
DCHECK(file().IsValid());
- ::CancelIo(file().GetPlatformFile());
+ if (!PurgeComm(file().GetPlatformFile(), PURGE_TXABORT))
+ VPLOG(1) << "TX abort failed";
}
bool SerialIoHandlerWin::ConfigurePortImpl() {
@@ -368,61 +270,21 @@ SerialIoHandlerWin::SerialIoHandlerWin(
: SerialIoHandler(port, std::move(ui_thread_task_runner)),
base::MessagePumpForIO::IOHandler(FROM_HERE) {}
-SerialIoHandlerWin::~SerialIoHandlerWin() {
- ui_thread_task_runner()->DeleteSoon(FROM_HERE, helper_);
-}
+SerialIoHandlerWin::~SerialIoHandlerWin() = default;
void SerialIoHandlerWin::OnIOCompleted(
base::MessagePumpForIO::IOContext* context,
DWORD bytes_transferred,
DWORD error) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (context == comm_context_.get()) {
- DWORD errors;
- 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) {
- ReadCompleted(0, mojom::SerialReceiveError::FRAME_ERROR);
- } else if (errors & CE_OVERRUN) {
- ReadCompleted(0, mojom::SerialReceiveError::OVERRUN);
- } else if (errors & CE_RXOVER) {
- ReadCompleted(0, mojom::SerialReceiveError::BUFFER_OVERFLOW);
- } else if (errors & CE_RXPARITY) {
- ReadCompleted(0, mojom::SerialReceiveError::PARITY_ERROR);
- } else {
- NOTIMPLEMENTED() << "Unexpected communication error: " << std::hex
- << errors;
- }
- return;
- }
-
- 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(),
- pending_read_buffer_len(), NULL,
- &read_context_->overlapped);
- if (!ok && GetLastError() != ERROR_IO_PENDING) {
- VPLOG(1) << "Read failed";
- ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
- }
- }
- } else if (context == read_context_.get()) {
+ if (context == read_context_.get()) {
if (read_canceled()) {
ReadCompleted(bytes_transferred, read_cancel_reason());
} else if (error == ERROR_SUCCESS || error == ERROR_OPERATION_ABORTED) {
ReadCompleted(bytes_transferred, mojom::SerialReceiveError::NONE);
+ } else if (error == ERROR_ACCESS_DENIED || error == ERROR_BAD_COMMAND ||
+ error == ERROR_DEVICE_REMOVED) {
+ ReadCompleted(0, mojom::SerialReceiveError::DEVICE_LOST);
} else {
VLOG(1) << "Read failed: " << logging::SystemErrorCodeToString(error);
ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
@@ -433,15 +295,17 @@ void SerialIoHandlerWin::OnIOCompleted(
WriteCompleted(0, write_cancel_reason());
} else if (error == ERROR_SUCCESS || error == ERROR_OPERATION_ABORTED) {
WriteCompleted(bytes_transferred, mojom::SerialSendError::NONE);
+ } else if (error == ERROR_GEN_FAILURE) {
+ WriteCompleted(0, mojom::SerialSendError::DISCONNECTED);
} 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
- // disconnected, the context is comm_context_ and the error is
+ // disconnected, the context is |read_context_| and the error is
// ERROR_OPERATION_ABORTED.
// However, for devices using CDC-ACM driver, when device is
- // disconnected, the context is write_context_ and the error is
+ // disconnected, the context is |write_context_| and the error is
// ERROR_GEN_FAILURE. In this situation, in addition to a write error
// signal, also need to generate a read error signal
// mojom::SerialOnReceiveError which will notify the app about the
@@ -454,12 +318,51 @@ void SerialIoHandlerWin::OnIOCompleted(
}
}
-bool SerialIoHandlerWin::Flush() const {
- if (!PurgeComm(file().GetPlatformFile(), PURGE_RXCLEAR | PURGE_TXCLEAR)) {
- VPLOG(1) << "Failed to flush serial port";
- return false;
+void SerialIoHandlerWin::ClearPendingError() {
+ DWORD errors;
+ if (!ClearCommError(file().GetPlatformFile(), &errors, nullptr)) {
+ VPLOG(1) << "Failed to clear communication error";
+ return;
}
- return true;
+
+ if (errors & CE_BREAK) {
+ ReadCompleted(0, mojom::SerialReceiveError::BREAK);
+ } else if (errors & CE_FRAME) {
+ ReadCompleted(0, mojom::SerialReceiveError::FRAME_ERROR);
+ } else if (errors & CE_OVERRUN) {
+ ReadCompleted(0, mojom::SerialReceiveError::OVERRUN);
+ } else if (errors & CE_RXOVER) {
+ ReadCompleted(0, mojom::SerialReceiveError::BUFFER_OVERFLOW);
+ } else if (errors & CE_RXPARITY) {
+ ReadCompleted(0, mojom::SerialReceiveError::PARITY_ERROR);
+ } else if (errors != 0) {
+ NOTIMPLEMENTED() << "Unexpected communication error: " << std::hex
+ << errors;
+ ReadCompleted(0, mojom::SerialReceiveError::SYSTEM_ERROR);
+ }
+}
+
+void SerialIoHandlerWin::Flush(mojom::SerialPortFlushMode mode) const {
+ DWORD flags;
+ switch (mode) {
+ case mojom::SerialPortFlushMode::kReceiveAndTransmit:
+ flags = PURGE_RXCLEAR | PURGE_TXCLEAR;
+ break;
+ case mojom::SerialPortFlushMode::kReceive:
+ flags = PURGE_RXCLEAR;
+ break;
+ case mojom::SerialPortFlushMode::kTransmit:
+ flags = PURGE_TXCLEAR;
+ break;
+ }
+
+ if (!PurgeComm(file().GetPlatformFile(), flags))
+ VPLOG(1) << "Failed to flush serial port";
+}
+
+void SerialIoHandlerWin::Drain() {
+ if (!FlushFileBuffers(file().GetPlatformFile()))
+ VPLOG(1) << "Failed to drain serial port";
}
mojom::SerialPortControlSignalsPtr SerialIoHandlerWin::GetControlSignals()
diff --git a/chromium/services/device/serial/serial_io_handler_win.h b/chromium/services/device/serial/serial_io_handler_win.h
index 9c25e8bfc18..151e127ac99 100644
--- a/chromium/services/device/serial/serial_io_handler_win.h
+++ b/chromium/services/device/serial/serial_io_handler_win.h
@@ -26,7 +26,8 @@ class SerialIoHandlerWin : public SerialIoHandler,
void CancelReadImpl() override;
void CancelWriteImpl() override;
bool ConfigurePortImpl() override;
- bool Flush() const override;
+ void Flush(mojom::SerialPortFlushMode mode) const override;
+ void Drain() override;
mojom::SerialPortControlSignalsPtr GetControlSignals() const override;
bool SetControlSignals(
const mojom::SerialHostControlSignals& control_signals) override;
@@ -47,10 +48,8 @@ class SerialIoHandlerWin : public SerialIoHandler,
DWORD bytes_transfered,
DWORD error) override;
- void OnDeviceRemoved(const base::string16& device_path);
-
- // Context used for asynchronous WaitCommEvent calls.
- std::unique_ptr<base::MessagePumpForIO::IOContext> comm_context_;
+ void ClearPendingError();
+ void OnDeviceRemoved(const std::wstring& device_path);
// Context used for overlapped reads.
std::unique_ptr<base::MessagePumpForIO::IOContext> read_context_;
@@ -58,14 +57,6 @@ class SerialIoHandlerWin : public SerialIoHandler,
// Context used for overlapped writes.
std::unique_ptr<base::MessagePumpForIO::IOContext> write_context_;
- // Asynchronous event mask state
- DWORD event_mask_ = 0;
-
- // Indicates if a pending read is waiting on initial data arrival via
- // WaitCommEvent, as opposed to waiting on actual ReadFile completion
- // after a corresponding WaitCommEvent has completed.
- bool is_comm_pending_ = false;
-
// The helper lives on the UI thread and holds a weak reference back to the
// handler that owns it.
UiThreadHelper* helper_ = nullptr;
diff --git a/chromium/services/device/serial/serial_port_impl.cc b/chromium/services/device/serial/serial_port_impl.cc
index efef354e9d4..01058c91808 100644
--- a/chromium/services/device/serial/serial_port_impl.cc
+++ b/chromium/services/device/serial/serial_port_impl.cc
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/device/serial/buffer.h"
#include "services/device/serial/serial_io_handler.h"
@@ -23,17 +22,27 @@ void SerialPortImpl::Create(
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner) {
// This SerialPortImpl is owned by |receiver| and |watcher|.
- new SerialPortImpl(path, std::move(receiver), std::move(watcher),
- std::move(ui_task_runner));
+ new SerialPortImpl(
+ device::SerialIoHandler::Create(path, std::move(ui_task_runner)),
+ std::move(receiver), std::move(watcher));
+}
+
+// static
+void SerialPortImpl::CreateForTesting(
+ scoped_refptr<SerialIoHandler> io_handler,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher) {
+ // This SerialPortImpl is owned by |receiver| and |watcher|.
+ new SerialPortImpl(std::move(io_handler), std::move(receiver),
+ std::move(watcher));
}
SerialPortImpl::SerialPortImpl(
- const base::FilePath& path,
+ scoped_refptr<SerialIoHandler> io_handler,
mojo::PendingReceiver<mojom::SerialPort> receiver,
- mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner)
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher)
: receiver_(this, std::move(receiver)),
- io_handler_(device::SerialIoHandler::Create(path, ui_task_runner)),
+ io_handler_(std::move(io_handler)),
watcher_(std::move(watcher)),
in_stream_watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL),
out_stream_watcher_(FROM_HERE,
@@ -94,8 +103,62 @@ void SerialPortImpl::StartReading(mojo::ScopedDataPipeProducerHandle producer) {
out_stream_watcher_.ArmOrNotify();
}
-void SerialPortImpl::Flush(FlushCallback callback) {
- std::move(callback).Run(io_handler_->Flush());
+void SerialPortImpl::Flush(mojom::SerialPortFlushMode mode,
+ FlushCallback callback) {
+ switch (mode) {
+ case mojom::SerialPortFlushMode::kReceiveAndTransmit:
+ // Do nothing. This case exists to support the chrome.serial.flush()
+ // method.
+ break;
+ case mojom::SerialPortFlushMode::kReceive:
+ io_handler_->CancelRead(mojom::SerialReceiveError::NONE);
+ break;
+ case mojom::SerialPortFlushMode::kTransmit:
+ io_handler_->CancelWrite(mojom::SerialSendError::NONE);
+ break;
+ }
+
+ io_handler_->Flush(mode);
+
+ switch (mode) {
+ case mojom::SerialPortFlushMode::kReceiveAndTransmit:
+ // Do nothing. This case exists to support the chrome.serial.flush()
+ // method.
+ break;
+ case mojom::SerialPortFlushMode::kReceive:
+ if (io_handler_->IsReadPending()) {
+ // Delay closing |out_stream_| because |io_handler_| still holds a
+ // pointer into the shared memory owned by the pipe.
+ read_flush_callback_ = std::move(callback);
+ return;
+ }
+
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ break;
+ case mojom::SerialPortFlushMode::kTransmit:
+ if (io_handler_->IsWritePending()) {
+ // Delay closing |in_stream_| because |io_handler_| still holds a
+ // pointer into the shared memory owned by the pipe.
+ write_flush_callback_ = std::move(callback);
+ return;
+ }
+
+ in_stream_watcher_.Cancel();
+ in_stream_.reset();
+ break;
+ }
+
+ std::move(callback).Run();
+}
+
+void SerialPortImpl::Drain(DrainCallback callback) {
+ if (!in_stream_) {
+ std::move(callback).Run();
+ return;
+ }
+
+ drain_callback_ = std::move(callback);
}
void SerialPortImpl::GetControlSignals(GetControlSignalsCallback callback) {
@@ -150,6 +213,11 @@ void SerialPortImpl::WriteToPort(MojoResult result,
// The |in_stream_| has been closed.
in_stream_watcher_.Cancel();
in_stream_.reset();
+
+ if (drain_callback_) {
+ io_handler_->Drain();
+ std::move(drain_callback_).Run();
+ }
return;
}
// The code should not reach other cases.
@@ -204,7 +272,7 @@ void SerialPortImpl::ReadFromPortAndWriteOut(
return;
}
// The code should not reach other cases.
- NOTREACHED();
+ NOTREACHED() << "Unexpected Mojo result: " << result;
}
void SerialPortImpl::WriteToOutStream(uint32_t bytes_read,
@@ -215,11 +283,20 @@ void SerialPortImpl::WriteToOutStream(uint32_t bytes_read,
if (error != mojom::SerialReceiveError::NONE) {
out_stream_watcher_.Cancel();
out_stream_.reset();
- if (client_) {
+ if (client_)
client_->OnReadError(error);
- }
+ if (read_flush_callback_)
+ std::move(read_flush_callback_).Run();
return;
}
+
+ if (read_flush_callback_) {
+ std::move(read_flush_callback_).Run();
+ out_stream_watcher_.Cancel();
+ out_stream_.reset();
+ return;
+ }
+
out_stream_watcher_.ArmOrNotify();
}
diff --git a/chromium/services/device/serial/serial_port_impl.h b/chromium/services/device/serial/serial_port_impl.h
index 2ba5d31d45c..1757a553316 100644
--- a/chromium/services/device/serial/serial_port_impl.h
+++ b/chromium/services/device/serial/serial_port_impl.h
@@ -39,12 +39,16 @@ class SerialPortImpl : public mojom::SerialPort {
mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+ static void CreateForTesting(
+ scoped_refptr<SerialIoHandler> io_handler,
+ mojo::PendingReceiver<mojom::SerialPort> receiver,
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher);
+
private:
SerialPortImpl(
- const base::FilePath& path,
+ scoped_refptr<SerialIoHandler> io_handler,
mojo::PendingReceiver<mojom::SerialPort> receiver,
- mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher,
- scoped_refptr<base::SingleThreadTaskRunner> ui_task_runner);
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher);
~SerialPortImpl() override;
// mojom::SerialPort methods:
@@ -53,7 +57,8 @@ class SerialPortImpl : public mojom::SerialPort {
OpenCallback callback) override;
void StartWriting(mojo::ScopedDataPipeConsumerHandle consumer) override;
void StartReading(mojo::ScopedDataPipeProducerHandle producer) override;
- void Flush(FlushCallback callback) override;
+ void Flush(mojom::SerialPortFlushMode mode, FlushCallback callback) override;
+ void Drain(DrainCallback callback) override;
void GetControlSignals(GetControlSignalsCallback callback) override;
void SetControlSignals(mojom::SerialHostControlSignalsPtr signals,
SetControlSignalsCallback callback) override;
@@ -85,6 +90,12 @@ class SerialPortImpl : public mojom::SerialPort {
mojo::ScopedDataPipeProducerHandle out_stream_;
mojo::SimpleWatcher out_stream_watcher_;
+ // Holds the callback for a flush or drain until pending operations have been
+ // completed.
+ FlushCallback read_flush_callback_;
+ FlushCallback write_flush_callback_;
+ DrainCallback drain_callback_;
+
base::WeakPtrFactory<SerialPortImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(SerialPortImpl);
};
diff --git a/chromium/services/device/serial/serial_port_impl_unittest.cc b/chromium/services/device/serial/serial_port_impl_unittest.cc
index 93c7f0aa317..fdd037496a9 100644
--- a/chromium/services/device/serial/serial_port_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_impl_unittest.cc
@@ -4,23 +4,86 @@
#include "services/device/serial/serial_port_impl.h"
-#include "base/macros.h"
+#include "base/stl_util.h"
+#include "base/test/bind_test_util.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
+#include "mojo/public/cpp/system/data_pipe.h"
+#include "mojo/public/cpp/system/simple_watcher.h"
#include "services/device/device_service_test_base.h"
#include "services/device/public/mojom/serial.mojom.h"
+#include "services/device/serial/serial_io_handler.h"
namespace device {
namespace {
+class FakeSerialIoHandler : public SerialIoHandler {
+ public:
+ FakeSerialIoHandler()
+ : SerialIoHandler(base::FilePath(), /*ui_thread_task_runner=*/nullptr) {}
+
+ void Open(const mojom::SerialConnectionOptions& options,
+ OpenCompleteCallback callback) override {
+ std::move(callback).Run(true);
+ }
+
+ void Flush(mojom::SerialPortFlushMode mode) const override {}
+ void Drain() override {}
+
+ mojom::SerialPortControlSignalsPtr GetControlSignals() const override {
+ return mojom::SerialPortControlSignals::New();
+ }
+
+ bool SetControlSignals(
+ const mojom::SerialHostControlSignals& control_signals) override {
+ return true;
+ }
+
+ mojom::SerialConnectionInfoPtr GetPortInfo() const override {
+ return mojom::SerialConnectionInfo::New();
+ }
+
+ void ReadImpl() override {}
+
+ void WriteImpl() override {}
+
+ void CancelReadImpl() override {
+ QueueReadCompleted(/*bytes_read=*/0, mojom::SerialReceiveError::NONE);
+ }
+
+ void CancelWriteImpl() override {
+ QueueWriteCompleted(/*bytes_written=*/0, mojom::SerialSendError::NONE);
+ }
+
+ bool ConfigurePortImpl() override { return true; }
+
+ private:
+ ~FakeSerialIoHandler() override = default;
+};
+
+} // namespace
+
class SerialPortImplTest : public DeviceServiceTestBase {
public:
SerialPortImplTest() = default;
+ SerialPortImplTest(const SerialPortImplTest& other) = delete;
+ void operator=(const SerialPortImplTest& other) = delete;
~SerialPortImplTest() override = default;
- protected:
+ void CreatePort(
+ mojo::Remote<mojom::SerialPort>* port,
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher>* watcher) {
+ mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher_remote;
+ *watcher = mojo::MakeSelfOwnedReceiver(
+ std::make_unique<mojom::SerialPortConnectionWatcher>(),
+ watcher_remote.InitWithNewPipeAndPassReceiver());
+ SerialPortImpl::CreateForTesting(
+ base::MakeRefCounted<FakeSerialIoHandler>(),
+ port->BindNewPipeAndPassReceiver(), std::move(watcher_remote));
+ }
+
void CreateDataPipe(mojo::ScopedDataPipeProducerHandle* producer,
mojo::ScopedDataPipeConsumerHandle* consumer) {
MojoCreateDataPipeOptions options;
@@ -50,8 +113,6 @@ class SerialPortImplTest : public DeviceServiceTestBase {
serial_port->StartWriting(std::move(consumer));
return producer;
}
-
- DISALLOW_COPY_AND_ASSIGN(SerialPortImplTest);
};
TEST_F(SerialPortImplTest, StartIoBeforeOpen) {
@@ -82,52 +143,121 @@ TEST_F(SerialPortImplTest, StartIoBeforeOpen) {
TEST_F(SerialPortImplTest, WatcherClosedWhenPortClosed) {
mojo::Remote<mojom::SerialPort> serial_port;
- mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher;
- auto watcher_receiver = mojo::MakeSelfOwnedReceiver(
- std::make_unique<mojom::SerialPortConnectionWatcher>(),
- watcher.InitWithNewPipeAndPassReceiver());
- SerialPortImpl::Create(
- base::FilePath(), serial_port.BindNewPipeAndPassReceiver(),
- std::move(watcher), base::ThreadTaskRunnerHandle::Get());
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
// To start with both the serial port connection and the connection watcher
// connection should remain open.
serial_port.FlushForTesting();
EXPECT_TRUE(serial_port.is_connected());
- watcher_receiver->FlushForTesting();
- EXPECT_TRUE(watcher_receiver);
+ watcher->FlushForTesting();
+ EXPECT_TRUE(watcher);
// When the serial port connection is closed the watcher connection should be
// closed.
serial_port.reset();
- watcher_receiver->FlushForTesting();
- EXPECT_FALSE(watcher_receiver);
+ watcher->FlushForTesting();
+ EXPECT_FALSE(watcher);
}
TEST_F(SerialPortImplTest, PortClosedWhenWatcherClosed) {
mojo::Remote<mojom::SerialPort> serial_port;
- mojo::PendingRemote<mojom::SerialPortConnectionWatcher> watcher;
- auto watcher_receiver = mojo::MakeSelfOwnedReceiver(
- std::make_unique<mojom::SerialPortConnectionWatcher>(),
- watcher.InitWithNewPipeAndPassReceiver());
- SerialPortImpl::Create(
- base::FilePath(), serial_port.BindNewPipeAndPassReceiver(),
- std::move(watcher), base::ThreadTaskRunnerHandle::Get());
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
// To start with both the serial port connection and the connection watcher
// connection should remain open.
serial_port.FlushForTesting();
EXPECT_TRUE(serial_port.is_connected());
- watcher_receiver->FlushForTesting();
- EXPECT_TRUE(watcher_receiver);
+ watcher->FlushForTesting();
+ EXPECT_TRUE(watcher);
// When the watcher connection is closed, for safety, the serial port
// connection should also be closed.
- watcher_receiver->Close();
+ watcher->Close();
serial_port.FlushForTesting();
EXPECT_FALSE(serial_port.is_connected());
}
-} // namespace
+TEST_F(SerialPortImplTest, FlushRead) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeConsumerHandle consumer = StartReading(serial_port.get());
+
+ // Calling Flush(kReceive) should cause the data pipe to close.
+ base::RunLoop watcher_loop;
+ mojo::SimpleWatcher pipe_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ EXPECT_EQ(pipe_watcher.Watch(consumer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindLambdaForTesting(
+ [&](MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_TRUE(state.peer_closed());
+ watcher_loop.Quit();
+ })),
+ MOJO_RESULT_OK);
+
+ base::RunLoop loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kReceive, loop.QuitClosure());
+ loop.Run();
+ watcher_loop.Run();
+}
+
+TEST_F(SerialPortImplTest, FlushWrite) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer = StartWriting(serial_port.get());
+
+ // Calling Flush(kTransmit) should cause the data pipe to close.
+ base::RunLoop watcher_loop;
+ mojo::SimpleWatcher pipe_watcher(
+ FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC);
+ EXPECT_EQ(pipe_watcher.Watch(producer.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
+ MOJO_TRIGGER_CONDITION_SIGNALS_SATISFIED,
+ base::BindLambdaForTesting(
+ [&](MojoResult result,
+ const mojo::HandleSignalsState& state) {
+ EXPECT_EQ(result, MOJO_RESULT_OK);
+ EXPECT_TRUE(state.peer_closed());
+ watcher_loop.Quit();
+ })),
+ MOJO_RESULT_OK);
+
+ base::RunLoop loop;
+ serial_port->Flush(mojom::SerialPortFlushMode::kTransmit, loop.QuitClosure());
+ loop.Run();
+ watcher_loop.Run();
+}
+
+TEST_F(SerialPortImplTest, Drain) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ mojo::ScopedDataPipeProducerHandle producer = StartWriting(serial_port.get());
+
+ // Drain() will wait for the data pipe to close before replying.
+ producer.reset();
+
+ base::RunLoop loop;
+ serial_port->Drain(loop.QuitClosure());
+ loop.Run();
+}
+
+TEST_F(SerialPortImplTest, Close) {
+ mojo::Remote<mojom::SerialPort> serial_port;
+ mojo::SelfOwnedReceiverRef<mojom::SerialPortConnectionWatcher> watcher;
+ CreatePort(&serial_port, &watcher);
+
+ base::RunLoop loop;
+ serial_port->Close(loop.QuitClosure());
+ loop.Run();
+}
} // namespace device
diff --git a/chromium/services/device/serial/serial_port_manager_impl.cc b/chromium/services/device/serial/serial_port_manager_impl.cc
index b893f4e2e2a..bdfecb35f78 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl.cc
@@ -6,10 +6,14 @@
#include <string>
#include <utility>
+#include <vector>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/sequenced_task_runner.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "services/device/public/cpp/serial/serial_switches.h"
+#include "services/device/serial/bluetooth_serial_device_enumerator.h"
#include "services/device/serial/serial_device_enumerator.h"
#include "services/device/serial/serial_port_impl.h"
@@ -35,6 +39,14 @@ void SerialPortManagerImpl::SetSerialEnumeratorForTesting(
observed_enumerator_.Add(enumerator_.get());
}
+void SerialPortManagerImpl::SetBluetoothSerialEnumeratorForTesting(
+ std::unique_ptr<BluetoothSerialDeviceEnumerator>
+ fake_bluetooth_enumerator) {
+ DCHECK(fake_bluetooth_enumerator);
+ bluetooth_enumerator_ = std::move(fake_bluetooth_enumerator);
+ observed_enumerator_.Add(bluetooth_enumerator_.get());
+}
+
void SerialPortManagerImpl::SetClient(
mojo::PendingRemote<mojom::SerialPortManagerClient> client) {
clients_.Add(std::move(client));
@@ -45,7 +57,21 @@ void SerialPortManagerImpl::GetDevices(GetDevicesCallback callback) {
enumerator_ = SerialDeviceEnumerator::Create(ui_task_runner_);
observed_enumerator_.Add(enumerator_.get());
}
- std::move(callback).Run(enumerator_->GetDevices());
+ auto devices = enumerator_->GetDevices();
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi)) {
+ if (!bluetooth_enumerator_) {
+ bluetooth_enumerator_ =
+ std::make_unique<BluetoothSerialDeviceEnumerator>();
+ observed_enumerator_.Add(bluetooth_enumerator_.get());
+ }
+ auto bluetooth_devices = bluetooth_enumerator_->GetDevices();
+ devices.insert(devices.end(),
+ std::make_move_iterator(bluetooth_devices.begin()),
+ std::make_move_iterator(bluetooth_devices.end()));
+ }
+
+ std::move(callback).Run(std::move(devices));
}
void SerialPortManagerImpl::GetPort(
diff --git a/chromium/services/device/serial/serial_port_manager_impl.h b/chromium/services/device/serial/serial_port_manager_impl.h
index 546e9a25fcb..7e918711fbf 100644
--- a/chromium/services/device/serial/serial_port_manager_impl.h
+++ b/chromium/services/device/serial/serial_port_manager_impl.h
@@ -15,6 +15,7 @@
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote_set.h"
#include "services/device/public/mojom/serial.mojom.h"
+#include "services/device/serial/bluetooth_serial_device_enumerator.h"
#include "services/device/serial/serial_device_enumerator.h"
namespace base {
@@ -38,6 +39,9 @@ class SerialPortManagerImpl : public mojom::SerialPortManager,
void Bind(mojo::PendingReceiver<mojom::SerialPortManager> receiver);
void SetSerialEnumeratorForTesting(
std::unique_ptr<SerialDeviceEnumerator> fake_enumerator);
+ void SetBluetoothSerialEnumeratorForTesting(
+ std::unique_ptr<BluetoothSerialDeviceEnumerator>
+ fake_bluetooth_enumerator);
private:
// mojom::SerialPortManager methods:
@@ -55,6 +59,7 @@ class SerialPortManagerImpl : public mojom::SerialPortManager,
void OnPortRemoved(const mojom::SerialPortInfo& port) override;
std::unique_ptr<SerialDeviceEnumerator> enumerator_;
+ std::unique_ptr<BluetoothSerialDeviceEnumerator> bluetooth_enumerator_;
ScopedObserver<SerialDeviceEnumerator, SerialDeviceEnumerator::Observer>
observed_enumerator_{this};
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 3b5b4da545f..05a599102b6 100644
--- a/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
+++ b/chromium/services/device/serial/serial_port_manager_impl_unittest.cc
@@ -10,16 +10,23 @@
#include <vector>
#include "base/bind.h"
+#include "base/command_line.h"
#include "base/macros.h"
#include "base/task/post_task.h"
#include "base/test/bind_test_util.h"
#include "base/threading/thread.h"
+#include "device/bluetooth/bluetooth_adapter_factory.h"
+#include "device/bluetooth/public/cpp/bluetooth_uuid.h"
+#include "device/bluetooth/test/mock_bluetooth_adapter.h"
+#include "device/bluetooth/test/mock_bluetooth_device.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
#include "services/device/device_service_test_base.h"
+#include "services/device/public/cpp/serial/serial_switches.h"
#include "services/device/public/mojom/serial.mojom.h"
+#include "services/device/serial/bluetooth_serial_device_enumerator.h"
#include "services/device/serial/fake_serial_device_enumerator.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -33,6 +40,7 @@ namespace {
const base::FilePath kFakeDevicePath1(FILE_PATH_LITERAL("/dev/fakeserialmojo"));
const base::FilePath kFakeDevicePath2(FILE_PATH_LITERAL("\\\\COM800\\"));
+constexpr char kDeviceAddress[] = "00:00:00:00:00:00";
class MockSerialPortManagerClient : public mojom::SerialPortManagerClient {
public:
@@ -72,8 +80,37 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase {
~SerialPortManagerImplTest() override = default;
+ // Since not all functions need to use a MockBluetoothAdapter, this function
+ // is called at the beginning of test cases that do require a
+ // MockBluetoothAdapter.
+ void SetupBluetoothEnumerator() {
+ base::CommandLine::ForCurrentProcess()->AppendSwitch(
+ switches::kEnableBluetoothSerialPortProfileInSerialApi);
+
+ ON_CALL(*adapter_, GetDevices())
+ .WillByDefault(
+ Invoke(adapter_.get(), &MockBluetoothAdapter::GetConstMockDevices));
+ device::BluetoothAdapterFactory::SetAdapterForTesting(adapter_);
+
+ auto mock_device = std::make_unique<MockBluetoothDevice>(
+ adapter_.get(), 0, "Test Device", kDeviceAddress, false, false);
+ static const BluetoothUUID kSerialPortProfileUUID("1101");
+ mock_device->AddUUID(kSerialPortProfileUUID);
+ adapter_->AddMockDevice(std::move(mock_device));
+
+ auto bluetooth_enumerator =
+ std::make_unique<BluetoothSerialDeviceEnumerator>();
+ bluetooth_enumerator_ = bluetooth_enumerator.get();
+
+ manager_->SetBluetoothSerialEnumeratorForTesting(
+ std::move(bluetooth_enumerator));
+ }
+
protected:
FakeSerialEnumerator* enumerator_;
+ BluetoothSerialDeviceEnumerator* bluetooth_enumerator_;
+ scoped_refptr<MockBluetoothAdapter> adapter_ =
+ base::MakeRefCounted<MockBluetoothAdapter>();
void Bind(mojo::PendingReceiver<mojom::SerialPortManager> receiver) {
manager_->Bind(std::move(receiver));
@@ -88,6 +125,8 @@ class SerialPortManagerImplTest : public DeviceServiceTestBase {
// This is to simply test that we can enumerate devices on the platform without
// hanging or crashing.
TEST_F(SerialPortManagerImplTest, SimpleConnectTest) {
+ // DeviceService has its own instance of SerialPortManagerImpl that is used to
+ // bind the receiver over the one created for this test.
mojo::Remote<mojom::SerialPortManager> port_manager;
device_service()->BindSerialPortManager(
port_manager.BindNewPipeAndPassReceiver());
@@ -112,10 +151,14 @@ TEST_F(SerialPortManagerImplTest, SimpleConnectTest) {
}
TEST_F(SerialPortManagerImplTest, GetDevices) {
+ SetupBluetoothEnumerator();
mojo::Remote<mojom::SerialPortManager> port_manager;
Bind(port_manager.BindNewPipeAndPassReceiver());
- const std::set<base::FilePath> expected_paths = {kFakeDevicePath1,
- kFakeDevicePath2};
+ const std::string address_identifier =
+ std::string(kDeviceAddress) + "-Identifier";
+ const std::set<base::FilePath> expected_paths = {
+ kFakeDevicePath1, kFakeDevicePath2,
+ base::FilePath::FromUTF8Unsafe(address_identifier)};
base::RunLoop loop;
port_manager->GetDevices(base::BindLambdaForTesting(
@@ -131,6 +174,7 @@ TEST_F(SerialPortManagerImplTest, GetDevices) {
}
TEST_F(SerialPortManagerImplTest, PortRemovedAndAdded) {
+ SetupBluetoothEnumerator();
mojo::Remote<mojom::SerialPortManager> port_manager;
Bind(port_manager.BindNewPipeAndPassReceiver());
@@ -180,6 +224,7 @@ TEST_F(SerialPortManagerImplTest, PortRemovedAndAdded) {
}
TEST_F(SerialPortManagerImplTest, GetPort) {
+ SetupBluetoothEnumerator();
mojo::Remote<mojom::SerialPortManager> port_manager;
Bind(port_manager.BindNewPipeAndPassReceiver());
@@ -202,4 +247,69 @@ TEST_F(SerialPortManagerImplTest, GetPort) {
loop.Run();
}
+TEST_F(SerialPortManagerImplTest, BluetoothPortRemovedAndAdded) {
+ SetupBluetoothEnumerator();
+ mojo::Remote<mojom::SerialPortManager> port_manager;
+ Bind(port_manager.BindNewPipeAndPassReceiver());
+
+ MockSerialPortManagerClient client;
+ port_manager->SetClient(client.BindNewPipeAndPassRemote());
+
+ const std::string address_identifier =
+ std::string(kDeviceAddress) + "-Identifier";
+ base::UnguessableToken port1_token;
+ {
+ base::RunLoop run_loop;
+ port_manager->GetDevices(base::BindLambdaForTesting(
+ [&](std::vector<mojom::SerialPortInfoPtr> results) {
+ for (const auto& port : results) {
+ if (port->path ==
+ base::FilePath::FromUTF8Unsafe(address_identifier)) {
+ port1_token = port->token;
+ break;
+ }
+ }
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+ ASSERT_FALSE(port1_token.is_empty());
+
+ bluetooth_enumerator_->DeviceRemoved(
+ adapter_.get(), adapter_->RemoveMockDevice(kDeviceAddress).get());
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client, OnPortRemoved(_))
+ .WillOnce(Invoke([&](mojom::SerialPortInfoPtr port) {
+ EXPECT_EQ(port1_token, port->token);
+ EXPECT_EQ(port->path,
+ base::FilePath::FromUTF8Unsafe(address_identifier));
+ EXPECT_EQ(mojom::DeviceType::SPP_DEVICE, port->type);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+
+ auto mock_device = std::make_unique<MockBluetoothDevice>(
+ adapter_.get(), 0, "Test Device", kDeviceAddress, false, false);
+ static const BluetoothUUID kSerialPortProfileUUID("1101");
+ mock_device->AddUUID(kSerialPortProfileUUID);
+ MockBluetoothDevice* mock_device_ptr = mock_device.get();
+ adapter_->AddMockDevice(std::move(mock_device));
+
+ bluetooth_enumerator_->DeviceAdded(adapter_.get(), mock_device_ptr);
+ {
+ base::RunLoop run_loop;
+ EXPECT_CALL(client, OnPortAdded(_))
+ .WillOnce(Invoke([&](mojom::SerialPortInfoPtr port) {
+ EXPECT_NE(port1_token, port->token);
+ EXPECT_EQ(port->path,
+ base::FilePath::FromUTF8Unsafe(address_identifier));
+ EXPECT_EQ(mojom::DeviceType::SPP_DEVICE, port->type);
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ }
+}
+
} // namespace device
diff --git a/chromium/services/device/time_zone_monitor/BUILD.gn b/chromium/services/device/time_zone_monitor/BUILD.gn
index 440344d3ef5..a46402d2f4e 100644
--- a/chromium/services/device/time_zone_monitor/BUILD.gn
+++ b/chromium/services/device/time_zone_monitor/BUILD.gn
@@ -44,7 +44,7 @@ source_set("time_zone_monitor") {
}
if (is_mac) {
- libs = [ "Foundation.framework" ]
+ frameworks = [ "Foundation.framework" ]
}
if (is_fuchsia) {
diff --git a/chromium/services/device/usb/BUILD.gn b/chromium/services/device/usb/BUILD.gn
index d754b63ec24..5b7ea62333d 100644
--- a/chromium/services/device/usb/BUILD.gn
+++ b/chromium/services/device/usb/BUILD.gn
@@ -32,10 +32,14 @@ static_library("usb") {
"usb_device_handle.h",
"usb_device_handle_android.cc",
"usb_device_handle_android.h",
+ "usb_device_handle_mac.cc",
+ "usb_device_handle_mac.h",
"usb_device_handle_win.cc",
"usb_device_handle_win.h",
"usb_device_linux.cc",
"usb_device_linux.h",
+ "usb_device_mac.cc",
+ "usb_device_mac.h",
"usb_device_win.cc",
"usb_device_win.h",
"usb_endpoint_android.cc",
@@ -46,6 +50,8 @@ static_library("usb") {
"usb_service.h",
"usb_service_android.cc",
"usb_service_android.h",
+ "usb_service_mac.cc",
+ "usb_service_mac.h",
"usb_service_win.cc",
"usb_service_win.h",
"webusb_descriptors.cc",
diff --git a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java
index 90371e53c0e..aeaae0e732b 100644
--- a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java
+++ b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbConfiguration.java
@@ -4,10 +4,8 @@
package org.chromium.device.usb;
-import android.annotation.TargetApi;
import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbInterface;
-import android.os.Build;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
@@ -20,7 +18,6 @@ import org.chromium.base.annotations.JNINamespace;
* Lifetime is controlled by device::UsbConfigurationAndroid.
*/
@JNINamespace("device")
-@TargetApi(Build.VERSION_CODES.LOLLIPOP)
final class ChromeUsbConfiguration {
private static final String TAG = "Usb";
diff --git a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java
index d407ef71427..223b8de337e 100644
--- a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java
+++ b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbDevice.java
@@ -7,7 +7,6 @@ package org.chromium.device.usb;
import android.annotation.TargetApi;
import android.hardware.usb.UsbConfiguration;
import android.hardware.usb.UsbDevice;
-import android.hardware.usb.UsbInterface;
import android.os.Build;
import org.chromium.base.Log;
@@ -83,25 +82,21 @@ final class ChromeUsbDevice {
return Integer.parseInt(parts[0]) << 8 | Integer.parseInt(parts[1]);
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@CalledByNative
private String getManufacturerName() {
return mDevice.getManufacturerName();
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@CalledByNative
private String getProductName() {
return mDevice.getProductName();
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@CalledByNative
private String getSerialNumber() {
return mDevice.getSerialNumber();
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@CalledByNative
private UsbConfiguration[] getConfigurations() {
int count = mDevice.getConfigurationCount();
@@ -111,14 +106,4 @@ final class ChromeUsbDevice {
}
return configurations;
}
-
- @CalledByNative
- private UsbInterface[] getInterfaces() {
- int count = mDevice.getInterfaceCount();
- UsbInterface[] interfaces = new UsbInterface[count];
- for (int i = 0; i < count; ++i) {
- interfaces[i] = mDevice.getInterface(i);
- }
- return interfaces;
- }
}
diff --git a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java
index 1637aae0f61..cd4f49270ed 100644
--- a/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java
+++ b/chromium/services/device/usb/android/java/src/org/chromium/device/usb/ChromeUsbInterface.java
@@ -4,10 +4,8 @@
package org.chromium.device.usb;
-import android.annotation.TargetApi;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
-import android.os.Build;
import org.chromium.base.Log;
import org.chromium.base.annotations.CalledByNative;
@@ -40,7 +38,6 @@ final class ChromeUsbInterface {
return mInterface.getId();
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
@CalledByNative
private int getAlternateSetting() {
return mInterface.getAlternateSetting();
diff --git a/chromium/services/device/usb/mojo/device_impl.cc b/chromium/services/device/usb/mojo/device_impl.cc
index 1e7a6a798cf..bc708148647 100644
--- a/chromium/services/device/usb/mojo/device_impl.cc
+++ b/chromium/services/device/usb/mojo/device_impl.cc
@@ -160,6 +160,7 @@ void DeviceImpl::OnOpen(base::WeakPtr<DeviceImpl> self,
return;
}
+ self->opening_ = false;
self->device_handle_ = std::move(handle);
if (self->device_handle_ && self->client_)
self->client_->OnDeviceOpened();
@@ -175,16 +176,19 @@ void DeviceImpl::OnPermissionGrantedForOpen(OpenCallback callback,
device_->Open(base::BindOnce(
&DeviceImpl::OnOpen, weak_factory_.GetWeakPtr(), std::move(callback)));
} else {
+ opening_ = false;
std::move(callback).Run(mojom::UsbOpenDeviceError::ACCESS_DENIED);
}
}
void DeviceImpl::Open(OpenCallback callback) {
- if (device_handle_) {
+ if (opening_ || device_handle_) {
std::move(callback).Run(mojom::UsbOpenDeviceError::ALREADY_OPEN);
return;
}
+ opening_ = true;
+
if (!device_->permission_granted()) {
device_->RequestPermission(
base::BindOnce(&DeviceImpl::OnPermissionGrantedForOpen,
diff --git a/chromium/services/device/usb/mojo/device_impl.h b/chromium/services/device/usb/mojo/device_impl.h
index ca3bffe4392..0965ca72663 100644
--- a/chromium/services/device/usb/mojo/device_impl.h
+++ b/chromium/services/device/usb/mojo/device_impl.h
@@ -106,7 +106,9 @@ class DeviceImpl : public mojom::UsbDevice, public device::UsbDevice::Observer {
ScopedObserver<device::UsbDevice, device::UsbDevice::Observer> observer_;
// The device handle. Will be null before the device is opened and after it
- // has been closed.
+ // has been closed. |opening_| is set to true while the asynchronous open is
+ // in progress.
+ bool opening_ = false;
scoped_refptr<UsbDeviceHandle> device_handle_;
mojo::SelfOwnedReceiverRef<mojom::UsbDevice> receiver_;
diff --git a/chromium/services/device/usb/mojo/device_impl_unittest.cc b/chromium/services/device/usb/mojo/device_impl_unittest.cc
index f0cd0eab4cf..4987fbe5519 100644
--- a/chromium/services/device/usb/mojo/device_impl_unittest.cc
+++ b/chromium/services/device/usb/mojo/device_impl_unittest.cc
@@ -22,8 +22,8 @@
#include "base/memory/ref_counted_memory.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
+#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/usb/mock_usb_device.h"
@@ -265,7 +265,10 @@ class USBDeviceImplTest : public testing::Test {
void OpenMockHandle(UsbDevice::OpenCallback& callback) {
EXPECT_FALSE(is_device_open_);
is_device_open_ = true;
- std::move(callback).Run(mock_handle_);
+ // Simulate the asynchronous device opening process.
+ base::SequencedTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::BindOnce(std::move(callback), mock_handle_),
+ base::TimeDelta::FromMilliseconds(1));
}
void CloseMockHandle() {
@@ -515,17 +518,39 @@ TEST_F(USBDeviceImplTest, OpenFailure) {
GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
EXPECT_CALL(mock_device(), OpenInternal(_))
- .WillOnce(Invoke([](UsbDevice::OpenCallback& callback) {
+ .WillOnce([](UsbDevice::OpenCallback& callback) {
std::move(callback).Run(nullptr);
- }));
+ });
EXPECT_CALL(device_client, OnDeviceOpened()).Times(0);
EXPECT_CALL(device_client, OnDeviceClosed()).Times(0);
- base::RunLoop loop;
- device->Open(base::BindOnce(&ExpectOpenAndThen,
- mojom::UsbOpenDeviceError::ACCESS_DENIED,
- loop.QuitClosure()));
- loop.Run();
+ {
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ACCESS_DENIED);
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ // A second attempt can succeed.
+ EXPECT_CALL(mock_device(), OpenInternal(_));
+ EXPECT_CALL(device_client, OnDeviceOpened());
+ EXPECT_CALL(device_client, OnDeviceClosed());
+
+ {
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
+ loop.Quit();
+ }));
+ loop.Run();
+ }
+
+ device.reset();
+ base::RunLoop().RunUntilIdle();
}
TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
@@ -549,6 +574,24 @@ TEST_F(USBDeviceImplTest, OpenDelayedFailure) {
std::move(saved_callback).Run(nullptr);
}
+TEST_F(USBDeviceImplTest, MultipleOpenNotAllowed) {
+ MockUsbDeviceClient device_client;
+ mojo::Remote<mojom::UsbDevice> device =
+ GetMockDeviceProxy(device_client.CreateInterfacePtrAndBind());
+
+ base::RunLoop loop;
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::OK);
+ }));
+ device->Open(
+ base::BindLambdaForTesting([&](mojom::UsbOpenDeviceError result) {
+ EXPECT_EQ(result, mojom::UsbOpenDeviceError::ALREADY_OPEN);
+ loop.Quit();
+ }));
+ loop.Run();
+}
+
TEST_F(USBDeviceImplTest, Close) {
MockUsbDeviceClient device_client;
mojo::Remote<mojom::UsbDevice> device =
diff --git a/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc b/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc
index b2869d0c9b6..d3a845fa2fd 100644
--- a/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc
+++ b/chromium/services/device/usb/mojo/device_manager_impl_unittest.cc
@@ -18,7 +18,6 @@
#include "base/test/task_environment.h"
#include "base/threading/thread_task_runner_handle.h"
#include "mojo/public/cpp/bindings/associated_receiver.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "services/device/public/mojom/usb_enumeration_options.mojom.h"
#include "services/device/public/mojom/usb_manager_client.mojom.h"
diff --git a/chromium/services/device/usb/usb_descriptors.cc b/chromium/services/device/usb/usb_descriptors.cc
index 65b28e9c4b4..a707fb0336f 100644
--- a/chromium/services/device/usb/usb_descriptors.cc
+++ b/chromium/services/device/usb/usb_descriptors.cc
@@ -110,8 +110,7 @@ void OnReadConfigDescriptor(UsbDeviceDescriptor* desc,
scoped_refptr<base::RefCountedBytes> buffer,
size_t length) {
if (status == UsbTransferStatus::COMPLETED) {
- if (!desc->Parse(
- std::vector<uint8_t>(buffer->front(), buffer->front() + length))) {
+ if (!desc->Parse(base::make_span(buffer->front(), length))) {
LOG(ERROR) << "Failed to parse configuration descriptor.";
}
} else {
@@ -157,8 +156,7 @@ void OnReadDeviceDescriptor(
}
std::unique_ptr<UsbDeviceDescriptor> desc(new UsbDeviceDescriptor());
- if (!desc->Parse(
- std::vector<uint8_t>(buffer->front(), buffer->front() + length))) {
+ if (!desc->Parse(base::make_span(buffer->front(), length))) {
LOG(ERROR) << "Device descriptor parsing error.";
std::move(callback).Run(nullptr);
return;
@@ -262,7 +260,7 @@ UsbDeviceDescriptor::UsbDeviceDescriptor()
UsbDeviceDescriptor::~UsbDeviceDescriptor() = default;
-bool UsbDeviceDescriptor::Parse(const std::vector<uint8_t>& buffer) {
+bool UsbDeviceDescriptor::Parse(base::span<const uint8_t> buffer) {
mojom::UsbConfigurationInfo* last_config = nullptr;
mojom::UsbInterfaceInfo* last_interface = nullptr;
mojom::UsbEndpointInfo* last_endpoint = nullptr;
diff --git a/chromium/services/device/usb/usb_descriptors.h b/chromium/services/device/usb/usb_descriptors.h
index ba173395e69..482bf4fa505 100644
--- a/chromium/services/device/usb/usb_descriptors.h
+++ b/chromium/services/device/usb/usb_descriptors.h
@@ -41,7 +41,7 @@ struct UsbDeviceDescriptor {
// be used to populate this struct's fields. This function may be called more
// than once (i.e. for multiple buffers containing a configuration descriptor
// each).
- bool Parse(const std::vector<uint8_t>& buffer);
+ bool Parse(base::span<const uint8_t> buffer);
uint8_t i_manufacturer = 0;
uint8_t i_product = 0;
diff --git a/chromium/services/device/usb/usb_device.cc b/chromium/services/device/usb/usb_device.cc
index 40eabd6c7e0..aaf39c26d7c 100644
--- a/chromium/services/device/usb/usb_device.cc
+++ b/chromium/services/device/usb/usb_device.cc
@@ -118,7 +118,7 @@ void UsbDevice::OnDisconnect() {
// Swap out the handle list as HandleClosed() will try to modify it.
std::list<UsbDeviceHandle*> handles;
handles.swap(handles_);
- for (auto* handle : handles_)
+ for (auto* handle : handles)
handle->Close();
}
diff --git a/chromium/services/device/usb/usb_device.h b/chromium/services/device/usb/usb_device.h
index 35b6c5d6de4..15d7430e890 100644
--- a/chromium/services/device/usb/usb_device.h
+++ b/chromium/services/device/usb/usb_device.h
@@ -145,11 +145,13 @@ class UsbDevice : public base::RefCountedThreadSafe<UsbDevice> {
private:
friend class base::RefCountedThreadSafe<UsbDevice>;
friend class UsbDeviceHandleImpl;
+ friend class UsbDeviceHandleMac;
friend class UsbDeviceHandleUsbfs;
friend class UsbDeviceHandleWin;
friend class UsbServiceAndroid;
friend class UsbServiceImpl;
friend class UsbServiceLinux;
+ friend class UsbServiceMac;
friend class UsbServiceWin;
void OnDisconnect();
diff --git a/chromium/services/device/usb/usb_device_android.cc b/chromium/services/device/usb/usb_device_android.cc
index c4c9283b2ee..24a0ae1d975 100644
--- a/chromium/services/device/usb/usb_device_android.cc
+++ b/chromium/services/device/usb/usb_device_android.cc
@@ -41,25 +41,26 @@ scoped_refptr<UsbDeviceAndroid> UsbDeviceAndroid::Create(
if (build_info->sdk_int() >= base::android::SDK_VERSION_MARSHMALLOW)
device_version = Java_ChromeUsbDevice_getDeviceVersion(env, wrapper);
- base::string16 manufacturer_string, product_string, serial_number;
- if (build_info->sdk_int() >= base::android::SDK_VERSION_LOLLIPOP) {
- ScopedJavaLocalRef<jstring> manufacturer_jstring =
- Java_ChromeUsbDevice_getManufacturerName(env, wrapper);
- if (!manufacturer_jstring.is_null())
- manufacturer_string = ConvertJavaStringToUTF16(env, manufacturer_jstring);
- ScopedJavaLocalRef<jstring> product_jstring =
- Java_ChromeUsbDevice_getProductName(env, wrapper);
- if (!product_jstring.is_null())
- product_string = ConvertJavaStringToUTF16(env, product_jstring);
-
- // Reading the serial number requires device access permission when
- // targeting the Q SDK.
- if (service->HasDevicePermission(wrapper) || !build_info->is_at_least_q()) {
- ScopedJavaLocalRef<jstring> serial_jstring =
- Java_ChromeUsbDevice_getSerialNumber(env, wrapper);
- if (!serial_jstring.is_null())
- serial_number = ConvertJavaStringToUTF16(env, serial_jstring);
- }
+ base::string16 manufacturer_string;
+ ScopedJavaLocalRef<jstring> manufacturer_jstring =
+ Java_ChromeUsbDevice_getManufacturerName(env, wrapper);
+ if (!manufacturer_jstring.is_null())
+ manufacturer_string = ConvertJavaStringToUTF16(env, manufacturer_jstring);
+
+ base::string16 product_string;
+ ScopedJavaLocalRef<jstring> product_jstring =
+ Java_ChromeUsbDevice_getProductName(env, wrapper);
+ if (!product_jstring.is_null())
+ product_string = ConvertJavaStringToUTF16(env, product_jstring);
+
+ // Reading the serial number requires device access permission when
+ // targeting the Q SDK.
+ base::string16 serial_number;
+ if (service->HasDevicePermission(wrapper) || !build_info->is_at_least_q()) {
+ ScopedJavaLocalRef<jstring> serial_jstring =
+ Java_ChromeUsbDevice_getSerialNumber(env, wrapper);
+ if (!serial_jstring.is_null())
+ serial_number = ConvertJavaStringToUTF16(env, serial_jstring);
}
return base::WrapRefCounted(new UsbDeviceAndroid(
@@ -134,33 +135,12 @@ UsbDeviceAndroid::UsbDeviceAndroid(JNIEnv* env,
device_id_(Java_ChromeUsbDevice_getDeviceId(env, wrapper)),
service_(service),
j_object_(wrapper) {
- if (base::android::BuildInfo::GetInstance()->sdk_int() >=
- base::android::SDK_VERSION_LOLLIPOP) {
- JavaObjectArrayReader<jobject> configurations(
- Java_ChromeUsbDevice_getConfigurations(env, j_object_));
- device_info_->configurations.reserve(configurations.size());
- for (auto config : configurations) {
- device_info_->configurations.push_back(
- UsbConfigurationAndroid::Convert(env, config));
- }
- } else {
- // Pre-lollipop only the first configuration was supported. Build a basic
- // configuration out of the available interfaces.
- mojom::UsbConfigurationInfoPtr config = BuildUsbConfigurationInfoPtr(
- 1, // Configuration value, reasonable guess.
- false, // Self powered, arbitrary default.
- false, // Remote wakeup, rbitrary default.
- 0); // Maximum power, aitrary default.
-
- JavaObjectArrayReader<jobject> interfaces(
- Java_ChromeUsbDevice_getInterfaces(env, wrapper));
- config->interfaces.reserve(interfaces.size());
- for (auto interface : interfaces) {
- config->interfaces.push_back(
- UsbInterfaceAndroid::Convert(env, interface));
- }
- AggregateInterfacesForConfig(config.get());
- device_info_->configurations.push_back(std::move(config));
+ JavaObjectArrayReader<jobject> configs(
+ Java_ChromeUsbDevice_getConfigurations(env, j_object_));
+ device_info_->configurations.reserve(configs.size());
+ for (auto config : configs) {
+ device_info_->configurations.push_back(
+ UsbConfigurationAndroid::Convert(env, config));
}
if (configurations().size() > 0)
diff --git a/chromium/services/device/usb/usb_device_handle_mac.cc b/chromium/services/device/usb/usb_device_handle_mac.cc
new file mode 100644
index 00000000000..c91439bce10
--- /dev/null
+++ b/chromium/services/device/usb/usb_device_handle_mac.cc
@@ -0,0 +1,925 @@
+// 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/device/usb/usb_device_handle_mac.h"
+
+#include <IOKit/IOCFBundle.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOReturn.h>
+#include <IOKit/IOTypes.h>
+#include <IOKit/usb/IOUSBLib.h>
+#include <MacTypes.h>
+
+#include <memory>
+#include <numeric>
+#include <utility>
+
+#include "base/mac/scoped_ioobject.h"
+#include "base/mac/scoped_ioplugininterface.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/strings/string_number_conversions.h"
+#include "components/device_event_log/device_event_log.h"
+#include "services/device/public/cpp/usb/usb_utils.h"
+#include "services/device/usb/usb_device_mac.h"
+
+namespace device {
+
+struct Transfer {
+ UsbDeviceHandleMac::TransferCallback generic_callback;
+ scoped_refptr<UsbDeviceHandleMac> handle;
+ scoped_refptr<base::RefCountedBytes> buffer;
+ std::vector<uint32_t> packet_lengths;
+ std::vector<IOUSBIsocFrame> frame_list;
+ mojom::UsbTransferType type;
+ UsbDeviceHandleMac::IsochronousTransferCallback isochronous_callback;
+};
+
+namespace {
+
+// This is the bit 7 of the request type.
+enum class EndpointDirection : uint8_t { kIn = 0x80, kOut = 0x00 };
+
+// These are bits 5 and 6 of the request type.
+enum class RequestType : uint8_t {
+ kStandard = 0x00,
+ kClass = 0x20,
+ kVendor = 0x40,
+ kReserved = 0x60
+};
+
+// These are bits 0 and 1 of the request type.
+enum class RequestRecipient : uint8_t {
+ kDevice = 0x00,
+ kInterface = 0x01,
+ kEndpoint = 0x02,
+ kOther = 0x03,
+};
+
+mojom::UsbTransferStatus ConvertTransferStatus(IOReturn status) {
+ switch (status) {
+ // kIOReturnUnderrun can be ignored because the lower-than-expected transfer
+ // size is reported alongside the COMPLETED status.
+ case kIOReturnUnderrun:
+ case kIOReturnSuccess:
+ return mojom::UsbTransferStatus::COMPLETED;
+ case kIOUSBTransactionTimeout:
+ return mojom::UsbTransferStatus::TIMEOUT;
+ case kIOUSBPipeStalled:
+ return mojom::UsbTransferStatus::STALLED;
+ case kIOReturnOverrun:
+ return mojom::UsbTransferStatus::BABBLE;
+ case kIOReturnAborted:
+ return mojom::UsbTransferStatus::CANCELLED;
+ default:
+ return mojom::UsbTransferStatus::TRANSFER_ERROR;
+ }
+}
+
+uint8_t ConvertTransferDirection(mojom::UsbTransferDirection direction) {
+ switch (direction) {
+ case mojom::UsbTransferDirection::INBOUND:
+ return static_cast<uint8_t>(EndpointDirection::kIn);
+ case mojom::UsbTransferDirection::OUTBOUND:
+ return static_cast<uint8_t>(EndpointDirection::kOut);
+ }
+ NOTREACHED();
+ return 0;
+}
+
+uint8_t CreateRequestType(mojom::UsbTransferDirection direction,
+ mojom::UsbControlTransferType request_type,
+ mojom::UsbControlTransferRecipient recipient) {
+ uint8_t result = ConvertTransferDirection(direction);
+
+ switch (request_type) {
+ case mojom::UsbControlTransferType::STANDARD:
+ result |= static_cast<uint8_t>(RequestType::kStandard);
+ break;
+ case mojom::UsbControlTransferType::CLASS:
+ result |= static_cast<uint8_t>(RequestType::kClass);
+ break;
+ case mojom::UsbControlTransferType::VENDOR:
+ result |= static_cast<uint8_t>(RequestType::kVendor);
+ break;
+ case mojom::UsbControlTransferType::RESERVED:
+ result |= static_cast<uint8_t>(RequestType::kReserved);
+ break;
+ }
+
+ switch (recipient) {
+ case mojom::UsbControlTransferRecipient::DEVICE:
+ result |= static_cast<uint8_t>(RequestRecipient::kDevice);
+ break;
+ case mojom::UsbControlTransferRecipient::INTERFACE:
+ result |= static_cast<uint8_t>(RequestRecipient::kInterface);
+ break;
+ case mojom::UsbControlTransferRecipient::ENDPOINT:
+ result |= static_cast<uint8_t>(RequestRecipient::kEndpoint);
+ break;
+ case mojom::UsbControlTransferRecipient::OTHER:
+ result |= static_cast<uint8_t>(RequestRecipient::kOther);
+ break;
+ }
+
+ return result;
+}
+
+} // namespace
+
+UsbDeviceHandleMac::UsbDeviceHandleMac(
+ scoped_refptr<UsbDeviceMac> device,
+ ScopedIOUSBDeviceInterface device_interface)
+ : device_interface_(std::move(device_interface)),
+ device_(std::move(device)) {}
+
+scoped_refptr<UsbDevice> UsbDeviceHandleMac::GetDevice() const {
+ return device_;
+}
+
+void UsbDeviceHandleMac::Close() {
+ if (!device_)
+ return;
+
+ IOReturn kr = (*device_interface_)->USBDeviceClose(device_interface_);
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to close device: " << std::hex << kr;
+ return;
+ }
+
+ Clear();
+ device_->HandleClosed(this);
+ device_ = nullptr;
+}
+
+void UsbDeviceHandleMac::SetConfiguration(int configuration_value,
+ ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ if (!base::IsValueInRangeForNumericType<uint8_t>(configuration_value)) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ Clear();
+
+ IOReturn kr =
+ (*device_interface_)
+ ->SetConfiguration(device_interface_,
+ static_cast<uint8_t>(configuration_value));
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ device_->ActiveConfigurationChanged(configuration_value);
+
+ std::move(callback).Run(true);
+}
+
+void UsbDeviceHandleMac::ClaimInterface(int interface_number,
+ ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ if (!base::IsValueInRangeForNumericType<uint8_t>(interface_number)) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ IOUSBFindInterfaceRequest request;
+ request.bInterfaceClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare;
+ request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare;
+ request.bAlternateSetting = kIOUSBFindInterfaceDontCare;
+
+ base::mac::ScopedIOObject<io_iterator_t> interface_iterator;
+ IOReturn kr =
+ (*device_interface_)
+ ->CreateInterfaceIterator(device_interface_, &request,
+ interface_iterator.InitializeInto());
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ base::mac::ScopedIOObject<io_service_t> usb_interface;
+ while (usb_interface.reset(IOIteratorNext(interface_iterator)),
+ usb_interface) {
+ base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_interface;
+ int32_t score;
+ kr = IOCreatePlugInInterfaceForService(
+ usb_interface, kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID,
+ plugin_interface.InitializeInto(), &score);
+
+ if (kr != kIOReturnSuccess || !plugin_interface) {
+ USB_LOG(ERROR) << "Unable to create a plug-in: " << std::hex << kr;
+ continue;
+ }
+
+ ScopedIOUSBInterfaceInterface interface_interface;
+ kr = (*plugin_interface)
+ ->QueryInterface(plugin_interface.get(),
+ CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID),
+ reinterpret_cast<LPVOID*>(
+ interface_interface.InitializeInto()));
+ if (kr != kIOReturnSuccess || !interface_interface) {
+ USB_LOG(ERROR) << "Could not create a device interface: " << std::hex
+ << kr;
+ continue;
+ }
+
+ uint8_t retrieved_interface_number;
+ kr = (*interface_interface)
+ ->GetInterfaceNumber(interface_interface,
+ &retrieved_interface_number);
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Could not retrieve an interface number: " << std::hex
+ << kr;
+ continue;
+ }
+
+ if (retrieved_interface_number != interface_number)
+ continue;
+
+ kr = (*interface_interface)->USBInterfaceOpen(interface_interface);
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Could not open interface: " << std::hex << kr;
+ break;
+ }
+
+ interfaces_[interface_number] = interface_interface;
+ base::ScopedCFTypeRef<CFRunLoopSourceRef> run_loop_source;
+ kr = (*interface_interface)
+ ->CreateInterfaceAsyncEventSource(
+ interface_interface, run_loop_source.InitializeInto());
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Could not retrieve port: " << std::hex << kr;
+ (*interface_interface)->USBInterfaceClose(interface_interface);
+ break;
+ }
+ RefreshEndpointMap();
+ CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source.get(),
+ kCFRunLoopDefaultMode);
+ sources_[interface_number] = run_loop_source;
+ std::move(callback).Run(true);
+ return;
+ }
+ std::move(callback).Run(false);
+ USB_LOG(ERROR) << "Could not find interface matching number: "
+ << interface_number;
+}
+
+void UsbDeviceHandleMac::ReleaseInterface(int interface_number,
+ ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ auto interface_it = interfaces_.find(static_cast<uint8_t>(interface_number));
+ if (interface_it == interfaces_.end()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ auto released_interface = std::move(interface_it->second);
+ interfaces_.erase(interface_it);
+
+ auto source_it = sources_.find(interface_number);
+ if (source_it != sources_.end()) {
+ CFRunLoopRemoveSource(CFRunLoopGetCurrent(), source_it->second.get(),
+ kCFRunLoopDefaultMode);
+ sources_.erase(source_it);
+ }
+
+ IOReturn kr = (*released_interface)->USBInterfaceClose(released_interface);
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+ RefreshEndpointMap();
+ std::move(callback).Run(true);
+}
+
+void UsbDeviceHandleMac::SetInterfaceAlternateSetting(int interface_number,
+ int alternate_setting,
+ ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ auto interface_it = interfaces_.find(interface_number);
+ if (interface_it == interfaces_.end()) {
+ std::move(callback).Run(false);
+ return;
+ }
+ const auto& interface_interface = interface_it->second;
+
+ IOReturn kr =
+ (*interface_interface)
+ ->SetAlternateInterface(interface_interface, alternate_setting);
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+ RefreshEndpointMap();
+ std::move(callback).Run(true);
+}
+
+void UsbDeviceHandleMac::ResetDevice(ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ // TODO(https://crbug.com/1096743): Figure out if open interfaces need to be
+ // closed as well.
+ IOReturn kr = (*device_interface_)->ResetDevice(device_interface_);
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ Clear();
+ std::move(callback).Run(true);
+}
+
+void UsbDeviceHandleMac::ClearHalt(mojom::UsbTransferDirection direction,
+ uint8_t endpoint_number,
+ ResultCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ uint8_t endpoint_address =
+ ConvertTransferDirection(direction) | endpoint_number;
+ auto* mojom_interface = FindInterfaceByEndpoint(endpoint_address);
+ uint8_t interface_number = mojom_interface->interface_number;
+
+ auto interface_it = interfaces_.find(interface_number);
+ if (interface_it == interfaces_.end()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ const auto endpoint_it = endpoint_map_.find(endpoint_address);
+ if (endpoint_it == endpoint_map_.end()) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ const auto& interface_interface = interface_it->second;
+ IOReturn kr = (*interface_interface)
+ ->ClearPipeStall(interface_interface,
+ endpoint_it->second.pipe_reference);
+ if (kr != kIOReturnSuccess) {
+ std::move(callback).Run(false);
+ return;
+ }
+
+ std::move(callback).Run(true);
+}
+
+void UsbDeviceHandleMac::ControlTransfer(
+ mojom::UsbTransferDirection direction,
+ mojom::UsbControlTransferType request_type,
+ mojom::UsbControlTransferRecipient recipient,
+ uint8_t request,
+ uint16_t value,
+ uint16_t index,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ unsigned int timeout,
+ TransferCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(mojom::UsbTransferStatus::DISCONNECT,
+ std::move(buffer), 0);
+ return;
+ }
+
+ if (!base::IsValueInRangeForNumericType<uint16_t>(buffer->size())) {
+ USB_LOG(ERROR) << "Transfer too long.";
+ std::move(callback).Run(mojom::UsbTransferStatus::TRANSFER_ERROR,
+ std::move(buffer), 0);
+ return;
+ }
+
+ auto interface_it = interfaces_.find(index & 0xff);
+ if (interface_it == interfaces_.end()) {
+ std::move(callback).Run(mojom::UsbTransferStatus::TRANSFER_ERROR,
+ std::move(buffer), 0);
+ return;
+ }
+
+ ScopedIOUSBInterfaceInterface interface = interface_it->second;
+ IOUSBDevRequestTO device_request;
+ device_request.bRequest = request;
+ device_request.wValue = value;
+ device_request.wIndex = index;
+ device_request.bmRequestType =
+ CreateRequestType(direction, request_type, recipient);
+ device_request.pData = buffer->front_as<void*>();
+ device_request.wLength = static_cast<uint16_t>(buffer->size());
+ device_request.completionTimeout = timeout;
+ device_request.noDataTimeout = timeout;
+
+ auto transfer = std::make_unique<Transfer>();
+ transfer->generic_callback = std::move(callback);
+ transfer->handle = this;
+ transfer->buffer = std::move(buffer);
+
+ Transfer* transfer_ptr = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+ IOReturn kr =
+ (*interface)
+ ->ControlRequestAsyncTO(interface, /*pipeRef=*/0, &device_request,
+ &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_ptr));
+
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to send control request: " << std::hex << kr;
+ std::move((*result.first)->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR,
+ std::move((*result.first)->buffer), 0);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::IsochronousTransferIn(
+ uint8_t endpoint,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ IsochronousTransferCallback callback) {
+ if (!device_) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::DISCONNECT);
+ return;
+ }
+
+ uint8_t endpoint_address =
+ ConvertTransferDirection(mojom::UsbTransferDirection::INBOUND) | endpoint;
+ const auto endpoint_it = endpoint_map_.find(endpoint_address);
+ if (endpoint_it == endpoint_map_.end()) {
+ USB_LOG(ERROR) << "Failed to submit transfer because endpoint "
+ << int{endpoint_address}
+ << " is not part of a claimed interface.";
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+
+ size_t length =
+ std::accumulate(packet_lengths.begin(), packet_lengths.end(), 0u);
+ auto buffer = base::MakeRefCounted<base::RefCountedBytes>(length);
+
+ auto interface_it =
+ interfaces_.find(endpoint_it->second.interface->interface_number);
+ if (interface_it == interfaces_.end()) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+ const auto& interface_interface = interface_it->second;
+
+ uint64_t bus_frame;
+ AbsoluteTime time;
+ IOReturn kr = (*interface_interface)
+ ->GetBusFrameNumber(interface_interface, &bus_frame, &time);
+ if (kr != kIOReturnSuccess) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+
+ auto transfer = std::make_unique<Transfer>();
+ transfer->isochronous_callback = std::move(callback);
+ transfer->handle = this;
+ transfer->buffer = buffer;
+ transfer->type = mojom::UsbTransferType::ISOCHRONOUS;
+
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+
+ std::vector<IOUSBIsocFrame> frame_list;
+ for (const auto& size : packet_lengths) {
+ if (!base::IsValueInRangeForNumericType<uint16_t>(size)) {
+ USB_LOG(ERROR) << "Transfer too long.";
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+ IOUSBIsocFrame frame_entry;
+ frame_entry.frReqCount = static_cast<uint16_t>(size);
+ frame_list.push_back(frame_entry);
+ }
+ transfer->frame_list = frame_list;
+
+ kr = (*interface_interface)
+ ->ReadIsochPipeAsync(interface_interface,
+ endpoint_it->second.pipe_reference,
+ buffer->front_as<void*>(), bus_frame,
+ static_cast<uint32_t>(packet_lengths.size()),
+ transfer->frame_list.data(), &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Isochrnous read failed.";
+ ReportIsochronousTransferError(
+ std::move((*result.first)->isochronous_callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ transfers_.erase(result.first);
+ return;
+ }
+}
+
+void UsbDeviceHandleMac::IsochronousTransferOut(
+ uint8_t endpoint,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ IsochronousTransferCallback callback) {
+ if (!device_) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::DISCONNECT);
+ return;
+ }
+
+ uint8_t endpoint_address =
+ ConvertTransferDirection(mojom::UsbTransferDirection::INBOUND) | endpoint;
+ const auto endpoint_it = endpoint_map_.find(endpoint_address);
+ if (endpoint_it == endpoint_map_.end()) {
+ USB_LOG(ERROR) << "Failed to submit transfer because endpoint "
+ << int{endpoint_address}
+ << " is not part of a claimed interface.";
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+
+ auto interface_it =
+ interfaces_.find(endpoint_it->second.interface->interface_number);
+ if (interface_it == interfaces_.end()) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+ const auto& interface_interface = interface_it->second;
+
+ uint64_t bus_frame;
+ AbsoluteTime time;
+ IOReturn kr = (*interface_interface)
+ ->GetBusFrameNumber(interface_interface, &bus_frame, &time);
+ if (kr != kIOReturnSuccess) {
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+
+ auto transfer = std::make_unique<Transfer>();
+ transfer->isochronous_callback = std::move(callback);
+ transfer->handle = this;
+ transfer->buffer = buffer;
+ transfer->type = mojom::UsbTransferType::ISOCHRONOUS;
+
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+
+ std::vector<IOUSBIsocFrame> frame_list;
+ for (const auto& size : packet_lengths) {
+ if (!base::IsValueInRangeForNumericType<uint16_t>(size)) {
+ USB_LOG(ERROR) << "Transfer too long.";
+ ReportIsochronousTransferError(std::move(callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ return;
+ }
+ IOUSBIsocFrame frame_entry;
+ frame_entry.frReqCount = static_cast<uint16_t>(size);
+ frame_list.push_back(frame_entry);
+ }
+ transfer->frame_list = frame_list;
+
+ kr = (*interface_interface)
+ ->WriteIsochPipeAsync(interface_interface,
+ endpoint_it->second.pipe_reference,
+ buffer->front_as<void*>(), bus_frame,
+ static_cast<uint32_t>(packet_lengths.size()),
+ transfer->frame_list.data(), &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Isochrnous write failed.";
+ ReportIsochronousTransferError(
+ std::move((*result.first)->isochronous_callback), packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::GenericTransfer(
+ mojom::UsbTransferDirection direction,
+ uint8_t endpoint_number,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ unsigned int timeout,
+ TransferCallback callback) {
+ if (!device_) {
+ std::move(callback).Run(mojom::UsbTransferStatus::DISCONNECT, buffer, 0);
+ return;
+ }
+
+ uint8_t endpoint_address =
+ ConvertEndpointNumberToAddress(endpoint_number, direction);
+
+ const auto endpoint_it = endpoint_map_.find(endpoint_address);
+ if (endpoint_it == endpoint_map_.end()) {
+ USB_LOG(ERROR) << "Failed to submit transfer because endpoint "
+ << int{endpoint_address}
+ << " is not part of a claimed interface.";
+ std::move(callback).Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer,
+ 0);
+ return;
+ }
+
+ if (!base::IsValueInRangeForNumericType<uint32_t>(buffer->size())) {
+ USB_LOG(ERROR) << "Transfer too long.";
+ std::move(callback).Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer,
+ 0);
+ return;
+ }
+
+ auto interface_it =
+ interfaces_.find(endpoint_it->second.interface->interface_number);
+ if (interface_it == interfaces_.end()) {
+ std::move(callback).Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer,
+ 0);
+ return;
+ }
+ const auto& interface_interface = interface_it->second;
+
+ auto transfer = std::make_unique<Transfer>();
+ transfer->generic_callback = std::move(callback);
+ transfer->handle = this;
+ transfer->buffer = buffer;
+
+ mojom::UsbTransferType transfer_type = endpoint_it->second.endpoint->type;
+ transfer->type = transfer_type;
+
+ switch (transfer_type) {
+ case mojom::UsbTransferType::BULK:
+ switch (direction) {
+ case mojom::UsbTransferDirection::INBOUND:
+ BulkIn(std::move(interface_interface),
+ endpoint_it->second.pipe_reference, buffer,
+ static_cast<uint32_t>(timeout), std::move(transfer));
+ return;
+ case mojom::UsbTransferDirection::OUTBOUND:
+ BulkOut(std::move(interface_interface),
+ endpoint_it->second.pipe_reference, buffer,
+ static_cast<uint32_t>(timeout), std::move(transfer));
+ return;
+ }
+ case mojom::UsbTransferType::INTERRUPT:
+ switch (direction) {
+ case mojom::UsbTransferDirection::INBOUND:
+ InterruptIn(interface_interface, endpoint_it->second.pipe_reference,
+ buffer, std::move(transfer));
+ return;
+ case mojom::UsbTransferDirection::OUTBOUND:
+ InterruptOut(interface_interface, endpoint_it->second.pipe_reference,
+ buffer, std::move(transfer));
+ return;
+ }
+ default:
+ std::move(transfer->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
+ }
+}
+
+const mojom::UsbInterfaceInfo* UsbDeviceHandleMac::FindInterfaceByEndpoint(
+ uint8_t endpoint_address) {
+ const auto endpoint_it = endpoint_map_.find(endpoint_address);
+ if (endpoint_it != endpoint_map_.end())
+ return endpoint_it->second.interface;
+ return nullptr;
+}
+
+UsbDeviceHandleMac::~UsbDeviceHandleMac() {}
+
+void UsbDeviceHandleMac::BulkIn(
+ const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ uint32_t timeout,
+ std::unique_ptr<Transfer> transfer) {
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+ IOReturn kr = (*interface_interface)
+ ->ReadPipeAsyncTO(interface_interface, pipe_reference,
+ buffer->front_as<void*>(),
+ static_cast<uint32_t>(buffer->size()),
+ timeout, timeout, &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to read from device: " << std::hex << kr;
+ std::move((*result.first)->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::BulkOut(
+ const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ uint32_t timeout,
+ std::unique_ptr<Transfer> transfer) {
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+ IOReturn kr = (*interface_interface)
+ ->WritePipeAsyncTO(interface_interface, pipe_reference,
+ buffer->front_as<void*>(),
+ static_cast<uint32_t>(buffer->size()),
+ timeout, timeout, &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to write to device: " << std::hex << kr;
+ std::move((*result.first)->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::InterruptIn(
+ const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ std::unique_ptr<Transfer> transfer) {
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+ IOReturn kr = (*interface_interface)
+ ->ReadPipeAsync(interface_interface, pipe_reference,
+ buffer->front_as<void*>(),
+ static_cast<uint32_t>(buffer->size()),
+ &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to read from device: " << std::hex << kr;
+ std::move(transfer->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::InterruptOut(
+ const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ std::unique_ptr<Transfer> transfer) {
+ Transfer* transfer_data = transfer.get();
+ auto result = transfers_.insert(std::move(transfer));
+ IOReturn kr = (*interface_interface)
+ ->WritePipeAsync(interface_interface, pipe_reference,
+ buffer->front_as<void*>(),
+ static_cast<uint32_t>(buffer->size()),
+ &AsyncIoCallback,
+ reinterpret_cast<void*>(transfer_data));
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to write to device: " << std::hex << kr;
+ std::move(transfer->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR, buffer, 0);
+ transfers_.erase(result.first);
+ }
+}
+
+void UsbDeviceHandleMac::RefreshEndpointMap() {
+ endpoint_map_.clear();
+ const mojom::UsbConfigurationInfo* config = device_->GetActiveConfiguration();
+ if (!config)
+ return;
+
+ for (const auto& map_entry : interfaces_) {
+ uint8_t alternate_setting;
+ IOReturn kr =
+ (*map_entry.second)
+ ->GetAlternateSetting(map_entry.second, &alternate_setting);
+ if (kr != kIOReturnSuccess)
+ continue;
+ CombinedInterfaceInfo interface_info =
+ FindInterfaceInfoFromConfig(config, map_entry.first, alternate_setting);
+
+ if (!interface_info.IsValid())
+ continue;
+
+ // macOS references an interface's endpoint via an index number of the
+ // endpoint we want in the given interface. It is called a pipe reference.
+ // The indices start at 1 for each interface.
+ uint8_t pipe_reference = 1;
+ for (const auto& endpoint : interface_info.alternate->endpoints) {
+ endpoint_map_[ConvertEndpointNumberToAddress(*endpoint)] = {
+ interface_info.interface, endpoint.get(), pipe_reference};
+ pipe_reference++;
+ }
+ }
+}
+
+void UsbDeviceHandleMac::ReportIsochronousTransferError(
+ UsbDeviceHandle::IsochronousTransferCallback callback,
+ std::vector<uint32_t> packet_lengths,
+ mojom::UsbTransferStatus status) {
+ std::vector<mojom::UsbIsochronousPacketPtr> packets;
+ packets.reserve(packet_lengths.size());
+ for (const auto& packet_length : packet_lengths) {
+ auto packet = mojom::UsbIsochronousPacket::New();
+ packet->length = packet_length;
+ packet->transferred_length = 0;
+ packet->status = status;
+ packets.push_back(std::move(packet));
+ }
+ std::move(callback).Run(nullptr, std::move(packets));
+}
+
+void UsbDeviceHandleMac::Clear() {
+ base::flat_set<std::unique_ptr<Transfer>, base::UniquePtrComparator>
+ transfers;
+ transfers.swap(transfers_);
+ for (auto& transfer : transfers) {
+ DCHECK(transfer);
+ if (transfer->type == mojom::UsbTransferType::ISOCHRONOUS) {
+ ReportIsochronousTransferError(std::move(transfer->isochronous_callback),
+ transfer->packet_lengths,
+ mojom::UsbTransferStatus::TRANSFER_ERROR);
+ } else {
+ std::move(transfer->generic_callback)
+ .Run(mojom::UsbTransferStatus::TRANSFER_ERROR,
+ std::move(transfer->buffer), 0);
+ }
+ }
+ transfers.clear();
+ interfaces_.clear();
+ sources_.clear();
+}
+
+void UsbDeviceHandleMac::OnAsyncGeneric(IOReturn result,
+ size_t size,
+ Transfer* transfer) {
+ auto transfer_it = transfers_.find(transfer);
+ if (transfer_it == transfers_.end())
+ return;
+ auto transfer_ptr = std::move(*transfer_it);
+
+ std::move(transfer_ptr->generic_callback)
+ .Run(mojom::UsbTransferStatus::COMPLETED, transfer_ptr->buffer,
+ transfer_ptr->buffer->size());
+ transfers_.erase(transfer_it);
+}
+
+void UsbDeviceHandleMac::OnAsyncIsochronous(IOReturn result,
+ size_t size,
+ Transfer* transfer) {
+ auto transfer_it = transfers_.find(transfer);
+ if (transfer_it == transfers_.end())
+ return;
+ auto transfer_ptr = std::move(*transfer_it);
+
+ std::vector<mojom::UsbIsochronousPacketPtr> packets;
+ packets.reserve(transfer_ptr->frame_list.size());
+ for (const auto& frame : transfer_ptr->frame_list) {
+ auto packet = mojom::UsbIsochronousPacket::New();
+ packet->length = frame.frReqCount;
+ packet->transferred_length = frame.frActCount;
+ packet->status = ConvertTransferStatus(frame.frStatus);
+ packets.push_back(std::move(packet));
+ }
+
+ std::move(transfer_ptr->isochronous_callback)
+ .Run(transfer_ptr->buffer, std::move(packets));
+ transfers_.erase(transfer_it);
+}
+
+// static
+void UsbDeviceHandleMac::AsyncIoCallback(void* refcon,
+ IOReturn result,
+ void* arg0) {
+ auto* transfer = reinterpret_cast<Transfer*>(refcon);
+ DCHECK(transfer);
+ DCHECK(transfer->handle);
+ if (transfer->type == mojom::UsbTransferType::ISOCHRONOUS) {
+ transfer->handle->OnAsyncIsochronous(result, reinterpret_cast<size_t>(arg0),
+ transfer);
+ return;
+ }
+ transfer->handle->OnAsyncGeneric(result, reinterpret_cast<size_t>(arg0),
+ transfer);
+}
+
+} // namespace device
diff --git a/chromium/services/device/usb/usb_device_handle_mac.h b/chromium/services/device/usb/usb_device_handle_mac.h
new file mode 100644
index 00000000000..a8fbd4c3a47
--- /dev/null
+++ b/chromium/services/device/usb/usb_device_handle_mac.h
@@ -0,0 +1,146 @@
+// 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_DEVICE_USB_USB_DEVICE_HANDLE_MAC_H_
+#define SERVICES_DEVICE_USB_USB_DEVICE_HANDLE_MAC_H_
+
+#include "services/device/usb/usb_device_handle.h"
+
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOReturn.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+#include <memory>
+#include <vector>
+
+#include "base/containers/flat_set.h"
+#include "base/containers/unique_ptr_adapters.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "base/mac/scoped_ioplugininterface.h"
+#include "services/device/public/mojom/usb_device.mojom.h"
+
+namespace base {
+class RefCountedBytes;
+}
+
+namespace device {
+
+class UsbDeviceMac;
+struct Transfer;
+
+class UsbDeviceHandleMac : public UsbDeviceHandle {
+ public:
+ using ScopedIOUSBDeviceInterface =
+ base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182>;
+ using ScopedIOUSBInterfaceInterface =
+ base::mac::ScopedIOPluginInterface<IOUSBInterfaceInterface182>;
+
+ // UsbDeviceHandle implementation:
+ UsbDeviceHandleMac(scoped_refptr<UsbDeviceMac> device,
+ ScopedIOUSBDeviceInterface device_interface);
+ UsbDeviceHandleMac(const UsbDeviceHandleMac&) = delete;
+ UsbDeviceHandleMac& operator=(const UsbDeviceHandleMac&) = delete;
+ scoped_refptr<UsbDevice> GetDevice() const override;
+ void Close() override;
+ void SetConfiguration(int configuration_value,
+ ResultCallback callback) override;
+ void ClaimInterface(int interface_number, ResultCallback callback) override;
+ void ReleaseInterface(int interface_number, ResultCallback callback) override;
+ void SetInterfaceAlternateSetting(int interface_number,
+ int alternate_setting,
+ ResultCallback callback) override;
+ void ResetDevice(ResultCallback callback) override;
+ void ClearHalt(mojom::UsbTransferDirection direction,
+ uint8_t endpoint_number,
+ ResultCallback callback) override;
+ void ControlTransfer(mojom::UsbTransferDirection direction,
+ mojom::UsbControlTransferType request_type,
+ mojom::UsbControlTransferRecipient recipient,
+ uint8_t request,
+ uint16_t value,
+ uint16_t index,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ unsigned int timeout,
+ TransferCallback callback) override;
+ void IsochronousTransferIn(uint8_t endpoint,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ IsochronousTransferCallback callback) override;
+ void IsochronousTransferOut(uint8_t endpoint,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ const std::vector<uint32_t>& packet_lengths,
+ unsigned int timeout,
+ IsochronousTransferCallback callback) override;
+ void GenericTransfer(mojom::UsbTransferDirection direction,
+ uint8_t endpoint_number,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ unsigned int timeout,
+ TransferCallback callback) override;
+ const mojom::UsbInterfaceInfo* FindInterfaceByEndpoint(
+ uint8_t endpoint_address) override;
+
+ protected:
+ ~UsbDeviceHandleMac() override;
+
+ private:
+ struct EndpointMapValue {
+ const mojom::UsbInterfaceInfo* interface;
+ const mojom::UsbEndpointInfo* endpoint;
+ uint8_t pipe_reference;
+ };
+
+ void BulkIn(const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ uint32_t timeout,
+ std::unique_ptr<Transfer> transfer);
+ void BulkOut(const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ uint32_t timeout,
+ std::unique_ptr<Transfer> transfer);
+ void InterruptIn(const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ std::unique_ptr<Transfer> transfer);
+ void InterruptOut(const ScopedIOUSBInterfaceInterface& interface_interface,
+ uint8_t pipe_reference,
+ scoped_refptr<base::RefCountedBytes> buffer,
+ std::unique_ptr<Transfer> transfer);
+ // Refresh endpoint_map_ after ClaimInterface, ReleaseInterface and
+ // SetInterfaceAlternateSetting. It is needed so that endpoints can be mapped
+ // to their respective mojom Interface.
+ void RefreshEndpointMap();
+
+ void ReportIsochronousTransferError(
+ UsbDeviceHandle::IsochronousTransferCallback callback,
+ std::vector<uint32_t> packet_lengths,
+ mojom::UsbTransferStatus status);
+
+ void Clear();
+
+ void OnAsyncGeneric(IOReturn result, size_t size, Transfer* transfer);
+ void OnAsyncIsochronous(IOReturn result, size_t size, Transfer* transfer);
+ static void AsyncIoCallback(void* refcon, IOReturn result, void* arg0);
+
+ // A map from the endpoint indices to its corresponding EndpointMapValue,
+ // which contains the Interface and Endpoint Mojo structures.
+ using EndpointMap = base::flat_map<int, EndpointMapValue>;
+ EndpointMap endpoint_map_;
+
+ base::flat_set<std::unique_ptr<Transfer>, base::UniquePtrComparator>
+ transfers_;
+
+ ScopedIOUSBDeviceInterface device_interface_;
+ scoped_refptr<UsbDeviceMac> device_;
+
+ // Both maps take the interface number in as the respective key.
+ base::flat_map<uint8_t, ScopedIOUSBInterfaceInterface> interfaces_;
+ base::flat_map<uint8_t, base::ScopedCFTypeRef<CFRunLoopSourceRef>> sources_;
+};
+
+} // namespace device
+
+#endif // SERVICES_DEVICE_USB_USB_DEVICE_HANDLE_MAC_H_
diff --git a/chromium/services/device/usb/usb_device_handle_win.cc b/chromium/services/device/usb/usb_device_handle_win.cc
index e9364245b16..1d94b7dc08c 100644
--- a/chromium/services/device/usb/usb_device_handle_win.cc
+++ b/chromium/services/device/usb/usb_device_handle_win.cc
@@ -46,7 +46,7 @@ using mojom::UsbTransferStatus;
namespace {
-const base::StringPiece16 kWinUsbDriverName = L"winusb";
+const base::WStringPiece kWinUsbDriverName = L"winusb";
uint8_t BuildRequestFlags(UsbTransferDirection direction,
UsbControlTransferType request_type,
@@ -618,8 +618,8 @@ UsbDeviceHandleWin::~UsbDeviceHandleWin() {
}
void UsbDeviceHandleWin::UpdateFunction(int interface_number,
- const base::string16& function_driver,
- const base::string16& function_path) {
+ const std::wstring& function_driver,
+ const std::wstring& function_path) {
auto it = interfaces_.find(interface_number);
if (it == interfaces_.end())
return;
diff --git a/chromium/services/device/usb/usb_device_handle_win.h b/chromium/services/device/usb/usb_device_handle_win.h
index c0a736b67d3..de6e1459697 100644
--- a/chromium/services/device/usb/usb_device_handle_win.h
+++ b/chromium/services/device/usb/usb_device_handle_win.h
@@ -86,8 +86,8 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
~UsbDeviceHandleWin() override;
void UpdateFunction(int interface_number,
- const base::string16& function_driver,
- const base::string16& function_path);
+ const std::wstring& function_driver,
+ const std::wstring& function_path);
private:
struct Interface;
@@ -102,8 +102,8 @@ class UsbDeviceHandleWin : public UsbDeviceHandle {
const mojom::UsbInterfaceInfo* info;
// In a composite device each function has its own driver and path to open.
- base::string16 function_driver;
- base::string16 function_path;
+ std::wstring function_driver;
+ std::wstring function_path;
base::win::ScopedHandle function_handle;
ScopedWinUsbHandle handle;
diff --git a/chromium/services/device/usb/usb_device_impl.cc b/chromium/services/device/usb/usb_device_impl.cc
index ed259413c9f..94f2d9c8cf4 100644
--- a/chromium/services/device/usb/usb_device_impl.cc
+++ b/chromium/services/device/usb/usb_device_impl.cc
@@ -78,7 +78,7 @@ void UsbDeviceImpl::ReadAllConfigurations() {
continue;
}
- if (!usb_descriptor.Parse(std::vector<uint8_t>(buffer, buffer + rv)))
+ if (!usb_descriptor.Parse(base::make_span(buffer, rv)))
USB_LOG(EVENT) << "Config descriptor index " << i << " was corrupt.";
free(buffer);
diff --git a/chromium/services/device/usb/usb_device_mac.cc b/chromium/services/device/usb/usb_device_mac.cc
new file mode 100644
index 00000000000..d67e566d1ea
--- /dev/null
+++ b/chromium/services/device/usb/usb_device_mac.cc
@@ -0,0 +1,87 @@
+// 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/device/usb/usb_device_mac.h"
+
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/IOReturn.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+#include <utility>
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_ionotificationportref.h"
+#include "base/mac/scoped_ioobject.h"
+#include "base/mac/scoped_ioplugininterface.h"
+#include "components/device_event_log/device_event_log.h"
+#include "services/device/usb/usb_descriptors.h"
+#include "services/device/usb/usb_device_handle.h"
+#include "services/device/usb/usb_device_handle_mac.h"
+
+namespace device {
+
+UsbDeviceMac::UsbDeviceMac(uint64_t entry_id,
+ mojom::UsbDeviceInfoPtr device_info)
+ : UsbDevice(std::move(device_info)), entry_id_(entry_id) {}
+
+UsbDeviceMac::~UsbDeviceMac() = default;
+
+void UsbDeviceMac::Open(OpenCallback callback) {
+ base::ScopedCFTypeRef<CFDictionaryRef> matching_dict(
+ IORegistryEntryIDMatching(entry_id()));
+ if (!matching_dict.get()) {
+ USB_LOG(ERROR) << "Failed to create matching dictionary for ID.";
+ std::move(callback).Run(nullptr);
+ return;
+ }
+ // IOServiceGetMatchingService consumes a reference to the matching dictionary
+ // passed to it.
+ base::mac::ScopedIOObject<io_service_t> usb_device(
+ IOServiceGetMatchingService(kIOMasterPortDefault,
+ matching_dict.release()));
+ if (!usb_device.get()) {
+ USB_LOG(ERROR) << "IOService not found for ID.";
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_interface;
+ int32_t score;
+ IOReturn kr = IOCreatePlugInInterfaceForService(
+ usb_device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
+ plugin_interface.InitializeInto(), &score);
+ if ((kr != kIOReturnSuccess) || !plugin_interface) {
+ USB_LOG(ERROR) << "Unable to create a plug-in: " << std::hex << kr;
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface;
+ kr = (*plugin_interface)
+ ->QueryInterface(
+ plugin_interface.get(),
+ CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
+ reinterpret_cast<LPVOID*>(device_interface.InitializeInto()));
+ if (kr != kIOReturnSuccess || !device_interface) {
+ USB_LOG(ERROR) << "Couldn’t create a device interface.";
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ kr = (*device_interface)->USBDeviceOpen(device_interface);
+ if (kr != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to open device: " << std::hex << kr;
+ std::move(callback).Run(nullptr);
+ return;
+ }
+
+ auto device_handle = base::MakeRefCounted<UsbDeviceHandleMac>(
+ this, std::move(device_interface));
+
+ handles().push_back(device_handle.get());
+ std::move(callback).Run(device_handle);
+}
+
+} // namespace device
diff --git a/chromium/services/device/usb/usb_device_mac.h b/chromium/services/device/usb/usb_device_mac.h
new file mode 100644
index 00000000000..f27b56b1ac3
--- /dev/null
+++ b/chromium/services/device/usb/usb_device_mac.h
@@ -0,0 +1,32 @@
+// 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_DEVICE_USB_USB_DEVICE_MAC_H_
+#define SERVICES_DEVICE_USB_USB_DEVICE_MAC_H_
+
+#include "services/device/usb/usb_device.h"
+
+namespace device {
+
+class UsbDeviceMac : public UsbDevice {
+ public:
+ UsbDeviceMac(uint64_t entry_id, mojom::UsbDeviceInfoPtr device_info);
+ UsbDeviceMac(const UsbDeviceMac&) = delete;
+ UsbDeviceMac& operator=(const UsbDeviceMac&) = delete;
+
+ // UsbDevice implementation:
+ void Open(OpenCallback callback) override;
+
+ uint64_t entry_id() const { return entry_id_; }
+
+ protected:
+ ~UsbDeviceMac() override;
+
+ private:
+ const uint64_t entry_id_;
+};
+
+} // namespace device
+
+#endif // SERVICES_DEVICE_USB_USB_DEVICE_MAC_H_
diff --git a/chromium/services/device/usb/usb_device_win.cc b/chromium/services/device/usb/usb_device_win.cc
index 940b0ee2ad8..f5303bf93b7 100644
--- a/chromium/services/device/usb/usb_device_win.cc
+++ b/chromium/services/device/usb/usb_device_win.cc
@@ -24,12 +24,12 @@ namespace {
const uint16_t kUsbVersion2_1 = 0x0210;
} // namespace
-UsbDeviceWin::UsbDeviceWin(const base::string16& device_path,
- const base::string16& hub_path,
+UsbDeviceWin::UsbDeviceWin(const std::wstring& device_path,
+ const std::wstring& hub_path,
const base::flat_map<int, FunctionInfo>& functions,
uint32_t bus_number,
uint32_t port_number,
- const base::string16& driver_name)
+ const std::wstring& driver_name)
: UsbDevice(bus_number, port_number),
device_path_(device_path),
hub_path_(hub_path),
@@ -111,11 +111,11 @@ void UsbDeviceWin::OnReadDescriptors(
auto string_map = std::make_unique<std::map<uint8_t, base::string16>>();
if (descriptor->i_manufacturer)
- (*string_map)[descriptor->i_manufacturer] = base::string16();
+ (*string_map)[descriptor->i_manufacturer];
if (descriptor->i_product)
- (*string_map)[descriptor->i_product] = base::string16();
+ (*string_map)[descriptor->i_product];
if (descriptor->i_serial_number)
- (*string_map)[descriptor->i_serial_number] = base::string16();
+ (*string_map)[descriptor->i_serial_number];
ReadUsbStringDescriptors(
device_handle, std::move(string_map),
diff --git a/chromium/services/device/usb/usb_device_win.h b/chromium/services/device/usb/usb_device_win.h
index 9a6198128b2..11fcdf533ee 100644
--- a/chromium/services/device/usb/usb_device_win.h
+++ b/chromium/services/device/usb/usb_device_win.h
@@ -23,16 +23,16 @@ struct WebUsbPlatformCapabilityDescriptor;
class UsbDeviceWin : public UsbDevice {
public:
struct FunctionInfo {
- base::string16 driver;
- base::string16 path;
+ std::wstring driver;
+ std::wstring path;
};
- UsbDeviceWin(const base::string16& device_path,
- const base::string16& hub_path,
+ UsbDeviceWin(const std::wstring& device_path,
+ const std::wstring& hub_path,
const base::flat_map<int, FunctionInfo>& functions,
uint32_t bus_number,
uint32_t port_number,
- const base::string16& driver_name);
+ const std::wstring& driver_name);
// UsbDevice implementation:
void Open(OpenCallback callback) override;
@@ -43,11 +43,11 @@ class UsbDeviceWin : public UsbDevice {
~UsbDeviceWin() override;
- const base::string16& device_path() const { return device_path_; }
+ const std::wstring& device_path() const { return device_path_; }
const base::flat_map<int, FunctionInfo>& functions() const {
return functions_;
}
- const base::string16& driver_name() const { return driver_name_; }
+ const std::wstring& driver_name() const { return driver_name_; }
// Opens the device's parent hub in order to read the device, configuration
// and string descriptors.
@@ -82,10 +82,10 @@ class UsbDeviceWin : public UsbDevice {
private:
SEQUENCE_CHECKER(sequence_checker_);
- const base::string16 device_path_;
- const base::string16 hub_path_;
+ const std::wstring device_path_;
+ const std::wstring hub_path_;
base::flat_map<int, FunctionInfo> functions_;
- const base::string16 driver_name_;
+ const std::wstring driver_name_;
DISALLOW_COPY_AND_ASSIGN(UsbDeviceWin);
};
diff --git a/chromium/services/device/usb/usb_interface_android.cc b/chromium/services/device/usb/usb_interface_android.cc
index decb143deda..707f0585627 100644
--- a/chromium/services/device/usb/usb_interface_android.cc
+++ b/chromium/services/device/usb/usb_interface_android.cc
@@ -4,7 +4,6 @@
#include "services/device/usb/usb_interface_android.h"
-#include "base/android/build_info.h"
#include "services/device/usb/jni_headers/ChromeUsbInterface_jni.h"
#include "services/device/usb/usb_endpoint_android.h"
@@ -19,12 +18,8 @@ mojom::UsbInterfaceInfoPtr UsbInterfaceAndroid::Convert(
ScopedJavaLocalRef<jobject> wrapper =
Java_ChromeUsbInterface_create(env, usb_interface);
- uint8_t alternate_setting = 0;
- if (base::android::BuildInfo::GetInstance()->sdk_int() >=
- base::android::SDK_VERSION_LOLLIPOP) {
- alternate_setting =
- Java_ChromeUsbInterface_getAlternateSetting(env, wrapper);
- }
+ uint8_t alternate_setting =
+ Java_ChromeUsbInterface_getAlternateSetting(env, wrapper);
auto interface = BuildUsbInterfaceInfoPtr(
Java_ChromeUsbInterface_getInterfaceNumber(env, wrapper),
diff --git a/chromium/services/device/usb/usb_service.cc b/chromium/services/device/usb/usb_service.cc
index b41322ff990..94be02cc9dd 100644
--- a/chromium/services/device/usb/usb_service.cc
+++ b/chromium/services/device/usb/usb_service.cc
@@ -4,6 +4,8 @@
#include "services/device/usb/usb_service.h"
+#include <utility>
+
#include "base/bind.h"
#include "base/feature_list.h"
#include "base/location.h"
@@ -21,7 +23,9 @@
#elif defined(USE_UDEV)
#include "services/device/usb/usb_service_linux.h"
#else
-#if defined(OS_WIN)
+#if defined(OS_MAC)
+#include "services/device/usb/usb_service_mac.h"
+#elif defined(OS_WIN)
#include "services/device/usb/usb_service_win.h"
#endif
#include "services/device/usb/usb_service_impl.h"
@@ -54,8 +58,11 @@ std::unique_ptr<UsbService> UsbService::Create() {
return base::WrapUnique(new UsbServiceWin());
else
return base::WrapUnique(new UsbServiceImpl());
-#elif defined(OS_MACOSX)
- return base::WrapUnique(new UsbServiceImpl());
+#elif defined(OS_MAC)
+ if (base::FeatureList::IsEnabled(kNewUsbBackend))
+ return base::WrapUnique(new UsbServiceMac());
+ else
+ return base::WrapUnique(new UsbServiceImpl());
#else
return nullptr;
#endif
diff --git a/chromium/services/device/usb/usb_service_impl.cc b/chromium/services/device/usb/usb_service_impl.cc
index 3cb6beea47a..759a3f19dc9 100644
--- a/chromium/services/device/usb/usb_service_impl.cc
+++ b/chromium/services/device/usb/usb_service_impl.cc
@@ -50,7 +50,7 @@ const uint16_t kUsbVersion2_1 = 0x0210;
#if defined(OS_WIN)
-bool IsWinUsbInterface(const base::string16& device_path) {
+bool IsWinUsbInterface(const std::wstring& device_path) {
DeviceInfoQueryWin device_info_query;
if (!device_info_query.device_info_list_valid()) {
USB_PLOG(ERROR) << "Failed to create a device information set";
@@ -97,7 +97,7 @@ scoped_refptr<UsbContext> InitializeUsbContextBlocking() {
}
base::Optional<std::vector<ScopedLibusbDeviceRef>> GetDeviceListBlocking(
- const base::string16& new_device_path,
+ const std::wstring& new_device_path,
scoped_refptr<UsbContext> usb_context) {
base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
base::BlockingType::MAY_BLOCK);
@@ -267,20 +267,20 @@ void UsbServiceImpl::GetDevices(GetDevicesCallback callback) {
#if defined(OS_WIN)
void UsbServiceImpl::OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& device_path) {
// Only the root node of a composite USB device has the class GUID
// GUID_DEVINTERFACE_USB_DEVICE but we want to wait until WinUSB is loaded.
// This first pass filter will catch anything that's sitting on the USB bus
// (including devices on 3rd party USB controllers) to avoid the more
// expensive driver check that needs to be done on the FILE thread.
- if (device_path.find(L"usb") != base::string16::npos) {
+ if (device_path.find(L"usb") != std::wstring::npos) {
pending_path_enumerations_.push(device_path);
RefreshDevices();
}
}
void UsbServiceImpl::OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& device_path) {
// The root USB device node is removed last.
if (class_guid == GUID_DEVINTERFACE_USB_DEVICE) {
RefreshDevices();
@@ -326,7 +326,7 @@ void UsbServiceImpl::RefreshDevices() {
enumeration_in_progress_ = true;
DCHECK(devices_being_enumerated_.empty());
- base::string16 device_path;
+ std::wstring device_path;
if (!pending_path_enumerations_.empty()) {
device_path = pending_path_enumerations_.front();
pending_path_enumerations_.pop();
diff --git a/chromium/services/device/usb/usb_service_impl.h b/chromium/services/device/usb/usb_service_impl.h
index 669f8576f24..32a2efb106b 100644
--- a/chromium/services/device/usb/usb_service_impl.h
+++ b/chromium/services/device/usb/usb_service_impl.h
@@ -53,9 +53,9 @@ class UsbServiceImpl final :
#if defined(OS_WIN)
// device::DeviceMonitorWin::Observer implementation
void OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
void OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
#endif // OS_WIN
void OnUsbContext(scoped_refptr<UsbContext> context);
@@ -101,7 +101,7 @@ class UsbServiceImpl final :
// Enumeration callbacks are queued until an enumeration completes.
bool enumeration_ready_ = false;
bool enumeration_in_progress_ = false;
- base::queue<base::string16> pending_path_enumerations_;
+ base::queue<std::wstring> pending_path_enumerations_;
std::vector<GetDevicesCallback> pending_enumeration_callbacks_;
// The map from libusb_device to UsbDeviceImpl. The key is a weak pointer to
diff --git a/chromium/services/device/usb/usb_service_linux.cc b/chromium/services/device/usb/usb_service_linux.cc
index 7e7eb833b76..2328c9300bb 100644
--- a/chromium/services/device/usb/usb_service_linux.cc
+++ b/chromium/services/device/usb/usb_service_linux.cc
@@ -149,8 +149,9 @@ void UsbServiceLinux::BlockingTaskRunnerHelper::OnDeviceAdded(
return;
std::unique_ptr<UsbDeviceDescriptor> descriptor(new UsbDeviceDescriptor());
- if (!descriptor->Parse(std::vector<uint8_t>(descriptors_str.begin(),
- descriptors_str.end()))) {
+ if (!descriptor->Parse(base::make_span(
+ reinterpret_cast<const uint8_t*>(descriptors_str.data()),
+ descriptors_str.size()))) {
return;
}
diff --git a/chromium/services/device/usb/usb_service_mac.cc b/chromium/services/device/usb/usb_service_mac.cc
new file mode 100644
index 00000000000..ecf36d7e6ea
--- /dev/null
+++ b/chromium/services/device/usb/usb_service_mac.cc
@@ -0,0 +1,326 @@
+// 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/device/usb/usb_service_mac.h"
+
+#include <CoreFoundation/CFBase.h>
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOCFPlugIn.h>
+#include <IOKit/IOReturn.h>
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_ioplugininterface.h"
+#include "base/optional.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/sys_string_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "components/device_event_log/device_event_log.h"
+#include "services/device/usb/usb_descriptors.h"
+#include "services/device/usb/usb_device_mac.h"
+
+namespace device {
+
+namespace {
+
+// USB class codes are defined by the USB specification.
+// https://www.usb.org/defined-class-codes
+constexpr uint8_t kDeviceClassHub = 0x09;
+
+// These methods are similar to the ones used by HidServiceMac.
+// TODO(https://crbug.com/1104271): Move these methods into a shared utility
+// file.
+base::Optional<base::string16> GetStringProperty(io_service_t service,
+ CFStringRef key) {
+ base::ScopedCFTypeRef<CFStringRef> ref(base::mac::CFCast<CFStringRef>(
+ IORegistryEntryCreateCFProperty(service, key, kCFAllocatorDefault, 0)));
+
+ if (!ref)
+ return base::nullopt;
+
+ return base::SysCFStringRefToUTF16(ref);
+}
+
+base::Optional<uint16_t> GetUint16Property(io_service_t service,
+ CFStringRef property) {
+ base::ScopedCFTypeRef<CFNumberRef> cf_number(
+ base::mac::CFCast<CFNumberRef>(IORegistryEntryCreateCFProperty(
+ service, property, kCFAllocatorDefault, 0)));
+
+ if (!cf_number)
+ return base::nullopt;
+ if (CFGetTypeID(cf_number) != CFNumberGetTypeID())
+ return base::nullopt;
+ uint16_t value;
+ if (!CFNumberGetValue((CFNumberRef)cf_number, kCFNumberSInt16Type, &value))
+ return base::nullopt;
+ return value;
+}
+
+base::Optional<uint8_t> GetUint8Property(io_service_t service,
+ CFStringRef property) {
+ base::ScopedCFTypeRef<CFNumberRef> cf_number(
+ base::mac::CFCast<CFNumberRef>(IORegistryEntryCreateCFProperty(
+ service, property, kCFAllocatorDefault, 0)));
+
+ bool success = false;
+ uint8_t value;
+ if (cf_number) {
+ if (CFGetTypeID(cf_number) == CFNumberGetTypeID()) {
+ success =
+ CFNumberGetValue((CFNumberRef)cf_number, kCFNumberSInt8Type, &value);
+ }
+ }
+
+ if (success)
+ return value;
+
+ return base::nullopt;
+}
+
+} // namespace
+
+UsbServiceMac::UsbServiceMac() {
+ notify_port_.reset(IONotificationPortCreate(kIOMasterPortDefault));
+ CFRunLoopAddSource(CFRunLoopGetMain(),
+ IONotificationPortGetRunLoopSource(notify_port_.get()),
+ kCFRunLoopDefaultMode);
+
+ IOReturn result = IOServiceAddMatchingNotification(
+ notify_port_.get(), kIOFirstMatchNotification,
+ IOServiceMatching(kIOUSBDeviceClassName), FirstMatchCallback, this,
+ devices_added_iterator_.InitializeInto());
+ if (result != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to listen for device arrival: " << std::hex
+ << result << ".";
+ return;
+ }
+ // Drain |devices_added_iterator_| to arm the notification.
+ AddDevices();
+
+ result = IOServiceAddMatchingNotification(
+ notify_port_.get(), kIOTerminatedNotification,
+ IOServiceMatching(kIOUSBDeviceClassName), TerminatedCallback, this,
+ devices_removed_iterator_.InitializeInto());
+ if (result != kIOReturnSuccess) {
+ USB_LOG(ERROR) << "Failed to listen for device removal: " << std::hex
+ << result << ".";
+ return;
+ }
+
+ // Drain |devices_removed_iterator_| to arm the notification.
+ RemoveDevices();
+}
+
+UsbServiceMac::~UsbServiceMac() = default;
+
+// static
+void UsbServiceMac::FirstMatchCallback(void* context, io_iterator_t iterator) {
+ DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent());
+ UsbServiceMac* service = reinterpret_cast<UsbServiceMac*>(context);
+ DCHECK_EQ(service->devices_added_iterator_, iterator);
+ service->AddDevices();
+}
+
+// static
+void UsbServiceMac::TerminatedCallback(void* context, io_iterator_t iterator) {
+ DCHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent());
+ UsbServiceMac* service = reinterpret_cast<UsbServiceMac*>(context);
+ DCHECK_EQ(service->devices_removed_iterator_, iterator);
+ service->RemoveDevices();
+}
+
+void UsbServiceMac::AddDevices() {
+ base::mac::ScopedIOObject<io_service_t> device;
+ while (device.reset(IOIteratorNext(devices_added_iterator_)), device) {
+ AddDevice(device);
+ }
+}
+
+void UsbServiceMac::AddDevice(io_service_t device) {
+ base::mac::ScopedIOPluginInterface<IOCFPlugInInterface> plugin_interface;
+ int32_t score;
+
+ // This call fails sometimes due to a resource shortage.
+ // TODO(richardmachado): Figure out what is causing this failure.
+ IOReturn kr = IOCreatePlugInInterfaceForService(
+ device, kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
+ plugin_interface.InitializeInto(), &score);
+
+ if ((kr != kIOReturnSuccess) || !plugin_interface.get()) {
+ USB_LOG(ERROR) << "Unable to create a plug-in: " << std::hex << kr << ".";
+ return;
+ }
+
+ base::mac::ScopedIOPluginInterface<IOUSBDeviceInterface182> device_interface;
+ kr = (*plugin_interface)
+ ->QueryInterface(
+ plugin_interface.get(),
+ CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID),
+ reinterpret_cast<LPVOID*>(device_interface.InitializeInto()));
+
+ if (kr != kIOReturnSuccess || !device_interface) {
+ USB_LOG(ERROR) << "Couldn’t create a device interface.";
+ return;
+ }
+
+ uint8_t device_class;
+ if ((*device_interface)->GetDeviceClass(device_interface, &device_class) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ // We don't want to enumerate hubs.
+ if (device_class == kDeviceClassHub)
+ return;
+
+ uint16_t vendor_id;
+ if ((*device_interface)->GetDeviceVendor(device_interface, &vendor_id) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint16_t product_id;
+ if ((*device_interface)->GetDeviceProduct(device_interface, &product_id) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint8_t device_protocol;
+ if ((*device_interface)
+ ->GetDeviceProtocol(device_interface, &device_protocol) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint8_t device_subclass;
+ if ((*device_interface)
+ ->GetDeviceSubClass(device_interface, &device_subclass) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint16_t device_version;
+ if ((*device_interface)
+ ->GetDeviceReleaseNumber(device_interface, &device_version) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint32_t location_id;
+ if ((*device_interface)->GetLocationID(device_interface, &location_id) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ uint64_t entry_id;
+ if (IORegistryEntryGetRegistryEntryID(device, &entry_id) != kIOReturnSuccess)
+ return;
+
+ base::Optional<uint8_t> property_uint8 =
+ GetUint8Property(device, CFSTR("PortNum"));
+ if (!property_uint8.has_value())
+ return;
+ uint8_t port_number = property_uint8.value();
+
+ base::Optional<uint16_t> property_uint16 =
+ GetUint16Property(device, CFSTR("bcdUSB"));
+ uint16_t usb_version;
+ if (!property_uint16.has_value())
+ return;
+ usb_version = property_uint16.value();
+
+ base::Optional<base::string16> property_string16 =
+ GetStringProperty(device, CFSTR(kUSBVendorString));
+ base::string16 manufacturer_string;
+ if (property_string16.has_value())
+ manufacturer_string = property_string16.value();
+
+ property_string16 = GetStringProperty(device, CFSTR(kUSBSerialNumberString));
+ base::string16 serial_number_string;
+ if (property_string16.has_value())
+ serial_number_string = property_string16.value();
+
+ property_string16 = GetStringProperty(device, CFSTR(kUSBProductString));
+ base::string16 product_string;
+ if (property_string16.has_value())
+ product_string = property_string16.value();
+
+ uint8_t num_config;
+ if ((*device_interface)
+ ->GetNumberOfConfigurations(device_interface, &num_config) !=
+ kIOReturnSuccess) {
+ return;
+ }
+
+ // Populate device descriptor with all necessary configuration info.
+ auto descriptor = std::make_unique<UsbDeviceDescriptor>();
+ IOUSBConfigurationDescriptorPtr desc;
+ for (uint8_t i = 0; i < num_config; i++) {
+ if ((*device_interface)
+ ->GetConfigurationDescriptorPtr(device_interface, i, &desc) !=
+ kIOReturnSuccess) {
+ return;
+ }
+ if (!descriptor->Parse(base::make_span(reinterpret_cast<uint8_t*>(desc),
+ desc->wTotalLength))) {
+ return;
+ }
+ }
+
+ descriptor->device_info->usb_version_major = usb_version >> 8;
+ descriptor->device_info->usb_version_minor = usb_version >> 4 & 0xf;
+ descriptor->device_info->usb_version_subminor = usb_version & 0xf;
+ descriptor->device_info->class_code = device_class;
+ descriptor->device_info->subclass_code = device_subclass;
+ descriptor->device_info->protocol_code = device_protocol;
+ descriptor->device_info->vendor_id = vendor_id;
+ descriptor->device_info->product_id = product_id;
+ descriptor->device_info->device_version_major = device_version >> 8;
+ descriptor->device_info->device_version_minor = device_version >> 4 & 0xf;
+ descriptor->device_info->device_version_subminor = device_version & 0xf;
+ descriptor->device_info->manufacturer_name = manufacturer_string;
+ descriptor->device_info->product_name = product_string;
+ descriptor->device_info->serial_number = serial_number_string;
+ descriptor->device_info->bus_number = location_id >> 24;
+ descriptor->device_info->port_number = port_number;
+
+ scoped_refptr<UsbDeviceMac> mac_device =
+ new UsbDeviceMac(entry_id, std::move(descriptor->device_info));
+
+ device_map_[entry_id] = mac_device;
+ devices()[mac_device->guid()] = mac_device;
+
+ NotifyDeviceAdded(mac_device);
+}
+
+void UsbServiceMac::RemoveDevices() {
+ base::mac::ScopedIOObject<io_service_t> device;
+ while (device.reset(IOIteratorNext(devices_removed_iterator_)), device) {
+ uint64_t entry_id;
+
+ if (kIOReturnSuccess !=
+ IORegistryEntryGetRegistryEntryID(device, &entry_id)) {
+ continue;
+ }
+
+ auto it = device_map_.find(entry_id);
+ if (it == device_map_.end())
+ continue;
+
+ auto mac_device = it->second;
+ device_map_.erase(it);
+
+ auto by_guid_it = devices().find(mac_device->guid());
+ devices().erase(by_guid_it);
+ NotifyDeviceRemoved(mac_device);
+ mac_device->OnDisconnect();
+ }
+}
+
+} // namespace device
diff --git a/chromium/services/device/usb/usb_service_mac.h b/chromium/services/device/usb/usb_service_mac.h
new file mode 100644
index 00000000000..41457029e51
--- /dev/null
+++ b/chromium/services/device/usb/usb_service_mac.h
@@ -0,0 +1,55 @@
+// 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_DEVICE_USB_USB_SERVICE_MAC_H_
+#define SERVICES_DEVICE_USB_USB_SERVICE_MAC_H_
+
+#include <CoreFoundation/CoreFoundation.h>
+#include <IOKit/IOKitLib.h>
+#include <IOKit/usb/IOUSBLib.h>
+
+#include <string>
+#include <unordered_map>
+
+#include "base/mac/foundation_util.h"
+#include "base/mac/scoped_ionotificationportref.h"
+#include "base/mac/scoped_ioobject.h"
+#include "base/memory/weak_ptr.h"
+#include "services/device/usb/usb_service.h"
+
+namespace device {
+
+class UsbDeviceMac;
+
+// The USB service is responsible for device discovery on the system, which
+// allows it to re-use device handles to prevent competition for the same USB
+// device.
+class UsbServiceMac final : public UsbService {
+ public:
+ UsbServiceMac();
+ UsbServiceMac(const UsbServiceMac&) = delete;
+ UsbServiceMac& operator=(const UsbServiceMac&) = delete;
+ ~UsbServiceMac() override;
+
+ private:
+ // IOService matching callbacks.
+ static void FirstMatchCallback(void* context, io_iterator_t iterator);
+ static void TerminatedCallback(void* context, io_iterator_t iterator);
+
+ void AddDevices();
+ void AddDevice(io_service_t device);
+ void RemoveDevices();
+
+ std::unordered_map<uint64_t, scoped_refptr<UsbDeviceMac>> device_map_;
+
+ base::mac::ScopedIONotificationPortRef notify_port_;
+ base::mac::ScopedIOObject<io_iterator_t> devices_added_iterator_;
+ base::mac::ScopedIOObject<io_iterator_t> devices_removed_iterator_;
+
+ base::WeakPtrFactory<UsbServiceMac> weak_factory_{this};
+};
+
+} // namespace device
+
+#endif // SERVICES_DEVICE_USB_USB_SERVICE_MAC_H_
diff --git a/chromium/services/device/usb/usb_service_win.cc b/chromium/services/device/usb/usb_service_win.cc
index 4e8989f6d3d..587fe95742a 100644
--- a/chromium/services/device/usb/usb_service_win.cc
+++ b/chromium/services/device/usb/usb_service_win.cc
@@ -8,6 +8,7 @@
#include <setupapi.h>
#include <stdint.h>
#include <usbiodef.h>
+#include "base/strings/string_piece_forward.h"
#define INITGUID
#include <devpkey.h>
@@ -59,7 +60,7 @@ base::Optional<uint32_t> GetDeviceUint32Property(HDEVINFO dev_info,
return buffer;
}
-base::Optional<base::string16> GetDeviceStringProperty(
+base::Optional<std::wstring> GetDeviceStringProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
@@ -76,7 +77,7 @@ base::Optional<base::string16> GetDeviceStringProperty(
return base::nullopt;
}
- base::string16 buffer;
+ std::wstring buffer;
if (!SetupDiGetDeviceProperty(
dev_info, dev_info_data, &property, &property_type,
reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
@@ -87,7 +88,7 @@ base::Optional<base::string16> GetDeviceStringProperty(
return buffer;
}
-base::Optional<std::vector<base::string16>> GetDeviceStringListProperty(
+base::Optional<std::vector<std::wstring>> GetDeviceStringListProperty(
HDEVINFO dev_info,
SP_DEVINFO_DATA* dev_info_data,
const DEVPROPKEY& property) {
@@ -104,7 +105,7 @@ base::Optional<std::vector<base::string16>> GetDeviceStringListProperty(
return base::nullopt;
}
- base::string16 buffer;
+ std::wstring buffer;
if (!SetupDiGetDeviceProperty(
dev_info, dev_info_data, &property, &property_type,
reinterpret_cast<PBYTE>(base::WriteInto(&buffer, required_size)),
@@ -113,33 +114,32 @@ base::Optional<std::vector<base::string16>> GetDeviceStringListProperty(
}
// Windows string list properties use a NUL character as the delimiter.
- return base::SplitString(buffer, base::StringPiece16(L"\0", 1),
+ return base::SplitString(buffer, base::WStringPiece(L"\0", 1),
base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
}
-base::string16 GetServiceName(HDEVINFO dev_info,
- SP_DEVINFO_DATA* dev_info_data) {
- base::Optional<base::string16> property =
+std::wstring GetServiceName(HDEVINFO dev_info, SP_DEVINFO_DATA* dev_info_data) {
+ base::Optional<std::wstring> property =
GetDeviceStringProperty(dev_info, dev_info_data, DEVPKEY_Device_Service);
if (!property.has_value())
- return base::string16();
+ return std::wstring();
// Windows pads this string with a variable number of NUL bytes for no
// discernible reason.
- return base::TrimString(*property, base::StringPiece16(L"\0", 1),
+ return base::TrimString(*property, base::WStringPiece(L"\0", 1),
base::TRIM_TRAILING)
.as_string();
}
bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
SP_DEVICE_INTERFACE_DATA* device_interface_data,
- base::string16* device_path,
+ std::wstring* device_path,
uint32_t* bus_number,
uint32_t* port_number,
- base::string16* instance_id,
- base::string16* parent_instance_id,
- std::vector<base::string16>* child_instance_ids,
- base::string16* service_name) {
+ std::wstring* instance_id,
+ std::wstring* parent_instance_id,
+ std::vector<std::wstring>* child_instance_ids,
+ std::wstring* service_name) {
SP_DEVINFO_DATA dev_info_data = {};
dev_info_data.cbSize = sizeof(dev_info_data);
@@ -175,7 +175,7 @@ bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
}
if (device_path)
- *device_path = base::string16(device_interface_detail_data->DevicePath);
+ *device_path = std::wstring(device_interface_detail_data->DevicePath);
if (bus_number) {
auto result = GetDeviceUint32Property(dev_info, &dev_info_data,
@@ -242,14 +242,14 @@ bool GetDeviceInterfaceDetails(HDEVINFO dev_info,
return true;
}
-base::string16 GetDevicePath(const base::string16& instance_id,
- const GUID& device_interface_guid) {
+std::wstring GetDevicePath(const std::wstring& instance_id,
+ const GUID& device_interface_guid) {
base::win::ScopedDevInfo dev_info(
SetupDiGetClassDevs(&device_interface_guid, instance_id.c_str(), 0,
DIGCF_DEVICEINTERFACE | DIGCF_PRESENT));
if (!dev_info.is_valid()) {
USB_PLOG(ERROR) << "SetupDiGetClassDevs";
- return base::string16();
+ return std::wstring();
}
SP_DEVICE_INTERFACE_DATA device_interface_data = {};
@@ -258,28 +258,28 @@ base::string16 GetDevicePath(const base::string16& instance_id,
&device_interface_guid, 0,
&device_interface_data)) {
USB_PLOG(ERROR) << "SetupDiEnumDeviceInterfaces";
- return base::string16();
+ return std::wstring();
}
- base::string16 device_path;
+ std::wstring device_path;
if (!GetDeviceInterfaceDetails(
dev_info.get(), &device_interface_data, &device_path,
/*bus_number=*/nullptr, /*port_number=*/nullptr,
/*instance_id=*/nullptr, /*parent_instance_id=*/nullptr,
/*child_instance_ids=*/nullptr, /*service_name=*/nullptr)) {
- return base::string16();
+ return std::wstring();
}
return device_path;
}
-int GetInterfaceNumber(const base::string16& instance_id) {
+int GetInterfaceNumber(const std::wstring& instance_id) {
// According to MSDN the instance IDs for the device nodes created by the
// composite driver is in the form "USB\VID_vvvv&PID_dddd&MI_zz" where "zz"
// is the interface number.
//
// https://docs.microsoft.com/en-us/windows-hardware/drivers/install/standard-usb-identifiers#multiple-interface-usb-devices
- std::string instance_id_ascii = base::UTF16ToASCII(instance_id);
+ std::string instance_id_ascii = base::WideToASCII(instance_id);
std::string interface_number_str;
if (!RE2::PartialMatch(instance_id_ascii, "MI_([0-9a-fA-F]{2})",
&interface_number_str)) {
@@ -292,7 +292,7 @@ int GetInterfaceNumber(const base::string16& instance_id) {
return interface_number;
}
-UsbDeviceWin::FunctionInfo GetFunctionInfo(const base::string16& instance_id) {
+UsbDeviceWin::FunctionInfo GetFunctionInfo(const std::wstring& instance_id) {
UsbDeviceWin::FunctionInfo info;
base::win::ScopedDevInfo dev_info(
@@ -404,7 +404,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
FROM_HERE, base::BindOnce(&UsbServiceWin::HelperStarted, service_));
}
- void OnDeviceAdded(const GUID& guid, const base::string16& device_path) {
+ void OnDeviceAdded(const GUID& guid, const std::wstring& device_path) {
// 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();
@@ -435,9 +435,9 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
private:
void EnumerateDevice(HDEVINFO dev_info,
SP_DEVICE_INTERFACE_DATA* device_interface_data,
- const base::Optional<base::string16>& opt_device_path) {
- base::string16 device_path;
- base::string16* device_path_ptr = &device_path;
+ const base::Optional<std::wstring>& opt_device_path) {
+ std::wstring device_path;
+ std::wstring* device_path_ptr = &device_path;
if (opt_device_path) {
device_path = *opt_device_path;
device_path_ptr = nullptr;
@@ -445,9 +445,9 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
uint32_t bus_number;
uint32_t port_number;
- base::string16 parent_instance_id;
- std::vector<base::string16> child_instance_ids;
- base::string16 service_name;
+ std::wstring parent_instance_id;
+ std::vector<std::wstring> child_instance_ids;
+ std::wstring service_name;
if (!GetDeviceInterfaceDetails(dev_info, device_interface_data,
device_path_ptr, &bus_number, &port_number,
/*instance_id=*/nullptr, &parent_instance_id,
@@ -461,7 +461,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
// child device nodes for each of the device functions. It is these device
// paths for these children which must be opened in order to communicate
// with the WinUSB driver.
- for (const base::string16& instance_id : child_instance_ids) {
+ for (const std::wstring& instance_id : child_instance_ids) {
int interface_number = GetInterfaceNumber(instance_id);
if (interface_number != -1) {
functions.emplace_back(interface_number,
@@ -477,7 +477,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
functions.emplace_back(/*interface_number=*/0, info);
}
- base::string16& hub_path = hub_paths_[parent_instance_id];
+ std::wstring& hub_path = hub_paths_[parent_instance_id];
if (hub_path.empty()) {
hub_path = GetDevicePath(parent_instance_id, GUID_DEVINTERFACE_USB_HUB);
if (hub_path.empty())
@@ -494,10 +494,10 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
void EnumeratePotentialFunction(
HDEVINFO dev_info,
SP_DEVICE_INTERFACE_DATA* device_interface_data,
- const base::string16& device_path) {
- base::string16 instance_id;
- base::string16 parent_instance_id;
- base::string16 service_name;
+ const std::wstring& device_path) {
+ std::wstring instance_id;
+ std::wstring parent_instance_id;
+ std::wstring service_name;
if (!GetDeviceInterfaceDetails(
dev_info, device_interface_data,
/*device_path=*/nullptr, /*bus_number=*/nullptr,
@@ -510,7 +510,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
if (interface_number == -1)
return;
- base::string16 parent_path =
+ std::wstring parent_path =
GetDevicePath(parent_instance_id, GUID_DEVINTERFACE_USB_DEVICE);
if (parent_path.empty())
return;
@@ -525,7 +525,7 @@ class UsbServiceWin::BlockingTaskRunnerHelper {
std::move(parent_path), interface_number, info));
}
- std::unordered_map<base::string16, base::string16> hub_paths_;
+ std::unordered_map<std::wstring, std::wstring> hub_paths_;
// Calls back to |service_| must be posted to |service_task_runner_|, which
// runs tasks on the thread where that object lives.
@@ -561,7 +561,7 @@ void UsbServiceWin::GetDevices(GetDevicesCallback callback) {
}
void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& device_path) {
blocking_task_runner_->PostTask(
FROM_HERE,
base::BindOnce(&BlockingTaskRunnerHelper::OnDeviceAdded,
@@ -569,7 +569,7 @@ void UsbServiceWin::OnDeviceAdded(const GUID& class_guid,
}
void UsbServiceWin::OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) {
+ const std::wstring& device_path) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto by_path_it = devices_by_path_.find(device_path);
if (by_path_it == devices_by_path_.end())
@@ -604,12 +604,12 @@ void UsbServiceWin::HelperStarted() {
}
void UsbServiceWin::CreateDeviceObject(
- const base::string16& device_path,
- const base::string16& hub_path,
+ const std::wstring& device_path,
+ const std::wstring& hub_path,
const base::flat_map<int, UsbDeviceWin::FunctionInfo>& functions,
uint32_t bus_number,
uint32_t port_number,
- const base::string16& driver_name) {
+ const std::wstring& driver_name) {
// Devices that appear during initial enumeration are gathered into the first
// result returned by GetDevices() and prevent device add/remove notifications
// from being sent.
@@ -624,7 +624,7 @@ void UsbServiceWin::CreateDeviceObject(
}
void UsbServiceWin::UpdateFunction(
- const base::string16& device_path,
+ const std::wstring& device_path,
int interface_number,
const UsbDeviceWin::FunctionInfo& function_info) {
auto it = devices_by_path_.find(device_path);
diff --git a/chromium/services/device/usb/usb_service_win.h b/chromium/services/device/usb/usb_service_win.h
index 78dfbf559f6..82acab8c681 100644
--- a/chromium/services/device/usb/usb_service_win.h
+++ b/chromium/services/device/usb/usb_service_win.h
@@ -35,20 +35,20 @@ class UsbServiceWin final : public DeviceMonitorWin::Observer,
// device::DeviceMonitorWin::Observer implementation
void OnDeviceAdded(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
void OnDeviceRemoved(const GUID& class_guid,
- const base::string16& device_path) override;
+ const std::wstring& device_path) override;
// Methods called by BlockingThreadHelper
void HelperStarted();
void CreateDeviceObject(
- const base::string16& device_path,
- const base::string16& hub_path,
+ const std::wstring& device_path,
+ const std::wstring& hub_path,
const base::flat_map<int, UsbDeviceWin::FunctionInfo>& functions,
uint32_t bus_number,
uint32_t port_number,
- const base::string16& driver_name);
- void UpdateFunction(const base::string16& device_path,
+ const std::wstring& driver_name);
+ void UpdateFunction(const std::wstring& device_path,
int interface_number,
const UsbDeviceWin::FunctionInfo& function_info);
@@ -65,7 +65,7 @@ class UsbServiceWin final : public DeviceMonitorWin::Observer,
scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
std::unique_ptr<BlockingTaskRunnerHelper, base::OnTaskRunnerDeleter> helper_;
- std::unordered_map<base::string16, scoped_refptr<UsbDeviceWin>>
+ std::unordered_map<std::wstring, scoped_refptr<UsbDeviceWin>>
devices_by_path_;
ScopedObserver<DeviceMonitorWin, DeviceMonitorWin::Observer> device_observer_;
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 9365bd609d5..c3b7727b181 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
+++ b/chromium/services/device/wake_lock/power_save_blocker/BUILD.gn
@@ -40,18 +40,21 @@ source_set("power_save_blocker") {
"//chromeos/dbus/power",
"//chromeos/dbus/power:power_manager_proto",
]
- } else if (is_linux && use_dbus) {
+ } else if ((is_linux || is_chromeos) && use_dbus) {
sources += [ "power_save_blocker_linux.cc" ]
deps += [
"//dbus",
"//ui/gfx",
]
if (use_x11) {
- deps += [ "//ui/gfx/x" ]
+ deps += [
+ "//ui/base:features",
+ "//ui/gfx/x",
+ ]
}
} else if (is_mac) {
sources += [ "power_save_blocker_mac.cc" ]
- libs = [
+ frameworks = [
"CoreFoundation.framework",
"IOKit.framework",
]
diff --git a/chromium/services/device/wake_lock/power_save_blocker/DEPS b/chromium/services/device/wake_lock/power_save_blocker/DEPS
index 8ab9716e496..3b6ce5f9f9d 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/DEPS
+++ b/chromium/services/device/wake_lock/power_save_blocker/DEPS
@@ -4,4 +4,5 @@ include_rules = [
"+services/device/public",
"+ui/android",
"+ui/gfx",
+ "+ui/base/ui_base_features.h",
]
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 6b28c96b7dc..3db98411212 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,10 @@
#include "ui/gfx/switches.h"
#if defined(USE_X11)
-#include "ui/gfx/x/connection.h" // nogncheck
-#include "ui/gfx/x/screensaver.h" // nogncheck
-#include "ui/gfx/x/x11_types.h" // nogncheck
+#include "ui/base/ui_base_features.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 {
@@ -242,8 +243,10 @@ void PowerSaveBlocker::Delegate::Init() {
}
#if defined(USE_X11)
- ui_task_runner_->PostTask(FROM_HERE,
- base::BindOnce(X11ScreenSaverSuspendSet, true));
+ if (!features::IsUsingOzonePlatform()) {
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(X11ScreenSaverSuspendSet, true));
+ }
#endif
}
@@ -254,8 +257,10 @@ void PowerSaveBlocker::Delegate::CleanUp() {
}
#if defined(USE_X11)
- ui_task_runner_->PostTask(FROM_HERE,
- base::BindOnce(X11ScreenSaverSuspendSet, false));
+ if (!features::IsUsingOzonePlatform()) {
+ ui_task_runner_->PostTask(FROM_HERE,
+ base::BindOnce(X11ScreenSaverSuspendSet, false));
+ }
#endif
}
diff --git a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
index bfb794c54ee..b4b31fb2c8a 100644
--- a/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
+++ b/chromium/services/device/wake_lock/power_save_blocker/power_save_blocker_win.cc
@@ -24,7 +24,7 @@ HANDLE CreatePowerRequest(POWER_REQUEST_TYPE type,
return INVALID_HANDLE_VALUE;
}
- base::string16 wide_description = base::ASCIIToUTF16(description);
+ std::wstring wide_description = base::ASCIIToWide(description);
REASON_CONTEXT context = {0};
context.Version = POWER_REQUEST_CONTEXT_VERSION;
context.Flags = POWER_REQUEST_CONTEXT_SIMPLE_STRING;
diff --git a/chromium/services/device/wake_lock/wake_lock_provider.h b/chromium/services/device/wake_lock/wake_lock_provider.h
index f9e252fa488..1b951ab031c 100644
--- a/chromium/services/device/wake_lock/wake_lock_provider.h
+++ b/chromium/services/device/wake_lock/wake_lock_provider.h
@@ -11,7 +11,6 @@
#include "base/sequenced_task_runner.h"
#include "base/single_thread_task_runner.h"
-#include "mojo/public/cpp/bindings/interface_request.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"
diff --git a/chromium/services/device/wake_lock/wake_lock_unittest.cc b/chromium/services/device/wake_lock/wake_lock_unittest.cc
index e7eec1bab17..f0dca917942 100644
--- a/chromium/services/device/wake_lock/wake_lock_unittest.cc
+++ b/chromium/services/device/wake_lock/wake_lock_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "base/run_loop.h"
-#include "mojo/public/cpp/bindings/interface_ptr.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"
diff --git a/chromium/services/image_annotation/public/cpp/image_processor.cc b/chromium/services/image_annotation/public/cpp/image_processor.cc
index 562d73e2ef4..2bedb4203e0 100644
--- a/chromium/services/image_annotation/public/cpp/image_processor.cc
+++ b/chromium/services/image_annotation/public/cpp/image_processor.cc
@@ -8,7 +8,6 @@
#include "base/task/post_task.h"
#include "base/task/thread_pool.h"
#include "base/task_runner_util.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/image_annotation/image_annotation_metrics.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "ui/gfx/codec/jpeg_codec.h"
diff --git a/chromium/services/media_session/audio_focus_request.cc b/chromium/services/media_session/audio_focus_request.cc
index a304a722e4b..b3346758bc6 100644
--- a/chromium/services/media_session/audio_focus_request.cc
+++ b/chromium/services/media_session/audio_focus_request.cc
@@ -125,13 +125,14 @@ void AudioFocusRequest::ReleaseTransientHold() {
return;
was_suspended_ = false;
- session_->Resume(mojom::MediaSession::SuspendType::kSystem);
- if (!delayed_action_)
+ if (delayed_action_) {
+ PerformUIAction(*delayed_action_);
+ delayed_action_.reset();
return;
+ }
- PerformUIAction(*delayed_action_);
- delayed_action_.reset();
+ session_->Resume(mojom::MediaSession::SuspendType::kSystem);
}
void AudioFocusRequest::PerformUIAction(mojom::MediaSessionAction action) {
diff --git a/chromium/services/media_session/media_controller.cc b/chromium/services/media_session/media_controller.cc
index 8ff49e78707..483b20b9980 100644
--- a/chromium/services/media_session/media_controller.cc
+++ b/chromium/services/media_session/media_controller.cc
@@ -291,6 +291,13 @@ void MediaController::ExitPictureInPicture() {
session_->ipc()->ExitPictureInPicture();
}
+void MediaController::SetAudioSinkId(const base::Optional<std::string>& id) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+
+ if (session_)
+ session_->ipc()->SetAudioSinkId(id);
+}
+
void MediaController::SetMediaSession(AudioFocusRequest* session) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
diff --git a/chromium/services/media_session/media_controller.h b/chromium/services/media_session/media_controller.h
index 6c9518eb28a..349199e2ae1 100644
--- a/chromium/services/media_session/media_controller.h
+++ b/chromium/services/media_session/media_controller.h
@@ -53,6 +53,7 @@ class MediaController : public mojom::MediaController,
void ScrubTo(base::TimeDelta seek_time) override;
void EnterPictureInPicture() override;
void ExitPictureInPicture() override;
+ void SetAudioSinkId(const base::Optional<std::string>& id) override;
// mojom::MediaSessionObserver overrides.
void MediaSessionInfoChanged(
diff --git a/chromium/services/media_session/public/cpp/OWNERS b/chromium/services/media_session/public/cpp/OWNERS
index 7aebc8abbf8..d5fefd82012 100644
--- a/chromium/services/media_session/public/cpp/OWNERS
+++ b/chromium/services/media_session/public/cpp/OWNERS
@@ -1,4 +1,2 @@
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/media_session/public/cpp/android/BUILD.gn b/chromium/services/media_session/public/cpp/android/BUILD.gn
index 0f863dce22f..ffa37cf7b70 100644
--- a/chromium/services/media_session/public/cpp/android/BUILD.gn
+++ b/chromium/services/media_session/public/cpp/android/BUILD.gn
@@ -16,7 +16,10 @@ generate_jni("media_session_jni_headers") {
if (current_toolchain == default_toolchain) {
android_library("media_session_java") {
- deps = [ "//base:base_java" ]
+ deps = [
+ "//base:base_java",
+ "//third_party/android_deps:androidx_annotation_annotation_java",
+ ]
sources = _jni_sources
}
}
diff --git a/chromium/services/media_session/public/cpp/media_session.typemap b/chromium/services/media_session/public/cpp/media_session.typemap
deleted file mode 100644
index 2eebff2348f..00000000000
--- a/chromium/services/media_session/public/cpp/media_session.typemap
+++ /dev/null
@@ -1,30 +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.
-
-mojom = "//services/media_session/public/mojom/media_session.mojom"
-public_headers = [
- "//services/media_session/public/cpp/media_image.h",
- "//services/media_session/public/cpp/media_metadata.h",
- "//services/media_session/public/cpp/media_position.h",
- "//third_party/skia/include/core/SkBitmap.h",
-]
-traits_headers =
- [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ]
-public_deps = [
- "//services/media_session/public/cpp:base_cpp",
- "//skia",
-]
-deps = [
- "//ui/gfx/geometry/mojom:mojom_traits",
-]
-type_mappings = [
- "media_session.mojom.MediaImage=::media_session::MediaImage",
- "media_session.mojom.MediaImageBitmap=::SkBitmap[nullable_is_same_type]",
- "media_session.mojom.MediaMetadata=::media_session::MediaMetadata",
- "media_session.mojom.MediaPosition=::media_session::MediaPosition",
-]
-sources = [
- "//services/media_session/public/cpp/media_session_mojom_traits.cc",
- "//services/media_session/public/cpp/media_session_mojom_traits.h",
-]
diff --git a/chromium/services/media_session/public/cpp/media_session_mojom_traits.cc b/chromium/services/media_session/public/cpp/media_session_mojom_traits.cc
index f9beae31815..c7f5830504a 100644
--- a/chromium/services/media_session/public/cpp/media_session_mojom_traits.cc
+++ b/chromium/services/media_session/public/cpp/media_session_mojom_traits.cc
@@ -6,7 +6,6 @@
#include "mojo/public/cpp/base/string16_mojom_traits.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
#include "url/mojom/url_gurl_mojom_traits.h"
diff --git a/chromium/services/media_session/public/cpp/media_session_mojom_traits.h b/chromium/services/media_session/public/cpp/media_session_mojom_traits.h
index 9051f6a4ef5..a049254da11 100644
--- a/chromium/services/media_session/public/cpp/media_session_mojom_traits.h
+++ b/chromium/services/media_session/public/cpp/media_session_mojom_traits.h
@@ -8,7 +8,13 @@
#include <vector>
#include "base/containers/span.h"
-#include "services/media_session/public/mojom/media_session.mojom.h"
+#include "base/strings/string16.h"
+#include "services/media_session/public/cpp/media_image.h"
+#include "services/media_session/public/cpp/media_metadata.h"
+#include "services/media_session/public/cpp/media_position.h"
+#include "services/media_session/public/mojom/media_session.mojom-shared.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/size.h"
namespace mojo {
diff --git a/chromium/services/media_session/public/cpp/mojom_traits_unittest.cc b/chromium/services/media_session/public/cpp/mojom_traits_unittest.cc
index 7e8c609c210..0ad144e499c 100644
--- a/chromium/services/media_session/public/cpp/mojom_traits_unittest.cc
+++ b/chromium/services/media_session/public/cpp/mojom_traits_unittest.cc
@@ -4,6 +4,7 @@
#include "mojo/public/cpp/test_support/test_utils.h"
#include "services/media_session/public/cpp/media_session_mojom_traits.h"
+#include "services/media_session/public/mojom/media_session.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
using media_session::mojom::MediaImageBitmap;
diff --git a/chromium/services/media_session/public/cpp/typemaps.gni b/chromium/services/media_session/public/cpp/typemaps.gni
deleted file mode 100644
index 280e7e00003..00000000000
--- a/chromium/services/media_session/public/cpp/typemaps.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.
-
-typemaps = [ "//services/media_session/public/cpp/media_session.typemap" ]
diff --git a/chromium/services/media_session/public/mojom/BUILD.gn b/chromium/services/media_session/public/mojom/BUILD.gn
index 1f30a298d32..4ee7adcc43e 100644
--- a/chromium/services/media_session/public/mojom/BUILD.gn
+++ b/chromium/services/media_session/public/mojom/BUILD.gn
@@ -27,4 +27,42 @@ mojom("mojom") {
export_class_attribute_blink = "BLINK_PLATFORM_EXPORT"
export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
export_header_blink = "third_party/blink/public/platform/web_common.h"
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "media_session.mojom.MediaImage"
+ cpp = "::media_session::MediaImage"
+ },
+ {
+ mojom = "media_session.mojom.MediaImageBitmap"
+ cpp = "::SkBitmap"
+ nullable_is_same_type = true
+ },
+ {
+ mojom = "media_session.mojom.MediaMetadata"
+ cpp = "::media_session::MediaMetadata"
+ },
+ {
+ mojom = "media_session.mojom.MediaPosition"
+ cpp = "::media_session::MediaPosition"
+ },
+ ]
+ traits_headers =
+ [ "//services/media_session/public/cpp/media_session_mojom_traits.h" ]
+ traits_sources = [
+ "//services/media_session/public/cpp/media_session_mojom_traits.cc",
+ ]
+ traits_public_deps = [
+ "//base",
+ "//services/media_session/public/cpp:base_cpp",
+ "//skia",
+ ]
+ traits_deps = [
+ "//mojo/public/mojom/base",
+ "//ui/gfx/geometry/mojom",
+ ]
+ },
+ ]
}
diff --git a/chromium/services/media_session/public/mojom/media_controller.mojom b/chromium/services/media_session/public/mojom/media_controller.mojom
index 4e9e5f33191..72490b00268 100644
--- a/chromium/services/media_session/public/mojom/media_controller.mojom
+++ b/chromium/services/media_session/public/mojom/media_controller.mojom
@@ -83,6 +83,10 @@ interface MediaController {
// Exit picture-in-picture.
ExitPictureInPicture();
+
+ // Routes the audio from this Media Session to the given output device. If
+ // |id| is null, we will route to the default output device.
+ SetAudioSinkId(string? id);
};
// The observer for observing media controller events. This is different to a
diff --git a/chromium/services/media_session/public/mojom/media_session.mojom b/chromium/services/media_session/public/mojom/media_session.mojom
index 53ba82e4fc9..63e95f72d78 100644
--- a/chromium/services/media_session/public/mojom/media_session.mojom
+++ b/chromium/services/media_session/public/mojom/media_session.mojom
@@ -9,7 +9,7 @@ import "mojo/public/mojom/base/time.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "url/mojom/url.mojom";
-// Next MinVersion: 9
+// Next MinVersion: 10
[Extensible]
enum MediaPlaybackState {
@@ -146,6 +146,11 @@ struct MediaSessionInfo {
// The audio/video state of the Media Session (if known).
[MinVersion=8] MediaAudioVideoState audio_video_state;
+
+ // The audio_sink_id tells the client the device_id of the audio output device
+ // being used for this media session. A null audio_sink_id implies that the
+ // default device is being used.
+ [MinVersion=9] string? audio_sink_id;
};
// Contains debugging information about a MediaSession. This will be displayed
@@ -188,7 +193,7 @@ interface MediaSessionObserver {
// WebContents or ARC app.
// TODO(https://crbug.com/875004): migrate media session from content/public
// to mojo.
-// Next Method ID: 17
+// Next Method ID: 18
interface MediaSession {
[Extensible]
enum SuspendType {
@@ -270,4 +275,8 @@ interface MediaSession {
// Exit picture-in-picture.
ExitPictureInPicture@16();
+
+ // Routes the audio from this Media Session to the given output device. If
+ // |id| is null, we will route to the default output device.
+ SetAudioSinkId@17(string? id);
};
diff --git a/chromium/services/metrics/public/cpp/ukm_source.cc b/chromium/services/metrics/public/cpp/ukm_source.cc
index b83454bd115..fee7fe50ef2 100644
--- a/chromium/services/metrics/public/cpp/ukm_source.cc
+++ b/chromium/services/metrics/public/cpp/ukm_source.cc
@@ -53,6 +53,8 @@ SourceType ToProtobufSourceType(SourceIdType source_id_type) {
return SourceType::PAYMENT_APP_ID;
case SourceIdType::DESKTOP_WEB_APP_ID:
return SourceType::DESKTOP_WEB_APP_ID;
+ case SourceIdType::WORKER_ID:
+ return SourceType::WORKER_ID;
default:
NOTREACHED();
return SourceType::DEFAULT;
diff --git a/chromium/services/network/BUILD.gn b/chromium/services/network/BUILD.gn
index 1a4135ea4b7..1941a52fd3f 100644
--- a/chromium/services/network/BUILD.gn
+++ b/chromium/services/network/BUILD.gn
@@ -2,13 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import("//build/config/jumbo.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//net/features.gni")
import("//services/network/public/cpp/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
-jumbo_component("network_service") {
+component("network_service") {
sources = [
"chunked_data_pipe_upload_data_stream.cc",
"chunked_data_pipe_upload_data_stream.h",
@@ -30,8 +29,8 @@ jumbo_component("network_service") {
"crash_keys.h",
"crl_set_distributor.cc",
"crl_set_distributor.h",
- "cross_origin_read_blocking.cc",
- "cross_origin_read_blocking.h",
+ "cross_origin_read_blocking_exception_for_plugin.cc",
+ "cross_origin_read_blocking_exception_for_plugin.h",
"data_pipe_element_reader.cc",
"data_pipe_element_reader.h",
"dns_config_change_manager.cc",
@@ -70,8 +69,6 @@ jumbo_component("network_service") {
"network_quality_estimator_manager.h",
"network_sandbox_hook_linux.cc",
"network_sandbox_hook_linux.h",
- "network_sandbox_win.cc",
- "network_sandbox_win.h",
"network_service.cc",
"network_service.h",
"network_service_network_delegate.cc",
@@ -242,7 +239,6 @@ jumbo_component("network_service") {
"//services/network/trust_tokens",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
- "//services/service_manager/sandbox:sandbox",
"//third_party/webrtc_overrides:webrtc_component",
"//url",
]
@@ -253,14 +249,16 @@ jumbo_component("network_service") {
sources += [
"expect_ct_reporter.cc",
"expect_ct_reporter.h",
+ "sct_auditing_cache.cc",
+ "sct_auditing_cache.h",
]
deps += [ "//components/certificate_transparency" ]
}
- if (is_linux) {
+ if (is_linux || is_chromeos) {
deps += [
"//sandbox/linux:sandbox_services",
- "//services/service_manager/sandbox:sandbox",
+ "//sandbox/policy",
]
}
@@ -288,7 +286,6 @@ source_set("tests") {
"cors/cors_url_loader_factory_unittest.cc",
"cors/cors_url_loader_unittest.cc",
"cors/preflight_controller_unittest.cc",
- "cross_origin_read_blocking_unittest.cc",
"data_pipe_element_reader_unittest.cc",
"dns_config_change_manager_unittest.cc",
"host_resolver_unittest.cc",
@@ -399,7 +396,10 @@ source_set("tests") {
]
if (is_ct_supported) {
- sources += [ "expect_ct_reporter_unittest.cc" ]
+ sources += [
+ "expect_ct_reporter_unittest.cc",
+ "sct_auditing_cache_unittest.cc",
+ ]
deps += [ "//components/certificate_transparency" ]
}
@@ -408,7 +408,7 @@ source_set("tests") {
}
}
-jumbo_source_set("test_support") {
+source_set("test_support") {
testonly = true
sources = [
@@ -440,8 +440,8 @@ jumbo_source_set("test_support") {
"test/test_url_loader_factory.h",
"test/test_utils.cc",
"test/test_utils.h",
- "udp_socket_test_util.cc",
- "udp_socket_test_util.h",
+ "test/udp_socket_test_util.cc",
+ "test/udp_socket_test_util.h",
]
if (is_chromeos) {
diff --git a/chromium/services/network/DEPS b/chromium/services/network/DEPS
index 2849a005c04..0d167b8cc46 100644
--- a/chromium/services/network/DEPS
+++ b/chromium/services/network/DEPS
@@ -17,7 +17,6 @@ include_rules = [
"+sandbox",
"+services/proxy_resolver/public/mojom",
"+services/service_manager/public",
- "+services/service_manager/sandbox",
"+third_party/boringssl/src/include",
"+url",
]
diff --git a/chromium/services/network/OWNERS b/chromium/services/network/OWNERS
index 9a92f27fa95..42433e48786 100644
--- a/chromium/services/network/OWNERS
+++ b/chromium/services/network/OWNERS
@@ -30,7 +30,6 @@ per-file *_type_converter*.*=set noparent
per-file *_type_converter*.*=file://ipc/SECURITY_OWNERS
per-file network_sandbox_hook_linux.*.cc=file://sandbox/OWNERS
-per-file network_sandbox_win.*=file://sandbox/win/OWNERS
per-file network_quality*=file://net/nqe/OWNERS
diff --git a/chromium/services/network/README.md b/chromium/services/network/README.md
index d9f0ca04baf..9cbb5bf219c 100644
--- a/chromium/services/network/README.md
+++ b/chromium/services/network/README.md
@@ -27,6 +27,7 @@ https://docs.google.com/document/d/1wAHLw9h7gGuqJNCgG1mP1BmLtCGfZ2pys-PdZQ1vg7M/
# Related docs
* [URLLoader](url_loader.md)
+* [Slides describing the relationship with the fetch spec](https://docs.google.com/presentation/d/1r9KHuYbNlgqQ6UABAMiWz0ONTpSTnMaDJ8UeYZGWjls/)
# Where does the network service run?
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 305bfa2ef3c..65202276331 100644
--- a/chromium/services/network/chunked_data_pipe_upload_data_stream.cc
+++ b/chromium/services/network/chunked_data_pipe_upload_data_stream.cc
@@ -49,9 +49,14 @@ int ChunkedDataPipeUploadDataStream::InitInternal(
return net::ERR_FAILED;
// Get a new data pipe and start.
- mojo::DataPipe data_pipe;
- chunked_data_pipe_getter_->StartReading(std::move(data_pipe.producer_handle));
- data_pipe_ = std::move(data_pipe.consumer_handle);
+ mojo::ScopedDataPipeProducerHandle data_pipe_producer;
+ mojo::ScopedDataPipeConsumerHandle data_pipe_consumer;
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &data_pipe_producer, &data_pipe_consumer);
+ if (result != MOJO_RESULT_OK)
+ return net::ERR_INSUFFICIENT_RESOURCES;
+ chunked_data_pipe_getter_->StartReading(std::move(data_pipe_producer));
+ data_pipe_ = std::move(data_pipe_consumer);
return net::OK;
}
diff --git a/chromium/services/network/cookie_manager_unittest.cc b/chromium/services/network/cookie_manager_unittest.cc
index b66d553eb79..671c169a780 100644
--- a/chromium/services/network/cookie_manager_unittest.cc
+++ b/chromium/services/network/cookie_manager_unittest.cc
@@ -17,6 +17,7 @@
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/time/time.h"
+#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_monster.h"
@@ -152,8 +153,8 @@ class SynchronousCookieManager {
cookie, net::cookie_util::SimulatedCookieSource(cookie, source_scheme),
options,
base::BindLambdaForTesting(
- [&run_loop, &result_out](net::CookieInclusionStatus result) {
- result_out = result;
+ [&run_loop, &result_out](net::CookieAccessResult result) {
+ result_out = result.status;
run_loop.Quit();
}));
@@ -161,7 +162,7 @@ class SynchronousCookieManager {
return result_out.IsInclude();
}
- net::CookieInclusionStatus SetCanonicalCookieWithStatus(
+ net::CookieAccessResult SetCanonicalCookieWithAccessResult(
const net::CanonicalCookie& cookie,
std::string source_scheme,
bool modify_http_only) {
@@ -171,13 +172,13 @@ class SynchronousCookieManager {
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
if (modify_http_only)
options.set_include_httponly();
- net::CookieInclusionStatus result_out(
- net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR);
+ auto result_out = net::CookieAccessResult(net::CookieInclusionStatus(
+ net::CookieInclusionStatus::EXCLUDE_UNKNOWN_ERROR));
cookie_service_->SetCanonicalCookie(
cookie, net::cookie_util::SimulatedCookieSource(cookie, source_scheme),
options,
base::BindLambdaForTesting(
- [&run_loop, &result_out](net::CookieInclusionStatus result) {
+ [&run_loop, &result_out](net::CookieAccessResult result) {
result_out = result;
run_loop.Quit();
}));
@@ -262,7 +263,7 @@ class CookieManagerTest : public testing::Test {
bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
std::string source_scheme,
bool can_modify_httponly) {
- net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> callback;
net::CookieOptions options;
options.set_same_site_cookie_context(
net::CookieOptions::SameSiteCookieContext::MakeInclusive());
@@ -272,11 +273,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::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ callback.MakeCallback());
callback.WaitUntilDone();
- return callback.result().IsInclude();
+ return callback.result().status.IsInclude();
}
std::string DumpAllCookies() {
@@ -832,17 +831,19 @@ TEST_F(CookieManagerTest, DeleteThroughSet) {
}
TEST_F(CookieManagerTest, ConfirmSecureSetFails) {
- EXPECT_TRUE(
- service_wrapper()
- ->SetCanonicalCookieWithStatus(
- net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
- base::Time(), base::Time(),
- /*secure=*/true, /*httponly=*/false,
- net::CookieSameSite::NO_RESTRICTION,
- net::COOKIE_PRIORITY_MEDIUM),
- "http", false)
- .HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
+ net::CookieAccessResult access_result =
+ service_wrapper()->SetCanonicalCookieWithAccessResult(
+ net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/true, /*httponly=*/false,
+ net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_MEDIUM),
+ "http", false);
+
+ EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
+ EXPECT_EQ(access_result.effective_same_site,
+ net::CookieEffectiveSameSite::NO_RESTRICTION);
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -850,17 +851,19 @@ TEST_F(CookieManagerTest, ConfirmSecureSetFails) {
}
TEST_F(CookieManagerTest, ConfirmHttpOnlySetFails) {
- EXPECT_TRUE(
- service_wrapper()
- ->SetCanonicalCookieWithStatus(
- net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
- base::Time(), base::Time(),
- /*secure=*/false, /*httponly=*/true,
- net::CookieSameSite::LAX_MODE,
- net::COOKIE_PRIORITY_MEDIUM),
- "http", false)
- .HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
+ net::CookieAccessResult access_result =
+ service_wrapper()->SetCanonicalCookieWithAccessResult(
+ net::CanonicalCookie("N", "O", kCookieDomain, "/", base::Time(),
+ base::Time(), base::Time(),
+ /*secure=*/false, /*httponly=*/true,
+ net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM),
+ "http", false);
+
+ EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_HTTP_ONLY}));
+ EXPECT_EQ(access_result.effective_same_site,
+ net::CookieEffectiveSameSite::LAX_MODE);
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -876,17 +879,19 @@ TEST_F(CookieManagerTest, ConfirmSecureOverwriteFails) {
net::COOKIE_PRIORITY_MEDIUM),
"https", true));
- EXPECT_TRUE(
- service_wrapper()
- ->SetCanonicalCookieWithStatus(
- net::CanonicalCookie(
- "Secure", "Nope", kCookieDomain, "/with/path", base::Time(),
- base::Time(), base::Time(), /*secure=*/false,
- /*httponly=*/false, net::CookieSameSite::LAX_MODE,
- net::COOKIE_PRIORITY_MEDIUM),
- "http", false)
- .HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE}));
+ net::CookieAccessResult access_result =
+ service_wrapper()->SetCanonicalCookieWithAccessResult(
+ net::CanonicalCookie(
+ "Secure", "Nope", kCookieDomain, "/with/path", base::Time(),
+ base::Time(), base::Time(), /*secure=*/false,
+ /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM),
+ "http", false);
+
+ EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_SECURE}));
+ EXPECT_EQ(access_result.effective_same_site,
+ net::CookieEffectiveSameSite::LAX_MODE);
std::vector<net::CanonicalCookie> cookies =
service_wrapper()->GetAllCookies();
@@ -905,17 +910,19 @@ TEST_F(CookieManagerTest, ConfirmHttpOnlyOverwriteFails) {
net::COOKIE_PRIORITY_MEDIUM),
"http", true));
- EXPECT_TRUE(
- service_wrapper()
- ->SetCanonicalCookieWithStatus(
- net::CanonicalCookie(
- "HttpOnly", "Nope", kCookieDomain, "/with/path", base::Time(),
- base::Time(), base::Time(), /*secure=*/false,
- /*httponly=*/false, net::CookieSameSite::LAX_MODE,
- net::COOKIE_PRIORITY_MEDIUM),
- "https", false)
- .HasExactlyExclusionReasonsForTesting(
- {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY}));
+ net::CookieAccessResult access_result =
+ service_wrapper()->SetCanonicalCookieWithAccessResult(
+ net::CanonicalCookie(
+ "HttpOnly", "Nope", kCookieDomain, "/with/path", base::Time(),
+ base::Time(), base::Time(), /*secure=*/false,
+ /*httponly=*/false, net::CookieSameSite::LAX_MODE,
+ net::COOKIE_PRIORITY_MEDIUM),
+ "https", false);
+
+ EXPECT_TRUE(access_result.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::EXCLUDE_OVERWRITE_HTTP_ONLY}));
+ EXPECT_EQ(access_result.effective_same_site,
+ net::CookieEffectiveSameSite::LAX_MODE);
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 5122960ccdd..581e395660e 100644
--- a/chromium/services/network/cookie_settings.cc
+++ b/chromium/services/network/cookie_settings.cc
@@ -7,6 +7,7 @@
#include <functional>
#include "base/bind.h"
+#include "base/callback.h"
#include "base/strings/string_split.h"
#include "components/content_settings/core/common/content_settings_utils.h"
#include "net/base/net_errors.h"
@@ -56,10 +57,10 @@ void CookieSettings::set_content_settings_for_legacy_cookie_access(
AppendEmergencyLegacyCookieAccess(&settings_for_legacy_cookie_access_);
}
-SessionCleanupCookieStore::DeleteCookiePredicate
-CookieSettings::CreateDeleteCookieOnExitPredicate() const {
+DeleteCookiePredicate CookieSettings::CreateDeleteCookieOnExitPredicate()
+ const {
if (!HasSessionOnlyOrigins())
- return SessionCleanupCookieStore::DeleteCookiePredicate();
+ return DeleteCookiePredicate();
return base::BindRepeating(&CookieSettings::ShouldDeleteCookieOnExit,
base::Unretained(this),
std::cref(content_settings_));
diff --git a/chromium/services/network/cookie_settings.h b/chromium/services/network/cookie_settings.h
index aab85a1a8c5..84eae422470 100644
--- a/chromium/services/network/cookie_settings.h
+++ b/chromium/services/network/cookie_settings.h
@@ -8,7 +8,7 @@
#include "base/component_export.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/content_settings/core/common/cookie_settings_base.h"
-#include "services/network/session_cleanup_cookie_store.h"
+#include "services/network/public/cpp/session_cookie_delete_predicate.h"
class GURL;
@@ -67,8 +67,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CookieSettings
// Returns a predicate that takes the domain of a cookie and a bool whether
// the cookie is secure and returns true if the cookie should be deleted on
// exit.
- SessionCleanupCookieStore::DeleteCookiePredicate
- CreateDeleteCookieOnExitPredicate() const;
+ DeleteCookiePredicate CreateDeleteCookieOnExitPredicate() const;
// content_settings::CookieSettingsBase:
void GetSettingForLegacyCookieAccess(const std::string& cookie_domain,
diff --git a/chromium/services/network/cors/cors_url_loader.cc b/chromium/services/network/cors/cors_url_loader.cc
index 2e7f769c7a3..56f851fdb16 100644
--- a/chromium/services/network/cors/cors_url_loader.cc
+++ b/chromium/services/network/cors/cors_url_loader.cc
@@ -28,21 +28,7 @@ namespace cors {
namespace {
-// These values are persisted to logs. Entries should not be renumbered and
-// numeric values should never be reused.
-enum class CompletionStatusMetric {
- kPassedWhenCorsFlagUnset = 0,
- kFailedWhenCorsFlagUnset = 1,
- kPassedWhenCorsFlagSet = 2,
- kFailedWhenCorsFlagSet = 3,
- kBlockedByCors = 4,
-
- kMaxValue = kBlockedByCors,
-};
-
-bool NeedsPreflight(
- const ResourceRequest& request,
- const base::flat_set<std::string>& extra_safelisted_header_names) {
+bool NeedsPreflight(const ResourceRequest& request) {
if (!IsCorsEnabledRequestMode(request.mode))
return false;
@@ -62,26 +48,10 @@ bool NeedsPreflight(
return true;
return !CorsUnsafeNotForbiddenRequestHeaderNames(
- request.headers.GetHeaderVector(), request.is_revalidating,
- extra_safelisted_header_names)
+ request.headers.GetHeaderVector(), request.is_revalidating)
.empty();
}
-void ReportCompletionStatusMetric(bool fetch_cors_flag,
- const URLLoaderCompletionStatus& status) {
- CompletionStatusMetric metric;
- if (status.error_code == net::OK) {
- metric = fetch_cors_flag ? CompletionStatusMetric::kPassedWhenCorsFlagSet
- : CompletionStatusMetric::kPassedWhenCorsFlagUnset;
- } else if (status.cors_error_status) {
- metric = CompletionStatusMetric::kBlockedByCors;
- } else {
- metric = fetch_cors_flag ? CompletionStatusMetric::kFailedWhenCorsFlagSet
- : CompletionStatusMetric::kFailedWhenCorsFlagUnset;
- }
- UMA_HISTOGRAM_ENUMERATION("Net.Cors.CompletionStatus", metric);
-}
-
constexpr const char kTimingAllowOrigin[] = "Timing-Allow-Origin";
} // namespace
@@ -250,9 +220,7 @@ void CorsURLLoader::FollowRedirect(
//
// After both OOR-CORS and network service are fully shipped, we may be able
// to remove the logic in net/.
- if ((fetch_cors_flag_ &&
- NeedsPreflight(
- request_, preflight_controller_->extra_safelisted_header_names())) ||
+ if ((fetch_cors_flag_ && NeedsPreflight(request_)) ||
(!original_fetch_cors_flag && fetch_cors_flag_) ||
(fetch_cors_flag_ && original_method != request_.method)) {
DCHECK_NE(request_.mode, mojom::RequestMode::kNoCors);
@@ -388,14 +356,20 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
tainted_ = true;
}
- // TODO(yhirano): Implement the following:
+ // TODO(crbug.com/1073353): Implement the following:
// If either |actualResponse|’s status is 301 or 302 and |request|’s method is
// `POST`, or |actualResponse|’s status is 303, set |request|’s method to
- // `GET` and request’s body to null.
-
- // TODO(yhirano): Implement the following:
+ // `GET` and request’s body to null, and remove request-body-header name from
+ // request's headers. Some of them are implemented in //net, but when we
+ // create another request on exceptional redirect cases, such newly created
+ // request doesn't reflect the spec comformant request modifications. See the
+ // linked crbug for details. See also 4.4. HTTP-redirect fetch
+ // (https://fetch.spec.whatwg.org/#http-redirect-fetch), step 11.
+
+ // TODO(crbug.com/1073353): Implement the following:
// Invoke |set request’s referrer policy on redirect| on |request| and
- // |actualResponse|.
+ // |actualResponse|. See 4.4. HTTP-redirect fetch
+ // (https://fetch.spec.whatwg.org/#http-redirect-fetch), step 14.
redirect_info_ = redirect_info;
@@ -510,9 +484,7 @@ void CorsURLLoader::StartRequest() {
// Note that even when |NeedsPreflight(request_)| holds we don't make a
// preflight request when |fetch_cors_flag_| is false (e.g., when the origin
// of the url is equal to the origin of the request.
- if (!fetch_cors_flag_ ||
- !NeedsPreflight(request_,
- preflight_controller_->extra_safelisted_header_names())) {
+ if (!fetch_cors_flag_ || !NeedsPreflight(request_)) {
StartNetworkRequest(net::OK, base::nullopt);
return;
}
@@ -566,7 +538,6 @@ void CorsURLLoader::StartNetworkRequest(
}
void CorsURLLoader::HandleComplete(const URLLoaderCompletionStatus& status) {
- ReportCompletionStatusMetric(fetch_cors_flag_, status);
forwarding_client_->OnComplete(status);
std::move(delete_callback_).Run(this);
// |this| is deleted here.
diff --git a/chromium/services/network/cors/cors_url_loader_factory.cc b/chromium/services/network/cors/cors_url_loader_factory.cc
index 9c73e446778..a33206ae639 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory.cc
@@ -7,19 +7,23 @@
#include <utility>
#include "base/bind.h"
+#include "base/debug/dump_without_crashing.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
+#include "base/util/type_safety/strong_alias.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/load_flags.h"
+#include "net/http/http_util.h"
#include "services/network/cors/cors_url_loader.h"
#include "services/network/cors/preflight_controller.h"
#include "services/network/crash_keys.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/cors/cors.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/header_util.h"
#include "services/network/public/cpp/initiator_lock_compatibility.h"
@@ -39,6 +43,22 @@ namespace cors {
namespace {
+using IsConsistent = ::util::StrongAlias<class IsConsistentTag, bool>;
+
+// Record, for requests with associated Trust Tokens operations of operation
+// types requiring initiators to have the Trust Tokens Feature Policy feature
+// enabled, whether the browser process thinks it's possible for the initiating
+// frame to have the feature enabled. (If the answer is "no," it indicates
+// a misbehaving renderer in theory but, unfortunately, is more likely a false
+// positive due to inconsistent state; see crbug.com/1117458.)
+void HistogramWhetherTrustTokenFeaturePolicyConsistentWithBrowserOpinion(
+ IsConsistent is_consistent) {
+ UMA_HISTOGRAM_BOOLEAN(
+ "Net.TrustTokens.SubresourceOperationRequiringFeaturePolicy."
+ "PolicyIsConsistentWithBrowserOpinion",
+ is_consistent.value());
+}
+
// Verifies state that should hold for Trust Tokens parameters provided by a
// functioning renderer:
// - Trust Tokens should be enabled
@@ -64,24 +84,22 @@ bool VerifyTrustTokenParamsIntegrityIfPresent(
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;
+ //
+ // TODO(crbug.com/1118183): Re-add a ReportBadMessage (and false return)
+ // once the false positives in crbug.com/1117458 have been resolved.
+ base::debug::DumpWithoutCrashing();
+ HistogramWhetherTrustTokenFeaturePolicyConsistentWithBrowserOpinion(
+ IsConsistent(false));
+ } else if (DoesTrustTokenOperationRequireFeaturePolicy(
+ url_request.trust_token_params->type)) {
+ HistogramWhetherTrustTokenFeaturePolicyConsistentWithBrowserOpinion(
+ IsConsistent(true));
}
return true;
@@ -166,7 +184,7 @@ CorsURLLoaderFactory::CorsURLLoaderFactory(
is_trusted_(params->is_trusted),
disable_web_security_(params->disable_web_security),
process_id_(params->process_id),
- request_initiator_site_lock_(params->request_initiator_site_lock),
+ request_initiator_origin_lock_(params->request_initiator_origin_lock),
ignore_isolated_world_origin_(params->ignore_isolated_world_origin),
trust_token_redemption_policy_(params->trust_token_redemption_policy),
isolation_info_(params->isolation_info),
@@ -374,10 +392,11 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
}
}
- // Compare |request_initiator| and |request_initiator_site_lock_|.
+ // Compare |request_initiator| and |request_initiator_origin_lock_|.
InitiatorLockCompatibility initiator_lock_compatibility =
- VerifyRequestInitiatorLockWithPluginCheck(
- process_id_, request_initiator_site_lock_, request.request_initiator);
+ VerifyRequestInitiatorLockWithPluginCheck(process_id_,
+ request_initiator_origin_lock_,
+ request.request_initiator);
UMA_HISTOGRAM_ENUMERATION(
"NetworkService.URLLoader.RequestInitiatorOriginLockCompatibility",
initiator_lock_compatibility);
@@ -389,11 +408,13 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
break;
case InitiatorLockCompatibility::kNoLock:
- // TODO(lukasza): https://crbug.com/891872: Browser process should always
- // specify the request_initiator_site_lock in URLLoaderFactories given to
- // a renderer process. Once https://crbug.com/891872 is fixed, the case
- // below should return |false| (i.e. = bad message).
- break;
+ // |request_initiator_origin_lock| should always be set in a
+ // URLLoaderFactory vended to a renderer process. See also
+ // https://crbug.com/1114906.
+ NOTREACHED();
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: no initiator lock in a renderer request");
+ return false;
case InitiatorLockCompatibility::kNoInitiator:
// Requests from the renderer need to always specify an initiator.
@@ -408,8 +429,8 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
if (base::FeatureList::IsEnabled(
features::kRequestInitiatorSiteLockEnfocement)) {
url::debug::ScopedOriginCrashKey initiator_lock_crash_key(
- debug::GetRequestInitiatorSiteLockCrashKey(),
- base::OptionalOrNullptr(request_initiator_site_lock_));
+ debug::GetRequestInitiatorOriginLockCrashKey(),
+ base::OptionalOrNullptr(request_initiator_origin_lock_));
mojo::ReportBadMessage(
"CorsURLLoaderFactory: lock VS initiator mismatch");
return false;
@@ -468,6 +489,13 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
return false;
}
+ if (!net::HttpUtil::IsToken(request.method)) {
+ // Callers are expected to ensure that |method| follows RFC 7230.
+ mojo::ReportBadMessage(
+ "CorsURLLoaderFactory: invalid characters in method");
+ return false;
+ }
+
// TODO(yhirano): If the request mode is "no-cors", the redirect mode should
// be "follow".
return true;
@@ -476,16 +504,17 @@ bool CorsURLLoaderFactory::IsValidRequest(const ResourceRequest& request,
InitiatorLockCompatibility
CorsURLLoaderFactory::VerifyRequestInitiatorLockWithPluginCheck(
uint32_t process_id,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator) {
if (process_id == mojom::kBrowserProcessId)
return InitiatorLockCompatibility::kBrowserProcess;
InitiatorLockCompatibility result = VerifyRequestInitiatorLock(
- request_initiator_site_lock, request_initiator);
+ request_initiator_origin_lock, request_initiator);
if (result == InitiatorLockCompatibility::kIncorrectLock &&
- CrossOriginReadBlocking::ShouldAllowForPlugin(process_id)) {
+ CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
+ process_id)) {
result = InitiatorLockCompatibility::kExcludedCorbForPlugin;
}
diff --git a/chromium/services/network/cors/cors_url_loader_factory.h b/chromium/services/network/cors/cors_url_loader_factory.h
index 1dfdeac49f8..86074799b74 100644
--- a/chromium/services/network/cors/cors_url_loader_factory.h
+++ b/chromium/services/network/cors/cors_url_loader_factory.h
@@ -87,7 +87,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
InitiatorLockCompatibility VerifyRequestInitiatorLockWithPluginCheck(
uint32_t process_id,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator);
bool GetAllowAnyCorsExemptHeaderForBrowser() const;
@@ -105,7 +105,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CorsURLLoaderFactory final
// Retained from URLLoaderFactoryParams:
const bool disable_web_security_;
const int32_t process_id_ = mojom::kInvalidProcessId;
- const base::Optional<url::Origin> request_initiator_site_lock_;
+ const base::Optional<url::Origin> request_initiator_origin_lock_;
const bool ignore_isolated_world_origin_;
const mojom::TrustTokenRedemptionPolicy trust_token_redemption_policy_;
net::IsolationInfo isolation_info_;
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 20e261e4a92..52d64b36c4c 100644
--- a/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_factory_unittest.cc
@@ -70,6 +70,8 @@ class CorsURLLoaderFactoryTest : public testing::Test {
auto factory_params = network::mojom::URLLoaderFactoryParams::New();
factory_params->process_id = kProcessId;
+ factory_params->request_initiator_origin_lock =
+ url::Origin::Create(GURL("http://localhost"));
auto resource_scheduler_client =
base::MakeRefCounted<ResourceSchedulerClient>(
kProcessId, kRouteId, &resource_scheduler_,
diff --git a/chromium/services/network/cors/cors_url_loader_unittest.cc b/chromium/services/network/cors/cors_url_loader_unittest.cc
index 3d64f7ef8c1..191d3b0480d 100644
--- a/chromium/services/network/cors/cors_url_loader_unittest.cc
+++ b/chromium/services/network/cors/cors_url_loader_unittest.cc
@@ -27,7 +27,7 @@
#include "net/http/http_request_headers.h"
#include "net/proxy_resolution/configured_proxy_resolution_service.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "net/url_request/url_request.h"
+#include "net/url_request/referrer_policy.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "services/network/cors/cors_url_loader_factory.h"
@@ -146,7 +146,7 @@ class TestURLLoaderFactory : public mojom::URLLoaderFactory {
class CorsURLLoaderTest : public testing::Test {
public:
- using ReferrerPolicy = net::URLRequest::ReferrerPolicy;
+ using ReferrerPolicy = net::ReferrerPolicy;
CorsURLLoaderTest()
: task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {
@@ -179,7 +179,9 @@ class CorsURLLoaderTest : public testing::Test {
network_context_remote_.BindNewPipeAndPassReceiver(),
std::move(context_params));
- ResetFactory(base::nullopt, kRendererProcessId);
+ const url::Origin default_initiator_origin =
+ url::Origin::Create(GURL("https://example.com"));
+ ResetFactory(default_initiator_origin, kRendererProcessId);
}
void SetUp() override { SetUp(mojom::NetworkContextParams::New()); }
@@ -333,7 +335,7 @@ 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::ReferrerPolicy::NO_REFERRER,
net::SiteForCookies site_for_cookies = net::SiteForCookies()) {
net::RedirectInfo redirect_info;
redirect_info.status_code = status_code;
@@ -350,6 +352,9 @@ class CorsURLLoaderTest : public testing::Test {
bool is_trusted,
bool ignore_isolated_world_origin,
bool skip_cors_enabled_scheme_check) {
+ if (process_id != mojom::kBrowserProcessId)
+ DCHECK(initiator.has_value());
+
test_url_loader_factory_ = std::make_unique<TestURLLoaderFactory>();
test_url_loader_factory_receiver_ =
std::make_unique<mojo::Receiver<mojom::URLLoaderFactory>>(
@@ -357,7 +362,7 @@ class CorsURLLoaderTest : public testing::Test {
auto factory_params = network::mojom::URLLoaderFactoryParams::New();
if (initiator) {
- factory_params->request_initiator_site_lock = *initiator;
+ factory_params->request_initiator_origin_lock = *initiator;
if (!initiator->opaque()) {
factory_params->factory_bound_access_patterns =
network::mojom::CorsOriginAccessPatterns::New();
@@ -466,11 +471,33 @@ class BadMessageTestHelper {
DISALLOW_COPY_AND_ASSIGN(BadMessageTestHelper);
};
+TEST_F(CorsURLLoaderTest, NoCorsWithInvalidMethod) {
+ ResourceRequest request;
+ request.mode = mojom::RequestMode::kNoCors;
+ request.credentials_mode = mojom::CredentialsMode::kInclude;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(request.url);
+ request.method = "GET\r\nHost: other.example.com";
+
+ BadMessageTestHelper bad_message_helper;
+ CreateLoaderAndStart(request);
+ RunUntilComplete();
+
+ EXPECT_FALSE(IsNetworkLoaderStarted());
+ EXPECT_FALSE(client().has_received_redirect());
+ EXPECT_FALSE(client().has_received_response());
+ EXPECT_TRUE(client().has_received_completion());
+ EXPECT_EQ(net::ERR_INVALID_ARGUMENT, client().completion_status().error_code);
+ EXPECT_THAT(bad_message_helper.bad_message_reports(),
+ ::testing::ElementsAre(
+ "CorsURLLoaderFactory: invalid characters in method"));
+}
+
TEST_F(CorsURLLoaderTest, SameOriginWithoutInitiator) {
ResourceRequest request;
request.mode = mojom::RequestMode::kSameOrigin;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
BadMessageTestHelper bad_message_helper;
@@ -488,10 +515,17 @@ TEST_F(CorsURLLoaderTest, SameOriginWithoutInitiator) {
}
TEST_F(CorsURLLoaderTest, NoCorsWithoutInitiator) {
+ // This test needs to simulate a factory used from the browser process,
+ // because only the browser process may start requests with no
+ // |request_initiator|. A renderer process would have run into NOTREACHED and
+ // mojo::ReportBadMessage via InitiatorLockCompatibility::kNoInitiator case in
+ // CorsURLLoaderFactory::IsValidRequest.
+ ResetFactory(base::nullopt /* initiator */, mojom::kBrowserProcessId);
+
ResourceRequest request;
request.mode = mojom::RequestMode::kNoCors;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
CreateLoaderAndStart(request);
@@ -511,7 +545,7 @@ TEST_F(CorsURLLoaderTest, CorsWithoutInitiator) {
ResourceRequest request;
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
BadMessageTestHelper bad_message_helper;
@@ -534,7 +568,7 @@ TEST_F(CorsURLLoaderTest, NavigateWithoutInitiator) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNavigate;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
CreateLoaderAndStart(request);
@@ -553,7 +587,7 @@ TEST_F(CorsURLLoaderTest, NavigateWithoutInitiator) {
TEST_F(CorsURLLoaderTest, NavigationFromRenderer) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNavigate;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
BadMessageTestHelper bad_message_helper;
@@ -571,7 +605,7 @@ TEST_F(CorsURLLoaderTest, NavigationFromRenderer) {
}
TEST_F(CorsURLLoaderTest, SameOriginRequest) {
- const GURL url("http://example.com/foo.png");
+ const GURL url("https://example.com/foo.png");
CreateLoaderAndStart(url.GetOrigin(), url, mojom::RequestMode::kSameOrigin);
RunUntilCreateLoaderAndStartCalled();
@@ -588,8 +622,8 @@ TEST_F(CorsURLLoaderTest, SameOriginRequest) {
}
TEST_F(CorsURLLoaderTest, CrossOriginRequestWithNoCorsMode) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
CreateLoaderAndStart(origin, url, mojom::RequestMode::kNoCors);
RunUntilCreateLoaderAndStartCalled();
@@ -608,8 +642,8 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestWithNoCorsMode) {
}
TEST_F(CorsURLLoaderTest, CrossOriginRequestWithNoCorsModeAndPatchMethod) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
ResourceRequest request;
request.mode = mojom::RequestMode::kNoCors;
request.credentials_mode = mojom::CredentialsMode::kInclude;
@@ -632,12 +666,12 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestWithNoCorsModeAndPatchMethod) {
std::string origin_header;
EXPECT_TRUE(GetRequest().headers.GetHeader(net::HttpRequestHeaders::kOrigin,
&origin_header));
- EXPECT_EQ(origin_header, "http://example.com");
+ EXPECT_EQ(origin_header, "https://example.com");
}
TEST_F(CorsURLLoaderTest, CrossOriginRequestFetchRequestModeSameOrigin) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
CreateLoaderAndStart(origin, url, mojom::RequestMode::kSameOrigin);
RunUntilComplete();
@@ -654,8 +688,8 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestFetchRequestModeSameOrigin) {
}
TEST_F(CorsURLLoaderTest, CrossOriginRequestWithCorsModeButMissingCorsHeader) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
CreateLoaderAndStart(origin, url, mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
@@ -668,7 +702,7 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestWithCorsModeButMissingCorsHeader) {
std::string origin_header;
EXPECT_TRUE(GetRequest().headers.GetHeader(net::HttpRequestHeaders::kOrigin,
&origin_header));
- EXPECT_EQ(origin_header, "http://example.com");
+ EXPECT_EQ(origin_header, "https://example.com");
EXPECT_FALSE(client().has_received_redirect());
EXPECT_FALSE(client().has_received_response());
EXPECT_EQ(net::ERR_FAILED, client().completion_status().error_code);
@@ -678,13 +712,13 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestWithCorsModeButMissingCorsHeader) {
}
TEST_F(CorsURLLoaderTest, CrossOriginRequestWithCorsMode) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
CreateLoaderAndStart(origin, url, mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse(
- {{"Access-Control-Allow-Origin", "http://example.com"}});
+ {{"Access-Control-Allow-Origin", "https://example.com"}});
NotifyLoaderClientOnComplete(net::OK);
RunUntilComplete();
@@ -698,8 +732,8 @@ TEST_F(CorsURLLoaderTest, CrossOriginRequestWithCorsMode) {
TEST_F(CorsURLLoaderTest,
CrossOriginRequestFetchRequestWithCorsModeButMismatchedCorsHeader) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
CreateLoaderAndStart(origin, url, mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
@@ -771,14 +805,14 @@ TEST_F(CorsURLLoaderTest, CorsEnabledSameCustomSchemeRequest) {
}
TEST_F(CorsURLLoaderTest, StripUsernameAndPassword) {
- const GURL origin("http://example.com");
- const GURL url("http://foo:bar@other.com/foo.png");
- std::string stripped_url = "http://other.com/foo.png";
+ const GURL origin("https://example.com");
+ const GURL url("http://foo:bar@other.example.com/foo.png");
+ std::string stripped_url = "http://other.example.com/foo.png";
CreateLoaderAndStart(origin, url, mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse(
- {{"Access-Control-Allow-Origin", "http://example.com"}});
+ {{"Access-Control-Allow-Origin", "https://example.com"}});
NotifyLoaderClientOnComplete(net::OK);
RunUntilComplete();
@@ -1158,7 +1192,7 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
request.request_initiator = url::Origin::Create(origin);
request.referrer = url;
request.referrer_policy =
- net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
+ net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
CreateLoaderAndStart(request);
RunUntilCreateLoaderAndStartCalled();
@@ -1166,12 +1200,12 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
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,
+ EXPECT_EQ(net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
GetRequest().referrer_policy);
NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(
303, "GET", new_url, "https://other.example.com",
- net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN));
+ net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN));
RunUntilRedirectReceived();
EXPECT_TRUE(IsNetworkLoaderStarted());
@@ -1187,7 +1221,7 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
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,
+ EXPECT_EQ(net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
GetRequest().referrer_policy);
NotifyLoaderClientOnReceiveResponse(
@@ -1207,11 +1241,6 @@ TEST_F(CorsURLLoaderTest, RedirectInfoShouldBeUsed) {
// 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 =
@@ -1222,6 +1251,11 @@ TEST_F(CorsURLLoaderTest,
const net::SiteForCookies new_url_site_for_cookies =
net::SiteForCookies::FromOrigin(new_url_origin);
+ auto params = network::mojom::URLLoaderFactoryParams::New();
+ ResetFactory(url_origin, kRendererProcessId, true /* is_trusted */,
+ params->ignore_isolated_world_origin,
+ false /* skip_cors_enabled_scheme_check */);
+
ResourceRequest request;
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
@@ -1241,7 +1275,7 @@ TEST_F(CorsURLLoaderTest,
EXPECT_EQ(url, GetRequest().url);
NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(
- 303, "GET", new_url, "" /* referrer */, net::URLRequest::NO_REFERRER,
+ 303, "GET", new_url, "" /* referrer */, net::ReferrerPolicy::NO_REFERRER,
new_url_site_for_cookies));
RunUntilRedirectReceived();
@@ -1349,8 +1383,8 @@ TEST_F(CorsURLLoaderTest, CorsExemptHeaderRemovalOnCrossOriginRedirects) {
RunUntilCreateLoaderAndStartCalled();
EXPECT_EQ(1, num_created_loaders());
- NotifyLoaderClientOnReceiveRedirect(
- CreateRedirectInfo(301, "GET", GURL("https://google.com/bar.png")));
+ NotifyLoaderClientOnReceiveRedirect(CreateRedirectInfo(
+ 301, "GET", GURL("https://other.example.com/bar.png")));
RunUntilRedirectReceived();
EXPECT_TRUE(IsNetworkLoaderStarted());
@@ -1371,6 +1405,7 @@ TEST_F(CorsURLLoaderTest, CorsExemptHeaderRemovalOnCrossOriginRedirects) {
TEST_F(CorsURLLoaderTest, CorsExemptHeaderModificationOnRedirects) {
ResourceRequest request;
request.url = GURL("https://example.com/foo.png");
+ request.request_initiator = url::Origin::Create(request.url);
request.cors_exempt_headers.SetHeader(kTestCorsExemptHeader, "test-value");
CreateLoaderAndStart(request);
RunUntilCreateLoaderAndStartCalled();
@@ -1404,8 +1439,8 @@ TEST_F(CorsURLLoaderTest, CorsExemptHeaderModificationOnRedirects) {
// OriginAccessListTest, but this test intends to verify if CorsURlLoader calls
// the list properly.
TEST_F(CorsURLLoaderTest, OriginAccessList_Allowed) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
// Adds an entry to allow the cross origin request beyond the CORS
// rules.
@@ -1434,10 +1469,10 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_Allowed) {
// ResourceRequest::isolated_world_origin when consulting OriginAccessList.
TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin) {
const url::Origin main_world_origin =
- url::Origin::Create(GURL("http://main-world.com"));
+ url::Origin::Create(GURL("http://main-world.example.com"));
const url::Origin isolated_world_origin =
- url::Origin::Create(GURL("http://isolated-world.com"));
- const GURL url("http://other.com/foo.png");
+ url::Origin::Create(GURL("http://isolated-world.example.com"));
+ const GURL url("http://other.example.com/foo.png");
ResetFactory(main_world_origin, kRendererProcessId, false /* trusted */,
false /* ignore_isolated_world_origin */,
@@ -1475,13 +1510,13 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin) {
// after redirects.
TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin_Redirect) {
const url::Origin main_world_origin =
- url::Origin::Create(GURL("http://main-world.com"));
+ url::Origin::Create(GURL("http://main-world.example.com"));
const url::Origin isolated_world_origin =
- url::Origin::Create(GURL("http://isolated-world.com"));
- const GURL url("http://other.com/foo.png");
+ url::Origin::Create(GURL("http://isolated-world.example.com"));
+ const GURL url("http://other.example.com/foo.png");
// |new_url| is same-origin as |url| to avoid tainting the response
// in CorsURLLoader::OnReceiveRedirect.
- const GURL new_url("http://other.com/bar.png");
+ const GURL new_url("http://other.example.com/bar.png");
ResetFactory(main_world_origin, kRendererProcessId, false /* trusted */,
false /* ignore_isolated_world_origin */,
@@ -1532,10 +1567,10 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOrigin_Redirect) {
// when URLLoaderFactoryParams::ignore_isolated_world_origin is set to true.
TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOriginIgnored) {
const url::Origin main_world_origin =
- url::Origin::Create(GURL("http://main-world.com"));
+ url::Origin::Create(GURL("http://main-world.example.com"));
const url::Origin isolated_world_origin =
- url::Origin::Create(GURL("http://isolated-world.com"));
- const GURL url("http://other.com/foo.png");
+ url::Origin::Create(GURL("http://isolated-world.example.com"));
+ const GURL url("http://other.example.com/foo.png");
ResetFactory(main_world_origin, kRendererProcessId, false /* trusted */,
true /* ignore_isolated_world_origin */,
@@ -1568,8 +1603,8 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_IsolatedWorldOriginIgnored) {
// Check if higher-priority block list wins.
TEST_F(CorsURLLoaderTest, OriginAccessList_Blocked) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
AddAllowListEntryForOrigin(url::Origin::Create(origin), url.scheme(),
url.host(),
@@ -1596,8 +1631,8 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_Blocked) {
// per-URLLoaderFactory list. This test verifies if per-URLLoaderFactory list
// works.
TEST_F(CorsURLLoaderTest, OriginAccessList_AllowedByFactoryList) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
AddFactoryBoundAllowListEntryForOrigin(
url::Origin::Create(origin), url.scheme(), url.host(),
@@ -1622,8 +1657,8 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_AllowedByFactoryList) {
// Checks if CorsURLLoader can respect the per-NetworkContext block list.
TEST_F(CorsURLLoaderTest, OriginAccessList_AllowedByFactoryListButBlocked) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
AddFactoryBoundAllowListEntryForOrigin(
url::Origin::Create(origin), url.scheme(), url.host(),
@@ -1648,8 +1683,8 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_AllowedByFactoryListButBlocked) {
// Tests if OriginAccessList is actually used to decide response tainting.
TEST_F(CorsURLLoaderTest, OriginAccessList_NoCors) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
// Adds an entry to allow the cross origin request without using
// CORS.
@@ -1675,8 +1710,8 @@ TEST_F(CorsURLLoaderTest, OriginAccessList_NoCors) {
}
TEST_F(CorsURLLoaderTest, OriginAccessList_POST) {
- const GURL origin("http://example.com");
- const GURL url("http://other.com/foo.png");
+ const GURL origin("https://example.com");
+ const GURL url("http://other.example.com/foo.png");
// Adds an entry to allow the cross origin request beyond the CORS
// rules.
@@ -1943,9 +1978,10 @@ TEST_F(CorsURLLoaderTest, RequestWithHostHeaderFails) {
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
request.method = net::HttpRequestHeaders::kGetMethod;
- request.url = GURL("https://foo.test/path");
- request.request_initiator = url::Origin::Create(GURL("https://foo.test"));
- request.headers.SetHeader(net::HttpRequestHeaders::kHost, "bar.test");
+ request.url = GURL("https://example.com/path");
+ request.request_initiator = url::Origin::Create(GURL("https://example.com"));
+ request.headers.SetHeader(net::HttpRequestHeaders::kHost,
+ "other.example.com");
CreateLoaderAndStart(request);
RunUntilComplete();
@@ -1960,8 +1996,8 @@ TEST_F(CorsURLLoaderTest, RequestWithProxyAuthorizationHeaderFails) {
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
request.method = net::HttpRequestHeaders::kGetMethod;
- request.url = GURL("https://foo.test/path");
- request.request_initiator = url::Origin::Create(GURL("https://foo.test"));
+ request.url = GURL("https://example.com/path");
+ request.request_initiator = url::Origin::Create(GURL("https://example.com"));
request.headers.SetHeader(net::HttpRequestHeaders::kProxyAuthorization,
"Basic Zm9vOmJhcg==");
CreateLoaderAndStart(request);
@@ -1979,8 +2015,8 @@ TEST_F(CorsURLLoaderTest, NoConcerningRequestHeadersLoggedCorrectly) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNoCors;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
- request.request_initiator = base::nullopt;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(GURL("https://example.com"));
request.headers.SetHeader("Not", "Concerning");
request.headers.SetHeader("Totally", "Fine");
@@ -2009,8 +2045,8 @@ TEST_F(CorsURLLoaderTest, ConcerningRequestHeadersLoggedCorrectly) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNoCors;
request.credentials_mode = mojom::CredentialsMode::kInclude;
- request.url = GURL("http://example.com/");
- request.request_initiator = base::nullopt;
+ request.url = GURL("https://example.com/");
+ request.request_initiator = url::Origin::Create(GURL("https://example.com"));
request.headers.SetHeader(net::HttpRequestHeaders::kConnection, "Close");
request.headers.SetHeader(net::HttpRequestHeaders::kCookie, "BadIdea=true");
@@ -2043,7 +2079,8 @@ TEST_F(CorsURLLoaderTest, ConcerningRequestHeadersLoggedCorrectly) {
}
TEST_F(CorsURLLoaderTest, SetHostHeaderOnRedirectFails) {
- CreateLoaderAndStart(GURL("http://foo.test/"), GURL("http://foo.test/path"),
+ CreateLoaderAndStart(GURL("https://example.com/"),
+ GURL("https://example.com/path"),
mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
@@ -2071,7 +2108,8 @@ TEST_F(CorsURLLoaderTest, SetHostHeaderOnRedirectFails) {
}
TEST_F(CorsURLLoaderTest, SetProxyAuthorizationHeaderOnRedirectFails) {
- CreateLoaderAndStart(GURL("http://foo.test/"), GURL("http://foo.test/path"),
+ CreateLoaderAndStart(GURL("https://example.com/"),
+ GURL("https://example.com/path"),
mojom::RequestMode::kCors);
RunUntilCreateLoaderAndStartCalled();
@@ -2100,10 +2138,17 @@ TEST_F(CorsURLLoaderTest, SetProxyAuthorizationHeaderOnRedirectFails) {
}
TEST_F(CorsURLLoaderTest, SameOriginCredentialsModeWithoutInitiator) {
+ // This test needs to simulate a factory used from the browser process,
+ // because only the browser process may start requests with no
+ // |request_initiator|. A renderer process would have run into NOTREACHED and
+ // mojo::ReportBadMessage via InitiatorLockCompatibility::kNoInitiator case in
+ // CorsURLLoaderFactory::IsValidRequest.
+ ResetFactory(base::nullopt /* initiator */, mojom::kBrowserProcessId);
+
ResourceRequest request;
request.mode = mojom::RequestMode::kNoCors;
request.credentials_mode = mojom::CredentialsMode::kSameOrigin;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = base::nullopt;
BadMessageTestHelper bad_message_helper;
@@ -2126,7 +2171,7 @@ TEST_F(CorsURLLoaderTest, SameOriginCredentialsModeOnNavigation) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNavigate;
request.credentials_mode = mojom::CredentialsMode::kSameOrigin;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = url::Origin::Create(request.url);
BadMessageTestHelper bad_message_helper;
@@ -2150,7 +2195,7 @@ TEST_F(CorsURLLoaderTest, OmitCredentialsModeOnNavigation) {
ResourceRequest request;
request.mode = mojom::RequestMode::kNavigate;
request.credentials_mode = mojom::CredentialsMode::kOmit;
- request.url = GURL("http://example.com/");
+ request.url = GURL("https://example.com/");
request.request_initiator = url::Origin::Create(request.url);
BadMessageTestHelper bad_message_helper;
@@ -2171,11 +2216,13 @@ TEST_F(CorsURLLoaderTest, OmitCredentialsModeOnNavigation) {
// Make sure than when a request is failed due to having |trusted_params| set
// and being sent to an untrusted URLLoaderFactory, no CORS request is made.
TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
+ url::Origin initiator = url::Origin::Create(GURL("https://example.com"));
+
// Run the test with a trusted URLLoaderFactory as well, to make sure a CORS
// request is in fact made when using a trusted factory.
for (bool is_trusted : {false, true}) {
bool ignore_isolated_world_origin = true; // This is the default.
- ResetFactory(base::nullopt, kRendererProcessId, is_trusted,
+ ResetFactory(initiator, kRendererProcessId, is_trusted,
ignore_isolated_world_origin,
false /* skip_cors_enabled_scheme_check */);
@@ -2185,8 +2232,8 @@ TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
request.method = net::HttpRequestHeaders::kGetMethod;
- request.url = GURL("http://other.com/foo.png");
- request.request_initiator = url::Origin::Create(GURL("http://example.com"));
+ request.url = GURL("http://other.example.com/foo.png");
+ request.request_initiator = initiator;
request.trusted_params = ResourceRequest::TrustedParams();
CreateLoaderAndStart(request);
@@ -2205,7 +2252,7 @@ TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
} else {
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse(
- {{"Access-Control-Allow-Origin", "http://example.com"}});
+ {{"Access-Control-Allow-Origin", "https://example.com"}});
NotifyLoaderClientOnComplete(net::OK);
RunUntilComplete();
@@ -2223,7 +2270,9 @@ TEST_F(CorsURLLoaderTest, TrustedParamsWithUntrustedFactoryFailsBeforeCORS) {
// Test that when a request has LOAD_RESTRICTED_PREFETCH and a
// NetworkIsolationKey, CorsURLLoaderFactory does not reject the request.
TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
- ResetFactory(base::nullopt, kRendererProcessId, true /* is_trusted */,
+ url::Origin initiator = url::Origin::Create(GURL("https://example.com"));
+
+ ResetFactory(initiator, kRendererProcessId, true /* is_trusted */,
true /* ignore_isolated_world_origin */,
false /* skip_cors_enabled_scheme_check */);
@@ -2233,8 +2282,8 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
request.method = net::HttpRequestHeaders::kGetMethod;
- request.url = GURL("http://other.com/foo.png");
- request.request_initiator = url::Origin::Create(GURL("http://example.com"));
+ request.url = GURL("http://other.example.com/foo.png");
+ request.request_initiator = initiator;
request.load_flags |= net::LOAD_RESTRICTED_PREFETCH;
request.trusted_params = ResourceRequest::TrustedParams();
@@ -2248,7 +2297,7 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
RunUntilCreateLoaderAndStartCalled();
NotifyLoaderClientOnReceiveResponse(
- {{"Access-Control-Allow-Origin", "http://example.com"}});
+ {{"Access-Control-Allow-Origin", "https://example.com"}});
NotifyLoaderClientOnComplete(net::OK);
RunUntilComplete();
@@ -2265,7 +2314,8 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchSucceedsWithNIK) {
// because the LOAD_RESTRICTED_PREFETCH flag must only appear on requests that
// make use of their TrustedParams' |isolation_info|.
TEST_F(CorsURLLoaderTest, RestrictedPrefetchFailsWithoutNIK) {
- ResetFactory(base::nullopt, kRendererProcessId, true /* is_trusted */,
+ url::Origin initiator = url::Origin::Create(GURL("https://example.com"));
+ ResetFactory(initiator, kRendererProcessId, true /* is_trusted */,
true /* ignore_isolated_world_origin */,
false /* skip_cors_enabled_scheme_check */);
@@ -2275,8 +2325,8 @@ TEST_F(CorsURLLoaderTest, RestrictedPrefetchFailsWithoutNIK) {
request.mode = mojom::RequestMode::kCors;
request.credentials_mode = mojom::CredentialsMode::kOmit;
request.method = net::HttpRequestHeaders::kGetMethod;
- request.url = GURL("http://other.com/foo.png");
- request.request_initiator = url::Origin::Create(GURL("http://example.com"));
+ request.url = GURL("http://other.example.com/foo.png");
+ request.request_initiator = initiator;
request.load_flags |= net::LOAD_RESTRICTED_PREFETCH;
request.trusted_params = ResourceRequest::TrustedParams();
@@ -2464,70 +2514,6 @@ TEST_F(CorsURLLoaderTest, TAOCheckPassRedirect2) {
EXPECT_TRUE(client().response_head()->timing_allow_passed);
}
-class CorsURLLoaderExtraSafelistedHeadersTest : public CorsURLLoaderTest {
- public:
- void SetUp() override {
- auto params = mojom::NetworkContextParams::New();
- params->cors_extra_safelisted_request_header_names = {
- "safelisted-1", "safelisted-2", "safelisted-3"};
- CorsURLLoaderTest::SetUp(std::move(params));
- }
-};
-
-TEST_F(CorsURLLoaderExtraSafelistedHeadersTest, ExtraSafelistedHeaders1) {
- const GURL origin("https://example.com");
- const GURL url("https://other.example.com/foo.png");
- const GURL new_url("https://other2.example.com/bar.png");
-
- ResourceRequest request;
- request.mode = mojom::RequestMode::kCors;
- request.credentials_mode = mojom::CredentialsMode::kOmit;
- request.method = "GET";
- request.url = url;
- request.request_initiator = url::Origin::Create(origin);
- request.headers.SetHeader("safelisted-1", "foo");
- request.headers.SetHeader("safelisted-2", "bar");
- request.headers.SetHeader("safelisted-3", "baz");
-
- CreateLoaderAndStart(request);
- RunUntilCreateLoaderAndStartCalled();
-
- // NO preflight request
- ASSERT_EQ(1, num_created_loaders());
- EXPECT_EQ(GetRequest().url, url);
- EXPECT_EQ(GetRequest().method, "GET");
-}
-
-TEST_F(CorsURLLoaderExtraSafelistedHeadersTest, ExtraSafelistedHeaders2) {
- const GURL origin("https://example.com");
- const GURL url("https://other.example.com/foo.png");
- const GURL new_url("https://other2.example.com/bar.png");
-
- ResourceRequest request;
- request.mode = mojom::RequestMode::kCors;
- request.credentials_mode = mojom::CredentialsMode::kOmit;
- request.method = "GET";
- request.url = url;
- request.request_initiator = url::Origin::Create(origin);
- request.headers.SetHeader("safelisted-1", "foo");
- request.headers.SetHeader("safelisted-2", "bar");
- request.headers.SetHeader("hoge", "fuga");
- request.headers.SetHeader("piyo", "hogera");
-
- CreateLoaderAndStart(request);
- RunUntilCreateLoaderAndStartCalled();
-
- // preflight request
- ASSERT_EQ(1, num_created_loaders());
- EXPECT_EQ(GetRequest().url, url);
- EXPECT_EQ(GetRequest().method, "OPTIONS");
-
- std::string headers;
- EXPECT_TRUE(GetRequest().headers.GetHeader("access-control-request-headers",
- &headers));
- EXPECT_EQ(headers, "hoge,piyo");
-}
-
} // namespace
} // namespace cors
diff --git a/chromium/services/network/cors/preflight_controller.cc b/chromium/services/network/cors/preflight_controller.cc
index 84bc1ec35d0..11e1a9fad64 100644
--- a/chromium/services/network/cors/preflight_controller.cc
+++ b/chromium/services/network/cors/preflight_controller.cc
@@ -55,15 +55,13 @@ base::Optional<std::string> GetHeaderString(
// - byte-lowercased
std::string CreateAccessControlRequestHeadersHeader(
const net::HttpRequestHeaders& headers,
- bool is_revalidating,
- const base::flat_set<std::string>& extra_safelisted_header_names) {
+ bool is_revalidating) {
// Exclude the forbidden headers because they may be added by the user
// agent. They must be checked separately and rejected for
// JavaScript-initiated requests.
std::vector<std::string> filtered_headers =
CorsUnsafeNotForbiddenRequestHeaderNames(headers.GetHeaderVector(),
- is_revalidating,
- extra_safelisted_header_names);
+ is_revalidating);
if (filtered_headers.empty())
return std::string();
@@ -76,7 +74,6 @@ std::string CreateAccessControlRequestHeadersHeader(
std::unique_ptr<ResourceRequest> CreatePreflightRequest(
const ResourceRequest& request,
bool tainted,
- const base::flat_set<std::string>& extra_safelisted_header_names,
const base::Optional<base::UnguessableToken>& devtools_request_id) {
DCHECK(!request.url.has_username());
DCHECK(!request.url.has_password());
@@ -92,6 +89,7 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest(
preflight_request->destination = request.destination;
preflight_request->referrer = request.referrer;
preflight_request->referrer_policy = request.referrer_policy;
+ preflight_request->mode = mojom::RequestMode::kCors;
preflight_request->credentials_mode = mojom::CredentialsMode::kOmit;
preflight_request->load_flags = RetrieveCacheFlags(request.load_flags);
@@ -106,7 +104,7 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest(
header_names::kAccessControlRequestMethod, request.method);
std::string request_headers = CreateAccessControlRequestHeadersHeader(
- request.headers, request.is_revalidating, extra_safelisted_header_names);
+ request.headers, request.is_revalidating);
if (!request_headers.empty()) {
preflight_request->headers.SetHeader(
header_names::kAccessControlRequestHeaders, request_headers);
@@ -123,6 +121,17 @@ std::unique_ptr<ResourceRequest> CreatePreflightRequest(
net::HttpRequestHeaders::kOrigin,
(tainted ? url::Origin() : *request.request_initiator).Serialize());
+ // We normally set User-Agent down in the network stack, but the DevTools
+ // emulation override is applied on a higher level (renderer or browser),
+ // so copy User-Agent from the original request, if present.
+ // TODO(caseq, morlovich): do the same for client hints.
+ std::string user_agent;
+ if (request.headers.GetHeader(net::HttpRequestHeaders::kUserAgent,
+ &user_agent)) {
+ preflight_request->headers.SetHeader(net::HttpRequestHeaders::kUserAgent,
+ user_agent);
+ }
+
// Additional headers that the algorithm in the spec does not require, but
// it's better that CORS preflight requests have them.
preflight_request->headers.SetHeader("Sec-Fetch-Mode", "cors");
@@ -178,16 +187,14 @@ std::unique_ptr<PreflightResult> CreatePreflightResult(
base::Optional<CorsErrorStatus> CheckPreflightResult(
PreflightResult* result,
- const ResourceRequest& original_request,
- const base::flat_set<std::string>& extra_safelisted_header_names) {
+ const ResourceRequest& original_request) {
base::Optional<CorsErrorStatus> status =
result->EnsureAllowedCrossOriginMethod(original_request.method);
if (status)
return status;
return result->EnsureAllowedCrossOriginHeaders(
- original_request.headers, original_request.is_revalidating,
- extra_safelisted_header_names);
+ original_request.headers, original_request.is_revalidating);
}
} // namespace
@@ -211,9 +218,8 @@ class PreflightController::PreflightLoader final {
auto* network_service_client = MaybeGetNetworkServiceClientForDevTools();
if (network_service_client)
devtools_request_id_ = base::UnguessableToken::Create();
- auto preflight_request = CreatePreflightRequest(
- request, tainted, controller->extra_safelisted_header_names(),
- devtools_request_id_);
+ auto preflight_request =
+ CreatePreflightRequest(request, tainted, devtools_request_id_);
if (network_service_client) {
DCHECK(devtools_request_id_);
@@ -291,8 +297,7 @@ class PreflightController::PreflightLoader final {
// Preflight succeeded. Check |original_request_| with |result|.
DCHECK(!detected_error_status);
detected_error_status =
- CheckPreflightResult(result.get(), original_request_,
- controller_->extra_safelisted_header_names());
+ CheckPreflightResult(result.get(), original_request_);
}
if (!(original_request_.load_flags & net::LOAD_DISABLE_CACHE) &&
@@ -370,7 +375,7 @@ std::unique_ptr<ResourceRequest>
PreflightController::CreatePreflightRequestForTesting(
const ResourceRequest& request,
bool tainted) {
- return CreatePreflightRequest(request, tainted, {}, base::nullopt);
+ return CreatePreflightRequest(request, tainted, base::nullopt);
}
// static
@@ -385,12 +390,8 @@ PreflightController::CreatePreflightResultForTesting(
detected_error_status);
}
-PreflightController::PreflightController(
- const std::vector<std::string>& extra_safelisted_header_names,
- NetworkService* network_service)
- : extra_safelisted_header_names_(extra_safelisted_header_names.cbegin(),
- extra_safelisted_header_names.cend()),
- network_service_(network_service) {}
+PreflightController::PreflightController(NetworkService* network_service)
+ : network_service_(network_service) {}
PreflightController::~PreflightController() = default;
diff --git a/chromium/services/network/cors/preflight_controller.h b/chromium/services/network/cors/preflight_controller.h
index 437840d7049..7e7cf4bec8b 100644
--- a/chromium/services/network/cors/preflight_controller.h
+++ b/chromium/services/network/cors/preflight_controller.h
@@ -52,9 +52,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
bool tainted,
base::Optional<CorsErrorStatus>* detected_error_status);
- PreflightController(
- const std::vector<std::string>& extra_safelisted_header_names,
- NetworkService* network_service);
+ explicit PreflightController(NetworkService* network_service);
~PreflightController();
// Determines if a CORS-preflight request is needed, and checks the cache, or
@@ -70,15 +68,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
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_;
- }
-
- void set_extra_safelisted_header_names(
- const base::flat_set<std::string>& extra_safelisted_header_names) {
- extra_safelisted_header_names_ = extra_safelisted_header_names;
- }
-
private:
class PreflightLoader;
@@ -94,8 +83,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) PreflightController final {
std::set<std::unique_ptr<PreflightLoader>, base::UniquePtrComparator>
loaders_;
- base::flat_set<std::string> extra_safelisted_header_names_;
-
NetworkService* const network_service_;
DISALLOW_COPY_AND_ASSIGN(PreflightController);
diff --git a/chromium/services/network/cors/preflight_controller_unittest.cc b/chromium/services/network/cors/preflight_controller_unittest.cc
index c252df4121a..effbbabe67e 100644
--- a/chromium/services/network/cors/preflight_controller_unittest.cc
+++ b/chromium/services/network/cors/preflight_controller_unittest.cc
@@ -229,8 +229,7 @@ TEST(PreflightControllerOptionsTest, CheckOptions) {
base::test::TaskEnvironment task_environment_(
base::test::TaskEnvironment::MainThreadType::IO);
TestURLLoaderFactory url_loader_factory;
- PreflightController preflight_controller(
- {} /* extra_safelisted_header_names */, nullptr /* network_service */);
+ PreflightController preflight_controller(nullptr /* network_service */);
network::ResourceRequest request;
request.url = GURL("https://example.com/");
@@ -300,7 +299,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
int32_t process_id,
int32_t routing_id,
const std::string& devtools_request_id,
- const net::CookieAndLineStatusList& cookies_with_status,
+ const net::CookieAndLineAccessResultList& cookies_with_access_result,
std::vector<network::mojom::HttpRawHeaderPairPtr> headers,
const base::Optional<std::string>& raw_response_headers) override {
on_raw_response_called_ = true;
@@ -364,6 +363,10 @@ class PreflightControllerTest : public testing::Test {
network::mojom::URLLoaderFactoryParamsPtr params =
network::mojom::URLLoaderFactoryParams::New();
params->process_id = mojom::kBrowserProcessId;
+ // We use network::CorsURLLoaderFactory for "internal" URLLoaderFactory
+ // used by the PreflightController. Hence here we disable CORS as otherwise
+ // the URLLoader would create a CORS-preflight for the preflight request.
+ params->disable_web_security = true;
params->is_corb_enabled = false;
network_context_remote_->CreateURLLoaderFactory(
url_loader_factory_remote_.BindNewPipeAndPassReceiver(),
@@ -418,8 +421,8 @@ class PreflightControllerTest : public testing::Test {
void SetUp() override {
SetAccessControlAllowOrigin(test_initiator_origin_);
- preflight_controller_ = std::make_unique<PreflightController>(
- std::vector<std::string>(), network_service_.get());
+ preflight_controller_ =
+ std::make_unique<PreflightController>(network_service_.get());
test_server_.RegisterRequestHandler(base::BindRepeating(
&PreflightControllerTest::ServePreflight, base::Unretained(this)));
diff --git a/chromium/services/network/crash_keys.cc b/chromium/services/network/crash_keys.cc
index 34e493d07ef..c4ddd387760 100644
--- a/chromium/services/network/crash_keys.cc
+++ b/chromium/services/network/crash_keys.cc
@@ -27,9 +27,9 @@ base::debug::CrashKeyString* GetRequestInitiatorCrashKey() {
} // namespace
-base::debug::CrashKeyString* GetRequestInitiatorSiteLockCrashKey() {
+base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey() {
static auto* crash_key = base::debug::AllocateCrashKeyString(
- "request_initiator_site_lock", base::debug::CrashKeySize::Size64);
+ "request_initiator_origin_lock", base::debug::CrashKeySize::Size64);
return crash_key;
}
diff --git a/chromium/services/network/crash_keys.h b/chromium/services/network/crash_keys.h
index cab44590e6e..52e96115827 100644
--- a/chromium/services/network/crash_keys.h
+++ b/chromium/services/network/crash_keys.h
@@ -15,7 +15,7 @@ struct ResourceRequest;
namespace debug {
-base::debug::CrashKeyString* GetRequestInitiatorSiteLockCrashKey();
+base::debug::CrashKeyString* GetRequestInitiatorOriginLockCrashKey();
class ScopedRequestCrashKeys {
public:
diff --git a/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.cc b/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.cc
new file mode 100644
index 00000000000..53faac40eae
--- /dev/null
+++ b/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.cc
@@ -0,0 +1,43 @@
+// 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 <set>
+
+#include "base/no_destructor.h"
+#include "base/stl_util.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
+
+namespace network {
+
+namespace {
+
+std::set<int>& GetPluginProxyingProcesses() {
+ static base::NoDestructor<std::set<int>> set;
+ return *set;
+}
+
+} // namespace
+
+// static
+void CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(
+ int process_id) {
+ std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+ plugin_proxies.insert(process_id);
+}
+
+// static
+bool CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
+ int process_id) {
+ std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+ return base::Contains(plugin_proxies, process_id);
+}
+
+// static
+void CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(
+ int process_id) {
+ std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
+ plugin_proxies.erase(process_id);
+}
+
+} // namespace network
diff --git a/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.h b/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.h
new file mode 100644
index 00000000000..820347506ea
--- /dev/null
+++ b/chromium/services/network/cross_origin_read_blocking_exception_for_plugin.h
@@ -0,0 +1,38 @@
+// 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_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
+#define SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
+
+#include "base/component_export.h"
+#include "base/macros.h"
+
+namespace network {
+
+class COMPONENT_EXPORT(NETWORK_SERVICE)
+ CrossOriginReadBlockingExceptionForPlugin {
+ public:
+ // Notifies CORB that |process_id| is proxying requests on behalf of a
+ // universal-access plugin and therefore CORB should stop blocking requests
+ // marked as ResourceType::kPluginResource.
+ //
+ // TODO(lukasza, laforge): https://crbug.com/702995: Remove the static
+ // ...ForPlugin methods once Flash support is removed from Chromium (probably
+ // around 2020 - see https://www.chromium.org/flash-roadmap).
+ static void AddExceptionForPlugin(int process_id);
+
+ // Returns true if CORB should ignore a request initiated by a universal
+ // access plugin - i.e. if |process_id| has been previously passed to
+ // AddExceptionForPlugin.
+ static bool ShouldAllowForPlugin(int process_id);
+
+ // Reverts AddExceptionForPlugin.
+ static void RemoveExceptionForPlugin(int process_id);
+
+ DISALLOW_COPY_AND_ASSIGN(CrossOriginReadBlockingExceptionForPlugin);
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_EXCEPTION_FOR_PLUGIN_H_
diff --git a/chromium/services/network/cross_origin_read_blocking_explainer.md b/chromium/services/network/cross_origin_read_blocking_explainer.md
index fe55d43dbd2..f29500ac6db 100644
--- a/chromium/services/network/cross_origin_read_blocking_explainer.md
+++ b/chromium/services/network/cross_origin_read_blocking_explainer.md
@@ -680,8 +680,8 @@ which are distributed via JSON (which is CORB-protected).
In the future CORB may be extended to protect additional resources as follows:
* **Covering more MIME types**.
- Instead of blacklisting HTML, XML, and JSON, CORB protection can be extended to
- all MIME types, except MIME types that are whitelisted as usable in `<img>`,
+ Instead of blocklisting HTML, XML, and JSON, CORB protection can be extended to
+ all MIME types, except MIME types that are allowlisted as usable in `<img>`,
`<audio>`, `<video>`, `<script>` and other similar elements that can be
embedded cross-origin:
* [JavaScript MIME type](https://html.spec.whatwg.org/#javascript-mime-type)
diff --git a/chromium/services/network/expect_ct_reporter.h b/chromium/services/network/expect_ct_reporter.h
index 559229601f2..30ea3b69656 100644
--- a/chromium/services/network/expect_ct_reporter.h
+++ b/chromium/services/network/expect_ct_reporter.h
@@ -26,7 +26,7 @@ namespace network {
// the URLRequestContext that is passed to the constructor, so that it
// can cancel its requests.
//
-// Since reports are sent with a non-CORS-whitelisted Content-Type, this class
+// Since reports are sent with a non-CORS-allowlisted Content-Type, this class
// sends CORS preflight requests before sending reports. Expect-CT is not
// evaluated with a particular frame or request as context, so the preflight
// request contains an `Origin: null` header instead of a particular origin.
diff --git a/chromium/services/network/expect_ct_reporter_unittest.cc b/chromium/services/network/expect_ct_reporter_unittest.cc
index 08449291e7c..e2fc979fdc7 100644
--- a/chromium/services/network/expect_ct_reporter_unittest.cc
+++ b/chromium/services/network/expect_ct_reporter_unittest.cc
@@ -48,12 +48,12 @@ class TestCertificateReportSender : public net::ReportSender {
: ReportSender(nullptr, TRAFFIC_ANNOTATION_FOR_TESTS) {}
~TestCertificateReportSender() override {}
- void Send(const GURL& report_uri,
- base::StringPiece content_type,
- base::StringPiece serialized_report,
- const base::RepeatingCallback<void()>& success_callback,
- const base::RepeatingCallback<void(const GURL&, int, int)>&
- error_callback) override {
+ void Send(
+ const GURL& report_uri,
+ base::StringPiece content_type,
+ base::StringPiece serialized_report,
+ base::OnceCallback<void()> success_callback,
+ base::OnceCallback<void(const GURL&, int, int)> error_callback) override {
sent_report_count_++;
latest_report_uri_ = report_uri;
latest_serialized_report_.assign(serialized_report.data(),
diff --git a/chromium/services/network/host_resolver.cc b/chromium/services/network/host_resolver.cc
index 561a1c22a90..1711176ecea 100644
--- a/chromium/services/network/host_resolver.cc
+++ b/chromium/services/network/host_resolver.cc
@@ -15,6 +15,7 @@
#include "net/dns/host_resolver.h"
#include "net/dns/host_resolver_source.h"
#include "net/log/net_log.h"
+#include "net/net_buildflags.h"
#include "services/network/host_resolver_mdns_listener.h"
#include "services/network/public/cpp/host_resolver_mojom_traits.h"
#include "services/network/resolve_host_request.h"
diff --git a/chromium/services/network/host_resolver_unittest.cc b/chromium/services/network/host_resolver_unittest.cc
index 509ff744f55..a7ba3ed9f2e 100644
--- a/chromium/services/network/host_resolver_unittest.cc
+++ b/chromium/services/network/host_resolver_unittest.cc
@@ -31,6 +31,7 @@
#include "net/dns/mock_host_resolver.h"
#include "net/dns/public/dns_protocol.h"
#include "net/log/net_log.h"
+#include "net/net_buildflags.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
diff --git a/chromium/services/network/ignore_errors_cert_verifier.h b/chromium/services/network/ignore_errors_cert_verifier.h
index a2ab2338d19..0c7f5324cdb 100644
--- a/chromium/services/network/ignore_errors_cert_verifier.h
+++ b/chromium/services/network/ignore_errors_cert_verifier.h
@@ -57,7 +57,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) IgnoreErrorsCertVerifier
private:
friend class IgnoreErrorsCertVerifierTest;
- void SetAllowlistForTesting(const SPKIHashSet& whitelist);
+ void SetAllowlistForTesting(const SPKIHashSet& allowlist);
std::unique_ptr<net::CertVerifier> verifier_;
SPKIHashSet allowlist_;
diff --git a/chromium/services/network/net_log_exporter.cc b/chromium/services/network/net_log_exporter.cc
index 717076e1fe1..d5694bec240 100644
--- a/chromium/services/network/net_log_exporter.cc
+++ b/chromium/services/network/net_log_exporter.cc
@@ -90,13 +90,13 @@ void NetLogExporter::Stop(base::Value polled_data_value,
return;
}
- std::unique_ptr<base::DictionaryValue> net_info = net::GetNetInfo(
+ base::Value net_info = net::GetNetInfo(
network_context_->url_request_context(), net::NET_INFO_ALL_SOURCES);
if (polled_data)
- net_info->MergeDictionary(polled_data);
+ net_info.MergeDictionary(polled_data);
file_net_observer_->StopObserving(
- std::move(net_info),
+ base::Value::ToUniquePtrValue(std::move(net_info)),
base::BindOnce([](StopCallback sc) { std::move(sc).Run(net::OK); },
std::move(callback)));
file_net_observer_ = nullptr;
@@ -150,14 +150,9 @@ void NetLogExporter::StartWithScratchDirOrCleanup(
base::ThreadPool::PostTask(
FROM_HERE,
{base::MayBlock(), base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
- base::BindOnce(
- [](const base::FilePath& dir) {
- // The delete is non-recursive (2nd argument
- // false) since the only time this is invoked
- // the directory is expected to be empty.
- base::DeleteFile(dir, false);
- },
- scratch_dir_path));
+ // The delete is non-recursive since the only time this is invoked is
+ // when the directory is expected to be empty.
+ base::BindOnce(base::GetDeleteFileCallback(), scratch_dir_path));
}
}
diff --git a/chromium/services/network/network_context.cc b/chromium/services/network/network_context.cc
index 3bb208bad23..5b4588fadf4 100644
--- a/chromium/services/network/network_context.cc
+++ b/chromium/services/network/network_context.cc
@@ -5,6 +5,7 @@
#include "services/network/network_context.h"
#include <memory>
+#include <string>
#include <utility>
#include "base/barrier_closure.h"
@@ -17,13 +18,13 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop_current.h"
#include "base/metrics/histogram_functions.h"
#include "base/optional.h"
#include "base/sequenced_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/task/current_thread.h"
#include "base/task/post_task.h"
#include "base/task/task_traits.h"
#include "base/task/thread_pool.h"
@@ -322,6 +323,52 @@ std::string HashesToBase64String(const net::HashValueVector& hashes) {
return str;
}
+#if BUILDFLAG(IS_CT_SUPPORTED)
+// SCTAuditingDelegate is an implementation of the delegate interface that is
+// aware of per-NetworkContext details (to allow the cache to notify the
+// associated NetworkContextClient of new reports, and to apply
+// per-NetworkContext enabled/disabled status for the auditing feature).
+class SCTAuditingDelegate : public net::SCTAuditingDelegate {
+ public:
+ explicit SCTAuditingDelegate(const base::WeakPtr<NetworkContext>& context);
+ ~SCTAuditingDelegate() override;
+
+ // net::SCTAuditingDelegate:
+ void MaybeEnqueueReport(
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps) override;
+ bool IsSCTAuditingEnabled() override;
+
+ private:
+ base::WeakPtr<NetworkContext> context_;
+};
+
+SCTAuditingDelegate::SCTAuditingDelegate(
+ const base::WeakPtr<NetworkContext>& context)
+ : context_(context) {}
+
+SCTAuditingDelegate::~SCTAuditingDelegate() = default;
+
+void SCTAuditingDelegate::MaybeEnqueueReport(
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps) {
+ if (!context_)
+ return;
+ context_->MaybeEnqueueSCTReport(host_port_pair, validated_certificate_chain,
+ signed_certificate_timestamps);
+}
+
+bool SCTAuditingDelegate::IsSCTAuditingEnabled() {
+ if (!context_)
+ return false;
+ return context_->is_sct_auditing_enabled();
+}
+#endif // BUILDFLAG(IS_CT_SUPPORTED)
+
} // namespace
constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess;
@@ -344,9 +391,7 @@ NetworkContext::NetworkContext(
std::make_unique<NetworkContextApplicationStatusListener>()),
#endif
receiver_(this, std::move(receiver)),
- cors_preflight_controller_(
- params_->cors_extra_safelisted_request_header_names,
- network_service) {
+ cors_preflight_controller_(network_service) {
mojo::PendingRemote<mojom::URLLoaderFactory>
url_loader_factory_for_cert_net_fetcher;
mojo::PendingReceiver<mojom::URLLoaderFactory>
@@ -417,7 +462,7 @@ NetworkContext::NetworkContext(
socket_factory_(
std::make_unique<SocketFactory>(url_request_context_->net_log(),
url_request_context)),
- cors_preflight_controller_(std::vector<std::string>(), network_service) {
+ cors_preflight_controller_(network_service) {
// May be nullptr in tests.
if (network_service_)
network_service_->RegisterNetworkContext(this);
@@ -1106,6 +1151,20 @@ void NetworkContext::GetExpectCTState(
std::move(callback).Run(std::move(result));
}
+
+void NetworkContext::MaybeEnqueueSCTReport(
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps) {
+ network_service()->sct_auditing_cache()->MaybeEnqueueReport(
+ this, host_port_pair, validated_certificate_chain,
+ signed_certificate_timestamps);
+}
+
+void NetworkContext::SetSCTAuditingEnabled(bool enabled) {
+ is_sct_auditing_enabled_ = enabled;
+}
#endif // BUILDFLAG(IS_CT_SUPPORTED)
void NetworkContext::CreateUDPSocket(
@@ -1204,16 +1263,25 @@ void NetworkContext::CreateWebSocket(
int32_t render_frame_id,
const url::Origin& origin,
uint32_t options,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client) {
#if !defined(OS_IOS)
if (!websocket_factory_)
websocket_factory_ = std::make_unique<WebSocketFactory>(this);
+
+ DCHECK_GE(process_id, 0);
+ if (process_id == mojom::kBrowserProcessId) {
+ DCHECK_EQ(render_frame_id, 0);
+ }
+
websocket_factory_->CreateWebSocket(
url, requested_protocols, site_for_cookies, isolation_info,
std::move(additional_headers), process_id, render_frame_id, origin,
- options, std::move(handshake_client), std::move(auth_handler),
+ options,
+ static_cast<net::NetworkTrafficAnnotationTag>(traffic_annotation),
+ std::move(handshake_client), std::move(auth_handler),
std::move(header_client));
#endif // !defined(OS_IOS)
}
@@ -1348,15 +1416,6 @@ void NetworkContext::SetCorsOriginAccessListsForOrigin(
std::move(callback).Run();
}
-void NetworkContext::SetCorsExtraSafelistedRequestHeaderNames(
- const std::vector<std::string>&
- cors_extra_safelisted_request_header_names) {
- cors_preflight_controller_.set_extra_safelisted_header_names(
- base::flat_set<std::string>(
- cors_extra_safelisted_request_header_names.cbegin(),
- cors_extra_safelisted_request_header_names.cend()));
-}
-
void NetworkContext::AddHSTS(const std::string& host,
base::Time expiry,
bool include_subdomains,
@@ -1667,6 +1726,44 @@ void NetworkContext::LookupServerBasicAuthCredentials(
std::move(callback).Run(base::nullopt);
}
+#if defined(OS_CHROMEOS)
+void NetworkContext::LookupProxyAuthCredentials(
+ const net::ProxyServer& proxy_server,
+ const std::string& auth_scheme,
+ const std::string& realm,
+ LookupProxyAuthCredentialsCallback callback) {
+ net::HttpAuth::Scheme net_scheme =
+ net::HttpAuth::StringToScheme(base::ToLowerASCII(auth_scheme));
+ if (net_scheme == net::HttpAuth::Scheme::AUTH_SCHEME_MAX) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+ net::HttpAuthCache* http_auth_cache =
+ url_request_context_->http_transaction_factory()
+ ->GetSession()
+ ->http_auth_cache();
+ // TODO(https://crbug.com/1103768): Mapping proxy addresses to URLs is a
+ // lossy conversion, shouldn't do this.
+ const char* scheme =
+ proxy_server.is_secure_http_like() ? "https://" : "http://";
+ GURL proxy_url(scheme + proxy_server.host_port_pair().ToString());
+ if (!proxy_url.is_valid()) {
+ std::move(callback).Run(base::nullopt);
+ return;
+ }
+
+ // Unlike server credentials, proxy credentials are not keyed on
+ // NetworkIsolationKey.
+ net::HttpAuthCache::Entry* entry =
+ http_auth_cache->Lookup(proxy_url, net::HttpAuth::AUTH_PROXY, realm,
+ net_scheme, net::NetworkIsolationKey());
+ if (entry)
+ std::move(callback).Run(entry->credentials());
+ else
+ std::move(callback).Run(base::nullopt);
+}
+#endif
+
const net::HttpAuthPreferences* NetworkContext::GetHttpAuthPreferences() const {
return &http_auth_merged_preferences_;
}
@@ -1971,6 +2068,8 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
if (params_->reporting_delivery_interval) {
reporting_policy->delivery_interval =
*params_->reporting_delivery_interval;
+ reporting_policy->endpoint_backoff_policy.initial_delay_ms =
+ params_->reporting_delivery_interval->InMilliseconds();
}
builder.set_reporting_policy(std::move(reporting_policy));
} else {
@@ -2071,6 +2170,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
params_->ct_log_update_time, disqualified_logs,
operated_by_google_logs));
}
+
+ builder.set_sct_auditing_delegate(
+ std::make_unique<SCTAuditingDelegate>(weak_factory_.GetWeakPtr()));
#endif // BUILDFLAG(IS_CT_SUPPORTED)
builder.set_host_mapping_rules(
@@ -2299,6 +2401,13 @@ void NetworkContext::OnCertVerifyForSignedExchangeComplete(int cert_verify_id,
ct_verify_result.policy_compliance,
net::NetworkIsolationKey::Todo());
+ if (url_request_context_->sct_auditing_delegate() &&
+ url_request_context_->sct_auditing_delegate()->IsSCTAuditingEnabled()) {
+ url_request_context_->sct_auditing_delegate()->MaybeEnqueueReport(
+ net::HostPortPair::FromURL(pending_cert_verify->url), verified_cert,
+ ct_verify_result.scts);
+ }
+
switch (ct_requirement_status) {
case net::TransportSecurityState::CT_REQUIREMENTS_NOT_MET:
result = net::ERR_CERTIFICATE_TRANSPARENCY_REQUIRED;
diff --git a/chromium/services/network/network_context.h b/chromium/services/network/network_context.h
index eced38ff04f..2025d29440b 100644
--- a/chromium/services/network/network_context.h
+++ b/chromium/services/network/network_context.h
@@ -54,6 +54,7 @@
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/public/mojom/url_loader_factory.mojom.h"
#include "services/network/public/mojom/websocket.mojom.h"
+#include "services/network/sct_auditing_cache.h"
#include "services/network/socket_factory.h"
#include "services/network/url_request_context_owner.h"
@@ -258,6 +259,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
void GetExpectCTState(const std::string& domain,
const net::NetworkIsolationKey& network_isolation_key,
GetExpectCTStateCallback callback) override;
+ void MaybeEnqueueSCTReport(
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps);
+ void SetSCTAuditingEnabled(bool enabled) override;
+ bool is_sct_auditing_enabled() { return is_sct_auditing_enabled_; }
#endif // BUILDFLAG(IS_CT_SUPPORTED)
void CreateUDPSocket(
mojo::PendingReceiver<mojom::UDPSocket> receiver,
@@ -300,6 +308,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
int32_t render_frame_id,
const url::Origin& origin,
uint32_t options,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client) override;
@@ -345,9 +354,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::vector<mojom::CorsOriginPatternPtr> allow_patterns,
std::vector<mojom::CorsOriginPatternPtr> block_patterns,
SetCorsOriginAccessListsForOriginCallback callback) override;
- void SetCorsExtraSafelistedRequestHeaderNames(
- const std::vector<std::string>&
- cors_extra_safelisted_request_header_names) override;
void EnableStaticKeyPinningForTesting(
EnableStaticKeyPinningForTestingCallback callback) override;
void VerifyCertificateForTesting(
@@ -400,6 +406,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
const GURL& url,
const net::NetworkIsolationKey& network_isolation_key,
LookupServerBasicAuthCredentialsCallback callback) override;
+#if defined(OS_CHROMEOS)
+ void LookupProxyAuthCredentials(
+ const net::ProxyServer& proxy_server,
+ const std::string& auth_scheme,
+ const std::string& realm,
+ LookupProxyAuthCredentialsCallback callback) override;
+#endif
void GetOriginPolicyManager(
mojo::PendingReceiver<mojom::OriginPolicyManager> receiver) override;
@@ -494,6 +507,12 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
return trust_token_store_.get();
}
+#if BUILDFLAG(IS_CT_SUPPORTED)
+ void SetIsSCTAuditingEnabledForTesting(bool enabled) {
+ is_sct_auditing_enabled_ = enabled;
+ }
+#endif // BUILDFLAG(IS_CT_SUPPORTED)
+
private:
URLRequestContextOwner MakeURLRequestContext(
mojo::PendingRemote<mojom::URLLoaderFactory>
@@ -647,6 +666,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
std::queue<SetExpectCTTestReportCallback>
outstanding_set_expect_ct_callbacks_;
+
+ bool is_sct_auditing_enabled_ = false;
#endif // BUILDFLAG(IS_CT_SUPPORTED)
#if defined(OS_CHROMEOS)
diff --git a/chromium/services/network/network_context_unittest.cc b/chromium/services/network/network_context_unittest.cc
index 22955e89804..dc8f31a7766 100644
--- a/chromium/services/network/network_context_unittest.cc
+++ b/chromium/services/network/network_context_unittest.cc
@@ -67,7 +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_access_result.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
#include "net/cookies/cookie_util.h"
@@ -103,6 +103,7 @@
#include "net/test/spawned_test_server/spawned_test_server.h"
#include "net/test/test_data_directory.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
+#include "net/url_request/referrer_policy.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_builder.h"
#include "net/url_request/url_request_job_factory.h"
@@ -122,11 +123,11 @@
#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/test/udp_socket_test_util.h"
+#include "services/network/test_mojo_proxy_resolver_factory.h"
#include "services/network/trust_tokens/pending_trust_token_store.h"
#include "services/network/trust_tokens/trust_token_parameterization.h"
#include "services/network/trust_tokens/trust_token_store.h"
-#include "services/network/udp_socket_test_util.h"
-#include "test_mojo_proxy_resolver_factory.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h"
@@ -1364,9 +1365,8 @@ TEST_F(NetworkContextTest, Referrers) {
ASSERT_TRUE(test_server.Start());
for (bool validate_referrer_policy_on_initial_request : {false, true}) {
- for (net::URLRequest::ReferrerPolicy referrer_policy :
- {net::URLRequest::NEVER_CLEAR_REFERRER,
- net::URLRequest::NO_REFERRER}) {
+ for (net::ReferrerPolicy referrer_policy :
+ {net::ReferrerPolicy::NEVER_CLEAR, net::ReferrerPolicy::NO_REFERRER}) {
mojom::NetworkContextParamsPtr context_params = CreateContextParams();
context_params->validate_referrer_policy_on_initial_request =
validate_referrer_policy_on_initial_request;
@@ -1399,7 +1399,7 @@ TEST_F(NetworkContextTest, Referrers) {
// If validating referrers, and the referrer policy is not to send
// referrers, the request should fail.
if (validate_referrer_policy_on_initial_request &&
- referrer_policy == net::URLRequest::NO_REFERRER) {
+ referrer_policy == net::ReferrerPolicy::NO_REFERRER) {
EXPECT_EQ(net::ERR_BLOCKED_BY_CLIENT,
client.completion_status().error_code);
EXPECT_FALSE(client.response_body().is_valid());
@@ -1412,7 +1412,7 @@ TEST_F(NetworkContextTest, Referrers) {
ASSERT_TRUE(client.response_body().is_valid());
EXPECT_TRUE(mojo::BlockingCopyToString(client.response_body_release(),
&response_body));
- if (referrer_policy == net::URLRequest::NO_REFERRER) {
+ if (referrer_policy == net::ReferrerPolicy::NO_REFERRER) {
// If not validating referrers, and the referrer policy is not to send
// referrers, the referrer should be cleared.
EXPECT_EQ("None", response_body);
@@ -1905,6 +1905,116 @@ TEST_F(NetworkContextTest, LookupServerBasicAuthCredentials) {
EXPECT_FALSE(result.has_value());
}
+#if defined(OS_CHROMEOS)
+base::Optional<net::AuthCredentials> GetProxyAuthCredentials(
+ NetworkContext* network_context,
+ const net::ProxyServer& proxy_server,
+ const std::string& scheme,
+ const std::string& realm) {
+ base::RunLoop run_loop;
+ base::Optional<net::AuthCredentials> result;
+ network_context->LookupProxyAuthCredentials(
+ proxy_server, scheme, realm,
+ base::BindLambdaForTesting(
+ [&](const base::Optional<net::AuthCredentials>& credentials) {
+ result = credentials;
+ run_loop.Quit();
+ }));
+ run_loop.Run();
+ return result;
+}
+
+TEST_F(NetworkContextTest, LookupProxyAuthCredentials) {
+ GURL http_proxy("http://bar.test:1080");
+ GURL https_proxy("https://bar.test:443");
+ GURL http_proxy2("http://bar.test:443");
+ GURL foo_proxy("foo://bar.test:1080");
+ GURL server_origin("http://foo.test:3128");
+
+ std::unique_ptr<NetworkContext> network_context =
+ CreateContextWithParams(CreateContextParams());
+ network_context->SetSplitAuthCacheByNetworkIsolationKey(true);
+ net::HttpAuthCache* cache = network_context->url_request_context()
+ ->http_transaction_factory()
+ ->GetSession()
+ ->http_auth_cache();
+
+ base::string16 user = base::ASCIIToUTF16("user");
+ base::string16 password = base::ASCIIToUTF16("pass");
+ cache->Add(http_proxy, net::HttpAuth::AUTH_PROXY, "Realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "basic realm=Realm", net::AuthCredentials(user, password),
+ /* path = */ "");
+ cache->Add(https_proxy, net::HttpAuth::AUTH_PROXY, "Realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "basic realm=Realm", net::AuthCredentials(user, password),
+ /* path = */ "");
+ cache->Add(server_origin, net::HttpAuth::AUTH_SERVER, "Realm",
+ net::HttpAuth::AUTH_SCHEME_BASIC, net::NetworkIsolationKey(),
+ "basic realm=Realm", net::AuthCredentials(user, password),
+ /* path = */ "/");
+ base::Optional<net::AuthCredentials> result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(http_proxy)),
+ "bAsIc", "Realm");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_EQ(user, result->username());
+ EXPECT_EQ(password, result->password());
+
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTPS,
+ net::HostPortPair::FromURL(https_proxy)),
+ "bAsIc", "Realm");
+ ASSERT_TRUE(result.has_value());
+ EXPECT_EQ(user, result->username());
+ EXPECT_EQ(password, result->password());
+
+ // Check that the proxy scheme is taken into account when looking for
+ // credentials
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(http_proxy2)),
+ "basic", "Realm");
+ EXPECT_FALSE(result.has_value());
+
+ // Check that the proxy authentication method is taken into account when
+ // looking for credentials
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(http_proxy)),
+ "digest", "Realm");
+ EXPECT_FALSE(result.has_value());
+
+ // Check that the realm is taken into account when looking for credentials
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(http_proxy)),
+ "basic", "Realm 2");
+ EXPECT_FALSE(result.has_value());
+
+ // All non-https proxies are cached as "http://" proxies
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(foo_proxy)),
+ "basic", "Realm");
+ EXPECT_FALSE(result.has_value());
+
+ // Server credentials should not be returned
+ result = GetProxyAuthCredentials(
+ network_context.get(),
+ net::ProxyServer(net::ProxyServer::Scheme::SCHEME_HTTP,
+ net::HostPortPair::FromURL(server_origin)),
+ "basic", "Realm");
+ EXPECT_FALSE(result.has_value());
+}
+#endif
+
#if BUILDFLAG(ENABLE_REPORTING)
TEST_F(NetworkContextTest, ClearReportingCacheReports) {
auto reporting_context = std::make_unique<net::TestReportingContext>(
@@ -2264,8 +2374,8 @@ TEST_F(NetworkContextTest, ClearEmptyNetworkErrorLoggingWithNoService) {
void SetCookieCallback(base::RunLoop* run_loop,
bool* result_out,
- net::CookieInclusionStatus result) {
- *result_out = result.IsInclude();
+ net::CookieAccessResult result) {
+ *result_out = result.status.IsInclude();
run_loop->Quit();
}
@@ -2889,7 +2999,7 @@ TEST_F(NetworkContextTest, CreateNetLogExporterUnbounded) {
// net:: methods.
EXPECT_NE(std::string::npos, contents.find("ERR_IO_PENDING")) << contents;
- base::DeleteFile(temp_path, false);
+ base::DeleteFile(temp_path);
}
TEST_F(NetworkContextTest, CreateNetLogExporterErrors) {
@@ -2931,8 +3041,8 @@ TEST_F(NetworkContextTest, CreateNetLogExporterErrors) {
net::NetLogCaptureMode::kDefault, 100 * 1024, start_callback2.callback());
EXPECT_EQ(net::ERR_UNEXPECTED, start_callback2.WaitForResult());
- base::DeleteFile(temp_path, false);
- base::DeleteFile(temp_path2, false);
+ base::DeleteFile(temp_path);
+ base::DeleteFile(temp_path2);
// Forgetting to stop is recovered from.
}
@@ -2979,7 +3089,7 @@ TEST_F(NetworkContextTest, DestroyNetLogExporterWhileCreatingScratchDir) {
task_environment_.RunUntilIdle();
EXPECT_FALSE(base::PathExists(path));
- base::DeleteFile(temp_path, false);
+ base::DeleteFile(temp_path);
}
net::IPEndPoint CreateExpectedEndPoint(const std::string& address,
@@ -4682,7 +4792,7 @@ TEST_F(NetworkContextTest, ForceReloadProxyConfig) {
EXPECT_NE(std::string::npos, log_contents.find("\"new_config\""))
<< log_contents;
- base::DeleteFile(net_log_path, false);
+ base::DeleteFile(net_log_path);
}
TEST_F(NetworkContextTest, ClearBadProxiesCache) {
@@ -5544,7 +5654,15 @@ class NetworkContextMockHostTest : public NetworkContextTest {
}
};
-TEST_F(NetworkContextMockHostTest, CustomProxyUsesSpecifiedProxyList) {
+#if defined(OS_LINUX)
+// Flaky crashes on Linux: https://crbug.com/1115201
+#define MAYBE_CustomProxyUsesSpecifiedProxyList \
+ DISABLED_CustomProxyUsesSpecifiedProxyList
+#else
+#define MAYBE_CustomProxyUsesSpecifiedProxyList \
+ CustomProxyUsesSpecifiedProxyList
+#endif
+TEST_F(NetworkContextMockHostTest, MAYBE_CustomProxyUsesSpecifiedProxyList) {
net::EmbeddedTestServer proxy_test_server;
net::test_server::RegisterDefaultHandlers(&proxy_test_server);
ASSERT_TRUE(proxy_test_server.Start());
@@ -6620,32 +6738,6 @@ TEST_F(NetworkContextExpectBadMessageTest,
}
TEST_F(NetworkContextExpectBadMessageTest,
- FailsTrustTokenBearingRequestFromInsecureContext) {
- 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.request_initiator =
- url::Origin::Create(GURL("http://insecure-initiator.com"));
- my_request.trust_token_params =
- OptionalTrustTokenParams(mojom::TrustTokenParams::New());
-
- std::unique_ptr<TestURLLoaderClient> client =
- FetchRequest(my_request, network_context.get());
-
- AssertBadMessage();
-}
-
-TEST_F(NetworkContextExpectBadMessageTest,
FailsTrustTokenRedemptionWhenForbidden) {
base::test::ScopedFeatureList scoped_feature_list;
scoped_feature_list.InitAndEnableFeature(features::kTrustTokens);
@@ -6672,7 +6764,12 @@ TEST_F(NetworkContextExpectBadMessageTest,
FetchRequest(my_request, network_context.get(), mojom::kURLLoadOptionNone,
mojom::kBrowserProcessId, std::move(factory_params));
- AssertBadMessage();
+ // TODO(crbug.com/1118183): This test's expectation is temporarily inverted
+ // since the the ReportBadMessage check is disabled pending investigating a
+ // number of false positives. Once this investigation is finished, we should
+ // flip the test back to expecting a bad message.
+ // AssertBadMessage();
+ EXPECT_FALSE(got_bad_message_);
}
TEST_F(NetworkContextExpectBadMessageTest,
@@ -6702,7 +6799,12 @@ TEST_F(NetworkContextExpectBadMessageTest,
FetchRequest(my_request, network_context.get(), mojom::kURLLoadOptionNone,
mojom::kBrowserProcessId, std::move(factory_params));
- AssertBadMessage();
+ // TODO(crbug.com/1118183): This test's expectation is temporarily inverted
+ // since the the ReportBadMessage check is disabled pending investigating a
+ // number of false positives. Once this investigation is finished, we should
+ // flip the test back to expecting a bad message.
+ // AssertBadMessage();
+ EXPECT_FALSE(got_bad_message_);
}
TEST_F(NetworkContextTest,
diff --git a/chromium/services/network/network_sandbox_hook_linux.cc b/chromium/services/network/network_sandbox_hook_linux.cc
index da2704dfeab..feb61a7316c 100644
--- a/chromium/services/network/network_sandbox_hook_linux.cc
+++ b/chromium/services/network/network_sandbox_hook_linux.cc
@@ -13,8 +13,8 @@ using sandbox::syscall_broker::MakeBrokerCommandSet;
namespace network {
-bool NetworkPreSandboxHook(service_manager::SandboxLinux::Options options) {
- auto* instance = service_manager::SandboxLinux::GetInstance();
+bool NetworkPreSandboxHook(sandbox::policy::SandboxLinux::Options options) {
+ auto* instance = sandbox::policy::SandboxLinux::GetInstance();
// TODO(tsepez): remove universal permission under filesytem root.
instance->StartBrokerProcess(
@@ -29,7 +29,7 @@ bool NetworkPreSandboxHook(service_manager::SandboxLinux::Options options) {
sandbox::syscall_broker::COMMAND_UNLINK,
}),
{BrokerFilePermission::ReadWriteCreateRecursive("/")},
- service_manager::SandboxLinux::PreSandboxHook(), options);
+ sandbox::policy::SandboxLinux::PreSandboxHook(), options);
instance->EngageNamespaceSandboxIfPossible();
return true;
diff --git a/chromium/services/network/network_sandbox_hook_linux.h b/chromium/services/network/network_sandbox_hook_linux.h
index c398ac424c5..0c09336fc4d 100644
--- a/chromium/services/network/network_sandbox_hook_linux.h
+++ b/chromium/services/network/network_sandbox_hook_linux.h
@@ -6,12 +6,12 @@
#define SERVICES_NETWORK_NETWORK_SANDBOX_HOOK_LINUX_H_
#include "base/component_export.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "sandbox/policy/linux/sandbox_linux.h"
namespace network {
COMPONENT_EXPORT(NETWORK_SERVICE)
-bool NetworkPreSandboxHook(service_manager::SandboxLinux::Options options);
+bool NetworkPreSandboxHook(sandbox::policy::SandboxLinux::Options options);
} // namespace network
diff --git a/chromium/services/network/network_sandbox_win.cc b/chromium/services/network/network_sandbox_win.cc
deleted file mode 100644
index 6fd36927899..00000000000
--- a/chromium/services/network/network_sandbox_win.cc
+++ /dev/null
@@ -1,28 +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.
-
-#include "services/network/network_sandbox_win.h"
-
-#include "sandbox/win/src/sandbox_types.h"
-#include "services/service_manager/sandbox/win/sandbox_win.h"
-
-// NOTE: changes to this code need to be reviewed by the security team.
-namespace network {
-
-// Right now, this policy is essentially unsandboxed, but with default process
-// mitigations applied. This will be tighted up in future releases.
-bool NetworkPreSpawnTarget(sandbox::TargetPolicy* policy,
- const base::CommandLine& cmd_line) {
- sandbox::ResultCode result = policy->SetTokenLevel(sandbox::USER_UNPROTECTED,
- sandbox::USER_UNPROTECTED);
- if (result != sandbox::ResultCode::SBOX_ALL_OK)
- return false;
- result = service_manager::SandboxWin::SetJobLevel(
- cmd_line, sandbox::JOB_UNPROTECTED, 0, policy);
- if (result != sandbox::ResultCode::SBOX_ALL_OK)
- return false;
- return true;
-}
-
-} // namespace network
diff --git a/chromium/services/network/network_sandbox_win.h b/chromium/services/network/network_sandbox_win.h
deleted file mode 100644
index b2e68a3cafc..00000000000
--- a/chromium/services/network/network_sandbox_win.h
+++ /dev/null
@@ -1,27 +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.
-
-#ifndef SERVICES_NETWORK_NETWORK_SANDBOX_WIN_H_
-#define SERVICES_NETWORK_NETWORK_SANDBOX_WIN_H_
-
-#include "base/component_export.h"
-#include "sandbox/win/src/sandbox_policy_base.h"
-#include "services/service_manager/sandbox/win/sandbox_win.h"
-
-// These sandbox-config extension functions should be called from
-// UtilitySandboxedProcessLauncherDelegate on Windows (or the appropriate
-// Delegate if SandboxType::kNetwork is removed from SandboxType::kUtility).
-//
-// NOTE: changes to this code need to be reviewed by the security team.
-
-namespace network {
-
-// PreSpawnTarget extension.
-COMPONENT_EXPORT(NETWORK_SERVICE)
-bool NetworkPreSpawnTarget(sandbox::TargetPolicy* policy,
- const base::CommandLine& cmd_line);
-
-} // namespace network
-
-#endif // SERVICES_NETWORK_NETWORK_SANDBOX_WIN_H_
diff --git a/chromium/services/network/network_service.cc b/chromium/services/network/network_service.cc
index 75b0c7e2e97..dbd0830737b 100644
--- a/chromium/services/network/network_service.cc
+++ b/chromium/services/network/network_service.cc
@@ -48,7 +48,7 @@
#include "net/ssl/ssl_key_logger_impl.h"
#include "net/url_request/url_request_context.h"
#include "services/network/crl_set_distributor.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
#include "services/network/dns_config_change_manager.h"
#include "services/network/http_auth_cache_copier.h"
#include "services/network/legacy_tls_config_distributor.h"
@@ -57,10 +57,12 @@
#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/cross_origin_read_blocking.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"
#include "services/network/public/cpp/network_switches.h"
+#include "services/network/sct_auditing_cache.h"
#include "services/network/url_loader.h"
#if defined(OS_ANDROID) && defined(ARCH_CPU_ARMEL)
@@ -366,6 +368,12 @@ void NetworkService::Initialize(mojom::NetworkServiceParamsPtr params,
doh_probe_activator_ = std::make_unique<DelayedDohProbeActivator>(this);
trust_token_key_commitments_ = std::make_unique<TrustTokenKeyCommitments>();
+
+#if BUILDFLAG(IS_CT_SUPPORTED)
+ constexpr size_t kMaxSCTAuditingCacheEntries = 1024;
+ sct_auditing_cache_ =
+ std::make_unique<SCTAuditingCache>(kMaxSCTAuditingCacheEntries);
+#endif
}
NetworkService::~NetworkService() {
@@ -672,7 +680,7 @@ void NetworkService::SetCryptConfig(mojom::CryptConfigPtr crypt_config) {
}
#endif
-#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_WIN) || defined(OS_MAC)
void NetworkService::SetEncryptionKey(const std::string& encryption_key) {
OSCrypt::SetRawEncryptionKey(encryption_key);
}
@@ -680,7 +688,7 @@ void NetworkService::SetEncryptionKey(const std::string& encryption_key) {
void NetworkService::AddCorbExceptionForPlugin(int32_t process_id) {
DCHECK_NE(mojom::kBrowserProcessId, process_id);
- CrossOriginReadBlocking::AddExceptionForPlugin(process_id);
+ CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(process_id);
}
void NetworkService::AddAllowedRequestInitiatorForPlugin(
@@ -694,7 +702,8 @@ void NetworkService::AddAllowedRequestInitiatorForPlugin(
void NetworkService::RemoveSecurityExceptionsForPlugin(int32_t process_id) {
DCHECK_NE(mojom::kBrowserProcessId, process_id);
- CrossOriginReadBlocking::RemoveExceptionForPlugin(process_id);
+ CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(
+ process_id);
std::map<int, std::set<url::Origin>>& map = plugin_origins_;
map.erase(process_id);
@@ -744,6 +753,12 @@ void NetworkService::SetTrustTokenKeyCommitments(
std::move(done).Run();
}
+#if BUILDFLAG(IS_CT_SUPPORTED)
+void NetworkService::ClearSCTAuditingCache() {
+ sct_auditing_cache_->ClearCache();
+}
+#endif
+
#if defined(OS_ANDROID)
void NetworkService::DumpWithoutCrashing(base::Time dump_request_time) {
static base::debug::CrashKeyString* time_key =
diff --git a/chromium/services/network/network_service.h b/chromium/services/network/network_service.h
index 50120d006a0..85dcae89361 100644
--- a/chromium/services/network/network_service.h
+++ b/chromium/services/network/network_service.h
@@ -62,6 +62,7 @@ class NetLogProxySink;
class NetworkContext;
class NetworkService;
class NetworkUsageAccumulator;
+class SCTAuditingCache;
// DataPipeUseTracker tracks the mojo data pipe usage in the network
// service.
@@ -195,7 +196,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
void SetCryptConfig(mojom::CryptConfigPtr crypt_config) override;
#endif
-#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_WIN) || defined(OS_MAC)
void SetEncryptionKey(const std::string& encryption_key) override;
#endif
void AddCorbExceptionForPlugin(int32_t process_id) override;
@@ -213,6 +214,9 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
std::vector<mojom::EnvironmentVariablePtr> environment) override;
void SetTrustTokenKeyCommitments(const std::string& raw_commitments,
base::OnceClosure done) override;
+#if BUILDFLAG(IS_CT_SUPPORTED)
+ void ClearSCTAuditingCache() override;
+#endif
#if defined(OS_ANDROID)
void DumpWithoutCrashing(base::Time dump_request_time) override;
@@ -283,6 +287,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
return trust_token_key_commitments_.get();
}
+#if BUILDFLAG(IS_CT_SUPPORTED)
+ SCTAuditingCache* sct_auditing_cache() { return sct_auditing_cache_.get(); }
+#endif
+
void OnDataPipeCreated(DataPipeUser user);
void OnDataPipeDropped(DataPipeUser user);
void StopMetricsTimerForTesting();
@@ -407,6 +415,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkService
std::unique_ptr<DelayedDohProbeActivator> doh_probe_activator_;
+#if BUILDFLAG(IS_CT_SUPPORTED)
+ std::unique_ptr<SCTAuditingCache> sct_auditing_cache_;
+#endif
+
// Map from a renderer process id, to the set of plugin origins embedded by
// that renderer process (the renderer will proxy requests from PPAPI - such
// requests should have their initiator origin within the set stored here).
diff --git a/chromium/services/network/network_service_network_delegate.cc b/chromium/services/network/network_service_network_delegate.cc
index abf4451b269..8199b693b81 100644
--- a/chromium/services/network/network_service_network_delegate.cc
+++ b/chromium/services/network/network_service_network_delegate.cc
@@ -15,6 +15,7 @@
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/url_request/referrer_policy.h"
#include "net/url_request/url_request.h"
#include "services/network/cookie_manager.h"
#include "services/network/network_context.h"
@@ -56,7 +57,7 @@ void NetworkServiceNetworkDelegate::MaybeTruncateReferrer(
const GURL& effective_url) {
if (!enable_referrers_) {
request->SetReferrer(std::string());
- request->set_referrer_policy(net::URLRequest::NO_REFERRER);
+ request->set_referrer_policy(net::ReferrerPolicy::NO_REFERRER);
return;
}
diff --git a/chromium/services/network/network_service_proxy_delegate_unittest.cc b/chromium/services/network/network_service_proxy_delegate_unittest.cc
index a4a8c49612a..0519a1edf0a 100644
--- a/chromium/services/network/network_service_proxy_delegate_unittest.cc
+++ b/chromium/services/network/network_service_proxy_delegate_unittest.cc
@@ -103,8 +103,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpProxy) {
expected_proxy_list.AddProxyServer(
net::ProxyServer::FromPacString("PROXY foo"));
EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
- // HTTP proxies are not used as alternative QUIC proxies.
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxySuccessHttpsUrl) {
@@ -150,7 +148,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyNoRuleForHttpsUrl) {
&result);
EXPECT_TRUE(result.is_direct());
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyLocalhost) {
@@ -164,7 +161,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyLocalhost) {
&result);
EXPECT_TRUE(result.is_direct());
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyEmptyConfig) {
@@ -176,7 +172,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyEmptyConfig) {
&result);
EXPECT_TRUE(result.is_direct());
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyNonIdempotentMethod) {
@@ -190,7 +185,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyNonIdempotentMethod) {
&result);
EXPECT_TRUE(result.is_direct());
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest,
@@ -225,7 +219,6 @@ TEST_F(NetworkServiceProxyDelegateTest,
&result);
EXPECT_TRUE(result.is_direct());
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyDoesNotOverrideExisting) {
@@ -243,7 +236,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyDoesNotOverrideExisting) {
expected_proxy_list.AddProxyServer(
net::ProxyServer::FromPacString("PROXY bar"));
EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyOverridesExisting) {
@@ -261,7 +253,6 @@ TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyOverridesExisting) {
expected_proxy_list.AddProxyServer(
net::ProxyServer::FromPacString("PROXY foo"));
EXPECT_TRUE(result.proxy_list().Equals(expected_proxy_list));
- EXPECT_FALSE(result.alternative_proxy().is_valid());
}
TEST_F(NetworkServiceProxyDelegateTest, OnResolveProxyDeprioritizesBadProxies) {
diff --git a/chromium/services/network/network_service_unittest.cc b/chromium/services/network/network_service_unittest.cc
index bb38b299fcb..20d7ed664ce 100644
--- a/chromium/services/network/network_service_unittest.cc
+++ b/chromium/services/network/network_service_unittest.cc
@@ -935,6 +935,8 @@ class NetworkServiceTestWithService : public testing::Test {
mojom::URLLoaderFactoryParamsPtr params =
mojom::URLLoaderFactoryParams::New();
params->process_id = process_id;
+ params->request_initiator_origin_lock =
+ url::Origin::Create(GURL("https://initiator.example.com"));
params->is_corb_enabled = false;
network_context_->CreateURLLoaderFactory(
loader_factory.BindNewPipeAndPassReceiver(), std::move(params));
diff --git a/chromium/services/network/proxy_resolving_client_socket_factory.cc b/chromium/services/network/proxy_resolving_client_socket_factory.cc
index 47d01a340d3..caa2d52a71d 100644
--- a/chromium/services/network/proxy_resolving_client_socket_factory.cc
+++ b/chromium/services/network/proxy_resolving_client_socket_factory.cc
@@ -29,6 +29,8 @@ ProxyResolvingClientSocketFactory::ProxyResolvingClientSocketFactory(
session_context.cert_transparency_verifier =
request_context->cert_transparency_verifier();
session_context.ct_policy_enforcer = request_context->ct_policy_enforcer();
+ session_context.sct_auditing_delegate =
+ request_context->sct_auditing_delegate();
session_context.proxy_resolution_service =
request_context->proxy_resolution_service();
session_context.proxy_delegate = request_context->proxy_delegate();
diff --git a/chromium/services/network/public/cpp/BUILD.gn b/chromium/services/network/public/cpp/BUILD.gn
index 8447695610e..039da2fdc70 100644
--- a/chromium/services/network/public/cpp/BUILD.gn
+++ b/chromium/services/network/public/cpp/BUILD.gn
@@ -3,7 +3,6 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
-import("//build/config/jumbo.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//services/network/public/cpp/features.gni")
import("//testing/libfuzzer/fuzzer_test.gni")
@@ -13,7 +12,7 @@ buildflag_header("buildflags") {
flags = [ "IS_CT_SUPPORTED=$is_ct_supported" ]
}
-jumbo_component("crash_keys") {
+component("crash_keys") {
sources = [
"crash_keys.cc",
"crash_keys.h",
@@ -22,7 +21,7 @@ jumbo_component("crash_keys") {
defines = [ "IS_NETWORK_CPP_CRASH_KEYS_IMPL" ]
}
-jumbo_component("cpp") {
+component("cpp") {
output_name = "network_cpp"
sources = [
@@ -52,6 +51,8 @@ jumbo_component("cpp") {
"cross_origin_embedder_policy_parser.h",
"cross_origin_opener_policy_parser.cc",
"cross_origin_opener_policy_parser.h",
+ "cross_origin_read_blocking.cc",
+ "cross_origin_read_blocking.h",
"cross_origin_resource_policy.cc",
"cross_origin_resource_policy.h",
"cross_thread_pending_shared_url_loader_factory.cc",
@@ -66,6 +67,8 @@ jumbo_component("cpp") {
"header_util.h",
"initiator_lock_compatibility.cc",
"initiator_lock_compatibility.h",
+ "ip_address_space_util.cc",
+ "ip_address_space_util.h",
"is_potentially_trustworthy.cc",
"is_potentially_trustworthy.h",
"load_info_util.cc",
@@ -78,6 +81,8 @@ jumbo_component("cpp") {
"network_quality_tracker.h",
"network_switches.cc",
"network_switches.h",
+ "not_implemented_url_loader_factory.cc",
+ "not_implemented_url_loader_factory.h",
"origin_isolation_parser.cc",
"origin_isolation_parser.h",
"parsed_headers.cc",
@@ -88,6 +93,7 @@ jumbo_component("cpp") {
"request_mode.h",
"resolve_host_client_base.cc",
"resolve_host_client_base.h",
+ "session_cookie_delete_predicate.h",
"shared_url_loader_factory.cc",
"shared_url_loader_factory.h",
"simple_url_loader.cc",
@@ -135,6 +141,7 @@ jumbo_component("cpp") {
deps = [
"//base",
+ "//base/util/ranges:ranges",
"//components/prefs",
"//ipc",
"//services/proxy_resolver/public/mojom",
@@ -174,7 +181,7 @@ component("cookies_mojom_support") {
defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
}
-jumbo_component("cpp_base") {
+component("cpp_base") {
output_name = "network_cpp_base"
sources = [
@@ -231,15 +238,6 @@ jumbo_component("cpp_base") {
"url_request_mojom_traits.cc",
"url_request_mojom_traits.h",
]
- jumbo_excluded_sources = [
- # IPC/Params code generators are based on macros and multiple
- # inclusion of headers using those macros. That is not
- # compatible with jumbo compiling all source, generators and
- # users, together, so exclude those files from jumbo compilation.
- "network_ipc_param_traits.cc",
- "p2p_param_traits.cc",
- "url_request_mojom_traits.cc",
- ]
configs += [ "//build/config/compiler:wexit_time_destructors" ]
@@ -250,6 +248,7 @@ jumbo_component("cpp_base") {
"//services/network/public/mojom:data_pipe_interfaces",
"//services/network/public/mojom:mutable_network_traffic_annotation_interface",
"//services/network/public/mojom:trust_tokens_interface",
+ "//third_party/webrtc_overrides:webrtc_component",
"//url/ipc:url_ipc",
"//url/mojom:url_mojom_gurl",
"//url/mojom:url_mojom_origin",
@@ -261,7 +260,6 @@ jumbo_component("cpp_base") {
"//net",
"//services/network/public/mojom:cookies_mojom",
"//services/network/public/mojom:mojom_shared",
- "//third_party/webrtc_overrides:webrtc_component",
]
defines = [ "IS_NETWORK_CPP_BASE_IMPL" ]
}
@@ -288,6 +286,7 @@ source_set("tests") {
"cors/preflight_result_unittest.cc",
"cross_origin_embedder_policy_parser_unittest.cc",
"cross_origin_opener_policy_parser_unittest.cc",
+ "cross_origin_read_blocking_unittest.cc",
"cross_origin_resource_policy_unittest.cc",
"cross_thread_pending_shared_url_loader_factory_unittest.cc",
"data_pipe_to_source_stream_unittest.cc",
@@ -297,6 +296,7 @@ source_set("tests") {
"host_resolver_mojom_traits_unittest.cc",
"initiator_lock_compatibility_unittest.cc",
"ip_address_mojom_traits_unittest.cc",
+ "ip_address_space_util_unittest.cc",
"is_potentially_trustworthy_unittest.cc",
"isolation_info_mojom_traits_unittest.cc",
"mutable_network_traffic_annotation_tag_mojom_traits_unittest.cc",
diff --git a/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.cc b/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.cc
index d6ca262a6a8..50c45e554ab 100644
--- a/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo.cc
@@ -13,7 +13,7 @@
#include "net/der/encode_values.h"
#include "net/der/parse_values.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
#include "net/cert/cert_verify_proc_mac.h"
#include "net/cert/internal/trust_store_mac.h"
#endif
@@ -74,7 +74,7 @@ void TrialComparisonCertVerifierMojo::OnSendTrialReport(
const net::CertVerifyResult& trial_result) {
network::mojom::CertVerifierDebugInfoPtr debug_info =
network::mojom::CertVerifierDebugInfo::New();
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
auto* mac_platform_debug_info =
net::CertVerifyProcMac::ResultDebugData::Get(&primary_result);
if (mac_platform_debug_info) {
diff --git a/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo_unittest.cc b/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo_unittest.cc
index f349c1f4497..73a5200e1d2 100644
--- a/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo_unittest.cc
+++ b/chromium/services/network/public/cpp/cert_verifier/trial_comparison_cert_verifier_mojo_unittest.cc
@@ -15,7 +15,7 @@
#include "net/test/test_data_directory.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
#include "net/cert/cert_verify_proc_mac.h"
#include "net/cert/internal/trust_store_mac.h"
#endif
@@ -104,7 +104,7 @@ TEST(TrialComparisonCertVerifierMojoTest, SendReportDebugInfo) {
net::CertVerifyResult trial_result;
trial_result.verified_cert = chain2;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
constexpr uint32_t kExpectedTrustResult = 4;
constexpr int32_t kExpectedResultCode = -12345;
std::vector<net::CertVerifyProcMac::ResultDebugData::CertEvidenceInfo>
@@ -169,7 +169,7 @@ TEST(TrialComparisonCertVerifierMojoTest, SendReportDebugInfo) {
std::string(report.sct_list.begin(), report.sct_list.end()));
ASSERT_TRUE(report.debug_info);
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
ASSERT_TRUE(report.debug_info->mac_platform_debug_info);
EXPECT_EQ(kExpectedTrustResult,
report.debug_info->mac_platform_debug_info->trust_result);
diff --git a/chromium/services/network/public/cpp/client_hints.cc b/chromium/services/network/public/cpp/client_hints.cc
index ab9b33e268e..0958d28b3ab 100644
--- a/chromium/services/network/public/cpp/client_hints.cc
+++ b/chromium/services/network/public/cpp/client_hints.cc
@@ -11,6 +11,7 @@
#include "base/no_destructor.h"
#include "base/optional.h"
#include "base/stl_util.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "net/http/structured_headers.h"
@@ -104,4 +105,13 @@ base::Optional<std::vector<network::mojom::WebClientHintsType>> ParseAcceptCH(
return base::make_optional(std::move(result));
}
+base::TimeDelta ParseAcceptCHLifetime(const std::string& header) {
+ int64_t persist_duration_seconds = 0;
+ if (!base::StringToInt64(header, &persist_duration_seconds) ||
+ persist_duration_seconds <= 0)
+ return base::TimeDelta();
+
+ return base::TimeDelta::FromSeconds(persist_duration_seconds);
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/client_hints.h b/chromium/services/network/public/cpp/client_hints.h
index 8f8db9548e1..a811582df39 100644
--- a/chromium/services/network/public/cpp/client_hints.h
+++ b/chromium/services/network/public/cpp/client_hints.h
@@ -10,6 +10,7 @@
#include "base/component_export.h"
#include "base/optional.h"
+#include "base/time/time.h"
#include "services/network/public/mojom/web_client_hints_types.mojom-shared.h"
namespace network {
@@ -27,6 +28,10 @@ COMPONENT_EXPORT(NETWORK_CPP) extern const size_t kClientHintsMappingsCount;
base::Optional<std::vector<network::mojom::WebClientHintsType>>
COMPONENT_EXPORT(NETWORK_CPP) ParseAcceptCH(const std::string& header);
+// Tries to parse Accept-CH-Lifetime. Returns base::TimeDelta() if unsuccessful.
+base::TimeDelta COMPONENT_EXPORT(NETWORK_CPP)
+ ParseAcceptCHLifetime(const std::string& header);
+
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_CLIENT_HINTS_H_
diff --git a/chromium/services/network/public/cpp/client_hints_unittest.cc b/chromium/services/network/public/cpp/client_hints_unittest.cc
index e1e4d2ceea4..3a2c0bbf1be 100644
--- a/chromium/services/network/public/cpp/client_hints_unittest.cc
+++ b/chromium/services/network/public/cpp/client_hints_unittest.cc
@@ -67,4 +67,12 @@ TEST(ClientHintsTest, ParseAcceptCHCaseInsensitive) {
network::mojom::WebClientHintsType::kLang));
}
+TEST(ClientHintsTest, ParseAcceptCHLifetime) {
+ EXPECT_EQ(base::TimeDelta(), ParseAcceptCHLifetime(""));
+ EXPECT_EQ(base::TimeDelta(), ParseAcceptCHLifetime("-1000"));
+ EXPECT_EQ(base::TimeDelta(), ParseAcceptCHLifetime("1000s"));
+ EXPECT_EQ(base::TimeDelta(), ParseAcceptCHLifetime("1000.5"));
+ EXPECT_EQ(base::TimeDelta::FromSeconds(1000), ParseAcceptCHLifetime("1000"));
+}
+
} // namespace network
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 6ae235de565..914a7871b47 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
@@ -6,56 +6,104 @@
#include <sstream>
#include <string>
-#include "base/containers/flat_map.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_piece.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/util/ranges/algorithm.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/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_source_list.h"
+#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/is_potentially_trustworthy.h"
#include "services/network/public/cpp/web_sandbox_flags.h"
#include "url/gurl.h"
+#include "url/origin.h"
#include "url/url_canon.h"
#include "url/url_util.h"
namespace network {
using CSPDirectiveName = mojom::CSPDirectiveName;
-using DirectivesMap = base::flat_map<base::StringPiece, base::StringPiece>;
+using DirectivesMap =
+ std::vector<std::pair<base::StringPiece, base::StringPiece>>;
namespace {
-static CSPDirectiveName CSPFallback(CSPDirectiveName directive) {
+bool IsDirectiveNameCharacter(char c) {
+ return base::IsAsciiAlpha(c) || c == '-';
+}
+
+bool IsDirectiveValueCharacter(char c) {
+ return base::IsAsciiWhitespace(c) ||
+ base::IsAsciiPrintable(c); // Whitespace + VCHAR
+}
+
+static CSPDirectiveName CSPFallback(CSPDirectiveName directive,
+ CSPDirectiveName original_directive) {
switch (directive) {
- case CSPDirectiveName::DefaultSrc:
- case CSPDirectiveName::FormAction:
- case CSPDirectiveName::NavigateTo:
- case CSPDirectiveName::FrameAncestors:
+ case CSPDirectiveName::ConnectSrc:
+ case CSPDirectiveName::FontSrc:
case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::ManifestSrc:
case CSPDirectiveName::MediaSrc:
+ case CSPDirectiveName::PrefetchSrc:
case CSPDirectiveName::ObjectSrc:
case CSPDirectiveName::ScriptSrc:
case CSPDirectiveName::StyleSrc:
- case CSPDirectiveName::WorkerSrc:
- case CSPDirectiveName::ConnectSrc:
- return CSPDirectiveName::Unknown;
+ return CSPDirectiveName::DefaultSrc;
+
+ case CSPDirectiveName::ScriptSrcAttr:
+ case CSPDirectiveName::ScriptSrcElem:
+ return CSPDirectiveName::ScriptSrc;
+
+ case CSPDirectiveName::StyleSrcAttr:
+ case CSPDirectiveName::StyleSrcElem:
+ return CSPDirectiveName::StyleSrc;
case CSPDirectiveName::FrameSrc:
+ case CSPDirectiveName::WorkerSrc:
return CSPDirectiveName::ChildSrc;
+ // Because the fallback chain of child-src can be different if we are
+ // checking a worker or a frame request, we need to know the original type
+ // of the request to decide. These are the fallback chains for worker-src
+ // and frame-src specifically.
+
+ // worker-src > child-src > script-src > default-src
+ // frame-src > child-src > default-src
+
+ // Since there are some situations and tests that will operate on the
+ // `child-src` directive directly (like for example the EE subsumption
+ // algorithm), we consider the child-src > default-src fallback path as the
+ // "default" and the worker-src fallback path as an exception.
case CSPDirectiveName::ChildSrc:
+ if (original_directive == CSPDirectiveName::WorkerSrc)
+ return CSPDirectiveName::ScriptSrc;
+
return CSPDirectiveName::DefaultSrc;
+ case CSPDirectiveName::BaseURI:
+ case CSPDirectiveName::BlockAllMixedContent:
+ case CSPDirectiveName::DefaultSrc:
+ case CSPDirectiveName::FormAction:
+ case CSPDirectiveName::FrameAncestors:
+ case CSPDirectiveName::NavigateTo:
+ case CSPDirectiveName::ReportTo:
+ case CSPDirectiveName::ReportURI:
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ case CSPDirectiveName::Sandbox:
+ case CSPDirectiveName::TreatAsPublicAddress:
+ case CSPDirectiveName::TrustedTypes:
+ case CSPDirectiveName::UpgradeInsecureRequests:
+ return CSPDirectiveName::Unknown;
case CSPDirectiveName::Unknown:
NOTREACHED();
return CSPDirectiveName::Unknown;
}
- NOTREACHED();
- return CSPDirectiveName::Unknown;
}
std::string ElideURLForReportViolation(const GURL& url) {
@@ -82,16 +130,32 @@ const char* ErrorMessage(CSPDirectiveName directive) {
return "Refused to navigate to '$1' because it violates the "
"following Content Security Policy directive: \"$2\".";
+ case CSPDirectiveName::BaseURI:
+ case CSPDirectiveName::BlockAllMixedContent:
case CSPDirectiveName::ChildSrc:
+ case CSPDirectiveName::ConnectSrc:
case CSPDirectiveName::DefaultSrc:
- case CSPDirectiveName::Unknown:
+ case CSPDirectiveName::FontSrc:
case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::ManifestSrc:
case CSPDirectiveName::MediaSrc:
case CSPDirectiveName::ObjectSrc:
+ case CSPDirectiveName::PrefetchSrc:
+ case CSPDirectiveName::ReportTo:
+ case CSPDirectiveName::ReportURI:
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ case CSPDirectiveName::Sandbox:
case CSPDirectiveName::ScriptSrc:
+ case CSPDirectiveName::ScriptSrcAttr:
+ case CSPDirectiveName::ScriptSrcElem:
case CSPDirectiveName::StyleSrc:
+ case CSPDirectiveName::StyleSrcAttr:
+ case CSPDirectiveName::StyleSrcElem:
+ case CSPDirectiveName::TreatAsPublicAddress:
+ case CSPDirectiveName::TrustedTypes:
+ case CSPDirectiveName::UpgradeInsecureRequests:
case CSPDirectiveName::WorkerSrc:
- case CSPDirectiveName::ConnectSrc:
+ case CSPDirectiveName::Unknown:
NOTREACHED();
return nullptr;
};
@@ -179,21 +243,16 @@ DirectivesMap ParseHeaderValue(base::StringPiece header) {
size_t pos = directive.find_first_of(base::kWhitespaceASCII);
base::StringPiece name = directive.substr(0, pos);
- // 5. If policy's directive set contains a directive whose name is
- // directive name, continue.
- if (result.find(name) != result.end())
- continue;
-
- // 6. Let directive value be the result of splitting token on ASCII
+ // 5. Let directive value be the result of splitting token on ASCII
// whitespace.
base::StringPiece value;
if (pos != std::string::npos)
value = directive.substr(pos + 1);
- // 7. Let directive be a new directive whose name is directive name,
+ // 6. Let directive be a new directive whose name is directive name,
// and value is directive value.
- // 8. Append directive to policy's directive set.
- result.insert({name, value});
+ // 7. Append directive to policy's directive set.
+ result.emplace_back(std::make_pair(name, value));
}
return result;
@@ -278,10 +337,6 @@ bool ParsePath(base::StringPiece path, mojom::CSPSource* csp_source) {
if (path[0] != '/')
return false;
- // TODO(lfg): Emit a warning to the user when a path containing # or ? is
- // seen.
- path = path.substr(0, path.find_first_of("#?"));
-
url::RawCanonOutputT<base::char16> unescaped;
url::DecodeURLEscapeSequences(path.data(), path.size(),
url::DecodeURLMode::kUTF8OrIsomorphic,
@@ -291,17 +346,17 @@ bool ParsePath(base::StringPiece path, mojom::CSPSource* csp_source) {
return true;
}
-// Parses an ancestor source expression.
-// https://www.w3.org/TR/CSP3/#grammardef-ancestor-source
+// Parses a CSP source expression.
+// https://w3c.github.io/webappsec-csp/#source-lists
//
// Return false on errors.
-bool ParseAncestorSource(base::StringPiece expression,
- mojom::CSPSource* csp_source) {
- // TODO(arthursonzogni): Blink reports an invalid source expression when
- // 'none' is parsed here.
- if (base::EqualsCaseInsensitiveASCII(expression, "'none'"))
- return false;
-
+// Adds parsing error messages to |parsing_errors|.
+// Notice that this can return true and still add some parsing error message
+// (for example, if there is a url with a non-empty query part).
+bool ParseSource(CSPDirectiveName directive_name,
+ base::StringPiece expression,
+ mojom::CSPSource* csp_source,
+ std::vector<std::string>& parsing_errors) {
size_t position = expression.find_first_of(":/");
if (position != std::string::npos && expression[position] == ':') {
// scheme:
@@ -348,15 +403,125 @@ bool ParseAncestorSource(base::StringPiece expression,
// /
// ^
- return expression.empty() || ParsePath(expression, csp_source);
+ if (expression.empty())
+ return true;
+
+ // Emit a warning to the user when a url contains a # or ?.
+ position = expression.find_first_of("#?");
+ bool path_parsed = ParsePath(expression.substr(0, position), csp_source);
+ if (path_parsed && position != std::string::npos) {
+ const char* ignoring =
+ expression[position] == '?'
+ ? "The query component, including the '?', will be ignored."
+ : "The fragment identifier, including the '#', will be ignored.";
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The source list for Content-Security-Policy directive '%s' "
+ "contains a source with an invalid path: '%s'. %s",
+ ToString(directive_name).c_str(), expression.as_string().c_str(),
+ ignoring));
+ }
+
+ return path_parsed;
+}
+
+bool IsBase64Char(char c) {
+ return base::IsAsciiAlpha(c) || base::IsAsciiDigit(c) || c == '+' ||
+ c == '-' || c == '_' || c == '/';
+}
+
+int EatChar(const char** it, const char* end, bool (*predicate)(char)) {
+ int count = 0;
+ while (*it != end) {
+ if (!predicate(**it))
+ break;
+ ++count;
+ ++(*it);
+ }
+ return count;
+}
+
+// Checks whether |expression| is a valid base64-encoded string.
+// Cf. https://w3c.github.io/webappsec-csp/#framework-directive-source-list.
+bool IsBase64(base::StringPiece expression) {
+ if (expression.empty())
+ return false;
+
+ auto* it = expression.begin();
+ auto* end = expression.end();
+
+ int count_1 = EatChar(&it, end, IsBase64Char);
+ int count_2 = EatChar(&it, end, [](char c) -> bool { return c == '='; });
+
+ // At least one non '=' char at the beginning, at most two '=' at the end.
+ return count_1 >= 1 && count_2 <= 2 && it == end;
+}
+
+// Parse a nonce-source, return false on error.
+bool ParseNonce(base::StringPiece expression, std::string* nonce) {
+ if (!base::StartsWith(expression, "'nonce-",
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ return false;
+ }
+
+ base::StringPiece subexpression =
+ expression.substr(7, expression.length() - 8);
+
+ if (!IsBase64(subexpression))
+ return false;
+
+ if (expression[expression.length() - 1] != '\'') {
+ return false;
+ }
+
+ *nonce = subexpression.as_string();
+ return true;
+}
+
+struct SupportedPrefixesStruct {
+ const char* prefix;
+ int prefix_length;
+ mojom::CSPHashAlgorithm type;
+};
+
+// Parse a hash-source, return false on error.
+bool ParseHash(base::StringPiece expression, mojom::CSPHashSource* hash) {
+ static const SupportedPrefixesStruct SupportedPrefixes[] = {
+ {"'sha256-", 8, mojom::CSPHashAlgorithm::SHA256},
+ {"'sha384-", 8, mojom::CSPHashAlgorithm::SHA384},
+ {"'sha512-", 8, mojom::CSPHashAlgorithm::SHA512},
+ {"'sha-256-", 9, mojom::CSPHashAlgorithm::SHA256},
+ {"'sha-384-", 9, mojom::CSPHashAlgorithm::SHA384},
+ {"'sha-512-", 9, mojom::CSPHashAlgorithm::SHA512}};
+
+ for (auto item : SupportedPrefixes) {
+ if (base::StartsWith(expression, item.prefix,
+ base::CompareCase::INSENSITIVE_ASCII)) {
+ base::StringPiece subexpression = expression.substr(
+ item.prefix_length, expression.length() - item.prefix_length - 1);
+ if (!IsBase64(subexpression))
+ return false;
+
+ if (expression[expression.length() - 1] != '\'')
+ return false;
+
+ hash->algorithm = item.type;
+ hash->value = subexpression.as_string();
+ return true;
+ }
+ }
+
+ return false;
}
-// Parse ancestor-source-list grammar.
-// https://www.w3.org/TR/CSP3/#directive-frame-ancestors
-mojom::CSPSourceListPtr ParseFrameAncestorsSourceList(
- base::StringPiece frame_ancestors_value) {
- base::StringPiece value = base::TrimString(
- frame_ancestors_value, base::kWhitespaceASCII, base::TRIM_ALL);
+// Parse source-list grammar.
+// https://www.w3.org/TR/CSP3/#grammardef-serialized-source-list
+// Append parsing errors to |parsing_errors|.
+mojom::CSPSourceListPtr ParseSourceList(
+ CSPDirectiveName directive_name,
+ base::StringPiece directive_value,
+ std::vector<std::string>& parsing_errors) {
+ base::StringPiece value =
+ base::TrimString(directive_value, base::kWhitespaceASCII, base::TRIM_ALL);
auto directive = mojom::CSPSourceList::New();
@@ -366,6 +531,16 @@ mojom::CSPSourceListPtr ParseFrameAncestorsSourceList(
for (const auto& expression : base::SplitStringPiece(
value, base::kWhitespaceASCII, base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)) {
+ if (base::EqualsCaseInsensitiveASCII(expression, "'none'")) {
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The Content-Security-Policy directive '%s' contains the keyword "
+ "'none' alongside with other source expressions. The keyword 'none' "
+ "must be the only source expression in the directive value, "
+ "otherwise it is ignored.",
+ ToString(directive_name).c_str()));
+ continue;
+ }
+
if (base::EqualsCaseInsensitiveASCII(expression, "'self'")) {
directive->allow_self = true;
continue;
@@ -376,16 +551,87 @@ mojom::CSPSourceListPtr ParseFrameAncestorsSourceList(
continue;
}
+ if (ToCSPDirectiveName(expression.as_string()) !=
+ CSPDirectiveName::Unknown) {
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The Content-Security-Policy directive '%s' contains '%s' as a "
+ "source expression. Did you want to add it as a directive and forget "
+ "a semicolon?",
+ ToString(directive_name).c_str(), expression.as_string().c_str()));
+ }
+
auto csp_source = mojom::CSPSource::New();
- if (ParseAncestorSource(expression, csp_source.get())) {
+ if (ParseSource(directive_name, expression, csp_source.get(),
+ parsing_errors)) {
directive->sources.push_back(std::move(csp_source));
continue;
}
+ if (directive_name == CSPDirectiveName::FrameAncestors) {
+ // The frame-ancestors directive does not support anything else
+ // https://w3c.github.io/webappsec-csp/#directive-frame-ancestors
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The Content-Security-Policy directive 'frame-ancestors' does not "
+ "support the source expression '%s'",
+ expression.as_string().c_str()));
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'unsafe-inline'")) {
+ directive->allow_inline = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'unsafe-eval'")) {
+ directive->allow_eval = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'wasm-eval'")) {
+ directive->allow_wasm_eval = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression,
+ "'unsafe-allow-redirects'") &&
+ directive_name == CSPDirectiveName::NavigateTo) {
+ directive->allow_response_redirects = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'strict-dynamic'")) {
+ directive->allow_dynamic = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'unsafe-hashes'")) {
+ directive->allow_unsafe_hashes = true;
+ continue;
+ }
+
+ if (base::EqualsCaseInsensitiveASCII(expression, "'report-sample'")) {
+ directive->report_sample = true;
+ continue;
+ }
+
+ std::string nonce;
+ if (ParseNonce(expression, &nonce)) {
+ directive->nonces.push_back(std::move(nonce));
+ continue;
+ }
+
+ auto hash = mojom::CSPHashSource::New();
+ if (ParseHash(expression, hash.get())) {
+ directive->hashes.push_back(std::move(hash));
+ continue;
+ }
+
// Parsing error.
// Ignore this source-expression.
- // TODO(lfg): Emit a warning to the user when parsing an invalid
- // expression.
+ parsing_errors.emplace_back(base::StringPrintf(
+ "The source list for the Content-Security-Policy directive '%s' "
+ "contains an invalid source: '%s'.",
+ ToString(directive_name).c_str(), expression.as_string().c_str()));
}
return directive;
@@ -428,38 +674,132 @@ void ParseReportDirective(const GURL& request_url,
}
}
-// Parses the frame-ancestor directive of a Content-Security-Policy header.
-void ParseFrameAncestors(const mojom::ContentSecurityPolicyPtr& policy,
- base::StringPiece frame_ancestors_value) {
- // A frame-ancestors directive has already been parsed. Skip further
- // frame-ancestors directives per
- // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
- // TODO(arthursonzogni, lfg): Should a warning be fired to the user here?
- if (policy->directives.count(CSPDirectiveName::FrameAncestors))
- return;
-
- auto source_list = ParseFrameAncestorsSourceList(frame_ancestors_value);
+void AddContentSecurityPolicyFromHeader(base::StringPiece header,
+ mojom::ContentSecurityPolicyType type,
+ const GURL& base_url,
+ mojom::ContentSecurityPolicyPtr& out) {
+ DirectivesMap directives = ParseHeaderValue(header);
+ out->header = mojom::ContentSecurityPolicyHeader::New(
+ header.as_string(), type, mojom::ContentSecurityPolicySource::kHTTP);
+
+ for (auto directive : directives) {
+ if (!util::ranges::all_of(directive.first, IsDirectiveNameCharacter)) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "The Content-Security-Policy directive name '%s' contains one or "
+ "more invalid characters. Only ASCII alphanumeric characters or "
+ "dashes '-' are allowed in directive names.",
+ directive.first.as_string().c_str()));
+ continue;
+ }
- // TODO(lfg): Emit a warning to the user when parsing an invalid
- // expression.
- if (!source_list)
- return;
+ if (!util::ranges::all_of(directive.second, IsDirectiveValueCharacter)) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "The value for the Content-Security-Policy directive '%s' contains "
+ "one or more invalid characters. Non-whitespace characters outside "
+ "ASCII 0x21-0x7E must be percent-encoded, as described in RFC 3986, "
+ "section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
+ directive.first.as_string().c_str()));
+ continue;
+ }
- policy->directives[CSPDirectiveName::FrameAncestors] = std::move(source_list);
-}
+ CSPDirectiveName directive_name =
+ ToCSPDirectiveName(directive.first.as_string());
-// Parses the report-uri directive of a Content-Security-Policy header.
-void ParseReportEndpoint(const mojom::ContentSecurityPolicyPtr& policy,
- const GURL& base_url,
- base::StringPiece header_value,
- bool using_reporting_api) {
- // A report-uri directive has already been parsed. Skip further directives per
- // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
- if (!policy->report_endpoints.empty())
- return;
+ // A directive with this name has already been parsed. Skip further
+ // directives per
+ // https://www.w3.org/TR/CSP3/#parse-serialized-policy.
+ if (out->directives.count(directive_name)) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "Ignoring duplicate Content-Security-Policy directive '%s'.",
+ directive.first.as_string().c_str()));
+ continue;
+ }
- ParseReportDirective(base_url, header_value, using_reporting_api,
- &(policy->report_endpoints));
+ switch (directive_name) {
+ case CSPDirectiveName::BaseURI:
+ case CSPDirectiveName::ChildSrc:
+ case CSPDirectiveName::ConnectSrc:
+ case CSPDirectiveName::DefaultSrc:
+ case CSPDirectiveName::FontSrc:
+ case CSPDirectiveName::FormAction:
+ case CSPDirectiveName::FrameAncestors:
+ case CSPDirectiveName::FrameSrc:
+ case CSPDirectiveName::ImgSrc:
+ case CSPDirectiveName::ManifestSrc:
+ case CSPDirectiveName::MediaSrc:
+ case CSPDirectiveName::NavigateTo:
+ case CSPDirectiveName::ObjectSrc:
+ case CSPDirectiveName::PrefetchSrc:
+ case CSPDirectiveName::ScriptSrc:
+ case CSPDirectiveName::ScriptSrcAttr:
+ case CSPDirectiveName::ScriptSrcElem:
+ case CSPDirectiveName::StyleSrc:
+ case CSPDirectiveName::StyleSrcAttr:
+ case CSPDirectiveName::StyleSrcElem:
+ case CSPDirectiveName::WorkerSrc:
+ out->directives[directive_name] = ParseSourceList(
+ directive_name, directive.second, out->parsing_errors);
+ break;
+ case CSPDirectiveName::Sandbox:
+ // Note: |ParseSandboxPolicy(...).error_message| is ignored here.
+ // Blink's CSP parser is already in charge of displaying it.
+ {
+ auto sandbox = ParseWebSandboxPolicy(directive.second,
+ mojom::WebSandboxFlags::kNone);
+ out->sandbox = ~sandbox.flags;
+ out->parsing_errors.emplace_back(std::move(sandbox.error_message));
+ }
+ break;
+ case CSPDirectiveName::UpgradeInsecureRequests:
+ out->upgrade_insecure_requests = true;
+ if (!directive.second.empty()) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "The Content Security Policy directive "
+ "'upgrade-insecure-requests' should be empty, but was delivered "
+ "with a value of '%s'. The directive has been applied, and the "
+ "value ignored.",
+ directive.second.as_string().c_str()));
+ }
+ break;
+ case CSPDirectiveName::TreatAsPublicAddress:
+ out->treat_as_public_address = true;
+ if (!directive.second.empty()) {
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "The Content Security Policy directive 'treat-as-public-address' "
+ "should be empty, but was delivered with a value of '%s'. The "
+ "directive has been applied, and the value ignored.",
+ directive.second.as_string().c_str()));
+ }
+ break;
+
+ // We check the following three directives so that we do not trigger a
+ // warning because of an unrecognized directive. However, we skip
+ // parsing them for now since we do not need these directives here (they
+ // are parsed and enforced in the blink CSP parser).
+ case CSPDirectiveName::BlockAllMixedContent:
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ case CSPDirectiveName::TrustedTypes:
+ break;
+
+ case CSPDirectiveName::ReportTo:
+ out->use_reporting_api = true;
+ out->report_endpoints.clear();
+ ParseReportDirective(base_url, directive.second, out->use_reporting_api,
+ &(out->report_endpoints));
+ break;
+ case CSPDirectiveName::ReportURI:
+ if (!out->use_reporting_api)
+ ParseReportDirective(base_url, directive.second,
+ out->use_reporting_api,
+ &(out->report_endpoints));
+ break;
+ case CSPDirectiveName::Unknown:
+ out->parsing_errors.emplace_back(base::StringPrintf(
+ "Unrecognized Content-Security-Policy directive '%s'.",
+ directive.first.as_string().c_str()));
+ break;
+ }
+ }
}
} // namespace
@@ -495,47 +835,35 @@ void AddContentSecurityPolicyFromHeaders(
for (const auto& header :
base::SplitStringPiece(header_value, ",", base::TRIM_WHITESPACE,
base::SPLIT_WANT_NONEMPTY)) {
- DirectivesMap directives = ParseHeaderValue(header);
auto policy = mojom::ContentSecurityPolicy::New();
+ AddContentSecurityPolicyFromHeader(header, type, base_url, policy);
- policy->header = mojom::ContentSecurityPolicyHeader::New(
- header.as_string(), type, mojom::ContentSecurityPolicySource::kHTTP);
+ out->push_back(std::move(policy));
+ }
+}
- auto frame_ancestors = directives.find("frame-ancestors");
- if (frame_ancestors != directives.end())
- ParseFrameAncestors(policy, frame_ancestors->second);
+mojom::AllowCSPFromHeaderValuePtr ParseAllowCSPFromHeader(
+ const net::HttpResponseHeaders& headers) {
+ if (!base::FeatureList::IsEnabled(features::kOutOfBlinkCSPEE))
+ return nullptr;
- auto sandbox = directives.find("sandbox");
- if (sandbox != directives.end()) {
- // Note: |ParseSandboxPolicy(...).error_message| is ignored here. Blink's
- // CSP parser is already in charge of displaying it.
- policy->sandbox =
- ~ParseWebSandboxPolicy(sandbox->second, mojom::WebSandboxFlags::kNone)
- .flags;
- }
+ std::string allow_csp_from;
+ if (!headers.GetNormalizedHeader("Allow-CSP-From", &allow_csp_from))
+ return nullptr;
- policy->upgrade_insecure_requests |=
- directives.contains("upgrade-insecure-requests");
- policy->treat_as_public_address |=
- directives.contains("treat-as-public-address");
-
- auto report_endpoints = directives.find("report-to");
- if (report_endpoints != directives.end()) {
- if (!policy->use_reporting_api) {
- policy->use_reporting_api = true;
- policy->report_endpoints.clear();
- }
- } else {
- report_endpoints = directives.find("report-uri");
- }
+ base::StringPiece trimmed =
+ base::TrimWhitespaceASCII(allow_csp_from, base::TRIM_ALL);
- if (report_endpoints != directives.end()) {
- ParseReportEndpoint(policy, base_url, report_endpoints->second,
- policy->use_reporting_api);
- }
+ if (trimmed == "*")
+ return mojom::AllowCSPFromHeaderValue::NewAllowStar(true);
- out->push_back(std::move(policy));
+ GURL parsed_url = GURL(trimmed);
+ if (!parsed_url.is_valid()) {
+ return mojom::AllowCSPFromHeaderValue::NewErrorMessage(
+ "The 'Allow-CSP-From' header contains neither '*' nor a valid origin.");
}
+ return mojom::AllowCSPFromHeaderValue::NewOrigin(
+ url::Origin::Create(parsed_url));
}
bool CheckContentSecurityPolicy(const mojom::ContentSecurityPolicyPtr& policy,
@@ -558,7 +886,8 @@ bool CheckContentSecurityPolicy(const mojom::ContentSecurityPolicyPtr& policy,
for (CSPDirectiveName effective_directive_name = directive_name;
effective_directive_name != CSPDirectiveName::Unknown;
- effective_directive_name = CSPFallback(effective_directive_name)) {
+ effective_directive_name =
+ CSPFallback(effective_directive_name, directive_name)) {
const auto& directive = policy->directives.find(effective_directive_name);
if (directive == policy->directives.end())
continue;
@@ -615,64 +944,187 @@ void UpgradeInsecureRequest(GURL* url) {
*url = url->ReplaceComponents(replacements);
}
+bool IsValidRequiredCSPAttr(
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policy,
+ const mojom::ContentSecurityPolicy* context,
+ std::string& error_message) {
+ DCHECK(policy.size() == 1);
+ if (!policy[0])
+ return false;
+
+ if (!policy[0]->parsing_errors.empty()) {
+ error_message =
+ "Parsing the csp attribute into a Content-Security-Policy returned one "
+ "or more parsing errors: " +
+ base::JoinString(policy[0]->parsing_errors, " ");
+ return false;
+ }
+
+ if (!policy[0]->report_endpoints.empty()) {
+ error_message =
+ "The csp attribute cannot contain the directives 'report-to' or "
+ "'report-uri'.";
+ return false;
+ }
+
+ if (context && !Subsumes(*context, policy)) {
+ error_message =
+ "The csp attribute Content-Security-Policy is not subsumed by the "
+ "frame's parent csp attribute Content-Security-Policy.";
+ return false;
+ }
+
+ return true;
+}
+
+bool Subsumes(const mojom::ContentSecurityPolicy& policy_a,
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b) {
+ if (policy_a.directives.empty())
+ return true;
+
+ if (policy_a.header->type == mojom::ContentSecurityPolicyType::kReport)
+ return true;
+
+ // TODO(antoniosartori): Complete the implementation of this function
+ return util::ranges::all_of(
+ policy_a.directives, [&policies_b](const auto& directive_a) {
+ return util::ranges::any_of(
+ policies_b, [&directive_a](const auto& policy_b) {
+ if (policy_b->header->type ==
+ mojom::ContentSecurityPolicyType::kReport) {
+ return false;
+ }
+
+ auto value_b = policy_b->directives.find(directive_a.first);
+ return value_b != policy_b->directives.end() &&
+ value_b->second == directive_a.second;
+ });
+ });
+}
+
CSPDirectiveName ToCSPDirectiveName(const std::string& name) {
- if (name == "default-src")
- return CSPDirectiveName::DefaultSrc;
+ if (name == "base-uri")
+ return CSPDirectiveName::BaseURI;
+ if (name == "block-all-mixed-content")
+ return CSPDirectiveName::BlockAllMixedContent;
if (name == "child-src")
return CSPDirectiveName::ChildSrc;
+ if (name == "connect-src")
+ return CSPDirectiveName::ConnectSrc;
+ if (name == "default-src")
+ return CSPDirectiveName::DefaultSrc;
+ if (name == "frame-ancestors")
+ return CSPDirectiveName::FrameAncestors;
if (name == "frame-src")
return CSPDirectiveName::FrameSrc;
+ if (name == "font-src")
+ return CSPDirectiveName::FontSrc;
if (name == "form-action")
return CSPDirectiveName::FormAction;
- if (name == "navigate-to")
- return CSPDirectiveName::NavigateTo;
- if (name == "frame-ancestors")
- return CSPDirectiveName::FrameAncestors;
if (name == "img-src")
return CSPDirectiveName::ImgSrc;
+ if (name == "manifest-src")
+ return CSPDirectiveName::ManifestSrc;
if (name == "media-src")
return CSPDirectiveName::MediaSrc;
if (name == "object-src")
return CSPDirectiveName::ObjectSrc;
+ if (name == "prefetch-src")
+ return CSPDirectiveName::PrefetchSrc;
+ if (name == "report-uri")
+ return CSPDirectiveName::ReportURI;
+ if (name == "require-trusted-types-for")
+ return CSPDirectiveName::RequireTrustedTypesFor;
+ if (name == "sandbox")
+ return CSPDirectiveName::Sandbox;
if (name == "script-src")
return CSPDirectiveName::ScriptSrc;
+ if (name == "script-src-attr")
+ return CSPDirectiveName::ScriptSrcAttr;
+ if (name == "script-src-elem")
+ return CSPDirectiveName::ScriptSrcElem;
if (name == "style-src")
return CSPDirectiveName::StyleSrc;
+ if (name == "style-src-attr")
+ return CSPDirectiveName::StyleSrcAttr;
+ if (name == "style-src-elem")
+ return CSPDirectiveName::StyleSrcElem;
+ if (name == "treat-as-public-address")
+ return CSPDirectiveName::TreatAsPublicAddress;
+ if (name == "trusted-types")
+ return CSPDirectiveName::TrustedTypes;
+ if (name == "upgrade-insecure-requests")
+ return CSPDirectiveName::UpgradeInsecureRequests;
if (name == "worker-src")
return CSPDirectiveName::WorkerSrc;
- if (name == "connect-src")
- return CSPDirectiveName::ConnectSrc;
+ if (name == "report-to")
+ return CSPDirectiveName::ReportTo;
+ if (name == "navigate-to")
+ return CSPDirectiveName::NavigateTo;
+
return CSPDirectiveName::Unknown;
}
std::string ToString(CSPDirectiveName name) {
switch (name) {
- case CSPDirectiveName::DefaultSrc:
- return "default-src";
+ case CSPDirectiveName::BaseURI:
+ return "base-uri";
+ case CSPDirectiveName::BlockAllMixedContent:
+ return "block-all-mixed-content";
case CSPDirectiveName::ChildSrc:
return "child-src";
+ case CSPDirectiveName::ConnectSrc:
+ return "connect-src";
+ case CSPDirectiveName::DefaultSrc:
+ return "default-src";
+ case CSPDirectiveName::FrameAncestors:
+ return "frame-ancestors";
case CSPDirectiveName::FrameSrc:
return "frame-src";
+ case CSPDirectiveName::FontSrc:
+ return "font-src";
case CSPDirectiveName::FormAction:
return "form-action";
- case CSPDirectiveName::NavigateTo:
- return "navigate-to";
- case CSPDirectiveName::FrameAncestors:
- return "frame-ancestors";
case CSPDirectiveName::ImgSrc:
return "img-src";
+ case CSPDirectiveName::ManifestSrc:
+ return "manifest-src";
case CSPDirectiveName::MediaSrc:
return "media-src";
case CSPDirectiveName::ObjectSrc:
return "object-src";
+ case CSPDirectiveName::PrefetchSrc:
+ return "prefetch-src";
+ case CSPDirectiveName::ReportURI:
+ return "report-uri";
+ case CSPDirectiveName::RequireTrustedTypesFor:
+ return "require-trusted-types-for";
+ case CSPDirectiveName::Sandbox:
+ return "sandbox";
case CSPDirectiveName::ScriptSrc:
return "script-src";
+ case CSPDirectiveName::ScriptSrcAttr:
+ return "script-src-attr";
+ case CSPDirectiveName::ScriptSrcElem:
+ return "script-src-elem";
case CSPDirectiveName::StyleSrc:
return "style-src";
+ case CSPDirectiveName::StyleSrcAttr:
+ return "style-src-attr";
+ case CSPDirectiveName::StyleSrcElem:
+ return "style-src-elem";
+ case CSPDirectiveName::UpgradeInsecureRequests:
+ return "upgrade-insecure-requests";
+ case CSPDirectiveName::TreatAsPublicAddress:
+ return "treat-as-public-address";
+ case CSPDirectiveName::TrustedTypes:
+ return "trusted-types";
case CSPDirectiveName::WorkerSrc:
return "worker-src";
- case CSPDirectiveName::ConnectSrc:
- return "connect-src";
+ case CSPDirectiveName::ReportTo:
+ return "report-to";
+ case CSPDirectiveName::NavigateTo:
+ return "navigate-to";
case CSPDirectiveName::Unknown:
return "";
}
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
index 82185a88df2..80b967e3b00 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy.h
@@ -36,6 +36,11 @@ void AddContentSecurityPolicyFromHeaders(
const GURL& base_url,
std::vector<mojom::ContentSecurityPolicyPtr>* out);
+// Parse and return the Allow-CSP-From header value from |headers|.
+COMPONENT_EXPORT(NETWORK_CPP)
+mojom::AllowCSPFromHeaderValuePtr ParseAllowCSPFromHeader(
+ const net::HttpResponseHeaders& headers);
+
// Return true when the |policy| allows a request to the |url| in relation to
// the |directive| for a given |context|.
// Note: Any policy violation are reported to the |context|.
@@ -66,6 +71,22 @@ bool ShouldTreatAsPublicAddress(
COMPONENT_EXPORT(NETWORK_CPP)
void UpgradeInsecureRequest(GURL* url);
+// Checks whether |policy| is a valid required CSP attribute according to
+// https://w3c.github.io/webappsec-cspee/#iframe-csp-valid-attribute-value.
+// |policy| must be a vector containing exactly one entry.
+// The context can be null.
+COMPONENT_EXPORT(NETWORK_CPP)
+bool IsValidRequiredCSPAttr(
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policy,
+ const mojom::ContentSecurityPolicy* context,
+ std::string& error_message);
+
+// Checks whether |policy_a| subsumes the policy list |policies_b| according to
+// the algorithm https://w3c.github.io/webappsec-cspee/#subsume-policy-list.
+COMPONENT_EXPORT(NETWORK_CPP)
+bool Subsumes(const mojom::ContentSecurityPolicy& policy_a,
+ const std::vector<mojom::ContentSecurityPolicyPtr>& policies_b);
+
COMPONENT_EXPORT(NETWORK_CPP)
mojom::CSPDirectiveName ToCSPDirectiveName(const std::string& name);
diff --git a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
index 6ac9b0d0d1b..c4ca0e20494 100644
--- a/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/content_security_policy_unittest.cc
@@ -4,7 +4,6 @@
#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
-#include "base/optional.h"
#include "base/stl_util.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/content_security_policy/csp_context.h"
@@ -234,17 +233,19 @@ TEST(ContentSecurityPolicy, ParseFrameAncestors) {
TestFrameAncestorsCSPParser(test.header, &test.expected_result);
}
-TEST(ContentSecurityPolicy, ParseMultipleDirectives) {
- // First directive is valid, second one is ignored.
+TEST(ContentSecurityPolicy, ParseDirectives) {
+ // One duplicate directive.
{
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
headers->SetHeader("Content-Security-Policy",
- "frame-ancestors example.com; other_directive "
- "value; frame-ancestors example.org");
+ "frame-ancestors example.com; script-src "
+ "example2.com; frame-ancestors example3.com");
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
+ EXPECT_EQ(2U, policies[0]->directives.size());
+
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -255,18 +256,37 @@ TEST(ContentSecurityPolicy, ParseMultipleDirectives) {
EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
EXPECT_EQ(frame_ancestors->allow_self, false);
+
+ auto& script_src =
+ policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc];
+ EXPECT_EQ(script_src->sources.size(), 1U);
+ EXPECT_EQ(script_src->sources[0]->scheme, "");
+ EXPECT_EQ(script_src->sources[0]->host, "example2.com");
+ EXPECT_EQ(script_src->sources[0]->port, url::PORT_UNSPECIFIED);
+ EXPECT_EQ(script_src->sources[0]->path, "");
+ EXPECT_EQ(script_src->sources[0]->is_host_wildcard, false);
+ EXPECT_EQ(script_src->sources[0]->is_port_wildcard, false);
+ EXPECT_EQ(script_src->allow_self, false);
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "Ignoring duplicate Content-Security-Policy directive "
+ "'frame-ancestors'.",
+ policies[0]->parsing_errors[0]);
}
- // Skip the first directive, which is not frame-ancestors.
+ // One invalid directive.
{
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
headers->SetHeader("Content-Security-Policy",
- "other_directive value; frame-ancestors "
+ "other-directive value; frame-ancestors "
"example.org");
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
+ EXPECT_EQ(1U, policies[0]->directives.size());
+
auto& frame_ancestors =
policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
EXPECT_EQ(frame_ancestors->sources.size(), 1U);
@@ -278,6 +298,143 @@ TEST(ContentSecurityPolicy, ParseMultipleDirectives) {
EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
EXPECT_EQ(frame_ancestors->allow_self, false);
EXPECT_EQ(frame_ancestors->allow_star, false);
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "Unrecognized Content-Security-Policy directive 'other-directive'.",
+ policies[0]->parsing_errors[0]);
+ }
+
+ // Invalid characters in directive name.
+ {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy",
+ "frame_ancestors example.com;");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_TRUE(policies[0]->directives.empty());
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "The Content-Security-Policy directive name 'frame_ancestors' contains "
+ "one or more invalid characters. Only ASCII alphanumeric characters or "
+ "dashes '-' are allowed in directive names.",
+ policies[0]->parsing_errors[0]);
+ }
+
+ // Invalid characters in directive value.
+ {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy", "frame-ancestors ü.com;");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_TRUE(policies[0]->directives.empty());
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "The value for the Content-Security-Policy directive 'frame-ancestors' "
+ "contains one or more invalid characters. Non-whitespace characters "
+ "outside ASCII 0x21-0x7E must be percent-encoded, as described in RFC "
+ "3986, section 2.1: http://tools.ietf.org/html/rfc3986#section-2.1.",
+ policies[0]->parsing_errors[0]);
+ }
+
+ // Missing semicolon between directive names.
+ {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy", "frame-ancestors object-src");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_EQ(1U, policies[0]->directives.size());
+
+ auto& frame_ancestors =
+ policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+ EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+ EXPECT_EQ(frame_ancestors->sources[0]->scheme, "");
+ EXPECT_EQ(frame_ancestors->sources[0]->host, "object-src");
+ EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+ EXPECT_EQ(frame_ancestors->sources[0]->path, "");
+ EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+ EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+ EXPECT_EQ(frame_ancestors->allow_self, false);
+ EXPECT_EQ(frame_ancestors->allow_star, false);
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "The Content-Security-Policy directive 'frame-ancestors' contains "
+ "'object-src' as a source expression. Did you want to add it as a "
+ "directive and forget a semicolon?",
+ policies[0]->parsing_errors[0]);
+ }
+
+ // Path containing query.
+ {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy",
+ "frame-ancestors http://example.org/index.html?a=b;");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_EQ(1U, policies[0]->directives.size());
+
+ auto& frame_ancestors =
+ policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+ EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+ EXPECT_EQ(frame_ancestors->sources[0]->scheme, "http");
+ EXPECT_EQ(frame_ancestors->sources[0]->host, "example.org");
+ EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+ EXPECT_EQ(frame_ancestors->sources[0]->path, "/index.html");
+ EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+ EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+ EXPECT_EQ(frame_ancestors->allow_self, false);
+ EXPECT_EQ(frame_ancestors->allow_star, false);
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "The source list for Content-Security-Policy directive "
+ "'frame-ancestors' contains a source with an invalid path: "
+ "'/index.html?a=b'. The query component, including the '?', will be "
+ "ignored.",
+ policies[0]->parsing_errors[0]);
+ }
+
+ // Path containing ref.
+ {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy",
+ "frame-ancestors http://example.org/index.html#a;");
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_EQ(1U, policies[0]->directives.size());
+
+ auto& frame_ancestors =
+ policies[0]->directives[mojom::CSPDirectiveName::FrameAncestors];
+ EXPECT_EQ(frame_ancestors->sources.size(), 1U);
+ EXPECT_EQ(frame_ancestors->sources[0]->scheme, "http");
+ EXPECT_EQ(frame_ancestors->sources[0]->host, "example.org");
+ EXPECT_EQ(frame_ancestors->sources[0]->port, url::PORT_UNSPECIFIED);
+ EXPECT_EQ(frame_ancestors->sources[0]->path, "/index.html");
+ EXPECT_EQ(frame_ancestors->sources[0]->is_host_wildcard, false);
+ EXPECT_EQ(frame_ancestors->sources[0]->is_port_wildcard, false);
+ EXPECT_EQ(frame_ancestors->allow_self, false);
+ EXPECT_EQ(frame_ancestors->allow_star, false);
+
+ EXPECT_EQ(1U, policies[0]->parsing_errors.size());
+ EXPECT_EQ(
+ "The source list for Content-Security-Policy directive "
+ "'frame-ancestors' contains a source with an invalid path: "
+ "'/index.html#a'. The fragment identifier, including the '#', will be "
+ "ignored.",
+ policies[0]->parsing_errors[0]);
}
// Multiple CSP headers with multiple frame-ancestors directives present.
@@ -324,7 +481,7 @@ TEST(ContentSecurityPolicy, ParseMultipleDirectives) {
scoped_refptr<net::HttpResponseHeaders> headers(
new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
headers->SetHeader("Content-Security-Policy",
- "other_directive value, frame-ancestors example.org");
+ "other-directive value, frame-ancestors example.org");
std::vector<mojom::ContentSecurityPolicyPtr> policies;
AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
&policies);
@@ -557,7 +714,9 @@ TEST(ContentSecurityPolicy, DirectiveFallback) {
auto allow_host = [](const char* host) {
std::vector<mojom::CSPSourcePtr> sources;
sources.push_back(BuildCSPSource("http", host));
- return mojom::CSPSourceList::New(std::move(sources), false, false, false);
+ auto csp_source_list = mojom::CSPSourceList::New();
+ csp_source_list->sources = std::move(sources);
+ return csp_source_list;
};
{
@@ -702,17 +861,16 @@ TEST(ContentSecurityPolicy, NavigateToChecks) {
GURL url_a("https://a");
GURL url_b("https://b");
CSPContextTest context;
- auto allow_none = [] {
- return mojom::CSPSourceList::New(std::vector<mojom::CSPSourcePtr>(), false,
- false, false);
- };
+ auto allow_none = [] { return mojom::CSPSourceList::New(); };
auto allow_self = [] {
- return mojom::CSPSourceList::New(std::vector<mojom::CSPSourcePtr>(), true,
- false, false);
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_self = true;
+ return csp;
};
auto allow_redirect = [] {
- return mojom::CSPSourceList::New(std::vector<mojom::CSPSourcePtr>(), false,
- false, true);
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_response_redirects = true;
+ return csp;
};
auto source_a = [] {
return mojom::CSPSource::New("https", "a", url::PORT_UNSPECIFIED, "", false,
@@ -721,12 +879,17 @@ TEST(ContentSecurityPolicy, NavigateToChecks) {
auto allow_a = [&] {
std::vector<mojom::CSPSourcePtr> sources;
sources.push_back(source_a());
- return mojom::CSPSourceList::New(std::move(sources), false, false, false);
+ auto csp = mojom::CSPSourceList::New();
+ csp->sources = std::move(sources);
+ return csp;
};
auto allow_redirect_a = [&] {
std::vector<mojom::CSPSourcePtr> sources;
sources.push_back(source_a());
- return mojom::CSPSourceList::New(std::move(sources), false, false, true);
+ auto csp = mojom::CSPSourceList::New();
+ csp->sources = std::move(sources);
+ csp->allow_response_redirects = true;
+ return csp;
};
context.SetSelf(source_a());
@@ -800,4 +963,249 @@ TEST(ContentSecurityPolicy, ParseSandbox) {
mojom::WebSandboxFlags::kAutomaticFeatures);
}
+TEST(ContentSecurityPolicy, ParseSerializedSourceList) {
+ struct TestCase {
+ std::string directive_value;
+ base::Callback<mojom::CSPSourceListPtr()> expected;
+ std::string expected_error;
+ } cases[] = {
+ {
+ "'nonce-a' 'nonce-a=' 'nonce-a==' 'nonce-a===' 'nonce-==' 'nonce-' "
+ "'nonce 'nonce-cde' 'nonce-cde=' 'nonce-cde==' 'nonce-cde==='",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->nonces.push_back("a");
+ csp->nonces.push_back("a=");
+ csp->nonces.push_back("a==");
+ csp->nonces.push_back("cde");
+ csp->nonces.push_back("cde=");
+ csp->nonces.push_back("cde==");
+ return csp;
+ }),
+ "",
+ },
+ {
+ "'sha256-abc' 'sha256-ABC' 'sha256 'sha256-' 'sha384-abc' "
+ "'sha512-abc' 'sha-abc' 'sha256-*' 'sha-256-cde' 'sha-384-cde' "
+ "'sha-512-cde'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA256, "abc"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA256, "ABC"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA384, "abc"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA512, "abc"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA256, "cde"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA384, "cde"));
+ csp->hashes.push_back(mojom::CSPHashSource::New(
+ mojom::CSPHashAlgorithm::SHA512, "cde"));
+ return csp;
+ }),
+ "",
+ },
+ {
+ "'none' ",
+ base::Bind([] { return mojom::CSPSourceList::New(); }),
+ "",
+ },
+ {
+ "'none' 'self'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_self = true;
+ return csp;
+ }),
+ "The Content-Security-Policy directive 'script-src' contains the "
+ "keyword 'none' alongside with other source expressions. The keyword "
+ "'none' must be the only source expression in the directive value, "
+ "otherwise it is ignored.",
+ },
+ {
+ "'self' 'none'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_self = true;
+ return csp;
+ }),
+ "The Content-Security-Policy directive 'script-src' contains the "
+ "keyword 'none' alongside with other source expressions. The keyword "
+ "'none' must be the only source expression in the directive value, "
+ "otherwise it is ignored.",
+ },
+ {
+ "'self'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_self = true;
+ return csp;
+ }),
+ },
+ {
+ "'wrong' *",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_star = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'unsafe-inline'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_inline = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'unsafe-eval'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_eval = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'wasm-eval'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_wasm_eval = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'strict-dynamic'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_dynamic = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'unsafe-hashes'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->allow_unsafe_hashes = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ {
+ "'wrong' 'report-sample'",
+ base::Bind([] {
+ auto csp = mojom::CSPSourceList::New();
+ csp->report_sample = true;
+ return csp;
+ }),
+ "The source list for the Content-Security-Policy directive "
+ "'script-src' contains an invalid source: ''wrong''.",
+ },
+ };
+
+ for (auto& test : cases) {
+ SCOPED_TRACE(test.directive_value);
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy",
+ "script-src " + test.directive_value);
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ EXPECT_TRUE(test.expected.Run().Equals(
+ policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]));
+
+ if (!test.expected_error.empty())
+ EXPECT_EQ(test.expected_error, policies[0]->parsing_errors[0]);
+ }
+}
+
+TEST(ContentSecurityPolicy, IsValidRequiredCSPAttr) {
+ struct TestCase {
+ const char* csp;
+ bool expected;
+ std::string expected_error;
+ } cases[] = {{"script-src 'none'", true, ""},
+ {"script-src 'none'; invalid-directive", false,
+ "Parsing the csp attribute into a Content-Security-Policy "
+ "returned one or more parsing errors: Unrecognized "
+ "Content-Security-Policy directive 'invalid-directive'."},
+ {"script-src 'none'; report-uri https://www.example.com", false,
+ "The csp attribute cannot contain the directives 'report-to' "
+ "or 'report-uri'."}};
+
+ for (auto& test : cases) {
+ SCOPED_TRACE(test.csp);
+ std::vector<mojom::ContentSecurityPolicyPtr> csp;
+ auto required_csp_headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+ required_csp_headers->SetHeader("Content-Security-Policy", test.csp);
+ AddContentSecurityPolicyFromHeaders(*required_csp_headers,
+ GURL("https://example.com/"), &csp);
+ std::string out;
+ EXPECT_EQ(test.expected, IsValidRequiredCSPAttr(csp, nullptr, out));
+ EXPECT_EQ(test.expected_error, out);
+ }
+}
+
+TEST(ContentSecurityPolicy, Subsumes) {
+ struct TestCase {
+ std::string name;
+ std::string required_csp;
+ std::string returned_csp;
+ bool expected;
+ } cases[] = {
+ {
+ "No required csp",
+ "",
+ "script-src 'none'",
+ true,
+ },
+ {
+ "Same CSPs",
+ "script-src 'none'",
+ "script-src 'none'",
+ true,
+ },
+ };
+
+ for (auto& test : cases) {
+ SCOPED_TRACE(test.name);
+ std::vector<mojom::ContentSecurityPolicyPtr> required_csp;
+ if (test.required_csp.empty()) {
+ required_csp.push_back(mojom::ContentSecurityPolicy::New());
+ } else {
+ auto required_csp_headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+ required_csp_headers->SetHeader("Content-Security-Policy",
+ test.required_csp);
+ AddContentSecurityPolicyFromHeaders(
+ *required_csp_headers, GURL("https://example.com/"), &required_csp);
+ }
+
+ auto returned_csp_headers =
+ base::MakeRefCounted<net::HttpResponseHeaders>("HTTP/1.1 200 OK");
+ returned_csp_headers->AddHeader("Content-Security-Policy",
+ test.returned_csp);
+ std::vector<mojom::ContentSecurityPolicyPtr> returned_csp;
+ AddContentSecurityPolicyFromHeaders(
+ *returned_csp_headers, GURL("https://example.com/"), &returned_csp);
+ EXPECT_EQ(test.expected, Subsumes(*required_csp[0], returned_csp));
+ }
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
index 1e029582b11..983b8a51642 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source.cc
@@ -48,6 +48,17 @@ enum class PortMatchingResult {
};
enum class SchemeMatchingResult { NotMatching, MatchingUpgrade, MatchingExact };
+SchemeMatchingResult MatchScheme(const std::string& scheme_a,
+ const std::string& scheme_b) {
+ if (scheme_a == scheme_b)
+ return SchemeMatchingResult::MatchingExact;
+ if ((scheme_a == url::kHttpScheme && scheme_b == url::kHttpsScheme) ||
+ (scheme_a == url::kWsScheme && scheme_b == url::kWssScheme)) {
+ return SchemeMatchingResult::MatchingUpgrade;
+ }
+ return SchemeMatchingResult::NotMatching;
+}
+
SchemeMatchingResult SourceAllowScheme(const mojom::CSPSourcePtr& source,
const GURL& url,
CSPContext* context) {
@@ -60,19 +71,11 @@ SchemeMatchingResult SourceAllowScheme(const mojom::CSPSourcePtr& source,
const std::string& allowed_scheme =
source->scheme.empty() ? context->self_source()->scheme : source->scheme;
- if (url.SchemeIs(allowed_scheme))
- return SchemeMatchingResult::MatchingExact;
-
- // Implicitly allow using a more secure version of a protocol when the
- // non-secure one is allowed.
- if ((allowed_scheme == url::kHttpScheme && url.SchemeIs(url::kHttpsScheme)) ||
- (allowed_scheme == url::kWsScheme && url.SchemeIs(url::kWssScheme))) {
- return SchemeMatchingResult::MatchingUpgrade;
- }
- return SchemeMatchingResult::NotMatching;
+ return MatchScheme(allowed_scheme, url.scheme());
}
-bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) {
+bool SourceAllowHost(const mojom::CSPSourcePtr& source,
+ const std::string& host) {
if (source->is_host_wildcard) {
if (source->host.empty())
return true;
@@ -80,66 +83,86 @@ bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) {
// The renderer version of this function counts how many times it happens.
// It might be useful to do it outside of blink too.
// See third_party/blink/renderer/core/frame/csp/csp_source.cc
- return base::EndsWith(url.host(), '.' + source->host,
+ return base::EndsWith(host, '.' + source->host,
base::CompareCase::INSENSITIVE_ASCII);
} else {
- return base::EqualsCaseInsensitiveASCII(url.host(), source->host);
+ return base::EqualsCaseInsensitiveASCII(host, source->host);
}
}
-PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
- const GURL& url) {
- int url_port = url.EffectiveIntPort();
+bool SourceAllowHost(const mojom::CSPSourcePtr& source, const GURL& url) {
+ return SourceAllowHost(source, url.host());
+}
+PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
+ int port,
+ const std::string& scheme) {
if (source->is_port_wildcard)
return PortMatchingResult::MatchingWildcard;
- if (source->port == url_port) {
+ if (source->port == port) {
if (source->port == url::PORT_UNSPECIFIED)
return PortMatchingResult::MatchingWildcard;
return PortMatchingResult::MatchingExact;
}
if (source->port == url::PORT_UNSPECIFIED) {
- if (DefaultPortForScheme(url.scheme()) == url_port) {
+ if (DefaultPortForScheme(scheme) == port)
+ return PortMatchingResult::MatchingWildcard;
+ }
+
+ if (port == url::PORT_UNSPECIFIED) {
+ if (source->port == DefaultPortForScheme(scheme))
return PortMatchingResult::MatchingWildcard;
- }
- return PortMatchingResult::NotMatching;
}
int source_port = source->port;
if (source_port == url::PORT_UNSPECIFIED)
source_port = DefaultPortForScheme(source->scheme);
- if (source_port == 80 && url_port == 443)
+ if (port == url::PORT_UNSPECIFIED)
+ port = DefaultPortForScheme(scheme);
+
+ if (source_port == 80 && port == 443)
return PortMatchingResult::MatchingUpgrade;
return PortMatchingResult::NotMatching;
}
-bool SourceAllowPath(const mojom::CSPSourcePtr& source,
- const GURL& url,
- bool has_followed_redirect) {
- if (has_followed_redirect)
- return true;
-
- if (source->path.empty() || url.path().empty())
- return true;
+PortMatchingResult SourceAllowPort(const mojom::CSPSourcePtr& source,
+ const GURL& url) {
+ return SourceAllowPort(source, url.EffectiveIntPort(), url.scheme());
+}
- std::string url_path;
- if (!DecodePath(url.path(), &url_path)) {
+bool SourceAllowPath(const mojom::CSPSourcePtr& source,
+ const std::string& path) {
+ std::string path_decoded;
+ if (!DecodePath(path, &path_decoded)) {
// TODO(arthursonzogni): try to figure out if that could happen and how to
// handle it.
return false;
}
+ if (source->path.empty() || (source->path == "/" && path_decoded.empty()))
+ return true;
+
// If the path represents a directory.
- if (base::EndsWith(source->path, "/", base::CompareCase::SENSITIVE))
- return base::StartsWith(url_path, source->path,
+ if (base::EndsWith(source->path, "/", base::CompareCase::SENSITIVE)) {
+ return base::StartsWith(path_decoded, source->path,
base::CompareCase::SENSITIVE);
+ }
// The path represents a file.
- return source->path == url_path;
+ return source->path == path_decoded;
+}
+
+bool SourceAllowPath(const mojom::CSPSourcePtr& source,
+ const GURL& url,
+ bool has_followed_redirect) {
+ if (has_followed_redirect)
+ return true;
+
+ return SourceAllowPath(source, url.path());
}
bool requiresUpgrade(const PortMatchingResult result) {
@@ -181,6 +204,42 @@ bool CheckCSPSource(const mojom::CSPSourcePtr& source,
SourceAllowPath(source, url, has_followed_redirect);
}
+// Check whether |source_a| subsumes |source_b|.
+bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a,
+ const mojom::CSPSourcePtr& source_b) {
+ // If the original source expressions didn't have a scheme, we should have
+ // filled that already with origin's scheme.
+ DCHECK(!source_a->scheme.empty());
+ DCHECK(!source_b->scheme.empty());
+
+ if (MatchScheme(source_a->scheme, source_b->scheme) ==
+ SchemeMatchingResult::NotMatching) {
+ return false;
+ }
+
+ if (IsSchemeOnly(source_a))
+ return true;
+ if (IsSchemeOnly(source_b))
+ return false;
+
+ if (!SourceAllowHost(source_a, (source_b->is_host_wildcard ? "*." : "") +
+ source_b->host)) {
+ return false;
+ }
+
+ if (source_b->is_port_wildcard && !source_a->is_port_wildcard)
+ return false;
+ PortMatchingResult port_matching =
+ SourceAllowPort(source_a, source_b->port, source_b->scheme);
+ if (port_matching == PortMatchingResult::NotMatching)
+ return false;
+
+ if (!SourceAllowPath(source_a, source_b->path))
+ return false;
+
+ return true;
+}
+
std::string ToString(const mojom::CSPSourcePtr& source) {
// scheme
if (IsSchemeOnly(source))
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source.h b/chromium/services/network/public/cpp/content_security_policy/csp_source.h
index 902aed3eb93..d0e6c05fa5a 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source.h
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source.h
@@ -22,6 +22,12 @@ bool CheckCSPSource(const mojom::CSPSourcePtr& source,
CSPContext* context,
bool has_followed_redirect = false);
+// Check if |source_a| subsumes |source_b| according to
+// https://w3c.github.io/webappsec-cspee/#subsume-source-expressions
+COMPONENT_EXPORT(NETWORK_CPP)
+bool CSPSourceSubsumes(const mojom::CSPSourcePtr& source_a,
+ const mojom::CSPSourcePtr& source_b);
+
// Serialize the CSPSource |source| as a string. This is used for reporting
// violations.
COMPONENT_EXPORT(NETWORK_CPP)
diff --git a/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc b/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
index 800919d0148..8b709edc6a4 100644
--- a/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
+++ b/chromium/services/network/public/cpp/content_security_policy/csp_source_list_unittest.cc
@@ -34,8 +34,8 @@ TEST(CSPSourceList, MultipleSource) {
"", false, false));
sources.push_back(mojom::CSPSource::New("", "b.com", url::PORT_UNSPECIFIED,
"", false, false));
- auto source_list =
- mojom::CSPSourceList::New(std::move(sources), false, false, false);
+ auto source_list = mojom::CSPSourceList::New();
+ source_list->sources = std::move(sources);
EXPECT_TRUE(Allow(source_list, GURL("http://a.com"), &context));
EXPECT_TRUE(Allow(source_list, GURL("http://b.com"), &context));
EXPECT_FALSE(Allow(source_list, GURL("http://c.com"), &context));
@@ -44,11 +44,8 @@ TEST(CSPSourceList, MultipleSource) {
TEST(CSPSourceList, AllowStar) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
- auto source_list = mojom::CSPSourceList::New(
- std::vector<mojom::CSPSourcePtr>(), // source_list
- false, // allow_self
- true, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
+ source_list->allow_star = true;
EXPECT_TRUE(Allow(source_list, GURL("http://not-example.com"), &context));
EXPECT_TRUE(Allow(source_list, GURL("https://not-example.com"), &context));
EXPECT_TRUE(Allow(source_list, GURL("ws://not-example.com"), &context));
@@ -67,11 +64,8 @@ TEST(CSPSourceList, AllowStar) {
TEST(CSPSourceList, AllowSelf) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
- auto source_list = mojom::CSPSourceList::New(
- std::vector<mojom::CSPSourcePtr>(), // source_list
- true, // allow_self,
- false, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
+ source_list->allow_self = true;
EXPECT_TRUE(Allow(source_list, GURL("http://example.com"), &context));
EXPECT_FALSE(Allow(source_list, GURL("http://not-example.com"), &context));
EXPECT_TRUE(Allow(source_list, GURL("https://example.com"), &context));
@@ -81,11 +75,7 @@ TEST(CSPSourceList, AllowSelf) {
TEST(CSPSourceList, AllowStarAndSelf) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("https://a.com")));
- auto source_list =
- mojom::CSPSourceList::New(std::vector<mojom::CSPSourcePtr>(),
- false, // allow_self
- false, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
// If the request is allowed by {*} and not by {'self'} then it should be
// allowed by the union {*,'self'}.
@@ -103,11 +93,8 @@ TEST(CSPSourceList, AllowStarAndSelf) {
TEST(CSPSourceList, AllowSelfWithUnspecifiedPort) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("https://example.com/")));
- auto source_list = mojom::CSPSourceList::New(
- std::vector<mojom::CSPSourcePtr>(), // source_list
- true, // allow_self
- false, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
+ source_list->allow_self = true;
EXPECT_TRUE(
Allow(source_list, GURL("https://example.com/print.pdf"), &context));
@@ -116,22 +103,15 @@ TEST(CSPSourceList, AllowSelfWithUnspecifiedPort) {
TEST(CSPSourceList, AllowNone) {
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://example.com")));
- auto source_list = mojom::CSPSourceList::New(
- std::vector<mojom::CSPSourcePtr>(), // source_list
- false, // allow_self
- false, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
EXPECT_FALSE(Allow(source_list, GURL("http://example.com"), &context));
EXPECT_FALSE(Allow(source_list, GURL("https://example.test/"), &context));
}
TEST(CSPSourceTest, SelfIsUnique) {
// Policy: 'self'
- auto source_list = mojom::CSPSourceList::New(
- std::vector<mojom::CSPSourcePtr>(), // source_list
- true, // allow_self
- false, // allow_star
- false); // allow_redirects
+ auto source_list = mojom::CSPSourceList::New();
+ source_list->allow_self = true;
CSPContext context;
context.SetSelf(url::Origin::Create(GURL("http://a.com")));
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 903aa5a2a25..0ff85abdc45 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
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "services/network/public/cpp/content_security_policy/csp_source.h"
+#include "net/http/http_response_headers.h"
+#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
#include "services/network/public/cpp/content_security_policy/csp_context.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "url/origin.h"
@@ -20,6 +22,17 @@ bool Allow(const network::mojom::CSPSourcePtr& source,
return CheckCSPSource(source, url, context, is_redirect);
}
+network::mojom::CSPSourcePtr CSPSource(const std::string& raw) {
+ scoped_refptr<net::HttpResponseHeaders> headers(
+ new net::HttpResponseHeaders("HTTP/1.1 200 OK"));
+ headers->SetHeader("Content-Security-Policy", "script-src " + raw);
+ std::vector<mojom::ContentSecurityPolicyPtr> policies;
+ AddContentSecurityPolicyFromHeaders(*headers, GURL("https://example.com/"),
+ &policies);
+ return std::move(
+ policies[0]->directives[mojom::CSPDirectiveName::ScriptSrc]->sources[0]);
+}
+
} // namespace
TEST(CSPSourceTest, BasicMatching) {
@@ -243,6 +256,8 @@ TEST(CSPSourceTest, AllowPath) {
Allow(source, GURL("http://a.com/path/to/file/subpath"), &context));
EXPECT_FALSE(
Allow(source, GURL("http://a.com/path/to/something"), &context));
+ EXPECT_FALSE(Allow(source, GURL("http://a.com/"), &context));
+ EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
}
// Path to a directory
@@ -254,6 +269,8 @@ TEST(CSPSourceTest, AllowPath) {
EXPECT_FALSE(Allow(source, GURL("http://a.com/path/"), &context));
EXPECT_FALSE(Allow(source, GURL("http://a.com/path/to"), &context));
EXPECT_FALSE(Allow(source, GURL("http://a.com/path/to"), &context));
+ EXPECT_FALSE(Allow(source, GURL("http://a.com/"), &context));
+ EXPECT_FALSE(Allow(source, GURL("http://a.com"), &context));
}
// Empty path
@@ -306,6 +323,184 @@ TEST(CSPSourceTest, RedirectMatching) {
EXPECT_FALSE(Allow(source, GURL("http://a.com:9000/foo/"), &context, false));
}
+TEST(CSPSourceTest, DoesNotSubsume) {
+ struct TestCase {
+ const char* a;
+ const char* b;
+ } cases[] = {
+ // In the following test cases, neither |a| subsumes |b| nor |b| subsumes
+ // |a|.
+ // Different hosts.
+ {"http://example.com", "http://another.com"},
+ // Different schemes (wss -> http).
+ {"wss://example.com", "http://example.com"},
+ // Different schemes (wss -> about).
+ {"wss://example.com/", "about://example.com/"},
+ // Different schemes (wss -> about).
+ {"http://example.com/", "about://example.com/"},
+ // Different paths.
+ {"http://example.com/1.html", "http://example.com/2.html"},
+ // Different ports.
+ {"http://example.com:443/", "http://example.com:800/"},
+ };
+ for (const auto& test : cases) {
+ auto a = CSPSource(test.a);
+ auto b = CSPSource(test.b);
+
+ EXPECT_FALSE(CSPSourceSubsumes(a, b))
+ << test.a << " should not subsume " << test.b;
+ EXPECT_FALSE(CSPSourceSubsumes(b, a))
+ << test.b << " should not subsume " << test.a;
+ }
+}
+
+TEST(CSPSourceTest, Subsumes) {
+ struct TestCase {
+ const char* a;
+ const char* b;
+ bool expected_a_subsumes_b;
+ bool expected_b_subsumes_a;
+ } cases[] = {
+ // Equal signals.
+ {"http://a.org/", "http://a.org/", true, true},
+ {"https://a.org/", "https://a.org/", true, true},
+ {"https://a.org/page.html", "https://a.org/page.html", true, true},
+ {"http://a.org:70", "http://a.org:70", true, true},
+ {"https://a.org:70", "https://a.org:70", true, true},
+ {"https://a.org/page.html", "https://a.org/page.html", true, true},
+ {"http://a.org:70/page.html", "http://a.org:70/page.html", true, true},
+ {"https://a.org:70/page.html", "https://a.org:70/page.html", true, true},
+ {"http://a.org/", "http://a.org", true, true},
+ {"http://a.org:80", "http://a.org:80", true, true},
+ {"http://a.org:80", "https://a.org:443", true, false},
+ {"http://a.org", "https://a.org:443", true, false},
+ {"http://a.org:80", "https://a.org", true, false},
+ // One stronger signal in the first CSPSource.
+ {"http://a.org/", "https://a.org/", true, false},
+ {"http://a.org/page.html", "http://a.org/", false, true},
+ {"http://a.org:80/page.html", "http://a.org:80/", false, true},
+ {"http://a.org:80", "http://a.org/", true, true},
+ {"http://a.org:700", "http://a.org/", false, false},
+ // Two stronger signals in the first CSPSource.
+ {"https://a.org/page.html", "http://a.org/", false, true},
+ {"https://a.org:80", "http://a.org/", false, false},
+ {"http://a.org:80/page.html", "http://a.org/", false, true},
+ // Three stronger signals in the first CSPSource.
+ {"https://a.org:70/page.html", "http://a.org/", false, false},
+ // Mixed signals.
+ {"https://a.org/", "http://a.org/page.html", false, false},
+ {"https://a.org", "http://a.org:70/", false, false},
+ {"http://a.org/page.html", "http://a.org:70/", false, false},
+ };
+
+ for (const auto& test : cases) {
+ auto a = CSPSource(test.a);
+ auto b = CSPSource(test.b);
+
+ EXPECT_EQ(CSPSourceSubsumes(a, b), test.expected_a_subsumes_b)
+ << test.a << " subsumes " << test.b << " should return "
+ << test.expected_a_subsumes_b;
+ EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a)
+ << test.b << " subsumes " << test.a << " should return "
+ << test.expected_b_subsumes_a;
+
+ a->is_host_wildcard = true;
+ EXPECT_FALSE(CSPSourceSubsumes(b, a))
+ << test.b << " should not subsume " << ToString(a);
+
+ // If also |b| has a wildcard host, then the result should be the expected
+ // one.
+ b->is_host_wildcard = true;
+ EXPECT_EQ(CSPSourceSubsumes(b, a), test.expected_b_subsumes_a)
+ << ToString(b) << " subsumes " << ToString(a) << " should return "
+ << test.expected_b_subsumes_a;
+ }
+}
+
+TEST(CSPSourceTest, HostWildcardSubsumes) {
+ const char* a = "http://*.example.org";
+ const char* b = "http://www.example.org";
+ const char* c = "http://example.org";
+ const char* d = "https://*.example.org";
+
+ auto source_a = CSPSource(a);
+ auto source_b = CSPSource(b);
+ auto source_c = CSPSource(c);
+ auto source_d = CSPSource(d);
+
+ // *.example.com subsumes www.example.com.
+ EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b))
+ << a << " should subsume " << b;
+ EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a))
+ << b << " should not subsume " << a;
+
+ // *.example.com and example.com have no relations.
+ EXPECT_FALSE(CSPSourceSubsumes(source_a, source_c))
+ << a << " should not subsume " << c;
+ EXPECT_FALSE(CSPSourceSubsumes(source_c, source_a))
+ << c << " should not subsume " << a;
+
+ // https://*.example.com and http://www.example.com have no relations.
+ EXPECT_FALSE(CSPSourceSubsumes(source_d, source_b))
+ << d << " should not subsume " << b;
+ EXPECT_FALSE(CSPSourceSubsumes(source_b, source_d))
+ << b << " should not subsume " << d;
+}
+
+TEST(CSPSourceTest, PortWildcardSubsumes) {
+ const char* a = "http://example.org:*";
+ const char* b = "http://example.org";
+ const char* c = "https://example.org:*";
+
+ auto source_a = CSPSource(a);
+ auto source_b = CSPSource(b);
+ auto source_c = CSPSource(c);
+
+ EXPECT_TRUE(CSPSourceSubsumes(source_a, source_b))
+ << a << " should subsume " << b;
+ EXPECT_FALSE(CSPSourceSubsumes(source_b, source_a))
+ << b << " should not subsume " << a;
+
+ // https://example.com:* and http://example.com have no relations.
+ EXPECT_FALSE(CSPSourceSubsumes(source_b, source_c))
+ << b << " should not subsume " << c;
+ EXPECT_FALSE(CSPSourceSubsumes(source_c, source_b))
+ << c << " should not subsume " << b;
+}
+
+TEST(CSPSourceTest, SchemesOnlySubsumes) {
+ struct TestCase {
+ const char* a;
+ const char* b;
+ bool expected;
+ } cases[] = {
+ // HTTP.
+ {"http:", "http:", true},
+ {"http:", "https:", true},
+ {"https:", "http:", false},
+ {"https:", "https:", true},
+ // WSS.
+ {"ws:", "ws:", true},
+ {"ws:", "wss:", true},
+ {"wss:", "ws:", false},
+ {"wss:", "wss:", true},
+ // Unequal.
+ {"ws:", "http:", false},
+ {"http:", "ws:", false},
+ {"http:", "about:", false},
+ {"wss:", "https:", false},
+ {"https:", "wss:", false},
+ };
+
+ for (const auto& test : cases) {
+ auto source_a = CSPSource(test.a);
+ auto source_b = CSPSource(test.b);
+ EXPECT_EQ(CSPSourceSubsumes(source_a, source_b), test.expected)
+ << test.a << " subsumes " << test.b << " should return "
+ << test.expected;
+ }
+}
+
TEST(CSPSourceTest, ToString) {
{
auto source = network::mojom::CSPSource::New(
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 d4897d169e5..56e5c6f6089 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.cc
@@ -93,6 +93,8 @@ network::mojom::CookieEffectiveSameSite EnumTraits<
return network::mojom::CookieEffectiveSameSite::kStrictMode;
case net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE:
return network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe;
+ case net::CookieEffectiveSameSite::UNDEFINED:
+ return network::mojom::CookieEffectiveSameSite::kUndefined;
default:
break;
}
@@ -117,6 +119,9 @@ bool EnumTraits<network::mojom::CookieEffectiveSameSite,
case network::mojom::CookieEffectiveSameSite::kLaxModeAllowUnsafe:
*output = net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE;
return true;
+ case network::mojom::CookieEffectiveSameSite::kUndefined:
+ *output = net::CookieEffectiveSameSite::UNDEFINED;
+ return true;
default:
break;
}
@@ -403,37 +408,21 @@ bool StructTraits<network::mojom::CookieInclusionStatusDataView,
return out->IsValid();
}
-bool StructTraits<
- network::mojom::CookieWithStatusDataView,
- net::CookieWithStatus>::Read(network::mojom::CookieWithStatusDataView c,
- net::CookieWithStatus* out) {
- net::CanonicalCookie cookie;
- net::CookieInclusionStatus status;
- if (!c.ReadCookie(&cookie))
- return false;
- if (!c.ReadStatus(&status))
- return false;
-
- *out = {cookie, status};
-
- return true;
-}
-
-bool StructTraits<network::mojom::CookieAndLineWithStatusDataView,
- net::CookieAndLineWithStatus>::
- Read(network::mojom::CookieAndLineWithStatusDataView c,
- net::CookieAndLineWithStatus* out) {
+bool StructTraits<network::mojom::CookieAndLineWithAccessResultDataView,
+ net::CookieAndLineWithAccessResult>::
+ Read(network::mojom::CookieAndLineWithAccessResultDataView c,
+ net::CookieAndLineWithAccessResult* out) {
base::Optional<net::CanonicalCookie> cookie;
std::string cookie_string;
- net::CookieInclusionStatus status;
+ net::CookieAccessResult access_result;
if (!c.ReadCookie(&cookie))
return false;
if (!c.ReadCookieString(&cookie_string))
return false;
- if (!c.ReadStatus(&status))
+ if (!c.ReadAccessResult(&access_result))
return false;
- *out = {cookie, cookie_string, status};
+ *out = {cookie, cookie_string, access_result};
return true;
}
@@ -444,13 +433,16 @@ bool StructTraits<
net::CookieAccessResult* out) {
net::CookieEffectiveSameSite effective_same_site;
net::CookieInclusionStatus status;
+ net::CookieAccessSemantics access_semantics;
if (!c.ReadEffectiveSameSite(&effective_same_site))
return false;
if (!c.ReadStatus(&status))
return false;
+ if (!c.ReadAccessSemantics(&access_semantics))
+ return false;
- *out = {effective_same_site, status};
+ *out = {effective_same_site, status, access_semantics};
return true;
}
@@ -476,17 +468,16 @@ bool StructTraits<
net::CookieChangeInfo>::Read(network::mojom::CookieChangeInfoDataView info,
net::CookieChangeInfo* out) {
net::CanonicalCookie cookie;
- net::CookieAccessSemantics access_semantics =
- net::CookieAccessSemantics::UNKNOWN;
+ net::CookieAccessResult access_result;
net::CookieChangeCause cause = net::CookieChangeCause::EXPLICIT;
if (!info.ReadCookie(&cookie))
return false;
- if (!info.ReadAccessSemantics(&access_semantics))
+ if (!info.ReadAccessResult(&access_result))
return false;
if (!info.ReadCause(&cause))
return false;
- *out = net::CookieChangeInfo(cookie, access_semantics, cause);
+ *out = net::CookieChangeInfo(cookie, access_result, cause);
return true;
}
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 8b5243cafcf..9baa054951b 100644
--- a/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
+++ b/chromium/services/network/public/cpp/cookie_manager_mojom_traits.h
@@ -168,36 +168,22 @@ struct StructTraits<network::mojom::CookieInclusionStatusDataView,
};
template <>
-struct StructTraits<network::mojom::CookieWithStatusDataView,
- net::CookieWithStatus> {
- static const net::CanonicalCookie& cookie(const net::CookieWithStatus& c) {
- return c.cookie;
- }
- static const net::CookieInclusionStatus& status(
- const net::CookieWithStatus& c) {
- return c.status;
- }
- static bool Read(network::mojom::CookieWithStatusDataView cookie,
- net::CookieWithStatus* out);
-};
-
-template <>
-struct StructTraits<network::mojom::CookieAndLineWithStatusDataView,
- net::CookieAndLineWithStatus> {
+struct StructTraits<network::mojom::CookieAndLineWithAccessResultDataView,
+ net::CookieAndLineWithAccessResult> {
static const base::Optional<net::CanonicalCookie>& cookie(
- const net::CookieAndLineWithStatus& c) {
+ const net::CookieAndLineWithAccessResult& c) {
return c.cookie;
}
static const std::string& cookie_string(
- const net::CookieAndLineWithStatus& c) {
+ const net::CookieAndLineWithAccessResult& c) {
return c.cookie_string;
}
- static const net::CookieInclusionStatus& status(
- const net::CookieAndLineWithStatus& c) {
- return c.status;
+ static const net::CookieAccessResult& access_result(
+ const net::CookieAndLineWithAccessResult& c) {
+ return c.access_result;
}
- static bool Read(network::mojom::CookieAndLineWithStatusDataView cookie,
- net::CookieAndLineWithStatus* out);
+ static bool Read(network::mojom::CookieAndLineWithAccessResultDataView cookie,
+ net::CookieAndLineWithAccessResult* out);
};
template <>
@@ -211,6 +197,10 @@ struct StructTraits<network::mojom::CookieAccessResultDataView,
const net::CookieAccessResult& c) {
return c.status;
}
+ static const net::CookieAccessSemantics& access_semantics(
+ const net::CookieAccessResult& c) {
+ return c.access_semantics;
+ }
static bool Read(network::mojom::CookieAccessResultDataView access_result,
net::CookieAccessResult* out);
};
@@ -236,9 +226,9 @@ struct StructTraits<network::mojom::CookieChangeInfoDataView,
static const net::CanonicalCookie& cookie(const net::CookieChangeInfo& c) {
return c.cookie;
}
- static net::CookieAccessSemantics access_semantics(
+ static const net::CookieAccessResult& access_result(
const net::CookieChangeInfo& c) {
- return c.access_semantics;
+ return c.access_result;
}
static net::CookieChangeCause cause(const net::CookieChangeInfo& c) {
return c.cause;
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 d3be1aee9de..94a7557da24 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
@@ -92,19 +92,42 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieInclusionStatus) {
&invalid, &copied));
}
-TEST(CookieManagerTraitsTest, Roundtrips_CookieWithStatus) {
+TEST(CookieManagerTraitsTest, Rountrips_CookieAccessResult) {
+ net::CookieAccessResult original = net::CookieAccessResult(
+ net::CookieEffectiveSameSite::LAX_MODE,
+ net::CookieInclusionStatus(
+ net::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX,
+ net::CookieInclusionStatus::
+ WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT),
+ net::CookieAccessSemantics::LEGACY);
+ net::CookieAccessResult copied;
+
+ EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieAccessResult>(
+ &original, &copied));
+
+ EXPECT_EQ(original.effective_same_site, copied.effective_same_site);
+ EXPECT_TRUE(copied.status.HasExactlyExclusionReasonsForTesting(
+ {net::CookieInclusionStatus::
+ EXCLUDE_SAMESITE_UNSPECIFIED_TREATED_AS_LAX}));
+ EXPECT_TRUE(copied.status.HasExactlyWarningReasonsForTesting(
+ {net::CookieInclusionStatus::
+ WARN_SAMESITE_UNSPECIFIED_CROSS_SITE_CONTEXT}));
+}
+
+TEST(CookieManagerTraitsTest, Rountrips_CookieWithAccessResult) {
net::CanonicalCookie original_cookie(
"A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
/* secure = */ true, /* http_only = */ false,
net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
- net::CookieWithStatus original = {original_cookie,
- net::CookieInclusionStatus()};
+ net::CookieWithAccessResult original = {original_cookie,
+ net::CookieAccessResult()};
+ net::CookieWithAccessResult copied;
- net::CookieWithStatus copied;
-
- EXPECT_TRUE(mojo::test::SerializeAndDeserialize<mojom::CookieWithStatus>(
- &original, &copied));
+ EXPECT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::CookieWithAccessResult>(
+ &original, &copied));
EXPECT_EQ(original.cookie.Name(), copied.cookie.Name());
EXPECT_EQ(original.cookie.Value(), copied.cookie.Value());
@@ -117,7 +140,39 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieWithStatus) {
EXPECT_EQ(original.cookie.IsHttpOnly(), copied.cookie.IsHttpOnly());
EXPECT_EQ(original.cookie.SameSite(), copied.cookie.SameSite());
EXPECT_EQ(original.cookie.Priority(), copied.cookie.Priority());
- EXPECT_EQ(original.status, copied.status);
+ EXPECT_EQ(original.access_result.effective_same_site,
+ copied.access_result.effective_same_site);
+ EXPECT_EQ(original.access_result.status, copied.access_result.status);
+}
+
+TEST(CookieManagerTraitsTest, Rountrips_CookieAndLineWithAccessResult) {
+ net::CanonicalCookie original_cookie(
+ "A", "B", "x.y", "/path", base::Time(), base::Time(), base::Time(),
+ /* secure = */ true, /* http_only = */ false,
+ net::CookieSameSite::NO_RESTRICTION, net::COOKIE_PRIORITY_LOW);
+
+ net::CookieAndLineWithAccessResult original(original_cookie, "cookie-string",
+ net::CookieAccessResult());
+ net::CookieAndLineWithAccessResult copied;
+
+ EXPECT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::CookieAndLineWithAccessResult>(
+ &original, &copied));
+
+ EXPECT_EQ(original.cookie->Name(), copied.cookie->Name());
+ EXPECT_EQ(original.cookie->Value(), copied.cookie->Value());
+ EXPECT_EQ(original.cookie->Domain(), copied.cookie->Domain());
+ EXPECT_EQ(original.cookie->Path(), copied.cookie->Path());
+ EXPECT_EQ(original.cookie->CreationDate(), copied.cookie->CreationDate());
+ EXPECT_EQ(original.cookie->LastAccessDate(), copied.cookie->LastAccessDate());
+ EXPECT_EQ(original.cookie->ExpiryDate(), copied.cookie->ExpiryDate());
+ EXPECT_EQ(original.cookie->IsSecure(), copied.cookie->IsSecure());
+ EXPECT_EQ(original.cookie->IsHttpOnly(), copied.cookie->IsHttpOnly());
+ EXPECT_EQ(original.cookie->SameSite(), copied.cookie->SameSite());
+ EXPECT_EQ(original.cookie->Priority(), copied.cookie->Priority());
+ EXPECT_EQ(original.access_result.effective_same_site,
+ copied.access_result.effective_same_site);
+ EXPECT_EQ(original.cookie_string, copied.cookie_string);
}
TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSite) {
@@ -131,6 +186,20 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieSameSite) {
}
}
+TEST(CookieManagerTraitsTest, Roundtrips_CookieEffectiveSameSite) {
+ for (net::CookieEffectiveSameSite cookie_state :
+ {net::CookieEffectiveSameSite::NO_RESTRICTION,
+ net::CookieEffectiveSameSite::LAX_MODE,
+ net::CookieEffectiveSameSite::STRICT_MODE,
+ net::CookieEffectiveSameSite::LAX_MODE_ALLOW_UNSAFE,
+ net::CookieEffectiveSameSite::UNDEFINED}) {
+ net::CookieEffectiveSameSite roundtrip;
+ ASSERT_TRUE(SerializeAndDeserializeEnum<mojom::CookieEffectiveSameSite>(
+ cookie_state, &roundtrip));
+ EXPECT_EQ(cookie_state, roundtrip);
+ }
+}
+
TEST(CookieManagerTraitsTest, Roundtrips_ContextType) {
using ContextType = net::CookieOptions::SameSiteCookieContext::ContextType;
for (ContextType context_type :
@@ -232,9 +301,12 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) {
/* secure = */ false, /* http_only = */ false,
net::CookieSameSite::UNSPECIFIED, net::COOKIE_PRIORITY_LOW);
- net::CookieChangeInfo original(original_cookie,
- net::CookieAccessSemantics::LEGACY,
- net::CookieChangeCause::EXPLICIT);
+ net::CookieChangeInfo original(
+ original_cookie,
+ net::CookieAccessResult(net::CookieEffectiveSameSite::UNDEFINED,
+ net::CookieInclusionStatus(),
+ net::CookieAccessSemantics::LEGACY),
+ net::CookieChangeCause::EXPLICIT);
net::CookieChangeInfo copied;
@@ -252,7 +324,8 @@ TEST(CookieManagerTraitsTest, Roundtrips_CookieChangeInfo) {
EXPECT_EQ(original.cookie.IsHttpOnly(), copied.cookie.IsHttpOnly());
EXPECT_EQ(original.cookie.SameSite(), copied.cookie.SameSite());
EXPECT_EQ(original.cookie.Priority(), copied.cookie.Priority());
- EXPECT_EQ(original.access_semantics, copied.access_semantics);
+ EXPECT_EQ(original.access_result.access_semantics,
+ copied.access_result.access_semantics);
EXPECT_EQ(original.cause, copied.cause);
}
diff --git a/chromium/services/network/public/cpp/cors/cors.cc b/chromium/services/network/public/cpp/cors/cors.cc
index 6e12d8f2970..92a86e4e6d5 100644
--- a/chromium/services/network/public/cpp/cors/cors.cc
+++ b/chromium/services/network/public/cpp/cors/cors.cc
@@ -392,17 +392,9 @@ bool IsCorsSafelistedContentType(const std::string& media_type) {
return IsCorsSafelistedLowerCaseContentType(base::ToLowerASCII(media_type));
}
-bool IsCorsSafelistedHeader(
- const std::string& name,
- const std::string& value,
- const base::flat_set<std::string>& extra_safelisted_header_names) {
+bool IsCorsSafelistedHeader(const std::string& name, const std::string& value) {
const std::string lower_name = base::ToLowerASCII(name);
- if (extra_safelisted_header_names.find(lower_name) !=
- extra_safelisted_header_names.end()) {
- return true;
- }
-
// If |value|’s length is greater than 128, then return false.
if (value.size() > 128)
return false;
@@ -535,8 +527,7 @@ std::vector<std::string> CorsUnsafeRequestHeaderNames(
std::vector<std::string> CorsUnsafeNotForbiddenRequestHeaderNames(
const net::HttpRequestHeaders::HeaderVector& headers,
- bool is_revalidating,
- const base::flat_set<std::string>& extra_safelisted_header_names) {
+ bool is_revalidating) {
std::vector<std::string> header_names;
std::vector<std::string> potentially_unsafe_names;
@@ -555,8 +546,7 @@ std::vector<std::string> CorsUnsafeNotForbiddenRequestHeaderNames(
continue;
}
}
- if (!IsCorsSafelistedHeader(name, header.value,
- extra_safelisted_header_names)) {
+ if (!IsCorsSafelistedHeader(name, header.value)) {
header_names.push_back(name);
} else {
potentially_unsafe_names.push_back(name);
diff --git a/chromium/services/network/public/cpp/cors/cors.h b/chromium/services/network/public/cpp/cors/cors.h
index bd3e9aee232..813abc9022b 100644
--- a/chromium/services/network/public/cpp/cors/cors.h
+++ b/chromium/services/network/public/cpp/cors/cors.h
@@ -108,10 +108,7 @@ bool IsCorsSafelistedMethod(const std::string& method);
COMPONENT_EXPORT(NETWORK_CPP)
bool IsCorsSafelistedContentType(const std::string& name);
COMPONENT_EXPORT(NETWORK_CPP)
-bool IsCorsSafelistedHeader(
- const std::string& name,
- const std::string& value,
- const base::flat_set<std::string>& extra_safelisted_header_names = {});
+bool IsCorsSafelistedHeader(const std::string& name, const std::string& value);
COMPONENT_EXPORT(NETWORK_CPP)
bool IsNoCorsSafelistedHeaderName(const std::string& name);
COMPONENT_EXPORT(NETWORK_CPP)
@@ -138,8 +135,7 @@ std::vector<std::string> CorsUnsafeRequestHeaderNames(
COMPONENT_EXPORT(NETWORK_CPP)
std::vector<std::string> CorsUnsafeNotForbiddenRequestHeaderNames(
const net::HttpRequestHeaders::HeaderVector& headers,
- bool is_revalidating,
- const base::flat_set<std::string>& extra_safelisted_header_names = {});
+ bool is_revalidating);
// Checks forbidden method in the fetch spec.
// See https://fetch.spec.whatwg.org/#forbidden-method.
diff --git a/chromium/services/network/public/cpp/cors/cors_legacy.h b/chromium/services/network/public/cpp/cors/cors_legacy.h
index af6c3bbe553..6da3b705e1b 100644
--- a/chromium/services/network/public/cpp/cors/cors_legacy.h
+++ b/chromium/services/network/public/cpp/cors/cors_legacy.h
@@ -22,12 +22,12 @@ namespace cors {
// TODO(toyoshim): Remove all functions after Network Service is enabled.
namespace legacy {
-// Registers whitelisted secure origins and hostname patterns for CORS checks in
+// Registers allowlisted secure origins and hostname patterns for CORS checks in
// CorsURLLoader.
COMPONENT_EXPORT(NETWORK_CPP)
void RegisterSecureOrigins(const std::vector<std::string>& secure_origins);
-// Refers the registered whitelisted secure origins and hostname patterns.
+// Refers the registered allowlisted secure origins and hostname patterns.
COMPONENT_EXPORT(NETWORK_CPP)
const std::vector<std::string>& GetSecureOrigins();
diff --git a/chromium/services/network/public/cpp/cors/origin_access_list.h b/chromium/services/network/public/cpp/cors/origin_access_list.h
index 4b6b8826fe3..e867106dc65 100644
--- a/chromium/services/network/public/cpp/cors/origin_access_list.h
+++ b/chromium/services/network/public/cpp/cors/origin_access_list.h
@@ -29,7 +29,7 @@ class CorsOriginAccessPatterns;
namespace cors {
// A class to manage origin access allow / block lists. If these lists conflict,
-// blacklisting is respected. These lists are managed per source-origin basis.
+// blocklisting is respected. These lists are managed per source-origin basis.
class COMPONENT_EXPORT(NETWORK_CPP) OriginAccessList {
public:
using CorsOriginPatternPtr = mojo::StructPtr<mojom::CorsOriginPattern>;
diff --git a/chromium/services/network/public/cpp/cors/preflight_result.cc b/chromium/services/network/public/cpp/cors/preflight_result.cc
index fe8e60f917b..022ff804e41 100644
--- a/chromium/services/network/public/cpp/cors/preflight_result.cc
+++ b/chromium/services/network/public/cpp/cors/preflight_result.cc
@@ -144,8 +144,7 @@ base::Optional<CorsErrorStatus> PreflightResult::EnsureAllowedCrossOriginMethod(
base::Optional<CorsErrorStatus>
PreflightResult::EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers,
- bool is_revalidating,
- const base::flat_set<std::string>& extra_safelisted_header_names) const {
+ bool is_revalidating) const {
if (!credentials_ && headers_.find("*") != headers_.end())
return base::nullopt;
@@ -153,8 +152,7 @@ PreflightResult::EnsureAllowedCrossOriginHeaders(
// beforehand. But user-agents may add these headers internally, and it's
// fine.
for (const auto& name : CorsUnsafeNotForbiddenRequestHeaderNames(
- headers.GetHeaderVector(), is_revalidating,
- extra_safelisted_header_names)) {
+ headers.GetHeaderVector(), is_revalidating)) {
// Header list check is performed in case-insensitive way. Here, we have a
// parsed header list set in lower case, and search each header in lower
// case.
diff --git a/chromium/services/network/public/cpp/cors/preflight_result.h b/chromium/services/network/public/cpp/cors/preflight_result.h
index c6ed14f3306..49ef1997066 100644
--- a/chromium/services/network/public/cpp/cors/preflight_result.h
+++ b/chromium/services/network/public/cpp/cors/preflight_result.h
@@ -57,9 +57,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) PreflightResult final {
// JavaScript-initiated requests.
base::Optional<CorsErrorStatus> EnsureAllowedCrossOriginHeaders(
const net::HttpRequestHeaders& headers,
- bool is_revalidating,
- const base::flat_set<std::string>& extra_safelisted_header_names = {})
- const;
+ bool is_revalidating) const;
// Checks if this entry is expired.
bool IsExpired() const;
diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy.cc b/chromium/services/network/public/cpp/cross_origin_opener_policy.cc
index c00cacec0b4..880dd98c33d 100644
--- a/chromium/services/network/public/cpp/cross_origin_opener_policy.cc
+++ b/chromium/services/network/public/cpp/cross_origin_opener_policy.cc
@@ -25,4 +25,17 @@ bool CrossOriginOpenerPolicy::operator==(
report_only_reporting_endpoint == other.report_only_reporting_endpoint;
}
+bool IsAccessFromCoopPage(mojom::CoopAccessReportType type) {
+ switch (type) {
+ case mojom::CoopAccessReportType::kAccessFromCoopPageToOpener:
+ case mojom::CoopAccessReportType::kAccessFromCoopPageToOpenee:
+ case mojom::CoopAccessReportType::kAccessFromCoopPageToOther:
+ return true;
+ case mojom::CoopAccessReportType::kAccessToCoopPageFromOpener:
+ case mojom::CoopAccessReportType::kAccessToCoopPageFromOpenee:
+ case mojom::CoopAccessReportType::kAccessToCoopPageFromOther:
+ return false;
+ }
+}
+
} // namespace network
diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy.h b/chromium/services/network/public/cpp/cross_origin_opener_policy.h
index b41f580e53f..5e4e16a8d22 100644
--- a/chromium/services/network/public/cpp/cross_origin_opener_policy.h
+++ b/chromium/services/network/public/cpp/cross_origin_opener_policy.h
@@ -31,6 +31,9 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) CrossOriginOpenerPolicy final {
base::Optional<std::string> report_only_reporting_endpoint;
};
+COMPONENT_EXPORT(NETWORK_CPP_BASE)
+bool IsAccessFromCoopPage(mojom::CoopAccessReportType);
+
} // namespace network
#endif // SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_OPENER_POLICY_H_
diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc
index 599a0284e20..3d8c8b93b63 100644
--- a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc
+++ b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.cc
@@ -9,7 +9,6 @@
#include "net/http/http_response_headers.h"
#include "net/http/structured_headers.h"
#include "services/network/public/cpp/features.h"
-
namespace network {
namespace {
@@ -50,20 +49,34 @@ ParseHeader(base::StringPiece header_value) {
} // namespace
CrossOriginOpenerPolicy ParseCrossOriginOpenerPolicy(
- const net::HttpResponseHeaders& headers) {
+ const net::HttpResponseHeaders& headers,
+ const CrossOriginEmbedderPolicy& coep) {
CrossOriginOpenerPolicy coop;
+
+ // This is the single line of code disabling COOP globally.
if (!base::FeatureList::IsEnabled(features::kCrossOriginOpenerPolicy))
return coop;
-
+
std::string header_value;
if (headers.GetNormalizedHeader(kCrossOriginOpenerPolicyHeader,
&header_value)) {
std::tie(coop.value, coop.reporting_endpoint) = ParseHeader(header_value);
+ if (coop.value == mojom::CrossOriginOpenerPolicyValue::kSameOrigin &&
+ coep.value == mojom::CrossOriginEmbedderPolicyValue::kRequireCorp)
+ coop.value = mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep;
}
if (headers.GetNormalizedHeader(kCrossOriginOpenerPolicyHeaderReportOnly,
&header_value)) {
std::tie(coop.report_only_value, coop.report_only_reporting_endpoint) =
ParseHeader(header_value);
+ if (coop.report_only_value ==
+ mojom::CrossOriginOpenerPolicyValue::kSameOrigin &&
+ (coep.value == mojom::CrossOriginEmbedderPolicyValue::kRequireCorp ||
+ coep.report_only_value ==
+ mojom::CrossOriginEmbedderPolicyValue::kRequireCorp)) {
+ coop.report_only_value =
+ mojom::CrossOriginOpenerPolicyValue::kSameOriginPlusCoep;
+ }
}
return coop;
}
diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.h b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.h
index b7b4e1ff0f5..caa0c435961 100644
--- a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.h
+++ b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser.h
@@ -5,6 +5,7 @@
#ifndef SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_OPENER_POLICY_PARSER_H_
#define SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_OPENER_POLICY_PARSER_H_
+#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
#include "services/network/public/mojom/cross_origin_opener_policy.mojom.h"
namespace net {
@@ -19,7 +20,8 @@ namespace network {
// services/network/content_security_policy_fuzzer.cc for an example.
COMPONENT_EXPORT(NETWORK_CPP)
CrossOriginOpenerPolicy ParseCrossOriginOpenerPolicy(
- const net::HttpResponseHeaders& headers);
+ const net::HttpResponseHeaders& headers,
+ const CrossOriginEmbedderPolicy& coep);
} // namespace network
diff --git a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc
index 6f4ddcbb701..b84ebbe23e7 100644
--- a/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_origin_opener_policy_parser_unittest.cc
@@ -10,6 +10,7 @@
#include "base/test/scoped_feature_list.h"
#include "net/http/http_response_headers.h"
#include "services/network/public/cpp/features.h"
+#include "services/network/public/mojom/cross_origin_embedder_policy.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@@ -23,123 +24,150 @@ TEST(CrossOriginOpenerPolicyTest, Parse) {
constexpr auto kSameOriginAllowPopups =
CrossOriginOpenerPolicyValue::kSameOriginAllowPopups;
constexpr auto kUnsafeNone = CrossOriginOpenerPolicyValue::kUnsafeNone;
+ constexpr auto kSameOriginPlusCoep =
+ CrossOriginOpenerPolicyValue::kSameOriginPlusCoep;
+ constexpr auto kCoepNone = mojom::CrossOriginEmbedderPolicyValue::kNone;
+ constexpr auto kCoepCorp =
+ mojom::CrossOriginEmbedderPolicyValue::kRequireCorp;
const auto kNoHeader = base::Optional<std::string>();
const auto kNoEndpoint = kNoHeader;
const struct {
base::Optional<std::string> raw_coop_string;
+ mojom::CrossOriginEmbedderPolicyValue coep_value;
base::Optional<std::string> raw_coop_report_only_string;
+ mojom::CrossOriginEmbedderPolicyValue coep_report_only_value;
base::Optional<std::string> expected_endpoint;
CrossOriginOpenerPolicyValue expected_policy;
base::Optional<std::string> expected_endpoit_report_only;
CrossOriginOpenerPolicyValue expected_policy_report_only;
} kTestCases[] = {
- {"same-origin", kNoHeader, kNoEndpoint, kSameOrigin, kNoEndpoint,
- kUnsafeNone},
- {"same-origin-allow-popups", kNoHeader, kNoEndpoint,
+ {"same-origin", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kSameOrigin,
+ kNoEndpoint, kUnsafeNone},
+ {"same-origin-allow-popups", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
- {"unsafe-none", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {"unsafe-none", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Leading whitespaces.
- {" same-origin", kNoHeader, kNoEndpoint, kSameOrigin, kNoEndpoint,
- kUnsafeNone},
+ {" same-origin", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
+ kSameOrigin, kNoEndpoint, kUnsafeNone},
// Leading character tabulation.
- {"\tsame-origin", kNoHeader, kNoEndpoint, kSameOrigin, kNoEndpoint,
- kUnsafeNone},
+ {"\tsame-origin", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
+ kSameOrigin, kNoEndpoint, kUnsafeNone},
// Trailing whitespaces.
- {"same-origin-allow-popups ", kNoHeader, kNoEndpoint,
- kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
+ {"same-origin-allow-popups ", kCoepNone, kNoHeader, kCoepNone,
+ kNoEndpoint, kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
// Empty string.
- {"", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint, kUnsafeNone},
+ {"", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Only whitespaces.
- {" ", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint, kUnsafeNone},
+ {" ", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Invalid same-site value
- {"same-site", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {"same-site", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Misspelling.
- {"some-origin", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {"some-origin", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Trailing line-tab.
- {"same-origin\x0B", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {"same-origin\x0B", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
+ kUnsafeNone, kNoEndpoint, kUnsafeNone},
// Adding report endpoint.
- {"same-origin; report-to=\"endpoint\"", kNoHeader, "endpoint",
- kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=\"endpoint\"", kCoepNone, kNoHeader, kCoepNone,
+ "endpoint", kSameOrigin, kNoEndpoint, kUnsafeNone},
// Extraneous parameter, ignored.
- {"same-origin; report-to=\"endpoint\"; foo=bar", kNoHeader, "endpoint",
- kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=\"endpoint\"; foo=bar", kCoepNone, kNoHeader,
+ kCoepNone, "endpoint", kSameOrigin, kNoEndpoint, kUnsafeNone},
// Multiple endpoints
- {"same-origin; report-to=\"endpoint\"; report-to=\"foo\"", kNoHeader,
- "foo", kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=\"endpoint\"; report-to=\"foo\"", kCoepNone,
+ kNoHeader, kCoepNone, "foo", kSameOrigin, kNoEndpoint, kUnsafeNone},
// Leading spaces in the reporting endpoint.
- {"same-origin-allow-popups; report-to=\"endpoint\"", kNoHeader,
- "endpoint", kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
+ {"same-origin-allow-popups; report-to=\"endpoint\"", kCoepNone,
+ kNoHeader, kCoepNone, "endpoint", kSameOriginAllowPopups, kNoEndpoint,
+ kUnsafeNone},
// Unsafe-none with endpoint.
- {"unsafe-none; report-to=\"endpoint\"", kNoHeader, "endpoint",
- kUnsafeNone, kNoEndpoint, kUnsafeNone},
+ {"unsafe-none; report-to=\"endpoint\"", kCoepNone, kNoHeader, kCoepNone,
+ "endpoint", kUnsafeNone, kNoEndpoint, kUnsafeNone},
// Unknown parameters should just be ignored.
- {"same-origin; invalidparameter=\"unknown\"", kNoHeader, kNoEndpoint,
- kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; invalidparameter=\"unknown\"", kCoepNone, kNoHeader,
+ kCoepNone, kNoEndpoint, kSameOrigin, kNoEndpoint, kUnsafeNone},
// Non-string report-to value.
- {"same-origin; report-to=other-endpoint", kNoHeader, kNoEndpoint,
- kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=other-endpoint", kCoepNone, kNoHeader, kCoepNone,
+ kNoEndpoint, kSameOrigin, kNoEndpoint, kUnsafeNone},
// Malformated parameter value.
- {"same-origin-allow-popups; foo", kNoHeader, kNoEndpoint,
- kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
+ {"same-origin-allow-popups; foo", kCoepNone, kNoHeader, kCoepNone,
+ kNoEndpoint, kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
// Report to empty string endpoint.
- {"same-origin; report-to=\"\"", kNoHeader, "", kSameOrigin, kNoEndpoint,
- kUnsafeNone},
+ {"same-origin; report-to=\"\"", kCoepNone, kNoHeader, kCoepNone, "",
+ kSameOrigin, kNoEndpoint, kUnsafeNone},
// Empty parameter value, parsing fails.
- {"same-origin; report-to=", kNoHeader, kNoEndpoint, kUnsafeNone,
- kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
+ kUnsafeNone, kNoEndpoint, kUnsafeNone},
// Empty parameter key, parsing fails.
- {"same-origin; =\"\"", kNoHeader, kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {"same-origin; =\"\"", kCoepNone, kNoHeader, kCoepNone, kNoEndpoint,
+ kUnsafeNone, kNoEndpoint, kUnsafeNone},
// Report only same origin header.
- {kNoHeader, "same-origin", kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kSameOrigin},
+ {kNoHeader, kCoepNone, "same-origin", kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kSameOrigin},
// Report only header.
- {kNoHeader, "same-origin-allow-popups", kNoEndpoint, kUnsafeNone,
- kNoEndpoint, kSameOriginAllowPopups},
+ {kNoHeader, kCoepNone, "same-origin-allow-popups", kCoepNone, kNoEndpoint,
+ kUnsafeNone, kNoEndpoint, kSameOriginAllowPopups},
// Report only header.
- {kNoHeader, "unsafe-none", kNoEndpoint, kUnsafeNone, kNoEndpoint,
- kUnsafeNone},
+ {kNoHeader, kCoepNone, "unsafe-none", kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kUnsafeNone},
// Report only same origin header with endpoint.
- {kNoHeader, "same-origin; report-to=\"endpoint\"", kNoEndpoint,
- kUnsafeNone, "endpoint", kSameOrigin},
+ {kNoHeader, kCoepNone, "same-origin; report-to=\"endpoint\"", kCoepNone,
+ kNoEndpoint, kUnsafeNone, "endpoint", kSameOrigin},
// Report only allow popups with endpoint.
- {kNoHeader, "same-origin-allow-popups; report-to=\"endpoint\"",
- kNoEndpoint, kUnsafeNone, "endpoint", kSameOriginAllowPopups},
+ {kNoHeader, kCoepNone, "same-origin-allow-popups; report-to=\"endpoint\"",
+ kCoepNone, kNoEndpoint, kUnsafeNone, "endpoint", kSameOriginAllowPopups},
// Report only unsafe none with endpoint.
- {kNoHeader, "unsafe-none; report-to=\"endpoint\" ", kNoEndpoint,
- kUnsafeNone, "endpoint", kUnsafeNone},
+ {kNoHeader, kCoepNone, "unsafe-none; report-to=\"endpoint\" ", kCoepNone,
+ kNoEndpoint, kUnsafeNone, "endpoint", kUnsafeNone},
// Invalid COOP header with valid COOP report only.
- {"INVALID HEADER", "same-origin; report-to=\"endpoint\"", kNoEndpoint,
- kUnsafeNone, "endpoint", kSameOrigin},
+ {"INVALID HEADER", kCoepNone, "same-origin; report-to=\"endpoint\"",
+ kCoepNone, kNoEndpoint, kUnsafeNone, "endpoint", kSameOrigin},
// Unsafe none COOP and allow popups COOP report only.
- {"unsafe-none", "same-origin-allow-popups; report-to=\"endpoint\"",
+ {"unsafe-none", kCoepNone,
+ "same-origin-allow-popups; report-to=\"endpoint\"", kCoepNone,
kNoEndpoint, kUnsafeNone, "endpoint", kSameOriginAllowPopups},
// Same-origin-allow-popups coop + same-origin report-only.
- {"same-origin-allow-popups", "same-origin; report-to=\"endpoint\" ",
- kNoEndpoint, kSameOriginAllowPopups, "endpoint", kSameOrigin},
+ {"same-origin-allow-popups", kCoepNone,
+ "same-origin; report-to=\"endpoint\" ", kCoepNone, kNoEndpoint,
+ kSameOriginAllowPopups, "endpoint", kSameOrigin},
// Same-origin-allow-popups coop + same-origin report-only, with reporting
// on both.
- {"same-origin-allow-popups; report-to=\"endpointA\"",
- "same-origin; report-to=\"endpointB\" ", "endpointA",
+ {"same-origin-allow-popups; report-to=\"endpointA\"", kCoepNone,
+ "same-origin; report-to=\"endpointB\" ", kCoepNone, "endpointA",
kSameOriginAllowPopups, "endpointB", kSameOrigin},
// Same-origin-allow-popups coop + same-origin report-only, with reporting
// on both, same endpoint.
- {"same-origin-allow-popups; report-to=\"endpoint\"",
- "same-origin; report-to=\"endpoint\" ", "endpoint",
+ {"same-origin-allow-popups; report-to=\"endpoint\"", kCoepNone,
+ "same-origin; report-to=\"endpoint\" ", kCoepNone, "endpoint",
kSameOriginAllowPopups, "endpoint", kSameOrigin},
// Unsafe coop + same-origin report-only, with reporting on both.
- {"unsafe-none; report-to=\"endpoint\"",
- "same-origin; report-to=\"endpoint\" ", "endpoint", kUnsafeNone,
- "endpoint", kSameOrigin},
+ {"unsafe-none; report-to=\"endpoint\"", kCoepNone,
+ "same-origin; report-to=\"endpoint\" ", kCoepNone, "endpoint",
+ kUnsafeNone, "endpoint", kSameOrigin},
// Same-origin with reporting COOP, invalid COOP report-only.
- {"same-origin; report-to=\"endpoint\"", "INVALID HEADER", "endpoint",
- kSameOrigin, kNoEndpoint, kUnsafeNone},
+ {"same-origin; report-to=\"endpoint\"", kCoepNone, "INVALID HEADER",
+ kCoepNone, "endpoint", kSameOrigin, kNoEndpoint, kUnsafeNone},
+ // Same-origin with COEP
+ {"same-origin", kCoepCorp, kNoHeader, kCoepNone, kNoEndpoint,
+ kSameOriginPlusCoep, kNoEndpoint, kUnsafeNone},
+ // Same-origin-allow-popups with COEP
+ {"same-origin-allow-popups", kCoepCorp, kNoHeader, kCoepNone, kNoEndpoint,
+ kSameOriginAllowPopups, kNoEndpoint, kUnsafeNone},
+ // Same-origin with report only COEP
+ {"same-origin", kCoepNone, kNoHeader, kCoepCorp, kNoEndpoint, kSameOrigin,
+ kNoEndpoint, kUnsafeNone},
+ // reporting Same-origin with COEP
+ {kNoHeader, kCoepCorp, "same-origin", kCoepNone, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kSameOriginPlusCoep},
+ // reporting Same-origin with reporting COEP
+ {kNoHeader, kCoepNone, "same-origin", kCoepCorp, kNoEndpoint, kUnsafeNone,
+ kNoEndpoint, kSameOriginPlusCoep},
};
for (const auto& test_case : kTestCases) {
@@ -164,7 +192,11 @@ TEST(CrossOriginOpenerPolicyTest, Parse) {
headers->AddHeader("cross-origin-opener-policy-report-only",
*test_case.raw_coop_report_only_string);
}
- auto parsed_policy = ParseCrossOriginOpenerPolicy(*headers);
+ network::CrossOriginEmbedderPolicy coep;
+ coep.value = test_case.coep_value;
+ coep.report_only_value = test_case.coep_report_only_value;
+
+ auto parsed_policy = ParseCrossOriginOpenerPolicy(*headers, coep);
EXPECT_EQ(test_case.expected_endpoint, parsed_policy.reporting_endpoint);
EXPECT_EQ(test_case.expected_policy, parsed_policy.value);
EXPECT_EQ(test_case.expected_endpoit_report_only,
diff --git a/chromium/services/network/cross_origin_read_blocking.cc b/chromium/services/network/public/cpp/cross_origin_read_blocking.cc
index c0eb842c5bc..5892de9625e 100644
--- a/chromium/services/network/cross_origin_read_blocking.cc
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking.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/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
#include <stddef.h>
@@ -137,7 +137,8 @@ size_t FindFirstJavascriptLineTerminator(const base::StringPiece& hay,
// TODO(lukasza): Prevent matching 3 bytes that span/straddle 2 UTF8
// characters.
base::StringPiece substr = hay.substr(pos);
- if (substr.starts_with("\u2028") || substr.starts_with("\u2029"))
+ if (base::StartsWith(substr, "\u2028") ||
+ base::StartsWith(substr, "\u2029"))
break;
pos++; // Skip the \xe2 character.
@@ -158,8 +159,8 @@ size_t FindFirstJavascriptLineTerminator(const base::StringPiece& hay,
// terminating character.
SniffingResult MaybeSkipHtmlComment(StringPiece* data) {
constexpr StringPiece kStartString = "<!--";
- if (!data->starts_with(kStartString)) {
- if (kStartString.starts_with(*data))
+ if (!base::StartsWith(*data, kStartString)) {
+ if (base::StartsWith(kStartString, *data))
return CrossOriginReadBlocking::kMaybe;
return CrossOriginReadBlocking::kNo;
}
@@ -220,11 +221,6 @@ void BlockResponseHeaders(
headers->RemoveHeaders(names_of_headers_to_remove);
}
-std::set<int>& GetPluginProxyingProcesses() {
- static base::NoDestructor<std::set<int>> set;
- return *set;
-}
-
// The function below returns a set of MIME types below may be blocked by CORB
// without any confirmation sniffing (in contrast to HTML/JSON/XML which require
// confirmation sniffing because images, scripts, etc. are frequently
@@ -257,7 +253,7 @@ base::flat_set<std::string>& GetNeverSniffedMimeTypes() {
// The types below (zip, protobuf, etc.) are based on most commonly used
// content types according to HTTP Archive - see:
// https://github.com/whatwg/fetch/issues/860#issuecomment-457330454
- "application/gzip",
+ "application/gzip",
"application/x-gzip",
"application/x-protobuf",
"application/zip",
@@ -325,6 +321,7 @@ base::flat_set<std::string>& GetNeverSniffedMimeTypes() {
} // namespace
+// static
MimeType CrossOriginReadBlocking::GetCanonicalMimeType(
base::StringPiece mime_type) {
// Checking for image/svg+xml and application/dash+xml early ensures that they
@@ -365,6 +362,7 @@ MimeType CrossOriginReadBlocking::GetCanonicalMimeType(
return MimeType::kOthers;
}
+// static
bool CrossOriginReadBlocking::IsBlockableScheme(const GURL& url) {
// We exclude ftp:// from here. FTP doesn't provide a Content-Type
// header which our policy depends on, so we cannot protect any
@@ -372,6 +370,7 @@ bool CrossOriginReadBlocking::IsBlockableScheme(const GURL& url) {
return url.SchemeIs(url::kHttpScheme) || url.SchemeIs(url::kHttpsScheme);
}
+// static
bool CrossOriginReadBlocking::IsValidCorsHeaderSet(
const url::Origin& frame_origin,
const std::string& access_control_origin) {
@@ -395,6 +394,7 @@ bool CrossOriginReadBlocking::IsValidCorsHeaderSet(
url::Origin::Create(GURL(access_control_origin)));
}
+// static
// This function is a slight modification of |net::SniffForHTML|.
SniffingResult CrossOriginReadBlocking::SniffForHTML(StringPiece data) {
// The content sniffers used by Chrome and Firefox are using "<!--" as one of
@@ -446,6 +446,7 @@ SniffingResult CrossOriginReadBlocking::SniffForHTML(StringPiece data) {
return kMaybe;
}
+// static
SniffingResult CrossOriginReadBlocking::SniffForXML(base::StringPiece data) {
// TODO(dsjang): Once CrossOriginReadBlocking is moved into the browser
// process, we should do single-thread checking here for the static
@@ -456,6 +457,7 @@ SniffingResult CrossOriginReadBlocking::SniffForXML(base::StringPiece data) {
base::CompareCase::SENSITIVE);
}
+// static
SniffingResult CrossOriginReadBlocking::SniffForJSON(base::StringPiece data) {
// Currently this function looks for an opening brace ('{'), followed by a
// double-quoted string literal, followed by a colon. Importantly, such a
@@ -518,6 +520,7 @@ SniffingResult CrossOriginReadBlocking::SniffForJSON(base::StringPiece data) {
return kMaybe;
}
+// static
SniffingResult CrossOriginReadBlocking::SniffForFetchOnlyResource(
base::StringPiece data) {
// kScriptBreakingPrefixes contains prefixes that are conventionally used to
@@ -659,7 +662,7 @@ CrossOriginReadBlocking::ResponseAnalyzer::ResponseAnalyzer(
const GURL& request_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
mojom::RequestMode request_mode,
const base::Optional<url::Origin>& isolated_world_origin,
mojom::NetworkServiceClient* network_service_client)
@@ -696,7 +699,7 @@ CrossOriginReadBlocking::ResponseAnalyzer::ResponseAnalyzer(
should_block_based_on_headers_ = ShouldBlockBasedOnHeaders(
request_mode, request_url, request_initiator, response,
- request_initiator_site_lock, canonical_mime_type_,
+ request_initiator_origin_lock, canonical_mime_type_,
&is_cors_blocking_expected_);
// Check if the response seems sensitive and if so include in our CORB
@@ -744,7 +747,7 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
const GURL& request_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
MimeType canonical_mime_type,
bool* is_cors_blocking_expected) {
if (is_cors_blocking_expected)
@@ -760,7 +763,7 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
// unique origin makes CORB treat the response as cross-origin and thus
// considers it eligible for blocking (based on content-type, sniffing, etc.).
url::Origin initiator =
- GetTrustworthyInitiator(request_initiator_site_lock, request_initiator);
+ GetTrustworthyInitiator(request_initiator_origin_lock, request_initiator);
// Don't block same-origin documents.
if (initiator.IsSameOriginWith(target_origin))
@@ -842,13 +845,13 @@ CrossOriginReadBlocking::ResponseAnalyzer::ShouldBlockBasedOnHeaders(
// block will no longer be necessary since all failed CORS requests will be
// blocked before reaching the renderer process (even without CORB's help).
// Of course this assumes that OOR-CORS will use trustworthy
- // |request_initiator| (i.e. vetted against |request_initiator|site_lock|).
+ // |request_initiator| (i.e. vetted against |request_initiator_origin_lock|).
constexpr mojom::RequestMode kOverreachingRequestMode =
mojom::RequestMode::kNoCors;
// COEP is not supported when OOR-CORS is disabled.
if (CrossOriginResourcePolicy::IsBlocked(
request_url, request_url, request_initiator, response,
- kOverreachingRequestMode, request_initiator_site_lock,
+ kOverreachingRequestMode, request_initiator_origin_lock,
CrossOriginEmbedderPolicy())) {
// Ignore mime types and/or sniffing and have CORB block all responses with
// COR*P* header.
@@ -1333,22 +1336,4 @@ void CrossOriginReadBlocking::ResponseAnalyzer::LogSensitiveResponseProtection(
supports_range_requests_);
}
-// static
-void CrossOriginReadBlocking::AddExceptionForPlugin(int process_id) {
- std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
- plugin_proxies.insert(process_id);
-}
-
-// static
-bool CrossOriginReadBlocking::ShouldAllowForPlugin(int process_id) {
- std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
- return base::Contains(plugin_proxies, process_id);
-}
-
-// static
-void CrossOriginReadBlocking::RemoveExceptionForPlugin(int process_id) {
- std::set<int>& plugin_proxies = GetPluginProxyingProcesses();
- plugin_proxies.erase(process_id);
-}
-
} // namespace network
diff --git a/chromium/services/network/cross_origin_read_blocking.h b/chromium/services/network/public/cpp/cross_origin_read_blocking.h
index 6538b0ff89f..5dcdd0e4579 100644
--- a/chromium/services/network/cross_origin_read_blocking.h
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking.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_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
-#define SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
#include <memory>
#include <string>
@@ -37,7 +37,7 @@ class NetworkServiceClient;
// steal private information from other sites. For more details see
// services/network/cross_origin_read_blocking_explainer.md
-class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
+class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginReadBlocking {
public:
// This enum describes how CORB should decide whether to block a given
// no-cors, cross-origin response.
@@ -73,7 +73,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
// An instance for tracking the state of analyzing a single response
// and deciding whether CORB should block the response.
- class COMPONENT_EXPORT(NETWORK_SERVICE) ResponseAnalyzer {
+ class COMPONENT_EXPORT(NETWORK_CPP) ResponseAnalyzer {
public:
// Categorizes the resource MIME type for CORB protection logging.
enum MimeTypeBucket {
@@ -115,7 +115,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
const GURL& request_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
mojom::RequestMode request_mode,
const base::Optional<url::Origin>& isolated_world_origin,
mojom::NetworkServiceClient* network_service_client);
@@ -197,7 +197,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
const GURL& request_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
MimeType canonical_mime_type,
bool* is_cors_blocking_expected);
@@ -334,23 +334,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) CrossOriginReadBlocking {
kYes,
};
- // Notifies CORB that |process_id| is proxying requests on behalf of a
- // universal-access plugin and therefore CORB should stop blocking requests
- // marked as ResourceType::kPluginResource.
- //
- // TODO(lukasza, laforge): https://crbug.com/702995: Remove the static
- // ...ForPlugin methods once Flash support is removed from Chromium (probably
- // around 2020 - see https://www.chromium.org/flash-roadmap).
- static void AddExceptionForPlugin(int process_id);
-
- // Returns true if CORB should ignore a request initiated by a universal
- // access plugin - i.e. if |process_id| has been previously passed to
- // AddExceptionForPlugin.
- static bool ShouldAllowForPlugin(int process_id);
-
- // Reverts AddExceptionForPlugin.
- static void RemoveExceptionForPlugin(int process_id);
-
private:
CrossOriginReadBlocking(); // Not instantiable.
@@ -406,4 +389,4 @@ inline std::ostream& operator<<(
} // namespace network
-#endif // SERVICES_NETWORK_CROSS_ORIGIN_READ_BLOCKING_H_
+#endif // SERVICES_NETWORK_PUBLIC_CPP_CROSS_ORIGIN_READ_BLOCKING_H_
diff --git a/chromium/services/network/cross_origin_read_blocking_unittest.cc b/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
index 5fd359aec28..d7638788cb5 100644
--- a/chromium/services/network/cross_origin_read_blocking_unittest.cc
+++ b/chromium/services/network/public/cpp/cross_origin_read_blocking_unittest.cc
@@ -20,7 +20,7 @@
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_test_util.h"
-#include "services/network/cross_origin_read_blocking.h"
+#include "services/network/public/cpp/cross_origin_read_blocking.h"
#include "services/network/public/mojom/url_response_head.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -2028,15 +2028,15 @@ class ResponseAnalyzerTest : public testing::Test,
// Create the site lock, which may differ from the initiator origin or be
// empty.
- base::Optional<url::Origin> request_initiator_site_lock;
+ base::Optional<url::Origin> request_initiator_origin_lock;
if (strlen(scenario.initiator_site_lock) > 0)
- request_initiator_site_lock =
+ request_initiator_origin_lock =
url::Origin::Create(GURL(scenario.initiator_site_lock));
// Create a ResponseAnalyzer to test.
analyzer_ = std::make_unique<ResponseAnalyzer>(
request->url(), request->initiator(), response,
- request_initiator_site_lock, request_mode,
+ request_initiator_origin_lock, request_mode,
base::nullopt /* isolated_world_origin */,
nullptr /* network_service_client */);
diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
index 52fbbfe08c8..cd2b23c6905 100644
--- a/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
+++ b/chromium/services/network/public/cpp/cross_origin_resource_policy.cc
@@ -143,7 +143,7 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternal(
const GURL& request_url,
const base::Optional<url::Origin>& request_initiator,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
mojom::CrossOriginEmbedderPolicyValue embedder_policy) {
// COEP https://mikewest.github.io/corpp/#corp-check
bool upgrade_to_same_origin = false;
@@ -172,7 +172,7 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternal(
// origin, then return allowed.
url::Origin target_origin = url::Origin::Create(request_url);
url::Origin initiator =
- GetTrustworthyInitiator(request_initiator_site_lock, request_initiator);
+ GetTrustworthyInitiator(request_initiator_origin_lock, request_initiator);
if (initiator == target_origin)
return base::nullopt;
@@ -207,7 +207,7 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternalWithReporting(
const GURL& original_url,
const base::Optional<url::Origin>& request_initiator,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter) {
constexpr auto kBlockedDueToCoep = mojom::BlockedByResponseReason::
@@ -217,7 +217,7 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternalWithReporting(
reporter) {
const auto result = IsBlockedInternal(
policy, request_url, request_initiator, request_mode,
- request_initiator_site_lock, embedder_policy.report_only_value);
+ request_initiator_origin_lock, embedder_policy.report_only_value);
UMA_HISTOGRAM_ENUMERATION(
"NetworkService.CrossOriginResourcePolicy.ReportOnlyResult",
ToCorpResult(result));
@@ -234,7 +234,7 @@ base::Optional<mojom::BlockedByResponseReason> IsBlockedInternalWithReporting(
const auto result =
IsBlockedInternal(policy, request_url, request_initiator, request_mode,
- request_initiator_site_lock, embedder_policy.value);
+ request_initiator_origin_lock, embedder_policy.value);
UMA_HISTOGRAM_ENUMERATION("NetworkService.CrossOriginResourcePolicy.Result",
ToCorpResult(result));
if (reporter &&
@@ -259,7 +259,7 @@ CrossOriginResourcePolicy::IsBlocked(
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter) {
// From https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header:
@@ -279,7 +279,7 @@ CrossOriginResourcePolicy::IsBlocked(
return IsBlockedInternalWithReporting(
policy, request_url, original_url, request_initiator, request_mode,
- request_initiator_site_lock, embedder_policy, reporter);
+ request_initiator_origin_lock, embedder_policy, reporter);
}
// static
@@ -290,7 +290,7 @@ CrossOriginResourcePolicy::IsBlockedByHeaderValue(
const base::Optional<url::Origin>& request_initiator,
base::Optional<std::string> corp_header_value,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter) {
// From https://fetch.spec.whatwg.org/#cross-origin-resource-policy-header:
@@ -302,7 +302,7 @@ CrossOriginResourcePolicy::IsBlockedByHeaderValue(
return IsBlockedInternalWithReporting(
policy, request_url, original_url, request_initiator, request_mode,
- request_initiator_site_lock, embedder_policy, reporter);
+ request_initiator_origin_lock, embedder_policy, reporter);
}
// static
@@ -312,7 +312,7 @@ CrossOriginResourcePolicy::IsNavigationBlocked(
const GURL& original_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter) {
ParsedHeader policy =
@@ -320,7 +320,7 @@ CrossOriginResourcePolicy::IsNavigationBlocked(
return IsBlockedInternalWithReporting(
policy, request_url, original_url, request_initiator,
- mojom::RequestMode::kNavigate, request_initiator_site_lock,
+ mojom::RequestMode::kNavigate, request_initiator_origin_lock,
embedder_policy, reporter);
}
diff --git a/chromium/services/network/public/cpp/cross_origin_resource_policy.h b/chromium/services/network/public/cpp/cross_origin_resource_policy.h
index f1ad4c3bcf6..0d7829faf1f 100644
--- a/chromium/services/network/public/cpp/cross_origin_resource_policy.h
+++ b/chromium/services/network/public/cpp/cross_origin_resource_policy.h
@@ -45,7 +45,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
WARN_UNUSED_RESULT;
@@ -58,7 +58,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
const base::Optional<url::Origin>& request_initiator,
base::Optional<std::string> corp_header_value,
mojom::RequestMode request_mode,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr)
WARN_UNUSED_RESULT;
@@ -70,7 +70,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) CrossOriginResourcePolicy {
const GURL& original_url,
const base::Optional<url::Origin>& request_initiator,
const network::mojom::URLResponseHead& response,
- base::Optional<url::Origin> request_initiator_site_lock,
+ base::Optional<url::Origin> request_initiator_origin_lock,
const CrossOriginEmbedderPolicy& embedder_policy,
mojom::CrossOriginEmbedderPolicyReporter* reporter = nullptr);
diff --git a/chromium/services/network/public/cpp/data_element.cc b/chromium/services/network/public/cpp/data_element.cc
index 9a959842e9d..4a09cb877c6 100644
--- a/chromium/services/network/public/cpp/data_element.cc
+++ b/chromium/services/network/public/cpp/data_element.cc
@@ -77,6 +77,13 @@ void DataElement::SetToChunkedDataPipe(
chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
}
+void DataElement::SetToReadOnceStream(
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+ chunked_data_pipe_getter) {
+ type_ = mojom::DataElementType::kReadOnceStream;
+ chunked_data_pipe_getter_ = std::move(chunked_data_pipe_getter);
+}
+
base::File DataElement::ReleaseFile() {
return std::move(file_);
}
@@ -103,7 +110,9 @@ mojo::PendingRemote<mojom::DataPipeGetter> DataElement::CloneDataPipeGetter()
mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
DataElement::ReleaseChunkedDataPipeGetter() {
- DCHECK_EQ(mojom::DataElementType::kChunkedDataPipe, type_);
+ DCHECK(type_ == mojom::DataElementType::kChunkedDataPipe ||
+ type_ == mojom::DataElementType::kReadOnceStream)
+ << type_;
return std::move(chunked_data_pipe_getter_);
}
@@ -138,6 +147,9 @@ void PrintTo(const DataElement& x, std::ostream* os) {
case mojom::DataElementType::kChunkedDataPipe:
*os << "TYPE_CHUNKED_DATA_PIPE";
break;
+ case mojom::DataElementType::kReadOnceStream:
+ *os << "TYPE_READ_ONCE_STREAM";
+ break;
case mojom::DataElementType::kUnknown:
*os << "TYPE_UNKNOWN";
break;
@@ -164,6 +176,8 @@ bool operator==(const DataElement& a, const DataElement& b) {
return false;
case mojom::DataElementType::kChunkedDataPipe:
return false;
+ case mojom::DataElementType::kReadOnceStream:
+ return false;
case mojom::DataElementType::kUnknown:
NOTREACHED();
return false;
diff --git a/chromium/services/network/public/cpp/data_element.h b/chromium/services/network/public/cpp/data_element.h
index 26d0f4fc4fe..ed2eed4a3d8 100644
--- a/chromium/services/network/public/cpp/data_element.h
+++ b/chromium/services/network/public/cpp/data_element.h
@@ -169,6 +169,10 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) DataElement {
// server known to support chunked uploads.
void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
chunked_data_pipe_getter);
+ // Almost same as above except |chunked_data_pipe_getter| is read only once
+ // and you must talk with a server supporting chunked upload.
+ void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+ chunked_data_pipe_getter);
// Takes ownership of the File, if this is of TYPE_RAW_FILE. The file is open
// for reading (asynchronous reading on Windows).
diff --git a/chromium/services/network/public/cpp/empty_url_loader_client.cc b/chromium/services/network/public/cpp/empty_url_loader_client.cc
index 6d869d05675..ded2ca53f31 100644
--- a/chromium/services/network/public/cpp/empty_url_loader_client.cc
+++ b/chromium/services/network/public/cpp/empty_url_loader_client.cc
@@ -26,7 +26,7 @@ EmptyURLLoaderClientWrapper::EmptyURLLoaderClientWrapper(
mojo::PendingRemote<mojom::URLLoader> url_loader)
: receiver_(&client_, std::move(receiver)),
url_loader_(std::move(url_loader)) {
- client_.Drain(base::BindOnce(&EmptyURLLoaderClientWrapper::DeleteSelf,
+ client_.Drain(base::BindOnce(&EmptyURLLoaderClientWrapper::DidDrain,
base::Unretained(this)));
receiver_.set_disconnect_handler(base::BindOnce(
&EmptyURLLoaderClientWrapper::DeleteSelf, base::Unretained(this)));
@@ -34,6 +34,11 @@ EmptyURLLoaderClientWrapper::EmptyURLLoaderClientWrapper(
EmptyURLLoaderClientWrapper::~EmptyURLLoaderClientWrapper() = default;
+void EmptyURLLoaderClientWrapper::DidDrain(
+ const network::URLLoaderCompletionStatus& status) {
+ DeleteSelf();
+}
+
void EmptyURLLoaderClientWrapper::DeleteSelf() {
delete this;
}
@@ -41,15 +46,16 @@ void EmptyURLLoaderClientWrapper::DeleteSelf() {
EmptyURLLoaderClient::EmptyURLLoaderClient() = default;
EmptyURLLoaderClient::~EmptyURLLoaderClient() = default;
-void EmptyURLLoaderClient::Drain(base::OnceClosure callback) {
+void EmptyURLLoaderClient::Drain(
+ base::OnceCallback<void(const URLLoaderCompletionStatus&)> callback) {
DCHECK(!callback_);
callback_ = std::move(callback);
MaybeDone();
}
void EmptyURLLoaderClient::MaybeDone() {
- if (done_ && callback_)
- std::move(callback_).Run();
+ if (done_status_ && callback_)
+ std::move(callback_).Run(*done_status_);
}
void EmptyURLLoaderClient::OnReceiveResponse(
@@ -77,7 +83,7 @@ void EmptyURLLoaderClient::OnStartLoadingResponseBody(
}
void EmptyURLLoaderClient::OnComplete(const URLLoaderCompletionStatus& status) {
- done_ = true;
+ done_status_ = status;
MaybeDone();
}
diff --git a/chromium/services/network/public/cpp/empty_url_loader_client.h b/chromium/services/network/public/cpp/empty_url_loader_client.h
index bcff77f086d..5a0947260c7 100644
--- a/chromium/services/network/public/cpp/empty_url_loader_client.h
+++ b/chromium/services/network/public/cpp/empty_url_loader_client.h
@@ -14,6 +14,7 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "mojo/public/cpp/system/data_pipe_drainer.h"
+#include "services/network/public/cpp/url_loader_completion_status.h"
#include "services/network/public/mojom/url_loader.mojom.h"
namespace network {
@@ -27,7 +28,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) EmptyURLLoaderClient
~EmptyURLLoaderClient() override;
// Calls |callback| when the request is done.
- void Drain(base::OnceClosure callback);
+ void Drain(base::OnceCallback<void(const URLLoaderCompletionStatus&)>);
private:
void MaybeDone();
@@ -51,8 +52,8 @@ class COMPONENT_EXPORT(NETWORK_CPP) EmptyURLLoaderClient
std::unique_ptr<mojo::DataPipeDrainer> response_body_drainer_;
- bool done_ = false;
- base::OnceClosure callback_;
+ base::Optional<URLLoaderCompletionStatus> done_status_;
+ base::OnceCallback<void(const URLLoaderCompletionStatus&)> callback_;
DISALLOW_COPY_AND_ASSIGN(EmptyURLLoaderClient);
};
@@ -75,6 +76,7 @@ class COMPONENT_EXPORT(NETWORK_CPP) EmptyURLLoaderClientWrapper {
mojo::PendingReceiver<mojom::URLLoaderClient> receiver,
mojo::PendingRemote<mojom::URLLoader> url_loader);
+ void DidDrain(const network::URLLoaderCompletionStatus& status);
void DeleteSelf();
EmptyURLLoaderClient client_;
diff --git a/chromium/services/network/public/cpp/features.cc b/chromium/services/network/public/cpp/features.cc
index 7ea2ac326c8..422dac7aba9 100644
--- a/chromium/services/network/public/cpp/features.cc
+++ b/chromium/services/network/public/cpp/features.cc
@@ -56,7 +56,7 @@ const base::Feature kDelayRequestsOnMultiplexedConnections{
// When kRequestInitiatorSiteLock is enabled, then CORB, CORP and Sec-Fetch-Site
// will validate network::ResourceRequest::request_initiator against
-// network::mojom::URLLoaderFactoryParams::request_initiator_site_lock.
+// network::mojom::URLLoaderFactoryParams::request_initiator_origin_lock.
const base::Feature kRequestInitiatorSiteLock{"RequestInitiatorSiteLock",
base::FEATURE_ENABLED_BY_DEFAULT};
@@ -84,17 +84,15 @@ const base::Feature kProactivelyThrottleLowPriorityRequests{
// Enables Cross-Origin Opener Policy (COOP).
// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
-// Currently this feature is enabled for all platforms except WebView. It is not
-// possible to distinguish between Android and WebView here, so we enable the
-// feature on Android via finch.
-const base::Feature kCrossOriginOpenerPolicy {
- "CrossOriginOpenerPolicy",
-#if defined(OS_ANDROID)
- base::FEATURE_DISABLED_BY_DEFAULT
-#else
- base::FEATURE_ENABLED_BY_DEFAULT
-#endif
-};
+// Currently this feature is enabled for all platforms except WebView.
+const base::Feature kCrossOriginOpenerPolicy{"CrossOriginOpenerPolicy",
+ base::FEATURE_ENABLED_BY_DEFAULT};
+
+// Enables Cross-Origin-Opener-Policy reporting API origin trial. It will be
+// used as a kill switch during the experiment.
+const base::Feature kCrossOriginOpenerPolicyReportingOriginTrial{
+ "CrossOriginOpenerPolicyReportingOriginTrial",
+ base::FEATURE_ENABLED_BY_DEFAULT};
// Enables Cross-Origin Opener Policy (COOP) reporting.
// https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
@@ -104,8 +102,7 @@ const base::Feature kCrossOriginOpenerPolicyReporting{
// 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};
+ "CrossOriginOpenerPolicyAccessReporting", base::FEATURE_ENABLED_BY_DEFAULT};
// Enables Cross-Origin Embedder Policy (COEP).
// https://github.com/mikewest/corpp
@@ -113,13 +110,18 @@ const base::Feature kCrossOriginOpenerPolicyAccessReporting{
const base::Feature kCrossOriginEmbedderPolicy{
"CrossOriginEmbedderPolicy", base::FEATURE_ENABLED_BY_DEFAULT};
-// When kBlockNonSecureExternalRequests is enabled, requests initiated from a
-// pubic network may only target a private network if the initiating context
-// is secure.
+// Enables the most recent developments on the crossOriginIsolated property.
+// https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/crossOriginIsolated
+const base::Feature kCrossOriginIsolated{"CrossOriginIsolated",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// When kBlockInsecurePrivateNetworkRequests is enabled, requests initiated
+// from a less-private network may only target a more-private network if the
+// initiating context is secure.
//
// https://wicg.github.io/cors-rfc1918/#integration-fetch
-const base::Feature kBlockNonSecureExternalRequests{
- "BlockNonSecureExternalRequests", base::FEATURE_DISABLED_BY_DEFAULT};
+const base::Feature kBlockInsecurePrivateNetworkRequests{
+ "BlockInsecurePrivateNetworkRequests", base::FEATURE_DISABLED_BY_DEFAULT};
// Enables or defaults splittup up server (not proxy) entries in the
// HttpAuthCache.
@@ -129,7 +131,7 @@ const base::Feature kSplitAuthCacheByNetworkIsolationKey{
// Enable usage of hardcoded DoH upgrade mapping for use in automatic mode.
const base::Feature kDnsOverHttpsUpgrade {
"DnsOverHttpsUpgrade",
-#if defined(OS_CHROMEOS) || defined(OS_MACOSX) || defined(OS_ANDROID) || \
+#if defined(OS_CHROMEOS) || defined(OS_MAC) || defined(OS_ANDROID) || \
defined(OS_WIN)
base::FEATURE_ENABLED_BY_DEFAULT
#else
@@ -183,7 +185,7 @@ const char kCorbAllowlistAlsoAppliesToOorCorsParamName[] =
"AllowlistForCorbAndCors";
// Controls whether a |request_initiator| that mismatches
-// |request_initiator_site_lock| leads to 1) failing the HTTP request and 2)
+// |request_initiator_origin_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).
@@ -253,5 +255,12 @@ bool ShouldEnableOutOfBlinkCorsForTesting() {
const base::Feature kWebSocketReassembleShortMessages{
"WebSocketReassembleShortMessages", base::FEATURE_ENABLED_BY_DEFAULT};
+// Controls whether SCT audit reports are queued and the rate at which they
+// should be sampled.
+const base::Feature kSCTAuditing{"SCTAuditing",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+constexpr base::FeatureParam<double> kSCTAuditingSamplingRate{
+ &kSCTAuditing, "sampling_rate", 0.0};
+
} // namespace features
} // namespace network
diff --git a/chromium/services/network/public/cpp/features.h b/chromium/services/network/public/cpp/features.h
index 213184d4cb4..92db9c96dde 100644
--- a/chromium/services/network/public/cpp/features.h
+++ b/chromium/services/network/public/cpp/features.h
@@ -39,11 +39,15 @@ extern const base::Feature kCrossOriginOpenerPolicy;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kCrossOriginOpenerPolicyReporting;
COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kCrossOriginOpenerPolicyReportingOriginTrial;
+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;
+extern const base::Feature kCrossOriginIsolated;
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kBlockInsecurePrivateNetworkRequests;
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kSplitAuthCacheByNetworkIsolationKey;
COMPONENT_EXPORT(NETWORK_CPP)
@@ -98,6 +102,11 @@ bool ShouldEnableOutOfBlinkCorsForTesting();
COMPONENT_EXPORT(NETWORK_CPP)
extern const base::Feature kWebSocketReassembleShortMessages;
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::Feature kSCTAuditing;
+COMPONENT_EXPORT(NETWORK_CPP)
+extern const base::FeatureParam<double> kSCTAuditingSamplingRate;
+
} // 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 9832b21aacd..c2126c1d7f4 100644
--- a/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits.cc
@@ -164,13 +164,6 @@ StructTraits<DnsConfigOverridesDataView, net::DnsConfigOverrides>::
// static
DnsConfigOverrides::Tristate
-StructTraits<DnsConfigOverridesDataView, net::DnsConfigOverrides>::
- randomize_ports(const net::DnsConfigOverrides& overrides) {
- return ToTristate(overrides.randomize_ports);
-}
-
-// static
-DnsConfigOverrides::Tristate
StructTraits<DnsConfigOverridesDataView, net::DnsConfigOverrides>::rotate(
const net::DnsConfigOverrides& overrides) {
return ToTristate(overrides.rotate);
@@ -230,7 +223,6 @@ bool StructTraits<DnsConfigOverridesDataView, net::DnsConfigOverrides>::Read(
out->append_to_multi_label_name =
FromTristate(data.append_to_multi_label_name());
- out->randomize_ports = FromTristate(data.randomize_ports());
if (data.ndots() < -1)
return false;
diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits.h b/chromium/services/network/public/cpp/host_resolver_mojom_traits.h
index cae8e0efdff..95910576110 100644
--- a/chromium/services/network/public/cpp/host_resolver_mojom_traits.h
+++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits.h
@@ -51,8 +51,6 @@ struct StructTraits<network::mojom::DnsConfigOverridesDataView,
static network::mojom::DnsConfigOverrides_Tristate append_to_multi_label_name(
const net::DnsConfigOverrides& overrides);
- static network::mojom::DnsConfigOverrides_Tristate randomize_ports(
- const net::DnsConfigOverrides& overrides);
static int ndots(const net::DnsConfigOverrides& overrides) {
return overrides.ndots.value_or(-1);
diff --git a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
index 9a5dacd8e88..448f3846bde 100644
--- a/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/host_resolver_mojom_traits_unittest.cc
@@ -37,7 +37,6 @@ TEST(HostResolverMojomTraitsTest, DnsConfigOverridesRoundtrip_FullySpecified) {
std::make_pair(net::DnsHostsKey("host2", net::ADDRESS_FAMILY_IPV4),
net::IPAddress(2, 3, 4, 5))});
original.append_to_multi_label_name = true;
- original.randomize_ports = false;
original.ndots = 2;
original.timeout = base::TimeDelta::FromHours(4);
original.attempts = 1;
diff --git a/chromium/services/network/public/cpp/initiator_lock_compatibility.cc b/chromium/services/network/public/cpp/initiator_lock_compatibility.cc
index 136424d1ef2..0068639a1ff 100644
--- a/chromium/services/network/public/cpp/initiator_lock_compatibility.cc
+++ b/chromium/services/network/public/cpp/initiator_lock_compatibility.cc
@@ -20,49 +20,34 @@
namespace network {
InitiatorLockCompatibility VerifyRequestInitiatorLock(
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator) {
- if (!request_initiator_site_lock.has_value())
+ if (!request_initiator_origin_lock.has_value())
return InitiatorLockCompatibility::kNoLock;
- const url::Origin& lock = request_initiator_site_lock.value();
+ const url::Origin& lock = request_initiator_origin_lock.value();
if (!request_initiator.has_value())
return InitiatorLockCompatibility::kNoInitiator;
const url::Origin& initiator = request_initiator.value();
- // TODO(lukasza, nasko): Also consider equality of precursor origins (e.g. if
- // |initiator| is opaque, then it's precursor origin should match the |lock|
- // [or |lock|'s precursor if |lock| is also opaque]).
- if (initiator.opaque() || (initiator == lock))
+ if (initiator == lock)
return InitiatorLockCompatibility::kCompatibleLock;
- // TODO(lukasza): https://crbug.com/891872: Return kIncorrectLock if
- // the origins do not match exactly in the previous if statement. This should
- // be possible to do once we no longer vend process-wide factory.
- if (!initiator.opaque() && !lock.opaque() &&
- initiator.scheme() == lock.scheme() &&
- initiator.GetURL().SchemeIsHTTPOrHTTPS()) {
- if (initiator.GetURL().HostIsIPAddress()) {
- // For IP addresses, we require host equality (allowing ports to differ,
- // since site_url ignores ports). See also https://crbug.com/1051674.
- if (initiator.host() == lock.host())
- return InitiatorLockCompatibility::kCompatibleLock;
- } else {
- // For non-IP-address origins, we require sites (eTLD+1) to match
- // (again ignoring ports).
- std::string lock_domain = lock.host();
- if (!lock_domain.empty() && lock_domain.back() == '.')
- lock_domain.erase(lock_domain.length() - 1);
- if (initiator.DomainIs(lock_domain))
- return InitiatorLockCompatibility::kCompatibleLock;
- }
+ // Opaque |initiator| is always allowed. In particular, a factory locked to a
+ // non-opaque |lock| may be used by an opaque |initiator| - for example when
+ // the factory is inherited by a data: URL frame.
+ if (initiator.opaque()) {
+ // TODO(lukasza, nasko): Also consider equality of precursor origins (e.g.
+ // if |initiator| is opaque, then it's precursor origin should match the
+ // |lock| [or |lock|'s precursor if |lock| is also opaque]).
+ return InitiatorLockCompatibility::kCompatibleLock;
}
return InitiatorLockCompatibility::kIncorrectLock;
}
url::Origin GetTrustworthyInitiator(
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator) {
// Returning a unique origin as a fallback should be safe - such origin will
// be considered cross-origin from all other origins.
@@ -75,7 +60,7 @@ url::Origin GetTrustworthyInitiator(
return request_initiator.value();
InitiatorLockCompatibility initiator_compatibility =
- VerifyRequestInitiatorLock(request_initiator_site_lock,
+ VerifyRequestInitiatorLock(request_initiator_origin_lock,
request_initiator);
if (initiator_compatibility == InitiatorLockCompatibility::kIncorrectLock)
return unique_origin_fallback;
diff --git a/chromium/services/network/public/cpp/initiator_lock_compatibility.h b/chromium/services/network/public/cpp/initiator_lock_compatibility.h
index e521251585d..9275c998bf3 100644
--- a/chromium/services/network/public/cpp/initiator_lock_compatibility.h
+++ b/chromium/services/network/public/cpp/initiator_lock_compatibility.h
@@ -21,11 +21,11 @@ class URLLoaderFactoryParams;
// tools/metrics/histograms/enums.xml.
enum class InitiatorLockCompatibility {
// Request came from a browser process and so the
- // |request_initiator_site_lock| doesn't apply.
+ // |request_initiator_origin_lock| doesn't apply.
kBrowserProcess = 0,
- // |request_initiator_site_lock| is missing - see https://crbug.com/891872
- // and RenderProcessHostImpl::CreateURLLoaderFactoryForRendererProcess.
+ // |request_initiator_origin_lock| is missing. For historical context see
+ // https://crbug.com/1098938.
kNoLock = 1,
// |request_initiator| is missing. This indicates that the renderer has a bug
@@ -33,18 +33,18 @@ enum class InitiatorLockCompatibility {
kNoInitiator = 2,
// |request.request_initiator| is compatible with
- // |factory_params_.request_initiator_site_lock| - either
+ // |factory_params_.request_initiator_origin_lock| - either
// |request.request_initiator| is opaque or it is equal to
- // |request_initiator_site_lock|.
+ // |request_initiator_origin_lock|.
kCompatibleLock = 3,
// |request.request_initiator| is incompatible with
- // |factory_params_.request_initiator_site_lock|. Cases known so far where
+ // |factory_params_.request_initiator_origin_lock|. Cases known so far where
// this can occur:
// - HTML Imports (see https://crbug.com/871827#c9).
kIncorrectLock = 4,
- // Covered by CrossOriginReadBlocking::ShouldAllowForPlugin.
+ // Covered by CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin.
kExcludedCorbForPlugin = 6,
// Covered by AddAllowedRequestInitiatorForPlugin.
@@ -54,24 +54,24 @@ enum class InitiatorLockCompatibility {
};
// Verifies if |request.request_initiator| matches
-// |factory_params.request_initiator_site_lock|.
+// |factory_params.request_initiator_origin_lock|.
//
// This should only be called for requests from renderer processes
// (ones that are not coverd by the kExcludedPlugin exception).
COMPONENT_EXPORT(NETWORK_CPP)
InitiatorLockCompatibility VerifyRequestInitiatorLock(
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator);
// Gets initiator of request, falling back to a unique origin if
// 1) |request_initiator| is missing or
-// 2) |request_initiator| is incompatible with |request_initiator_site_lock|.
+// 2) |request_initiator| is incompatible with |request_initiator_origin_lock|.
//
-// |request_initiator_site_lock| is the origin to which the URLLoaderFactory of
-// the request is locked in a trustworthy way.
+// |request_initiator_origin_lock| is the origin to which the URLLoaderFactory
+// of the request is locked in a trustworthy way.
// Example:
-// URLLoaderFactoryParams::request_initiator_site_lock
-// SubresourceSignedExchangeURLLoaderFactory::request_initiator_site_lock
+// URLLoaderFactoryParams::request_initiator_origin_lock
+// SubresourceSignedExchangeURLLoaderFactory::request_initiator_origin_lock
// |request_initiator| should come from net::URLRequest::initiator() or
// network::ResourceRequest::request_initiator which may be initially set in an
// untrustworthy process (eg: renderer process).
@@ -82,7 +82,7 @@ InitiatorLockCompatibility VerifyRequestInitiatorLock(
// remove this, this header can be moved to non-public directory.
COMPONENT_EXPORT(NETWORK_CPP)
url::Origin GetTrustworthyInitiator(
- const base::Optional<url::Origin>& request_initiator_site_lock,
+ const base::Optional<url::Origin>& request_initiator_origin_lock,
const base::Optional<url::Origin>& request_initiator);
} // namespace network
diff --git a/chromium/services/network/public/cpp/initiator_lock_compatibility_unittest.cc b/chromium/services/network/public/cpp/initiator_lock_compatibility_unittest.cc
index 552c0aaccf2..c65d77a43d4 100644
--- a/chromium/services/network/public/cpp/initiator_lock_compatibility_unittest.cc
+++ b/chromium/services/network/public/cpp/initiator_lock_compatibility_unittest.cc
@@ -12,7 +12,7 @@
namespace network {
-TEST(InitiatorLockCompatibilityTest, VerifyRequestInitiatorSiteLock) {
+TEST(InitiatorLockCompatibilityTest, VerifyRequestInitiatorOriginLock) {
url::Origin opaque_origin = url::Origin();
url::Origin opaque_origin2 = url::Origin();
@@ -66,24 +66,19 @@ TEST(InitiatorLockCompatibilityTest, VerifyRequestInitiatorSiteLock) {
EXPECT_EQ(InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(foo_example_com, bar_example_com));
- // Site-URL-based comparisons.
- //
- // TODO(lukasza): These should result in kIncorrectLock eventually (once
- // request_initiator_site_lock becomes request_initiator_origin_lock - see
- // https://crbug.com/891872.
- EXPECT_EQ(InitiatorLockCompatibility::kCompatibleLock,
+ // Site != origin.
+ EXPECT_EQ(InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(example_com, bar_foo_example_com));
- EXPECT_EQ(InitiatorLockCompatibility::kCompatibleLock,
+ EXPECT_EQ(InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(foo_example_com, bar_foo_example_com));
EXPECT_EQ(
- InitiatorLockCompatibility::kCompatibleLock,
+ InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(ip_origin1, ip_origin1_with_different_port));
- // The trailing dot is not important (at least for site-URL-based
- // comparisons).
- EXPECT_EQ(InitiatorLockCompatibility::kCompatibleLock,
+ // The trailing dot.
+ EXPECT_EQ(InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(foo_example_com_dot, foo_example_com));
- EXPECT_EQ(InitiatorLockCompatibility::kCompatibleLock,
+ EXPECT_EQ(InitiatorLockCompatibility::kIncorrectLock,
VerifyRequestInitiatorLock(foo_example_com, foo_example_com_dot));
}
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.cc b/chromium/services/network/public/cpp/ip_address_space_util.cc
new file mode 100644
index 00000000000..a9824b1f17f
--- /dev/null
+++ b/chromium/services/network/public/cpp/ip_address_space_util.cc
@@ -0,0 +1,44 @@
+// 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/ip_address_space_util.h"
+
+#include "net/base/ip_address.h"
+
+namespace network {
+
+using mojom::IPAddressSpace;
+
+IPAddressSpace IPAddressToIPAddressSpace(const net::IPAddress& address) {
+ if (!address.IsValid()) {
+ return IPAddressSpace::kUnknown;
+ }
+
+ if (address.IsLoopback()) {
+ return IPAddressSpace::kLocal;
+ }
+
+ if (!address.IsPubliclyRoutable()) {
+ return IPAddressSpace::kPrivate;
+ }
+
+ return IPAddressSpace::kPublic;
+}
+
+// For comparison purposes, we treat kUnknown the same as kPublic.
+IPAddressSpace CollapseUnknown(IPAddressSpace space) {
+ if (space == IPAddressSpace::kUnknown) {
+ return IPAddressSpace::kPublic;
+ }
+ return space;
+}
+
+bool IsLessPublicAddressSpace(IPAddressSpace lhs, IPAddressSpace rhs) {
+ // Apart from the special case for kUnknown, the built-in comparison operator
+ // works just fine. The comment on IPAddressSpace's definition notes that the
+ // enum values' ordering matters.
+ return CollapseUnknown(lhs) < CollapseUnknown(rhs);
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/ip_address_space_util.h b/chromium/services/network/public/cpp/ip_address_space_util.h
new file mode 100644
index 00000000000..d16f8f981eb
--- /dev/null
+++ b/chromium/services/network/public/cpp/ip_address_space_util.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_IP_ADDRESS_SPACE_UTIL_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_
+
+#include "services/network/public/mojom/ip_address_space.mojom.h"
+
+namespace net {
+
+class IPAddress;
+
+} // namespace net
+
+namespace network {
+
+// Returns the IPAddressSpace from an IPAddress.
+//
+// This can be used as-is for subresource requests. For documents, also take
+// into account the 'treat-as-public-address' CSP directive.
+mojom::IPAddressSpace COMPONENT_EXPORT(NETWORK_CPP)
+ IPAddressToIPAddressSpace(const net::IPAddress& address);
+
+// Returns whether |lhs| is less public than |rhs|.
+//
+// This comparator is compatible with std::less.
+//
+// Address spaces go from most public to least public in the following order:
+//
+// - public and unknown
+// - private
+// - local
+//
+bool COMPONENT_EXPORT(NETWORK_CPP)
+ IsLessPublicAddressSpace(mojom::IPAddressSpace lhs,
+ mojom::IPAddressSpace rhs);
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_IP_ADDRESS_SPACE_UTIL_H_
diff --git a/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
new file mode 100644
index 00000000000..c29491b3a14
--- /dev/null
+++ b/chromium/services/network/public/cpp/ip_address_space_util_unittest.cc
@@ -0,0 +1,97 @@
+// 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/ip_address_space_util.h"
+
+#include "net/base/ip_address.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+namespace {
+
+using mojom::IPAddressSpace;
+using net::IPAddress;
+using net::IPAddressBytes;
+
+TEST(IPAddressSpaceTest, IPAddressToIPAddressSpacev4) {
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress()), IPAddressSpace::kUnknown);
+
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(64, 233, 160, 0)),
+ IPAddressSpace::kPublic);
+
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(192, 168, 1, 1)),
+ IPAddressSpace::kPrivate);
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(10, 1, 1, 1)),
+ IPAddressSpace::kPrivate);
+
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(127, 0, 0, 1)),
+ IPAddressSpace::kLocal);
+}
+
+IPAddressBytes IPv6BytesWithPrefix(uint8_t prefix) {
+ IPAddressBytes bytes;
+ bytes.Resize(IPAddress::kIPv6AddressSize);
+ bytes.data()[0] = prefix;
+ return bytes;
+}
+
+TEST(IPAddressSpaceTest, IPAddressToAddressSpacev6) {
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(IPv6BytesWithPrefix(42))),
+ IPAddressSpace::kPublic);
+
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress(IPv6BytesWithPrefix(0xfd))),
+ IPAddressSpace::kPrivate);
+
+ EXPECT_EQ(IPAddressToIPAddressSpace(IPAddress::IPv6Localhost()),
+ IPAddressSpace::kLocal);
+}
+
+TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanLocal) {
+ EXPECT_FALSE(
+ IsLessPublicAddressSpace(IPAddressSpace::kLocal, IPAddressSpace::kLocal));
+
+ EXPECT_TRUE(IsLessPublicAddressSpace(IPAddressSpace::kLocal,
+ IPAddressSpace::kPrivate));
+ EXPECT_TRUE(IsLessPublicAddressSpace(IPAddressSpace::kLocal,
+ IPAddressSpace::kPublic));
+ EXPECT_TRUE(IsLessPublicAddressSpace(IPAddressSpace::kLocal,
+ IPAddressSpace::kUnknown));
+}
+
+TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanPrivate) {
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPrivate,
+ IPAddressSpace::kLocal));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPrivate,
+ IPAddressSpace::kPrivate));
+
+ EXPECT_TRUE(IsLessPublicAddressSpace(IPAddressSpace::kPrivate,
+ IPAddressSpace::kPublic));
+ EXPECT_TRUE(IsLessPublicAddressSpace(IPAddressSpace::kPrivate,
+ IPAddressSpace::kUnknown));
+}
+
+TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanPublic) {
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPublic,
+ IPAddressSpace::kLocal));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPublic,
+ IPAddressSpace::kPrivate));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPublic,
+ IPAddressSpace::kPublic));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kPublic,
+ IPAddressSpace::kUnknown));
+}
+
+TEST(IPAddressSpaceTest, IsLessPublicAddressSpaceThanUnknown) {
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kUnknown,
+ IPAddressSpace::kLocal));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kUnknown,
+ IPAddressSpace::kPrivate));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kUnknown,
+ IPAddressSpace::kPublic));
+ EXPECT_FALSE(IsLessPublicAddressSpace(IPAddressSpace::kUnknown,
+ IPAddressSpace::kUnknown));
+}
+
+} // namespace
+} // namespace network
diff --git a/chromium/services/network/public/cpp/load_info_util.cc b/chromium/services/network/public/cpp/load_info_util.cc
index 2a81a60198c..28394496e13 100644
--- a/chromium/services/network/public/cpp/load_info_util.cc
+++ b/chromium/services/network/public/cpp/load_info_util.cc
@@ -4,6 +4,7 @@
#include "services/network/public/cpp/load_info_util.h"
+#include "net/base/load_states.h"
#include "services/network/public/mojom/network_service.mojom.h"
namespace network {
diff --git a/chromium/services/network/public/cpp/net_ipc_param_traits.h b/chromium/services/network/public/cpp/net_ipc_param_traits.h
index 0ad0fe96373..c3835ff3efa 100644
--- a/chromium/services/network/public/cpp/net_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/net_ipc_param_traits.h
@@ -8,6 +8,7 @@
#include <string>
#include "base/component_export.h"
+#include "base/memory/ref_counted.h"
#include "base/pickle.h"
#include "ipc/ipc_param_traits.h"
#include "ipc/param_traits_macros.h"
@@ -15,6 +16,7 @@
#include "net/base/host_port_pair.h"
#include "net/base/ip_address.h"
#include "net/base/ip_endpoint.h"
+#include "net/base/load_timing_info.h"
#include "net/base/proxy_server.h"
#include "net/base/request_priority.h"
#include "net/cert/cert_verify_result.h"
@@ -23,12 +25,17 @@
#include "net/cert/signed_certificate_timestamp.h"
#include "net/cert/signed_certificate_timestamp_and_status.h"
#include "net/cert/x509_certificate.h"
+#include "net/dns/public/resolve_error_info.h"
#include "net/http/http_request_headers.h"
+#include "net/http/http_response_headers.h"
+#include "net/http/http_response_info.h"
#include "net/http/http_version.h"
#include "net/nqe/effective_connection_type.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_info.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/url_request/redirect_info.h"
+#include "net/url_request/referrer_policy.h"
#include "url/ipc/url_param_traits.h"
#include "url/origin.h"
@@ -272,8 +279,7 @@ IPC_ENUM_TRAITS_MAX_VALUE(net::SSLClientCertType,
IPC_ENUM_TRAITS_MAX_VALUE(net::SSLInfo::HandshakeType,
net::SSLInfo::HANDSHAKE_FULL)
-IPC_ENUM_TRAITS_MAX_VALUE(net::URLRequest::ReferrerPolicy,
- net::URLRequest::MAX_REFERRER_POLICY)
+IPC_ENUM_TRAITS_MAX_VALUE(net::ReferrerPolicy, net::ReferrerPolicy::MAX)
IPC_STRUCT_TRAITS_BEGIN(net::HttpRequestHeaders::HeaderKeyValuePair)
IPC_STRUCT_TRAITS_MEMBER(key)
diff --git a/chromium/services/network/public/cpp/network_ipc_param_traits.cc b/chromium/services/network/public/cpp/network_ipc_param_traits.cc
index ad07a680ea5..e0f982d4d34 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.cc
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.cc
@@ -57,6 +57,7 @@ void ParamTraits<network::DataElement>::Write(base::Pickle* m,
.release());
break;
}
+ case network::mojom::DataElementType::kReadOnceStream:
case network::mojom::DataElementType::kUnknown: {
NOTREACHED();
break;
@@ -148,6 +149,7 @@ bool ParamTraits<network::DataElement>::Read(const base::Pickle* m,
r->SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
return true;
}
+ case network::mojom::DataElementType::kReadOnceStream:
case network::mojom::DataElementType::kUnknown: {
NOTREACHED();
return false;
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 90fb4bf7d95..b8ee874ba32 100644
--- a/chromium/services/network/public/cpp/network_ipc_param_traits.h
+++ b/chromium/services/network/public/cpp/network_ipc_param_traits.h
@@ -25,7 +25,6 @@
#include "net/nqe/effective_connection_type.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_info.h"
-#include "net/url_request/redirect_info.h"
#include "services/network/public/cpp/isolation_opt_in_hints.h"
#include "services/network/public/cpp/net_ipc_param_traits.h"
#include "services/network/public/cpp/origin_policy.h"
diff --git a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc
new file mode 100644
index 00000000000..149e6734a6e
--- /dev/null
+++ b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.cc
@@ -0,0 +1,37 @@
+// 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.
+
+#include "services/network/public/cpp/not_implemented_url_loader_factory.h"
+
+#include "base/logging.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "services/network/public/mojom/url_loader.mojom.h"
+
+namespace network {
+
+NotImplementedURLLoaderFactory::NotImplementedURLLoaderFactory() = default;
+
+NotImplementedURLLoaderFactory::~NotImplementedURLLoaderFactory() = default;
+
+void NotImplementedURLLoaderFactory::CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation) {
+ NOTREACHED();
+ network::URLLoaderCompletionStatus status;
+ status.error_code = net::ERR_NOT_IMPLEMENTED;
+ mojo::Remote<network::mojom::URLLoaderClient>(std::move(client))
+ ->OnComplete(status);
+}
+
+void NotImplementedURLLoaderFactory::Clone(
+ mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver) {
+ receivers_.Add(this, std::move(receiver));
+}
+
+} // namespace network
diff --git a/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h
new file mode 100644
index 00000000000..baca98d17a3
--- /dev/null
+++ b/chromium/services/network/public/cpp/not_implemented_url_loader_factory.h
@@ -0,0 +1,46 @@
+// 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.
+
+#ifndef SERVICES_NETWORK_PUBLIC_CPP_NOT_IMPLEMENTED_URL_LOADER_FACTORY_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_NOT_IMPLEMENTED_URL_LOADER_FACTORY_H_
+
+#include "base/component_export.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"
+#include "services/network/public/mojom/url_loader_factory.mojom.h"
+
+namespace network {
+
+// A URLLoaderFactory which just fails to create a loader with
+// net::ERR_NOT_IMPLEMENTED.
+class COMPONENT_EXPORT(NETWORK_CPP) NotImplementedURLLoaderFactory final
+ : public network::mojom::URLLoaderFactory {
+ public:
+ NotImplementedURLLoaderFactory();
+ ~NotImplementedURLLoaderFactory() override;
+
+ // network::mojom::URLLoaderFactory implementation.
+ void CreateLoaderAndStart(
+ mojo::PendingReceiver<network::mojom::URLLoader> receiver,
+ int32_t routing_id,
+ int32_t request_id,
+ uint32_t options,
+ const network::ResourceRequest& url_request,
+ mojo::PendingRemote<network::mojom::URLLoaderClient> client,
+ const net::MutableNetworkTrafficAnnotationTag& traffic_annotation)
+ override;
+
+ void Clone(mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver)
+ override;
+
+ private:
+ mojo::ReceiverSet<network::mojom::URLLoaderFactory> receivers_;
+
+ DISALLOW_COPY_AND_ASSIGN(NotImplementedURLLoaderFactory);
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_NOT_IMPLEMENTED_URL_LOADER_FACTORY_H_
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 7722e574bb2..35ea9b24717 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
@@ -27,7 +27,7 @@ OptionalTrustTokenParams NonemptyTrustTokenParams() {
mojom::TrustTokenRefreshPolicy::kRefresh,
mojom::TrustTokenSignRequestData::kInclude,
/*include_timestamp_header=*/true,
- url::Origin::Create(GURL("https://issuer.com")),
+ std::vector<url::Origin>{url::Origin::Create(GURL("https://issuer.com"))},
std::vector<std::string>{"some_header", "another_header"},
"some additional signing data");
}
diff --git a/chromium/services/network/public/cpp/parsed_headers.cc b/chromium/services/network/public/cpp/parsed_headers.cc
index dc7b9ae7adc..2ce3770b3a6 100644
--- a/chromium/services/network/public/cpp/parsed_headers.cc
+++ b/chromium/services/network/public/cpp/parsed_headers.cc
@@ -24,10 +24,12 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
AddContentSecurityPolicyFromHeaders(*headers, url,
&parsed_headers->content_security_policy);
+ parsed_headers->allow_csp_from = ParseAllowCSPFromHeader(*headers);
+
parsed_headers->cross_origin_embedder_policy =
ParseCrossOriginEmbedderPolicy(*headers);
- parsed_headers->cross_origin_opener_policy =
- ParseCrossOriginOpenerPolicy(*headers);
+ parsed_headers->cross_origin_opener_policy = ParseCrossOriginOpenerPolicy(
+ *headers, parsed_headers->cross_origin_embedder_policy);
std::string origin_isolation;
if (headers->GetNormalizedHeader("Origin-Isolation", &origin_isolation))
@@ -37,6 +39,12 @@ mojom::ParsedHeadersPtr PopulateParsedHeaders(
if (headers->GetNormalizedHeader("Accept-CH", &accept_ch))
parsed_headers->accept_ch = ParseAcceptCH(accept_ch);
+ std::string accept_ch_lifetime;
+ if (headers->GetNormalizedHeader("Accept-CH-Lifetime", &accept_ch_lifetime)) {
+ parsed_headers->accept_ch_lifetime =
+ ParseAcceptCHLifetime(accept_ch_lifetime);
+ }
+
return parsed_headers;
}
diff --git a/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
index f64ff8e4ca8..b5ec2918e6a 100644
--- a/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/proxy_config_mojom_traits_unittest.cc
@@ -62,8 +62,8 @@ TEST(ProxyConfigTraitsTest, ProxyRules) {
"ftp=ftp1,ftp2,ftp3",
"http=http1,http2; http=http3",
"ftp=ftp1,ftp2,ftp3 ; http=http1,http2; ",
- "http=https://secure_proxy; ftp=socks4://socks_proxy; "
- "https=socks://foo",
+ ("http=https://secure_proxy; ftp=socks4://socks_proxy; "
+ "https=socks://foo"),
"socks=foopy",
"http=httpproxy ; https=httpsproxy ; ftp=ftpproxy ; socks=foopy ",
"http=httpproxy ; https=httpsproxy ; socks=socks5://foopy ",
diff --git a/chromium/services/network/public/cpp/resource_request.cc b/chromium/services/network/public/cpp/resource_request.cc
index 7d32256054a..d258166332b 100644
--- a/chromium/services/network/public/cpp/resource_request.cc
+++ b/chromium/services/network/public/cpp/resource_request.cc
@@ -128,34 +128,32 @@ bool ResourceRequest::SavesCookies() const {
!(load_flags & net::LOAD_DO_NOT_SAVE_COOKIES);
}
-net::URLRequest::ReferrerPolicy ReferrerPolicyForUrlRequest(
+net::ReferrerPolicy ReferrerPolicyForUrlRequest(
mojom::ReferrerPolicy referrer_policy) {
switch (referrer_policy) {
case mojom::ReferrerPolicy::kAlways:
- return net::URLRequest::NEVER_CLEAR_REFERRER;
+ return net::ReferrerPolicy::NEVER_CLEAR;
case mojom::ReferrerPolicy::kNever:
- return net::URLRequest::NO_REFERRER;
+ return net::ReferrerPolicy::NO_REFERRER;
case mojom::ReferrerPolicy::kOrigin:
- return net::URLRequest::ORIGIN;
+ return net::ReferrerPolicy::ORIGIN;
case mojom::ReferrerPolicy::kNoReferrerWhenDowngrade:
- return net::URLRequest::
- CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+ return net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
case mojom::ReferrerPolicy::kOriginWhenCrossOrigin:
- return net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
+ return net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
case mojom::ReferrerPolicy::kSameOrigin:
- return net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN;
+ return net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN;
case mojom::ReferrerPolicy::kStrictOrigin:
- return net::URLRequest::
+ return net::ReferrerPolicy::
ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
case mojom::ReferrerPolicy::kDefault:
CHECK(false);
- return net::URLRequest::NO_REFERRER;
+ return net::ReferrerPolicy::NO_REFERRER;
case mojom::ReferrerPolicy::kStrictOriginWhenCrossOrigin:
- return net::URLRequest::
- REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
+ return net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
}
NOTREACHED();
- return net::URLRequest::CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+ return net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
}
} // namespace network
diff --git a/chromium/services/network/public/cpp/resource_request.h b/chromium/services/network/public/cpp/resource_request.h
index 44cb6c0964e..d911066399e 100644
--- a/chromium/services/network/public/cpp/resource_request.h
+++ b/chromium/services/network/public/cpp/resource_request.h
@@ -17,7 +17,7 @@
#include "net/base/request_priority.h"
#include "net/cookies/site_for_cookies.h"
#include "net/http/http_request_headers.h"
-#include "net/url_request/url_request.h"
+#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/optional_trust_token_params.h"
#include "services/network/public/cpp/resource_request_body.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
@@ -73,8 +73,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
base::Optional<url::Origin> request_initiator;
base::Optional<url::Origin> isolated_world_origin;
GURL referrer;
- net::URLRequest::ReferrerPolicy referrer_policy =
- net::URLRequest::NEVER_CLEAR_REFERRER;
+ net::ReferrerPolicy referrer_policy = net::ReferrerPolicy::NEVER_CLEAR;
net::HttpRequestHeaders headers;
net::HttpRequestHeaders cors_exempt_headers;
int load_flags = 0;
@@ -123,7 +122,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequest {
// This does not accept |kDefault| referrer policy.
COMPONENT_EXPORT(NETWORK_CPP_BASE)
-net::URLRequest::ReferrerPolicy ReferrerPolicyForUrlRequest(
+net::ReferrerPolicy ReferrerPolicyForUrlRequest(
mojom::ReferrerPolicy referrer_policy);
} // namespace network
diff --git a/chromium/services/network/public/cpp/resource_request_body.cc b/chromium/services/network/public/cpp/resource_request_body.cc
index a865aeb4395..8797143dde6 100644
--- a/chromium/services/network/public/cpp/resource_request_body.cc
+++ b/chromium/services/network/public/cpp/resource_request_body.cc
@@ -21,9 +21,15 @@ scoped_refptr<ResourceRequestBody> ResourceRequestBody::CreateFromBytes(
return result;
}
+bool ResourceRequestBody::EnableToAppendElement() const {
+ return elements_.empty() ||
+ (elements_.front().type() !=
+ mojom::DataElementType::kChunkedDataPipe &&
+ elements_.front().type() != mojom::DataElementType::kReadOnceStream);
+}
+
void ResourceRequestBody::AppendBytes(std::vector<uint8_t> bytes) {
- DCHECK(elements_.empty() ||
- elements_.front().type() != mojom::DataElementType::kChunkedDataPipe);
+ DCHECK(EnableToAppendElement());
if (bytes.size() > 0) {
elements_.push_back(DataElement());
@@ -44,8 +50,7 @@ void ResourceRequestBody::AppendFileRange(
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time) {
- DCHECK(elements_.empty() ||
- elements_.front().type() != mojom::DataElementType::kChunkedDataPipe);
+ DCHECK(EnableToAppendElement());
elements_.push_back(DataElement());
elements_.back().SetToFilePathRange(file_path, offset, length,
@@ -58,8 +63,7 @@ void ResourceRequestBody::AppendRawFileRange(
uint64_t offset,
uint64_t length,
const base::Time& expected_modification_time) {
- DCHECK(elements_.empty() ||
- elements_.front().type() != mojom::DataElementType::kChunkedDataPipe);
+ DCHECK(EnableToAppendElement());
elements_.push_back(DataElement());
elements_.back().SetToFileRange(std::move(file), file_path, offset, length,
@@ -71,8 +75,7 @@ void ResourceRequestBody::AppendBlob(const std::string& uuid) {
}
void ResourceRequestBody::AppendBlob(const std::string& uuid, uint64_t length) {
- DCHECK(elements_.empty() ||
- elements_.front().type() != mojom::DataElementType::kChunkedDataPipe);
+ DCHECK(EnableToAppendElement());
elements_.push_back(DataElement());
elements_.back().SetToBlobRange(uuid, 0 /* offset */, length);
@@ -80,8 +83,7 @@ void ResourceRequestBody::AppendBlob(const std::string& uuid, uint64_t length) {
void ResourceRequestBody::AppendDataPipe(
mojo::PendingRemote<mojom::DataPipeGetter> data_pipe_getter) {
- DCHECK(elements_.empty() ||
- elements_.front().type() != mojom::DataElementType::kChunkedDataPipe);
+ DCHECK(EnableToAppendElement());
elements_.push_back(DataElement());
elements_.back().SetToDataPipe(std::move(data_pipe_getter));
@@ -96,6 +98,15 @@ void ResourceRequestBody::SetToChunkedDataPipe(
elements_.back().SetToChunkedDataPipe(std::move(chunked_data_pipe_getter));
}
+void ResourceRequestBody::SetToReadOnceStream(
+ mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+ chunked_data_pipe_getter) {
+ DCHECK(elements_.empty());
+
+ elements_.push_back(DataElement());
+ elements_.back().SetToReadOnceStream(std::move(chunked_data_pipe_getter));
+}
+
std::vector<base::FilePath> ResourceRequestBody::GetReferencedFiles() const {
std::vector<base::FilePath> result;
for (const auto& element : *elements()) {
diff --git a/chromium/services/network/public/cpp/resource_request_body.h b/chromium/services/network/public/cpp/resource_request_body.h
index 2634327fdac..e3679f2b1e7 100644
--- a/chromium/services/network/public/cpp/resource_request_body.h
+++ b/chromium/services/network/public/cpp/resource_request_body.h
@@ -80,6 +80,10 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
// support chunked uploads.
void SetToChunkedDataPipe(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
chunked_data_pipe_getter);
+ // Almost same as above except |chunked_data_pipe_getter| is read only once
+ // and you must talk with a server supporting chunked upload.
+ void SetToReadOnceStream(mojo::PendingRemote<mojom::ChunkedDataPipeGetter>
+ chunked_data_pipe_getter);
void SetAllowHTTP1ForStreamingUpload(bool allow) {
allow_http1_for_streaming_upload_ = allow;
}
@@ -118,6 +122,8 @@ class COMPONENT_EXPORT(NETWORK_CPP_BASE) ResourceRequestBody
scoped_refptr<network::ResourceRequestBody>>;
~ResourceRequestBody();
+ bool EnableToAppendElement() const;
+
std::vector<DataElement> elements_;
int64_t identifier_;
diff --git a/chromium/services/network/public/cpp/session_cookie_delete_predicate.h b/chromium/services/network/public/cpp/session_cookie_delete_predicate.h
new file mode 100644
index 00000000000..8b2162d8705
--- /dev/null
+++ b/chromium/services/network/public/cpp/session_cookie_delete_predicate.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_SESSION_COOKIE_DELETE_PREDICATE_H_
+#define SERVICES_NETWORK_PUBLIC_CPP_SESSION_COOKIE_DELETE_PREDICATE_H_
+
+#include <string>
+
+#include "base/callback_forward.h"
+
+namespace network {
+// A DeleteCookiePredicate callback function decides if the cookie associated
+// with the domain and is_https status should be deleted on exit, and is used
+// when creating a cookie storage policy. It has two parameters, the first one
+// is the domain of a cookie and the second one is a bool which represents
+// whether the cookie is secure as parameters.
+using DeleteCookiePredicate =
+ base::RepeatingCallback<bool(const std::string&, bool)>;
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_PUBLIC_CPP_SESSION_COOKIE_DELETE_PREDICATE_H_
diff --git a/chromium/services/network/public/cpp/simple_url_loader.cc b/chromium/services/network/public/cpp/simple_url_loader.cc
index e9e0c936a64..3e505a01541 100644
--- a/chromium/services/network/public/cpp/simple_url_loader.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader.cc
@@ -999,7 +999,7 @@ class SaveToFileBodyHandler : public BodyHandler {
on_done_callback_.Reset();
DCHECK(!path_.empty());
- base::DeleteFile(path_, false /* recursive */);
+ base::DeleteFile(path_);
owns_file_ = false;
}
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 beea0a11e91..afce68ff2d9 100644
--- a/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
+++ b/chromium/services/network/public/cpp/simple_url_loader_unittest.cc
@@ -47,6 +47,7 @@
#include "net/test/embedded_test_server/http_response.h"
#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
#include "net/url_request/redirect_info.h"
+#include "net/url_request/url_request.h"
#include "services/network/network_service.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"
@@ -375,7 +376,7 @@ class SimpleLoaderTestHelper : public SimpleURLLoaderStreamConsumer {
// Clean up file, so tests don't leave around files in the temp directory.
// Only matters in the TO_TEMP_FILE case.
if (!file_path.empty())
- base::DeleteFile(file_path, false);
+ base::DeleteFile(file_path);
done_ = true;
run_loop_.Quit();
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 ce1478f6df6..34f6223f495 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.cc
@@ -74,80 +74,70 @@ bool EnumTraits<network::mojom::RequestPriority, net::RequestPriority>::
return true;
}
-network::mojom::URLRequestReferrerPolicy EnumTraits<
- network::mojom::URLRequestReferrerPolicy,
- net::URLRequest::ReferrerPolicy>::ToMojom(net::URLRequest::ReferrerPolicy
- policy) {
+network::mojom::URLRequestReferrerPolicy
+EnumTraits<network::mojom::URLRequestReferrerPolicy,
+ net::ReferrerPolicy>::ToMojom(net::ReferrerPolicy policy) {
switch (policy) {
- case net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
+ case net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
return network::mojom::URLRequestReferrerPolicy::
kClearReferrerOnTransitionFromSecureToInsecure;
- case net::URLRequest::ReferrerPolicy::
- REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN:
+ case net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN:
return network::mojom::URLRequestReferrerPolicy::
kReduceReferrerGranularityOnTransitionCrossOrigin;
- case net::URLRequest::ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN:
+ case net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN:
return network::mojom::URLRequestReferrerPolicy::
kOriginOnlyOnTransitionCrossOrigin;
- case net::URLRequest::ReferrerPolicy::NEVER_CLEAR_REFERRER:
+ case net::ReferrerPolicy::NEVER_CLEAR:
return network::mojom::URLRequestReferrerPolicy::kNeverClearReferrer;
- case net::URLRequest::ReferrerPolicy::ORIGIN:
+ case net::ReferrerPolicy::ORIGIN:
return network::mojom::URLRequestReferrerPolicy::kOrigin;
- case net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN:
+ case net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN:
return network::mojom::URLRequestReferrerPolicy::
kClearReferrerOnTransitionCrossOrigin;
- case net::URLRequest::ReferrerPolicy::
+ case net::ReferrerPolicy::
ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE:
return network::mojom::URLRequestReferrerPolicy::
kOriginClearOnTransitionFromSecureToInsecure;
- case net::URLRequest::ReferrerPolicy::NO_REFERRER:
+ case net::ReferrerPolicy::NO_REFERRER:
return network::mojom::URLRequestReferrerPolicy::kNoReferrer;
}
NOTREACHED();
return static_cast<network::mojom::URLRequestReferrerPolicy>(policy);
}
-bool EnumTraits<network::mojom::URLRequestReferrerPolicy,
- net::URLRequest::ReferrerPolicy>::
+bool EnumTraits<network::mojom::URLRequestReferrerPolicy, net::ReferrerPolicy>::
FromMojom(network::mojom::URLRequestReferrerPolicy in,
- net::URLRequest::ReferrerPolicy* out) {
+ net::ReferrerPolicy* out) {
switch (in) {
case network::mojom::URLRequestReferrerPolicy::
kClearReferrerOnTransitionFromSecureToInsecure:
- *out = net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
+ *out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
return true;
case network::mojom::URLRequestReferrerPolicy::
kReduceReferrerGranularityOnTransitionCrossOrigin:
- *out = net::URLRequest::ReferrerPolicy::
- REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
+ *out = net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN;
return true;
case network::mojom::URLRequestReferrerPolicy::
kOriginOnlyOnTransitionCrossOrigin:
- *out = net::URLRequest::ReferrerPolicy::
- ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
+ *out = net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
return true;
case network::mojom::URLRequestReferrerPolicy::kNeverClearReferrer:
- *out = net::URLRequest::ReferrerPolicy::NEVER_CLEAR_REFERRER;
+ *out = net::ReferrerPolicy::NEVER_CLEAR;
return true;
case network::mojom::URLRequestReferrerPolicy::kOrigin:
- *out = net::URLRequest::ReferrerPolicy::ORIGIN;
+ *out = net::ReferrerPolicy::ORIGIN;
return true;
case network::mojom::URLRequestReferrerPolicy::
kClearReferrerOnTransitionCrossOrigin:
- *out = net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN;
+ *out = net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN;
return true;
case network::mojom::URLRequestReferrerPolicy::
kOriginClearOnTransitionFromSecureToInsecure:
- *out = net::URLRequest::ReferrerPolicy::
+ *out = net::ReferrerPolicy::
ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE;
return true;
case network::mojom::URLRequestReferrerPolicy::kNoReferrer:
- *out = net::URLRequest::ReferrerPolicy::NO_REFERRER;
+ *out = net::ReferrerPolicy::NO_REFERRER;
return true;
}
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 9e1dd066185..f3daedb4570 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits.h
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits.h
@@ -17,7 +17,7 @@
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
#include "net/base/request_priority.h"
-#include "net/url_request/url_request_job.h"
+#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/data_element.h"
#include "services/network/public/cpp/network_isolation_key_mojom_traits.h"
#include "services/network/public/cpp/resource_request.h"
@@ -42,12 +42,11 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
template <>
struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
- EnumTraits<network::mojom::URLRequestReferrerPolicy,
- net::URLRequest::ReferrerPolicy> {
+ EnumTraits<network::mojom::URLRequestReferrerPolicy, net::ReferrerPolicy> {
static network::mojom::URLRequestReferrerPolicy ToMojom(
- net::URLRequest::ReferrerPolicy policy);
+ net::ReferrerPolicy policy);
static bool FromMojom(network::mojom::URLRequestReferrerPolicy in,
- net::URLRequest::ReferrerPolicy* out);
+ net::ReferrerPolicy* out);
};
template <>
@@ -112,7 +111,7 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
static const GURL& referrer(const network::ResourceRequest& request) {
return request.referrer;
}
- static net::URLRequest::ReferrerPolicy referrer_policy(
+ static net::ReferrerPolicy referrer_policy(
const network::ResourceRequest& request) {
return request.referrer_policy;
}
@@ -328,7 +327,8 @@ struct COMPONENT_EXPORT(NETWORK_CPP_BASE)
}
static mojo::PendingRemote<network::mojom::ChunkedDataPipeGetter>
chunked_data_pipe_getter(const network::DataElement& element) {
- if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe)
+ if (element.type_ != network::mojom::DataElementType::kChunkedDataPipe &&
+ element.type_ != network::mojom::DataElementType::kReadOnceStream)
return mojo::NullRemote();
return const_cast<network::DataElement&>(element)
.ReleaseChunkedDataPipeGetter();
diff --git a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
index 2f104d7306a..7daeae3834a 100644
--- a/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
+++ b/chromium/services/network/public/cpp/url_request_mojom_traits_unittest.cc
@@ -8,6 +8,7 @@
#include "mojo/public/cpp/base/unguessable_token_mojom_traits.h"
#include "mojo/public/cpp/test_support/test_utils.h"
#include "net/base/isolation_info.h"
+#include "net/url_request/referrer_policy.h"
#include "services/network/public/cpp/http_request_headers_mojom_traits.h"
#include "services/network/public/cpp/network_ipc_param_traits.h"
#include "services/network/public/cpp/optional_trust_token_params.h"
@@ -21,27 +22,22 @@ namespace {
TEST(URLRequestMojomTraitsTest, Roundtrips_URLRequestReferrerPolicy) {
for (auto referrer_policy :
- {net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- net::URLRequest::ReferrerPolicy::
- REDUCE_REFERRER_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
- net::URLRequest::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
- net::URLRequest::ReferrerPolicy::NEVER_CLEAR_REFERRER,
- net::URLRequest::ReferrerPolicy::ORIGIN,
- net::URLRequest::ReferrerPolicy::
- CLEAR_REFERRER_ON_TRANSITION_CROSS_ORIGIN,
- net::URLRequest::ReferrerPolicy::
- ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
- net::URLRequest::ReferrerPolicy::NO_REFERRER}) {
+ {net::ReferrerPolicy::CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+ net::ReferrerPolicy::REDUCE_GRANULARITY_ON_TRANSITION_CROSS_ORIGIN,
+ net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN,
+ net::ReferrerPolicy::NEVER_CLEAR, net::ReferrerPolicy::ORIGIN,
+ net::ReferrerPolicy::CLEAR_ON_TRANSITION_CROSS_ORIGIN,
+ net::ReferrerPolicy::ORIGIN_CLEAR_ON_TRANSITION_FROM_SECURE_TO_INSECURE,
+ net::ReferrerPolicy::NO_REFERRER}) {
int32_t serialized = -1;
using URLRequestReferrerPolicySerializer =
mojo::internal::Serializer<mojom::URLRequestReferrerPolicy,
- net::URLRequest::ReferrerPolicy>;
+ net::ReferrerPolicy>;
URLRequestReferrerPolicySerializer::Serialize(referrer_policy, &serialized);
- EXPECT_EQ(referrer_policy, serialized);
- net::URLRequest::ReferrerPolicy deserialized;
+ EXPECT_EQ(static_cast<int32_t>(referrer_policy), serialized);
+ net::ReferrerPolicy deserialized;
URLRequestReferrerPolicySerializer::Deserialize(serialized, &deserialized);
- EXPECT_EQ(serialized, deserialized);
+ EXPECT_EQ(referrer_policy, deserialized);
}
}
@@ -58,7 +54,7 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
url::Origin::Create(GURL("chrome-extension://blah"));
original.referrer = GURL("https://referrer.com/");
original.referrer_policy =
- net::URLRequest::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
+ net::ReferrerPolicy::ORIGIN_ONLY_ON_TRANSITION_CROSS_ORIGIN;
original.headers.SetHeader("Accept", "text/xml");
original.cors_exempt_headers.SetHeader("X-Requested-With", "ForTesting");
original.load_flags = 3;
@@ -97,8 +93,8 @@ TEST(URLRequestMojomTraitsTest, Roundtrips_ResourceRequest) {
original.trusted_params->disable_secure_dns = true;
original.trust_token_params = network::mojom::TrustTokenParams();
- original.trust_token_params->issuer =
- url::Origin::Create(GURL("https://issuer.com"));
+ original.trust_token_params->issuers.push_back(
+ url::Origin::Create(GURL("https://issuer.com")));
original.trust_token_params->type =
mojom::TrustTokenOperationType::kRedemption;
original.trust_token_params->include_timestamp_header = true;
diff --git a/chromium/services/network/public/mojom/BUILD.gn b/chromium/services/network/public/mojom/BUILD.gn
index 4d5bef25d3c..c659ffa75bc 100644
--- a/chromium/services/network/public/mojom/BUILD.gn
+++ b/chromium/services/network/public/mojom/BUILD.gn
@@ -385,16 +385,17 @@ mojom("cookies_mojom") {
move_only = true
},
{
- mojom = "network.mojom.CookieWithStatus"
- cpp = "::net::CookieWithStatus"
+ mojom = "network.mojom.CookieAccessResult"
+ cpp = "::net::CookieAccessResult"
+ move_only = true
},
{
mojom = "network.mojom.CookieWithAccessResult"
cpp = "::net::CookieWithAccessResult"
},
{
- mojom = "network.mojom.CookieAndLineWithStatus"
- cpp = "::net::CookieAndLineWithStatus"
+ mojom = "network.mojom.CookieAndLineWithAccessResult"
+ cpp = "::net::CookieAndLineWithAccessResult"
},
{
mojom = "network.mojom.CookieChangeCause"
@@ -416,9 +417,20 @@ mojom("cookies_mojom") {
traits_public_deps = [ "//net" ]
},
]
-
cpp_typemaps += shared_cpp_typemaps
- blink_cpp_typemaps = shared_cpp_typemaps
+
+ blink_cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "network.mojom.CanonicalCookie"
+ cpp = "::blink::CanonicalCookie"
+ },
+ ]
+ traits_headers = [ "//third_party/blink/renderer/platform/cookie/canonical_cookie_mojom_traits.h" ]
+ },
+ ]
+ blink_cpp_typemaps += shared_cpp_typemaps
}
mojom("mojom") {
@@ -561,7 +573,7 @@ mojom("mojom") {
},
{
mojom = "network.mojom.URLRequestReferrerPolicy"
- cpp = "::net::URLRequest::ReferrerPolicy"
+ cpp = "::net::ReferrerPolicy"
},
{
mojom = "network.mojom.RequestPriority"
diff --git a/chromium/services/network/public/mojom/content_security_policy.mojom b/chromium/services/network/public/mojom/content_security_policy.mojom
index ca7d5062a8f..8c763092363 100644
--- a/chromium/services/network/public/mojom/content_security_policy.mojom
+++ b/chromium/services/network/public/mojom/content_security_policy.mojom
@@ -4,6 +4,7 @@
module network.mojom;
+import "url/mojom/origin.mojom";
import "url/mojom/url.mojom";
import "services/network/public/mojom/source_location.mojom";
import "services/network/public/mojom/web_sandbox_flags.mojom";
@@ -62,32 +63,67 @@ struct CSPSource {
bool is_port_wildcard = false;
};
+enum CSPHashAlgorithm {
+ SHA256,
+ SHA384,
+ SHA512,
+};
+
+struct CSPHashSource {
+ CSPHashAlgorithm algorithm;
+ string value;
+};
+
struct CSPSourceList {
array<CSPSource> sources;
+ array<string> nonces;
+ array<CSPHashSource> hashes;
// Wildcard hosts and 'self' aren't stored in |sources|, but as attributes
// on the source list itself.
bool allow_self = false;
bool allow_star = false;
bool allow_response_redirects = false;
+ bool allow_inline = false;
+ bool allow_eval = false;
+ bool allow_wasm_eval = false;
+ bool allow_dynamic = false;
+ bool allow_unsafe_hashes = false;
+ bool report_sample = false;
};
enum CSPDirectiveName {
Unknown,
- DefaultSrc,
+ BaseURI,
+ BlockAllMixedContent,
ChildSrc,
- FrameSrc,
+ ConnectSrc,
+ DefaultSrc,
+ FontSrc,
FormAction,
- NavigateTo,
FrameAncestors,
+ FrameSrc,
ImgSrc,
+ ManifestSrc,
MediaSrc,
+ NavigateTo,
ObjectSrc,
+ PrefetchSrc,
+ ReportTo,
+ ReportURI,
+ RequireTrustedTypesFor,
+ Sandbox,
ScriptSrc,
+ ScriptSrcAttr,
+ ScriptSrcElem,
StyleSrc,
+ StyleSrcAttr,
+ StyleSrcElem,
+ TreatAsPublicAddress,
+ TrustedTypes,
+ UpgradeInsecureRequests,
WorkerSrc,
- ConnectSrc
};
struct ContentSecurityPolicy {
@@ -116,6 +152,9 @@ struct ContentSecurityPolicy {
// Set of reporting endpoints to which violation reports are sent.
array<string> report_endpoints;
+
+ // An array containing a set of errors occurred while parsing the CSP header.
+ array<string> parsing_errors;
};
// Data to report Content-Security-Policy violations.
@@ -155,3 +194,14 @@ struct CSPViolation {
// The source code location that triggered the blocked navigation.
SourceLocation source_location;
};
+
+union AllowCSPFromHeaderValue {
+ // Set to true if the 'Allow-CSP-From' header just contains '*'.
+ bool allow_star;
+
+ // The parsed origin contained in the 'Allow-CSP-From' header.
+ url.mojom.Origin origin;
+
+ // If the header value is invalid, an error message will be stored here.
+ string error_message;
+}; \ No newline at end of file
diff --git a/chromium/services/network/public/mojom/cookie_access_observer.mojom b/chromium/services/network/public/mojom/cookie_access_observer.mojom
index 8cf5dd7ed5c..04dc1ae40b2 100644
--- a/chromium/services/network/public/mojom/cookie_access_observer.mojom
+++ b/chromium/services/network/public/mojom/cookie_access_observer.mojom
@@ -23,7 +23,7 @@ struct CookieAccessDetails {
url.mojom.Url url;
SiteForCookies site_for_cookies;
- array<CookieWithStatus> cookie_list;
+ array<CookieWithAccessResult> cookie_list;
// |devtools_request_id| contains the DevTools request id of the request
// that triggered the cookie change, if the read was triggered by a request.
diff --git a/chromium/services/network/public/mojom/cookie_manager.mojom b/chromium/services/network/public/mojom/cookie_manager.mojom
index 07aaee6a595..efb5fa353ef 100644
--- a/chromium/services/network/public/mojom/cookie_manager.mojom
+++ b/chromium/services/network/public/mojom/cookie_manager.mojom
@@ -83,6 +83,7 @@ enum CookieEffectiveSameSite {
kLaxMode = 1,
kStrictMode = 2,
kLaxModeAllowUnsafe = 3,
+ kUndefined = 4,
};
enum ContextType {
@@ -141,19 +142,15 @@ struct CookieInclusionStatus {
uint32 warning_reasons;
};
-struct CookieWithStatus {
- CanonicalCookie cookie;
- CookieInclusionStatus status;
-};
-
-struct CookieAndLineWithStatus {
+struct CookieAndLineWithAccessResult {
CanonicalCookie? cookie;
string cookie_string;
- CookieInclusionStatus status;
+ CookieAccessResult access_result;
};
struct CookieAccessResult {
CookieEffectiveSameSite effective_same_site;
+ CookieAccessSemantics access_semantics;
CookieInclusionStatus status;
};
@@ -184,8 +181,8 @@ enum CookieChangeCause {
struct CookieChangeInfo {
// The cookie that changed, in its post-change state.
CanonicalCookie cookie;
- // Access semantics of the cookie at the time of the change.
- CookieAccessSemantics access_semantics;
+ // Access results at the time of the change.
+ CookieAccessResult access_result;
CookieChangeCause cause;
};
@@ -305,7 +302,7 @@ interface CookieManager {
// |status| will be set to INCLUDE.
SetCanonicalCookie(CanonicalCookie cookie, url.mojom.Url source_url,
CookieOptions cookie_options)
- => (CookieInclusionStatus status);
+ => (CookieAccessResult access_result);
// Delete a cookie. Returns true if a cookie was deleted.
DeleteCanonicalCookie(CanonicalCookie cookie) => (bool success);
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 ac96351bc7a..8afb0851d96 100644
--- a/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom
+++ b/chromium/services/network/public/mojom/cross_origin_opener_policy.mojom
@@ -5,23 +5,28 @@
module network.mojom;
import "url/mojom/url.mojom";
+import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/network/public/mojom/source_location.mojom";
+
+enum CoopAccessReportType {
+ kAccessFromCoopPageToOpener,
+ kAccessFromCoopPageToOpenee,
+ kAccessFromCoopPageToOther,
+ kAccessToCoopPageFromOpener,
+ kAccessToCoopPageFromOpenee,
+ kAccessToCoopPageFromOther,
+};
// 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);
+ // Sends a report when two browsing contexts from different virtual browsing
+ // context groups tries to access each other.
+ // - |property| is the name of the access property (postMessage, open, ...).
+ // - |source_location| represents the line of code that triggered the access.
+ QueueAccessReport(CoopAccessReportType report_type, string property,
+ SourceLocation source_location);
// Connects a new pipe to this instance.
Clone(pending_receiver<CrossOriginOpenerPolicyReporter> receiver);
@@ -40,7 +45,10 @@ enum CrossOriginOpenerPolicyValue {
// No restriction is applied, the relationship is kept with openers and
// opened documents.
- kUnsafeNone
+ kUnsafeNone,
+
+ // Same origin with Cross-Origin-Embedder-Policy: require-corp.
+ kSameOriginPlusCoep,
};
// Cross-Origin-Opener-Policy enum representing parsed values.
@@ -58,4 +66,3 @@ struct CrossOriginOpenerPolicy {
// The reporting endpoint for the "report only" mode.
string? report_only_reporting_endpoint;
};
-
diff --git a/chromium/services/network/public/mojom/host_resolver.mojom b/chromium/services/network/public/mojom/host_resolver.mojom
index aa9566a011e..7d48d2a4620 100644
--- a/chromium/services/network/public/mojom/host_resolver.mojom
+++ b/chromium/services/network/public/mojom/host_resolver.mojom
@@ -75,10 +75,6 @@ struct DnsConfigOverrides {
// Whether suffix search should be performed for multi-label names.
Tristate append_to_multi_label_name = Tristate.NO_OVERRIDE;
- // Whether source port randomization is required. This uses additional
- // resources on some platforms.
- Tristate randomize_ports = Tristate.NO_OVERRIDE;
-
// Minimum number of dots before global resolution precedes |search|.
int8 ndots = -1; // -1 for no override.
diff --git a/chromium/services/network/public/mojom/network_context.mojom b/chromium/services/network/public/mojom/network_context.mojom
index 6d5110add0e..87b26150440 100644
--- a/chromium/services/network/public/mojom/network_context.mojom
+++ b/chromium/services/network/public/mojom/network_context.mojom
@@ -441,9 +441,6 @@ struct NetworkContextParams {
// policy.
array<string> hsts_policy_bypass_list;
- // Extra CORS safelisted request headers names.
- array<string> cors_extra_safelisted_request_header_names;
-
// Specifies the CORS mode.
// kDefault - Decided by base::Feature
// kEnable - Enable CORS in Network Service (aka OOR-CORS)
@@ -574,16 +571,35 @@ struct URLLoaderFactoryOverride {
bool skip_cors_enabled_scheme_check = false;
};
+// How to treat private network requests.
+//
+// Private network requests are any requests to a resource served by a
+// non-public IP address.
+//
+// See the CORS-RFC1918 spec for details: https://wicg.github.io/cors-rfc1918.
+enum PrivateNetworkRequestPolicy {
+ // Allow all requests.
+ kAllow,
+
+ // Forbid requests to more-private address spaces than that of the initiator,
+ // when the initiator is not in a secure context.
+ kBlockFromInsecureToMorePrivate,
+};
+
struct ClientSecurityState {
// https://mikewest.github.io/corpp/#integration-html
// https://mikewest.github.io/corpp/#initialize-embedder-policy-for-global
CrossOriginEmbedderPolicy cross_origin_embedder_policy;
// Whether the initiator of the requests is in a web secure context.
+ // See: https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts
bool is_web_secure_context = false;
// The initiator's IP AddressSpace.
- IPAddressSpace ip_address_space = IPAddressSpace.kUnknown;
+ IPAddressSpace ip_address_space = kUnknown;
+
+ // The policy to apply to private network requests.
+ PrivateNetworkRequestPolicy private_network_request_policy = kAllow;
};
// Whether to forbid all Trust Tokens redemption and signing operations
@@ -598,11 +614,14 @@ struct URLLoaderFactoryParams {
// Set to kBrowserProcessId to indicate the browser process.
int32 process_id = kInvalidProcessId;
- // If specified, then |request_initiator_site_lock| locks
+ // If specified, then |request_initiator_origin_lock| locks
// |ResourceRequest::request_initiator| to the specified origin.
- // TODO(lukasza): https://crbug.com/891872: 1) Make this non-optional,
- // 2) Make this an *origin* lock (rather than a *site* lock).
- url.mojom.Origin? request_initiator_site_lock;
+ //
+ // SECURITY NOTE: |request_initiator_origin_lock| should be present in all
+ // factories that may be vended to a Renderer process.
+ // |request_initiator_origin_lock| may be missing only in factories used by
+ // the Browser process.
+ url.mojom.Origin? request_initiator_origin_lock;
// Cross-origin read blocking (CORB) configuration.
bool is_corb_enabled = true;
@@ -844,6 +863,10 @@ interface NetworkContextClient {
// Notification that a trust anchor was used for the given user.
[EnableIf=is_chromeos]
OnTrustAnchorUsed();
+
+ // Notification that a report was enqueued in the SCT auditing cache.
+ [EnableIf=is_ct_supported]
+ OnSCTReportReady(string cache_key);
};
// Represents a distinct context for making network requests, with its own
@@ -1183,6 +1206,11 @@ interface NetworkContext {
// performance impact because of the extra process hops, so use should be
// minimized.
//
+ // Requests from a system context should set |process_id| to
+ // |kBrowserProcessId|. In that case |render_frame_id| MUST be zero. These
+ // values will still be passed to |OnSSLCertificateError| as needed but no
+ // throttling will be performed for such WebSockets.
+ //
// Detect mojo connection errors on |handshake_client| until the connection
// is established.
// Do *NOT* interpret mojo connection errors on |auth_handler| and
@@ -1199,6 +1227,7 @@ interface NetworkContext {
int32 render_frame_id,
url.mojom.Origin origin,
uint32 options,
+ MutableNetworkTrafficAnnotationTag traffic_annotation,
pending_remote<WebSocketHandshakeClient> handshake_client,
pending_remote<AuthenticationHandler>? auth_handler,
pending_remote<TrustedHeaderClient>? header_client);
@@ -1322,11 +1351,6 @@ interface NetworkContext {
url.mojom.Origin source_origin, array<CorsOriginPattern> allow_patterns,
array<CorsOriginPattern> block_patterns) => ();
- // Sets extra CORS safelisted request headers names dynamically. Headers need
- // to be in lower case.
- SetCorsExtraSafelistedRequestHeaderNames(
- array<string> cors_extra_safelisted_request_header_names);
-
// Deletes any dynamic data stored for |host| from the transport
// security state. Returns true iff an entry was deleted.
// See net::TransportSecurityState::DeleteDynamicDataForHost for more detail.
@@ -1376,6 +1400,16 @@ interface NetworkContext {
NetworkIsolationKey network_isolation_key)
=> (AuthCredentials? credentials);
+ // Looks up the proxy authentication credentials associated with
+ // |proxy_server|, |auth_scheme| and |realm| in the HttpAuthCache.
+ // |auth_scheme| is the authentication scheme of the challenge and it's
+ // specified as a case-insensitive string. Unlike server credentials, proxy
+ // credentials are not keyed on NetworkIsolationKey.
+ [EnableIf=is_chromeos]
+ LookupProxyAuthCredentials(proxy_resolver.mojom.ProxyServer proxy_server,
+ string auth_scheme, string realm)
+ => (AuthCredentials? credentials);
+
[Sync]
// Enables the checking of static PKP records.
EnableStaticKeyPinningForTesting() => ();
@@ -1400,4 +1434,8 @@ interface NetworkContext {
// Gets the OriginPolicyManager associated with this network context.
GetOriginPolicyManager(
pending_receiver<OriginPolicyManager> origin_policy_manager);
+
+ // Set whether SCT auditing is enabled for this NetworkContext.
+ [EnableIf=is_ct_supported]
+ SetSCTAuditingEnabled(bool enabled);
};
diff --git a/chromium/services/network/public/mojom/network_service.mojom b/chromium/services/network/public/mojom/network_service.mojom
index 6a016cc0eb0..b5cd71dbb98 100644
--- a/chromium/services/network/public/mojom/network_service.mojom
+++ b/chromium/services/network/public/mojom/network_service.mojom
@@ -74,7 +74,7 @@ interface NetworkServiceClient {
int32 process_id,
int32 routing_id,
string devtool_request_id,
- array<CookieAndLineWithStatus> cookies_with_status,
+ array<CookieAndLineWithAccessResult> cookies_with_access_result,
array<HttpRawHeaderPair> headers,
string? raw_response_headers);
@@ -363,7 +363,7 @@ interface NetworkService {
// - see https://www.chromium.org/flash-roadmap).
AddCorbExceptionForPlugin(int32 process_id);
- // Notifies |request_initiator_site_lock| enforcement code that |process_id|
+ // Notifies |request_initiator_origin_lock| enforcement code that |process_id|
// is proxying requests on behalf of a plugin from
// |allowed_request_initiator| origin.
//
@@ -399,6 +399,10 @@ interface NetworkService {
// https://docs.google.com/document/d/1TNnya6B8pyomDK2F1R9CL3dY10OAmqWlnCxsWyOBDVQ/edit#heading=h.z52drgpfgulz.
SetTrustTokenKeyCommitments(string raw_commitments) => ();
+ // Clears the SCT auditing cache.
+ [EnableIf=is_ct_supported]
+ ClearSCTAuditingCache();
+
// Calls base::debug::DumpWithoutCrashing for the network process.
// TODO(http://crbug.com/934317): Remove this once done debugging renderer
// hangs.
diff --git a/chromium/services/network/public/mojom/network_service_test.mojom b/chromium/services/network/public/mojom/network_service_test.mojom
index 70a8683f767..895e88cd6d2 100644
--- a/chromium/services/network/public/mojom/network_service_test.mojom
+++ b/chromium/services/network/public/mojom/network_service_test.mojom
@@ -112,4 +112,9 @@ interface NetworkServiceTest {
// Activates the specified field trial. Intended for use verifying that the
// network service informs the main process when a field trial is activated.
ActivateFieldTrial(string field_trial_name);
+
+ // Instantiates a net::ScopedTestEVPolicy with the specified fingerprint and
+ // policy oid.
+ [Sync]
+ SetEVPolicy(array<uint8, 32> fingerprint_sha256, string policy_oid) => ();
};
diff --git a/chromium/services/network/public/mojom/parsed_headers.mojom b/chromium/services/network/public/mojom/parsed_headers.mojom
index 01f1bf852cb..ab10d3cfd16 100644
--- a/chromium/services/network/public/mojom/parsed_headers.mojom
+++ b/chromium/services/network/public/mojom/parsed_headers.mojom
@@ -4,6 +4,7 @@
module network.mojom;
+import "mojo/public/mojom/base/time.mojom";
import "services/network/public/mojom/content_security_policy.mojom";
import "services/network/public/mojom/cross_origin_embedder_policy.mojom";
import "services/network/public/mojom/cross_origin_opener_policy.mojom";
@@ -15,6 +16,9 @@ struct ParsedHeaders {
// The parsed Content-Security-Policy from the response headers.
array<ContentSecurityPolicy> content_security_policy;
+ // The parsed value of the Allow-CSP-From response header.
+ AllowCSPFromHeaderValue? allow_csp_from;
+
// The parsed representation of Cross-Origin-Embedder-Policy and
// Cross-Origin-Embedder-Policy-Report-Only headers.
CrossOriginEmbedderPolicy cross_origin_embedder_policy;
@@ -34,4 +38,7 @@ struct ParsedHeaders {
// If this is present and an empty array, this means that client hints should
// be disabled (if updating client hint preference is valid in this context).
array<WebClientHintsType>? accept_ch;
+
+ // Parsed Accept-CH-Lifetime value, if any. Zero if missing or on parse error.
+ mojo_base.mojom.TimeDelta accept_ch_lifetime;
};
diff --git a/chromium/services/network/public/mojom/referrer_policy.mojom b/chromium/services/network/public/mojom/referrer_policy.mojom
index b159d7cba5e..237e8f28c65 100644
--- a/chromium/services/network/public/mojom/referrer_policy.mojom
+++ b/chromium/services/network/public/mojom/referrer_policy.mojom
@@ -15,5 +15,4 @@ enum ReferrerPolicy {
kStrictOriginWhenCrossOrigin,
kSameOrigin,
kStrictOrigin,
- kLast = kStrictOrigin,
};
diff --git a/chromium/services/network/public/mojom/ssl_config.mojom b/chromium/services/network/public/mojom/ssl_config.mojom
index f95093c16ae..c2b636e9884 100644
--- a/chromium/services/network/public/mojom/ssl_config.mojom
+++ b/chromium/services/network/public/mojom/ssl_config.mojom
@@ -20,10 +20,6 @@ struct SSLConfig {
bool sha1_local_anchors_enabled = false;
bool symantec_enforcement_disabled = false;
- // 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 = true;
-
// SSL 2.0 and 3.0 are not supported. Note these lines must be kept in sync
// with net/ssl/ssl_config.cc.
SSLVersion version_min = kTLS1;
@@ -42,7 +38,7 @@ struct SSLConfig {
// Patterns for matching hostnames to determine when to allow connection
// coalescing when client certificates are also in use. Patterns follow
- // the rules for host matching from the URL Blacklist filter format:
+ // the rules for host matching from the URL Blocklist filter format:
// "example.com" matches "example.com" and all subdomains, while
// ".example.net" matches exactly "example.net". Hostnames must be
// canonicalized according to the rules used by GURL.
diff --git a/chromium/services/network/public/mojom/trust_tokens.mojom b/chromium/services/network/public/mojom/trust_tokens.mojom
index 8f599953b9f..c138d2c8b21 100644
--- a/chromium/services/network/public/mojom/trust_tokens.mojom
+++ b/chromium/services/network/public/mojom/trust_tokens.mojom
@@ -109,7 +109,7 @@ struct TrustTokenParams {
// client-provided data).
TrustTokenSignRequestData sign_request_data = kOmit;
bool include_timestamp_header = false;
- url.mojom.Origin? issuer;
+ array<url.mojom.Origin> issuers;
array<string> additional_signed_headers;
// "possibly_unsafe_additional_signing_data", which stores the request's
diff --git a/chromium/services/network/public/mojom/url_loader.mojom b/chromium/services/network/public/mojom/url_loader.mojom
index b3b921ae7a5..eaf364de661 100644
--- a/chromium/services/network/public/mojom/url_loader.mojom
+++ b/chromium/services/network/public/mojom/url_loader.mojom
@@ -42,7 +42,7 @@ enum RequestPriority {
kHighest
};
-// This enum corresponds to net::URLRequest::ReferrerPolicy. See its comments.
+// This enum corresponds to net::ReferrerPolicy. See its comments.
enum URLRequestReferrerPolicy {
kClearReferrerOnTransitionFromSecureToInsecure,
kReduceReferrerGranularityOnTransitionCrossOrigin,
@@ -62,6 +62,7 @@ enum DataElementType {
// Only used for Upload with Network Service as of now:
kDataPipe,
kChunkedDataPipe,
+ kReadOnceStream,
kRawFile,
// Used for Upload when Network Service is disabled:
@@ -150,7 +151,7 @@ struct URLRequest {
//
// See also:
// - |isolated_world_origin|
- // - URLLoaderFactoryParams::request_initiator_site_lock
+ // - URLLoaderFactoryParams::request_initiator_origin_lock
url.mojom.Origin? request_initiator;
// If this is a subresource request initiated from an isolated world (e.g.
diff --git a/chromium/services/network/public/mojom/url_loader_factory.mojom b/chromium/services/network/public/mojom/url_loader_factory.mojom
index 8fecf02d4ff..b141eff3d63 100644
--- a/chromium/services/network/public/mojom/url_loader_factory.mojom
+++ b/chromium/services/network/public/mojom/url_loader_factory.mojom
@@ -8,27 +8,48 @@ import "services/network/public/mojom/mutable_network_traffic_annotation_tag.moj
import "services/network/public/mojom/url_loader.mojom";
const uint32 kURLLoadOptionNone = 0;
+
// Sends the net::SSLInfo struct in OnReceiveResponse.
const uint32 kURLLoadOptionSendSSLInfoWithResponse = 1;
+
// Enables mime sniffing.
const uint32 kURLLoadOptionSniffMimeType = 2;
+
// Indicates that execution is blocking on the completion of the request.
const uint32 kURLLoadOptionSynchronous = 4;
+
// Sends the net::SSLInfo struct in OnComplete when the connection had a major
// certificate error.
const uint32 kURLLoadOptionSendSSLInfoForCertificateError = 8;
+
// Uses the header client set in URLLoaderFactoryParams for this request.
const uint32 kURLLoadOptionUseHeaderClient = 16;
+
// Disallow the request from sending cookies. Disallow the response from writing
// cookies.
const uint32 kURLLoadOptionBlockAllCookies = 32;
+
// Similar to |kURLLoadOptionBlockAllCookies|, but only for third party cookies.
const uint32 kURLLoadOptionBlockThirdPartyCookies = 64;
+
// This request is for CORS preflight. This is used in the network service.
// This is set and used only in the network service, no callsites outside the
// service must set this.
const uint32 kURLLoadOptionAsCorsPreflight = 128;
+// Specifies that the request must not be made to a non-public IP address. This
+// option is needed even with CORS-RFC1918 because CORS-RFC1918 is not enabled
+// by default, and sometimes the client security state is not known as the time
+// of the request, which skips CORS-RFC1918.
+//
+// This option is supported by the network service, but might not be supported
+// by other URLLoaderFactory implementations.
+//
+// TODO(crbug.com/1115776): This option can be removed if CORS-RFC1918 ships
+// without a feature flag, and additionally it changes to block requests by
+// default if the security state is unknown.
+const uint32 kURLLoadOptionBlockLocalRequest = 256;
+
// URLLoaderFactory is an interface for requesting URLs. It creates URLLoader
// instances. One URLLoader instance can load one URL.
interface URLLoaderFactory {
diff --git a/chromium/services/network/quic_transport.cc b/chromium/services/network/quic_transport.cc
index 0ef85a5b839..8a06b3ebea3 100644
--- a/chromium/services/network/quic_transport.cc
+++ b/chromium/services/network/quic_transport.cc
@@ -148,7 +148,10 @@ class QuicTransport::Stream final {
MayDisposeLater();
}
- ~Stream() { transport_->transport_->session()->CloseStream(id_); }
+ ~Stream() {
+ transport_->transport_->session()->ResetStream(
+ id_, quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
+ }
private:
using ArmingPolicy = mojo::SimpleWatcher::ArmingPolicy;
@@ -506,13 +509,15 @@ void QuicTransport::OnIncomingBidirectionalStreamAvailable() {
sizeof(options), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 256 * 1024};
if (mojo::CreateDataPipe(&options, &writable_for_outgoing,
&readable_for_outgoing) != MOJO_RESULT_OK) {
- transport_->session()->CloseStream(stream->id());
+ transport_->session()->ResetStream(
+ stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
// TODO(yhirano): Error the entire connection.
return;
}
if (mojo::CreateDataPipe(&options, &writable_for_incoming,
&readable_for_incoming) != MOJO_RESULT_OK) {
- transport_->session()->CloseStream(stream->id());
+ transport_->session()->ResetStream(
+ stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
// TODO(yhirano): Error the entire connection.
return;
}
@@ -547,7 +552,8 @@ void QuicTransport::OnIncomingUnidirectionalStreamAvailable() {
sizeof(options), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 256 * 1024};
if (mojo::CreateDataPipe(&options, &writable_for_incoming,
&readable_for_incoming) != MOJO_RESULT_OK) {
- transport_->session()->CloseStream(stream->id());
+ transport_->session()->ResetStream(
+ stream->id(), quic::QuicRstStreamErrorCode::QUIC_STREAM_CANCELLED);
// TODO(yhirano): Error the entire connection.
return;
}
diff --git a/chromium/services/network/resource_scheduler/OWNERS b/chromium/services/network/resource_scheduler/OWNERS
index 6fa38eea7ea..bd5f1d8a351 100644
--- a/chromium/services/network/resource_scheduler/OWNERS
+++ b/chromium/services/network/resource_scheduler/OWNERS
@@ -1,4 +1,4 @@
tbansal@chromium.org
-dougarnett@chromium.org
+ryansturm@chromium.org
# COMPONENT: Internals>Network>NetworkQuality \ No newline at end of file
diff --git a/chromium/services/network/restricted_cookie_manager.cc b/chromium/services/network/restricted_cookie_manager.cc
index 888cc78e436..99cbccd4443 100644
--- a/chromium/services/network/restricted_cookie_manager.cc
+++ b/chromium/services/network/restricted_cookie_manager.cc
@@ -20,6 +20,7 @@
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/bindings/remote.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
+#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_constants.h"
#include "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
@@ -84,8 +85,9 @@ net::CookieOptions MakeOptionsForGet(
return options;
}
-void MarkSameSiteCompatPairs(std::vector<net::CookieWithStatus>& cookie_list,
- const net::CookieOptions& options) {
+void MarkSameSiteCompatPairs(
+ std::vector<net::CookieWithAccessResult>& 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() >
@@ -100,9 +102,9 @@ void MarkSameSiteCompatPairs(std::vector<net::CookieWithStatus>& cookie_list,
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(
+ cookie_list[i].access_result.status.AddWarningReason(
net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR);
- cookie_list[j].status.AddWarningReason(
+ cookie_list[j].access_result.status.AddWarningReason(
net::CookieInclusionStatus::WARN_SAMESITE_COMPAT_PAIR);
}
}
@@ -151,7 +153,8 @@ class RestrictedCookieManager::Listener : public base::LinkNode<Listener> {
void OnCookieChange(const net::CookieChangeInfo& change) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!change.cookie
- .IncludeForRequestURL(url_, options_, change.access_semantics)
+ .IncludeForRequestURL(url_, options_,
+ change.access_result.access_semantics)
.status.IsInclude()) {
return;
}
@@ -269,20 +272,18 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
url, site_for_cookies.RepresentativeUrl(), top_frame_origin);
std::vector<net::CookieWithAccessResult> result;
- std::vector<net::CookieWithStatus> result_with_status;
+ std::vector<net::CookieWithAccessResult> on_cookies_accessed_result;
// TODO(https://crbug.com/977040): Remove once samesite tightening up is
// rolled out.
- // |result_with_status| is populated with excluded cookies here based on
- // warnings present before WARN_SAMESITE_COMPAT_PAIR can be applied by
+ // |on_cookies_accessed_result| 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_access_result.cookie,
- cookie_and_access_result.access_result.status});
+ on_cookies_accessed_result.push_back(cookie_and_access_result);
}
}
@@ -293,7 +294,7 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
// TODO(https://crbug.com/993843): Use the statuses passed in |cookie_list|.
for (const net::CookieWithAccessResult& cookie_item : cookie_list) {
const net::CanonicalCookie& cookie = cookie_item.cookie;
- net::CookieInclusionStatus status = cookie_item.access_result.status;
+ net::CookieAccessResult access_result = cookie_item.access_result;
const std::string& cookie_name = cookie.Name();
if (match_type == mojom::CookieMatchType::EQUALS) {
@@ -309,22 +310,22 @@ void RestrictedCookieManager::CookieListToGetAllForUrlCallback(
}
if (blocked) {
- status.AddExclusionReason(
+ access_result.status.AddExclusionReason(
net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES);
} else {
result.push_back(cookie_item);
}
- result_with_status.push_back({cookie, status});
+ on_cookies_accessed_result.push_back({cookie, access_result});
}
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);
+ // Mark the CookieInclusionStatuses of items in |result_with_access_result|
+ // if they are part of a presumed SameSite compatibility pair.
+ MarkSameSiteCompatPairs(on_cookies_accessed_result, net_options);
cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
mojom::CookieAccessDetails::Type::kRead, url, site_for_cookies,
- result_with_status, base::nullopt));
+ on_cookies_accessed_result, base::nullopt));
}
if (blocked) {
@@ -343,7 +344,8 @@ void RestrictedCookieManager::SetCanonicalCookie(
const url::Origin& top_frame_origin,
SetCanonicalCookieCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
- if (!ValidateAccessToCookiesAt(url, site_for_cookies, top_frame_origin)) {
+ if (!ValidateAccessToCookiesAt(url, site_for_cookies, top_frame_origin,
+ &cookie)) {
std::move(callback).Run(false);
return;
}
@@ -363,24 +365,13 @@ void RestrictedCookieManager::SetCanonicalCookie(
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(
- net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH);
- UMA_HISTOGRAM_BOOLEAN(
- "Net.RestrictedCookieManager.SetCanonicalCookieDomainMatch",
- domain_match);
-
if (!status.IsInclude()) {
if (cookie_observer_) {
- std::vector<net::CookieWithStatus> result_with_status = {
- {cookie, status}};
+ std::vector<net::CookieWithAccessResult> result_with_access_result = {
+ {cookie, net::CookieAccessResult(status)}};
cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
mojom::CookieAccessDetails::Type::kChange, url, site_for_cookies,
- result_with_status, base::nullopt));
+ result_with_access_result, base::nullopt));
}
std::move(callback).Run(false);
return;
@@ -420,22 +411,22 @@ void RestrictedCookieManager::SetCanonicalCookieResult(
const net::CanonicalCookie& cookie,
const net::CookieOptions& net_options,
SetCanonicalCookieCallback user_callback,
- net::CookieInclusionStatus status) {
- std::vector<net::CookieWithStatus> notify;
+ net::CookieAccessResult access_result) {
+ std::vector<net::CookieWithAccessResult> notify;
// TODO(https://crbug.com/977040): Only report pure INCLUDE once samesite
// tightening up is rolled out.
- DCHECK(!status.HasExclusionReason(
+ DCHECK(!access_result.status.HasExclusionReason(
net::CookieInclusionStatus::EXCLUDE_USER_PREFERENCES));
- if (status.IsInclude() || status.ShouldWarn()) {
+ if (access_result.status.IsInclude() || access_result.status.ShouldWarn()) {
if (cookie_observer_) {
- notify.push_back({cookie, status});
+ notify.push_back({cookie, access_result});
cookie_observer_->OnCookiesAccessed(mojom::CookieAccessDetails::New(
mojom::CookieAccessDetails::Type::kChange, url, site_for_cookies,
notify, base::nullopt));
}
}
- std::move(user_callback).Run(status.IsInclude());
+ std::move(user_callback).Run(access_result.status.IsInclude());
}
void RestrictedCookieManager::AddChangeListener(
@@ -540,7 +531,8 @@ void RestrictedCookieManager::RemoveChangeListener(Listener* listener) {
bool RestrictedCookieManager::ValidateAccessToCookiesAt(
const GURL& url,
const net::SiteForCookies& site_for_cookies,
- const url::Origin& top_frame_origin) {
+ const url::Origin& top_frame_origin,
+ const net::CanonicalCookie* cookie_being_set) {
if (origin_.opaque()) {
mojo::ReportBadMessage("Access is denied in this context");
return false;
@@ -561,6 +553,12 @@ bool RestrictedCookieManager::ValidateAccessToCookiesAt(
UMA_HISTOGRAM_BOOLEAN("Net.RestrictedCookieManager.TopFrameOriginOK",
top_frame_origin_ok);
+ // Don't allow setting cookies on other domains. See crbug.com/996786.
+ if (cookie_being_set && !cookie_being_set->IsDomainMatch(url.host())) {
+ mojo::ReportBadMessage("Setting cookies on other domains is disallowed.");
+ return false;
+ }
+
if (origin_.IsSameOriginWith(url::Origin::Create(url)))
return true;
diff --git a/chromium/services/network/restricted_cookie_manager.h b/chromium/services/network/restricted_cookie_manager.h
index 1b0b50812e5..9c89588b80b 100644
--- a/chromium/services/network/restricted_cookie_manager.h
+++ b/chromium/services/network/restricted_cookie_manager.h
@@ -122,7 +122,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
const net::CanonicalCookie& cookie,
const net::CookieOptions& net_options,
SetCanonicalCookieCallback user_callback,
- net::CookieInclusionStatus status);
+ net::CookieAccessResult access_result);
// Called when the Mojo pipe associated with a listener is closed.
void RemoveChangeListener(Listener* listener);
@@ -132,11 +132,16 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) RestrictedCookieManager
// Returns true if the access should be allowed, or false if it should be
// blocked.
//
+ // |cookie_being_set| should be non-nullptr if setting a cookie, and should be
+ // nullptr otherwise (getting cookies, subscribing to cookie changes).
+ //
// If the access would not be allowed, this helper calls
// mojo::ReportBadMessage(), which closes the pipe.
- bool ValidateAccessToCookiesAt(const GURL& url,
- const net::SiteForCookies& site_for_cookies,
- const url::Origin& top_frame_origin);
+ bool ValidateAccessToCookiesAt(
+ const GURL& url,
+ const net::SiteForCookies& site_for_cookies,
+ const url::Origin& top_frame_origin,
+ const net::CanonicalCookie* cookie_being_set = nullptr);
const mojom::RestrictedCookieManagerRole role_;
net::CookieStore* const cookie_store_;
diff --git a/chromium/services/network/restricted_cookie_manager_unittest.cc b/chromium/services/network/restricted_cookie_manager_unittest.cc
index 36db8313971..d91c0c563ef 100644
--- a/chromium/services/network/restricted_cookie_manager_unittest.cc
+++ b/chromium/services/network/restricted_cookie_manager_unittest.cc
@@ -60,13 +60,13 @@ class RecordingCookieObserver : public network::mojom::CookieAccessObserver {
}
void OnCookiesAccessed(mojom::CookieAccessDetailsPtr details) override {
- for (const auto& cookie_and_status : details->cookie_list) {
+ for (const auto& cookie_and_access_result : details->cookie_list) {
CookieOp op;
op.get = details->type == mojom::CookieAccessDetails::Type::kRead;
op.url = details->url;
op.site_for_cookies = details->site_for_cookies.RepresentativeUrl();
- op.cookie.push_back(cookie_and_status.cookie);
- op.status = cookie_and_status.status;
+ op.cookie.push_back(cookie_and_access_result.cookie);
+ op.status = cookie_and_access_result.access_result.status;
op.devtools_request_id = details->devtools_request_id;
recorded_activity_.push_back(op);
}
@@ -204,33 +204,31 @@ class RestrictedCookieManagerTest
bool SetCanonicalCookie(const net::CanonicalCookie& cookie,
std::string source_scheme,
bool can_modify_httponly) {
- net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> 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::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ callback.MakeCallback());
callback.WaitUntilDone();
- return callback.result().IsInclude();
+ return callback.result().status.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;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> 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,
+ &net::ResultSavingCookieCallback<net::CookieAccessResult>::Run,
base::Unretained(&callback)));
callback.WaitUntilDone();
- return callback.result().IsInclude();
+ return callback.result().status.IsInclude();
}
// Simplified helper for SetCanonicalCookie.
@@ -616,28 +614,6 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieHttpOnly) {
}
}
-TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieValidateDomain) {
- GURL other_site("https://not-example.com");
- auto cookie = net::CanonicalCookie::Create(
- other_site, "cookie=foo;domain=not-example.com", base::Time::Now(),
- base::nullopt);
- ASSERT_EQ(".not-example.com", cookie->Domain());
- EXPECT_FALSE(sync_service_->SetCanonicalCookie(
- *cookie, GURL("https://example.com/test"), GURL("https://example.com"),
- url::Origin::Create(GURL("https://example.com"))));
- ASSERT_EQ(1u, recorded_activity().size());
- EXPECT_TRUE(recorded_activity()[0].status.HasExclusionReason(
- net::CookieInclusionStatus::EXCLUDE_DOMAIN_MISMATCH));
-
- auto options = mojom::CookieManagerGetOptions::New();
- options->name = "cookie";
- options->match_type = mojom::CookieMatchType::EQUALS;
- std::vector<net::CanonicalCookie> cookies = sync_service_->GetAllForUrl(
- GURL("https://example.com/test/"), GURL("https://example.com"),
- url::Origin::Create(GURL("https://example.com")), std::move(options));
- EXPECT_THAT(cookies, testing::SizeIs(0));
-}
-
TEST_P(RestrictedCookieManagerTest, SetCookieFromString) {
EXPECT_TRUE(backend()->SetCookieFromString(
GURL("https://example.com/test/"),
@@ -687,6 +663,19 @@ TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieFromOpaqueOrigin) {
ASSERT_TRUE(received_bad_message());
}
+TEST_P(RestrictedCookieManagerTest, SetCanonicalCookieWithMismatchingDomain) {
+ ExpectBadMessage();
+ EXPECT_FALSE(sync_service_->SetCanonicalCookie(
+ net::CanonicalCookie(
+ "new-name", "new-value", "not-example.com", "/", base::Time(),
+ base::Time(), base::Time(), /* secure = */ true,
+ /* httponly = */ false, net::CookieSameSite::NO_RESTRICTION,
+ net::COOKIE_PRIORITY_DEFAULT),
+ GURL("https://example.com/test/"), GURL("https://example.com"),
+ url::Origin::Create(GURL("https://example.com"))));
+ ASSERT_TRUE(received_bad_message());
+}
+
TEST_P(RestrictedCookieManagerTest, SetCookieFromStringWrongOrigin) {
ExpectBadMessage();
EXPECT_TRUE(backend()->SetCookieFromString(
@@ -1290,21 +1279,19 @@ TEST_P(RestrictedCookieManagerTest, ChangeNotificationIncludesAccessSemantics) {
base::nullopt);
// Set cookie directly into the CookieMonster, using all-inclusive options.
- net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> callback;
cookie_monster_.SetCanonicalCookieAsync(
std::move(cookie), cookie_url, net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(
- &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
- base::Unretained(&callback)));
+ callback.MakeCallback());
callback.WaitUntilDone();
- ASSERT_TRUE(callback.result().IsInclude());
+ ASSERT_TRUE(callback.result().status.IsInclude());
// The listener only receives the change because the cookie is legacy.
listener.WaitForChange();
ASSERT_THAT(listener.observed_changes(), testing::SizeIs(1));
EXPECT_EQ(net::CookieAccessSemantics::LEGACY,
- listener.observed_changes()[0].access_semantics);
+ listener.observed_changes()[0].access_result.access_semantics);
}
TEST_P(RestrictedCookieManagerTest, NoChangeNotificationForNonlegacyCookie) {
@@ -1345,30 +1332,24 @@ TEST_P(RestrictedCookieManagerTest, NoChangeNotificationForNonlegacyCookie) {
base::Time::Now(), base::nullopt);
// Set cookies directly into the CookieMonster, using all-inclusive options.
- net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback1;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> callback1;
cookie_monster_.SetCanonicalCookieAsync(
std::move(unspecified_cookie), cookie_url,
- net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(
- &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
- base::Unretained(&callback1)));
+ net::CookieOptions::MakeAllInclusive(), callback1.MakeCallback());
callback1.WaitUntilDone();
- ASSERT_TRUE(callback1.result().IsInclude());
+ ASSERT_TRUE(callback1.result().status.IsInclude());
// Listener doesn't receive notification because cookie is not included for
// request URL for being unspecified and treated as lax.
base::RunLoop().RunUntilIdle();
ASSERT_THAT(listener.observed_changes(), testing::SizeIs(0));
- net::ResultSavingCookieCallback<net::CookieInclusionStatus> callback2;
+ net::ResultSavingCookieCallback<net::CookieAccessResult> callback2;
cookie_monster_.SetCanonicalCookieAsync(
std::move(samesite_none_cookie), cookie_url,
- net::CookieOptions::MakeAllInclusive(),
- base::BindOnce(
- &net::ResultSavingCookieCallback<net::CookieInclusionStatus>::Run,
- base::Unretained(&callback2)));
+ net::CookieOptions::MakeAllInclusive(), callback2.MakeCallback());
callback2.WaitUntilDone();
- ASSERT_TRUE(callback2.result().IsInclude());
+ ASSERT_TRUE(callback2.result().status.IsInclude());
// Listener only receives notification about the SameSite=None cookie.
listener.WaitForChange();
@@ -1377,7 +1358,7 @@ TEST_P(RestrictedCookieManagerTest, NoChangeNotificationForNonlegacyCookie) {
EXPECT_EQ("samesite_none_cookie",
listener.observed_changes()[0].cookie.Name());
EXPECT_EQ(net::CookieAccessSemantics::NONLEGACY,
- listener.observed_changes()[0].access_semantics);
+ listener.observed_changes()[0].access_result.access_semantics);
}
INSTANTIATE_TEST_SUITE_P(
diff --git a/chromium/services/network/sct_auditing_cache.cc b/chromium/services/network/sct_auditing_cache.cc
new file mode 100644
index 00000000000..c6b01f76ab2
--- /dev/null
+++ b/chromium/services/network/sct_auditing_cache.cc
@@ -0,0 +1,100 @@
+// 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/sct_auditing_cache.h"
+
+#include "base/feature_list.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/rand_util.h"
+#include "crypto/secure_hash.h"
+#include "crypto/sha2.h"
+#include "net/base/hash_value.h"
+#include "net/base/host_port_pair.h"
+#include "net/cert/ct_serialization.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
+#include "net/cert/x509_certificate.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
+#include "third_party/boringssl/src/include/openssl/pool.h"
+#include "third_party/boringssl/src/include/openssl/sha.h"
+
+namespace network {
+
+SCTAuditReport::SCTAuditReport() = default;
+SCTAuditReport::~SCTAuditReport() = default;
+SCTAuditReport::SCTAuditReport(const SCTAuditReport& other) = default;
+SCTAuditReport::SCTAuditReport(SCTAuditReport&& other) = default;
+
+SCTAuditingCache::SCTAuditingCache(size_t cache_size) : cache_(cache_size) {}
+SCTAuditingCache::~SCTAuditingCache() = default;
+
+void SCTAuditingCache::MaybeEnqueueReport(
+ NetworkContext* context,
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps) {
+ if (!base::FeatureList::IsEnabled(features::kSCTAuditing) ||
+ !context->is_sct_auditing_enabled()) {
+ return;
+ }
+
+ // Generate the cache key for this report. In order to have the cache
+ // deduplicate reports for the same SCTs, we compute the cache key as the
+ // hash of the SCTs. The digest is converted to a string for use over Mojo.
+ SHA256_CTX ctx;
+ SHA256_Init(&ctx);
+ for (const auto& sct : signed_certificate_timestamps) {
+ std::string serialized_sct;
+ net::ct::EncodeSignedCertificateTimestamp(sct.sct, &serialized_sct);
+ SHA256_Update(&ctx, serialized_sct.data(), serialized_sct.size());
+ }
+ net::SHA256HashValue cache_key;
+ SHA256_Final(reinterpret_cast<uint8_t*>(&cache_key), &ctx);
+
+ // Check if the SCTs are already in the cache. This will update the last seen
+ // time if they are present in the cache.
+ auto it = cache_.Get(cache_key);
+ if (it != cache_.end())
+ return;
+
+ // Insert SCTs into cache.
+ // TODO(crbug.com/1082860): Construct the proto object directly and store that
+ // in the cache instead of this intermediate form, once the proto is added.
+ auto report = std::make_unique<SCTAuditReport>();
+ report->time_seen = base::Time::Now();
+ report->host_port_pair = host_port_pair;
+
+ // GetPEMEncodedChain() can fail, but we still want to enqueue the report for
+ // the SCTs (in that case, |report->certificate_chain| is not guaranteed to
+ // be valid).
+ report->certificate_chain = std::vector<std::string>();
+ validated_certificate_chain->GetPEMEncodedChain(&report->certificate_chain);
+
+ for (const auto& sct : signed_certificate_timestamps) {
+ report->sct_list.push_back(sct);
+ }
+
+ cache_.Put(cache_key, std::move(report));
+
+ double sampling_rate = features::kSCTAuditingSamplingRate.Get();
+ if (base::RandDouble() > sampling_rate)
+ return;
+
+ context->client()->OnSCTReportReady(net::HashValue(cache_key).ToString());
+}
+
+SCTAuditReport* SCTAuditingCache::GetPendingReport(
+ const net::SHA256HashValue& cache_key) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+void SCTAuditingCache::ClearCache() {
+ cache_.Clear();
+}
+
+} // namespace network
diff --git a/chromium/services/network/sct_auditing_cache.h b/chromium/services/network/sct_auditing_cache.h
new file mode 100644
index 00000000000..1ddfdd56e40
--- /dev/null
+++ b/chromium/services/network/sct_auditing_cache.h
@@ -0,0 +1,87 @@
+// 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_SCT_AUDITING_CACHE_H_
+#define SERVICES_NETWORK_SCT_AUDITING_CACHE_H_
+
+#include <string>
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/mru_cache.h"
+#include "base/time/time.h"
+#include "net/base/hash_value.h"
+#include "net/base/host_port_pair.h"
+#include "net/cert/sct_auditing_delegate.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
+
+namespace net {
+class X509Certificate;
+}
+
+namespace network {
+class NetworkContext;
+
+struct SCTAuditReport {
+ SCTAuditReport();
+ ~SCTAuditReport();
+
+ SCTAuditReport(const SCTAuditReport& other);
+ SCTAuditReport& operator=(const SCTAuditReport& other) = default;
+ SCTAuditReport(SCTAuditReport&& other);
+ SCTAuditReport& operator=(SCTAuditReport&& other) = default;
+
+ base::Time time_seen;
+ net::HostPortPair host_port_pair;
+ std::vector<std::string> certificate_chain;
+ std::vector<net::SignedCertificateTimestampAndStatus> sct_list;
+};
+
+// SCTAuditingCache tracks SCTs seen during CT verification. The cache supports
+// a configurable sample rate to reduce load, and deduplicates SCTs seen more
+// than once. The cache evicts least-recently-used entries after it reaches its
+// capacity.
+//
+// A single SCTAuditingCache should be shared among all contexts that want to
+// deduplicate reports and use a single sampling mechanism. Currently, one
+// SCTAuditingCache is created and owned by the NetworkService and shared
+// across all NetworkContexts.
+class COMPONENT_EXPORT(NETWORK_SERVICE) SCTAuditingCache {
+ public:
+ explicit SCTAuditingCache(size_t cache_size);
+ ~SCTAuditingCache();
+
+ SCTAuditingCache(const SCTAuditingCache&) = delete;
+ SCTAuditingCache& operator=(const SCTAuditingCache&) = delete;
+
+ // Creates a report containing the details about the connection context and
+ // SCTs and adds it to the cache if the SCTs are not already in the
+ // cache. If the SCTs were not already in the cache, a random sample is drawn
+ // to determine whether to notify the NetworkContextClient (and thus send a
+ // report). This means we sample a subset of *certificates* rather than a
+ // subset of *connections*. If a new entry is sampled, the associated
+ // NetworkContextClient is notified.
+ void MaybeEnqueueReport(
+ NetworkContext* context,
+ const net::HostPortPair& host_port_pair,
+ const net::X509Certificate* validated_certificate_chain,
+ const net::SignedCertificateTimestampAndStatusList&
+ signed_certificate_timestamps);
+
+ SCTAuditReport* GetPendingReport(const net::SHA256HashValue& cache_key);
+
+ void ClearCache();
+
+ base::MRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditReport>>*
+ GetCacheForTesting() {
+ return &cache_;
+ }
+
+ private:
+ base::MRUCache<net::SHA256HashValue, std::unique_ptr<SCTAuditReport>> cache_;
+};
+
+} // namespace network
+
+#endif // SERVICES_NETWORK_SCT_AUDITING_CACHE_H_
diff --git a/chromium/services/network/sct_auditing_cache_unittest.cc b/chromium/services/network/sct_auditing_cache_unittest.cc
new file mode 100644
index 00000000000..b1a86e6805e
--- /dev/null
+++ b/chromium/services/network/sct_auditing_cache_unittest.cc
@@ -0,0 +1,272 @@
+// 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/sct_auditing_cache.h"
+
+#include "base/feature_list.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/metrics/field_trial_params.h"
+#include "base/test/scoped_feature_list.h"
+#include "base/test/task_environment.h"
+#include "net/base/host_port_pair.h"
+#include "net/cert/sct_status_flags.h"
+#include "net/cert/signed_certificate_timestamp.h"
+#include "net/cert/signed_certificate_timestamp_and_status.h"
+#include "net/test/cert_test_util.h"
+#include "net/test/test_data_directory.h"
+#include "services/network/network_context.h"
+#include "services/network/network_service.h"
+#include "services/network/public/cpp/features.h"
+#include "services/network/test/test_network_context_client.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace network {
+
+namespace {
+
+base::test::ScopedFeatureList::FeatureAndParams probability_zero{
+ network::features::kSCTAuditing,
+ {{network::features::kSCTAuditingSamplingRate.name, "0.0"}}};
+base::test::ScopedFeatureList::FeatureAndParams probability_one{
+ network::features::kSCTAuditing,
+ {{network::features::kSCTAuditingSamplingRate.name, "1.0"}}};
+
+class SCTAuditingCacheTest : public testing::Test {
+ public:
+ SCTAuditingCacheTest()
+ : network_service_(NetworkService::CreateForTesting()) {}
+ ~SCTAuditingCacheTest() override = default;
+
+ SCTAuditingCacheTest(const SCTAuditingCacheTest&) = delete;
+ SCTAuditingCacheTest& operator=(const SCTAuditingCacheTest&) = delete;
+
+ void SetUp() override {
+ InitNetworkContext();
+ network_context_->SetIsSCTAuditingEnabledForTesting(true);
+ chain_ =
+ net::ImportCertFromFile(net::GetTestCertsDirectory(), "ok_cert.pem");
+ ASSERT_TRUE(chain_.get());
+ }
+
+ protected:
+ void InitNetworkContext() {
+ network_context_ = std::make_unique<NetworkContext>(
+ network_service_.get(),
+ network_context_remote_.BindNewPipeAndPassReceiver(),
+ mojom::NetworkContextParams::New());
+
+ // A NetworkContextClient is needed for embedder notifications to work.
+ mojo::PendingRemote<network::mojom::NetworkContextClient>
+ network_context_client_remote;
+ network_context_client_ =
+ std::make_unique<network::TestNetworkContextClient>(
+ network_context_client_remote.InitWithNewPipeAndPassReceiver());
+ network_context_->SetClient(std::move(network_context_client_remote));
+ }
+
+ base::test::TaskEnvironment task_environment_{
+ base::test::TaskEnvironment::MainThreadType::IO};
+ std::unique_ptr<NetworkService> network_service_;
+ std::unique_ptr<NetworkContext> network_context_;
+ std::unique_ptr<network::mojom::NetworkContextClient> network_context_client_;
+
+ scoped_refptr<net::X509Certificate> chain_;
+
+ // Stores the mojo::Remote<mojom::NetworkContext> of the most recently created
+ // NetworkContext.
+ mojo::Remote<mojom::NetworkContext> network_context_remote_;
+};
+
+// Constructs a net::SignedCertificateTimestampAndStatus with the given
+// information and appends it to |sct_list|.
+void MakeTestSCTAndStatus(
+ net::ct::SignedCertificateTimestamp::Origin origin,
+ const std::string& extensions,
+ const std::string& signature_data,
+ const base::Time& timestamp,
+ net::ct::SCTVerifyStatus status,
+ net::SignedCertificateTimestampAndStatusList* sct_list) {
+ scoped_refptr<net::ct::SignedCertificateTimestamp> sct(
+ new net::ct::SignedCertificateTimestamp());
+ sct->version = net::ct::SignedCertificateTimestamp::V1;
+
+ // The particular value of the log ID doesn't matter; it just has to be the
+ // correct length.
+ const unsigned char kTestLogId[] = {
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01};
+ const std::string log_id(reinterpret_cast<const char*>(kTestLogId),
+ sizeof(kTestLogId));
+ sct->log_id = log_id;
+
+ sct->extensions = extensions;
+ sct->timestamp = timestamp;
+ sct->signature.signature_data = signature_data;
+ sct->origin = origin;
+ sct_list->push_back(net::SignedCertificateTimestampAndStatus(sct, status));
+}
+
+} // namespace
+
+// Test that if auditing is disabled on the NetworkContext, no reports are
+// cached.
+TEST_F(SCTAuditingCacheTest, NoReportsCachedWhenAuditingDisabled) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({probability_one}, {});
+ SCTAuditingCache cache(10);
+
+ network_context_->SetIsSCTAuditingEnabledForTesting(false);
+
+ const net::HostPortPair host_port_pair("example.com", 443);
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature1", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
+
+ ASSERT_EQ(0u, cache.GetCacheForTesting()->size());
+}
+
+// Test that inserting and retrieving a report works.
+TEST_F(SCTAuditingCacheTest, InsertAndRetrieveReport) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({probability_one}, {});
+ SCTAuditingCache cache(10);
+
+ const net::HostPortPair host_port_pair("example.com", 443);
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature1", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair, chain_.get(),
+ sct_list);
+
+ ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
+}
+
+// Tests that old entries are evicted when the cache is full.
+TEST_F(SCTAuditingCacheTest, EvictLRUAfterCacheFull) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({probability_one}, {});
+ SCTAuditingCache cache(2);
+
+ const net::HostPortPair host_port_pair1("example1.com", 443);
+ const net::HostPortPair host_port_pair2("example2.com", 443);
+ const net::HostPortPair host_port_pair3("example3.com", 443);
+
+ {
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature1", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
+ chain_.get(), sct_list);
+ ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
+ }
+
+ {
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature2", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list);
+ ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
+ }
+
+ // Cache is now full, so the first entry (for "example1.com") should no longer
+ // be in the cache after inserting a third entry.
+ {
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature3", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
+ chain_.get(), sct_list);
+ ASSERT_EQ(2u, cache.GetCacheForTesting()->size());
+ for (const auto& entry : *cache.GetCacheForTesting()) {
+ ASSERT_NE("example1.com", entry.second->host_port_pair.host());
+ }
+ }
+}
+
+// Tests that a new report gets dropped if the same SCTs are already in the
+// cache.
+TEST_F(SCTAuditingCacheTest, ReportWithSameSCTsDeduplicated) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({probability_one}, {});
+ SCTAuditingCache cache(10);
+
+ const net::HostPortPair host_port_pair1("example.com", 443);
+ const net::HostPortPair host_port_pair2("example.org", 443);
+
+ net::SignedCertificateTimestampAndStatusList sct_list;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature1", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
+ chain_.get(), sct_list);
+
+ ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
+
+ // Enqueuing the same SCTs won't cause a new report to be added to the queue
+ // (even if the connection origin is different).
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list);
+ ASSERT_EQ(1u, cache.GetCacheForTesting()->size());
+}
+
+// When a report gets deduplicated, the existing entry should have its last-seen
+// time bumped up.
+TEST_F(SCTAuditingCacheTest, DeduplicationUpdatesLastSeenTime) {
+ base::test::ScopedFeatureList feature_list;
+ feature_list.InitWithFeaturesAndParameters({probability_one}, {});
+ SCTAuditingCache cache(2);
+
+ const net::HostPortPair host_port_pair1("example1.com", 443);
+ const net::HostPortPair host_port_pair2("example2.com", 443);
+ const net::HostPortPair host_port_pair3("example3.com", 443);
+
+ // Fill the cache with two reports.
+ net::SignedCertificateTimestampAndStatusList sct_list1;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions1", "signature1", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list1);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
+ chain_.get(), sct_list1);
+
+ net::SignedCertificateTimestampAndStatusList sct_list2;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions2", "signature2", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list2);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair2,
+ chain_.get(), sct_list2);
+
+ EXPECT_EQ(2u, cache.GetCacheForTesting()->size());
+
+ // Try to enqueue the report for "example1.com" again. It should be deduped.
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair1,
+ chain_.get(), sct_list1);
+ EXPECT_EQ(2u, cache.GetCacheForTesting()->size());
+
+ // If we enqueue a new report causing the cache size limit to be exceeded,
+ // "example1.com" should be the most-recent due to getting updated during
+ // deduping, and "example2.com" should get evicted instead.
+ net::SignedCertificateTimestampAndStatusList sct_list3;
+ MakeTestSCTAndStatus(net::ct::SignedCertificateTimestamp::SCT_EMBEDDED,
+ "extensions3", "signature3", base::Time::Now(),
+ net::ct::SCT_STATUS_LOG_UNKNOWN, &sct_list3);
+ cache.MaybeEnqueueReport(network_context_.get(), host_port_pair3,
+ chain_.get(), sct_list3);
+
+ EXPECT_EQ(2u, cache.GetCacheForTesting()->size());
+ for (const auto& entry : *cache.GetCacheForTesting()) {
+ ASSERT_NE("example2.com", entry.second->host_port_pair.host());
+ }
+}
+
+} // namespace network
diff --git a/chromium/services/network/sec_header_helpers.cc b/chromium/services/network/sec_header_helpers.cc
index a02160b2170..7e64d9cc575 100644
--- a/chromium/services/network/sec_header_helpers.cc
+++ b/chromium/services/network/sec_header_helpers.cc
@@ -78,7 +78,7 @@ void SetSecFetchSiteHeader(
const mojom::URLLoaderFactoryParams& factory_params) {
SecFetchSiteValue header_value;
url::Origin initiator = GetTrustworthyInitiator(
- factory_params.request_initiator_site_lock, request->initiator());
+ factory_params.request_initiator_origin_lock, request->initiator());
// Browser-initiated requests with no initiator origin, and
// privileged requests initiated from a "non-webby" context will send
diff --git a/chromium/services/network/session_cleanup_cookie_store.h b/chromium/services/network/session_cleanup_cookie_store.h
index 7e9a12ea700..46c6a84dc3b 100644
--- a/chromium/services/network/session_cleanup_cookie_store.h
+++ b/chromium/services/network/session_cleanup_cookie_store.h
@@ -18,6 +18,7 @@
#include "net/cookies/cookie_monster.h"
#include "net/extras/sqlite/sqlite_persistent_cookie_store.h"
#include "net/log/net_log_with_source.h"
+#include "services/network/public/cpp/session_cookie_delete_predicate.h"
namespace net {
class CanonicalCookie;
@@ -26,16 +27,12 @@ class CanonicalCookie;
namespace network {
// Implements a PersistentCookieStore that keeps an in-memory map of cookie
-// origins, and allows deletion of cookies using the DeleteCookiePredicate. This
-// is used to clear cookies with session-only policy at the end of a session.
+// origins, and allows deletion of cookies using the
+// network::DeleteCookiePredicate. This is used to clear cookies with
+// session-only policy at the end of a session.
class COMPONENT_EXPORT(NETWORK_SERVICE) SessionCleanupCookieStore
: public net::CookieMonster::PersistentCookieStore {
public:
- // Returns true if the cookie associated with the domain and is_https status
- // should be deleted.
- using DeleteCookiePredicate =
- base::RepeatingCallback<bool(const std::string&, bool)>;
-
using CookiesPerOriginMap =
std::map<net::SQLitePersistentCookieStore::CookieOrigin, size_t>;
diff --git a/chromium/services/network/ssl_config_service_mojo.cc b/chromium/services/network/ssl_config_service_mojo.cc
index e874fa7c3fc..247d8dfae4b 100644
--- a/chromium/services/network/ssl_config_service_mojo.cc
+++ b/chromium/services/network/ssl_config_service_mojo.cc
@@ -5,7 +5,7 @@
#include "services/network/ssl_config_service_mojo.h"
#include "base/strings/string_piece.h"
-#include "base/strings/string_piece_forward.h"
+#include "base/strings/string_util.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "services/network/legacy_tls_config_distributor.h"
#include "services/network/ssl_config_type_converter.h"
@@ -24,7 +24,7 @@ bool IsSubdomain(const base::StringPiece hostname,
if (hostname.length() <= (pattern.length() + 1)) {
return false;
}
- if (!hostname.ends_with(pattern)) {
+ if (!base::EndsWith(hostname, pattern)) {
return false;
}
return hostname[hostname.length() - pattern.length() - 1] == '.';
diff --git a/chromium/services/network/ssl_config_service_mojo_unittest.cc b/chromium/services/network/ssl_config_service_mojo_unittest.cc
index 8679184550f..2b85ba4a52c 100644
--- a/chromium/services/network/ssl_config_service_mojo_unittest.cc
+++ b/chromium/services/network/ssl_config_service_mojo_unittest.cc
@@ -439,16 +439,6 @@ TEST_F(NetworkServiceSSLConfigServiceTest,
RunConversionTests(*mojo_config, expected_net_config);
}
-TEST_F(NetworkServiceSSLConfigServiceTest, InitialConfigTLS13Hardening) {
- net::SSLContextConfig expected_net_config;
- 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 = false;
-
- RunConversionTests(*mojo_config, expected_net_config);
-}
-
TEST_F(NetworkServiceSSLConfigServiceTest, CanShareConnectionWithClientCerts) {
// Create a default NetworkContext and test that
// CanShareConnectionWithClientCerts returns false.
diff --git a/chromium/services/network/ssl_config_type_converter.cc b/chromium/services/network/ssl_config_type_converter.cc
index 3fc0c4db592..7d09bb5cd51 100644
--- a/chromium/services/network/ssl_config_type_converter.cc
+++ b/chromium/services/network/ssl_config_type_converter.cc
@@ -37,8 +37,6 @@ net::SSLContextConfig MojoSSLConfigToSSLContextConfig(
DCHECK_LE(net_config.version_min, net_config.version_max);
net_config.disabled_cipher_suites = mojo_config->disabled_cipher_suites;
- net_config.tls13_hardening_for_local_anchors_enabled =
- mojo_config->tls13_hardening_for_local_anchors_enabled;
return net_config;
}
diff --git a/chromium/services/network/tcp_bound_socket_unittest.cc b/chromium/services/network/tcp_bound_socket_unittest.cc
index facd307dd87..c6800ff89a9 100644
--- a/chromium/services/network/tcp_bound_socket_unittest.cc
+++ b/chromium/services/network/tcp_bound_socket_unittest.cc
@@ -226,7 +226,7 @@ TEST_F(TCPBoundSocketTest, BindError) {
//
// Don't run on Apple platforms because this pattern ends in a connect timeout
// on OSX (after 25+ seconds) instead of connection refused.
-#if !defined(OS_MACOSX) && !defined(OS_IOS)
+#if !defined(OS_APPLE)
TEST_F(TCPBoundSocketTest, ConnectError) {
mojo::Remote<mojom::TCPBoundSocket> bound_socket1;
net::IPEndPoint bound_address1;
@@ -248,7 +248,7 @@ TEST_F(TCPBoundSocketTest, ConnectError) {
&connected_socket, mojo::NullRemote(),
&client_socket_receive_handle, &client_socket_send_handle));
}
-#endif // !defined(OS_MACOSX) && !defined(OS_IOS)
+#endif // !defined(OS_APPLE)
// Test listen failure.
@@ -258,7 +258,7 @@ TEST_F(TCPBoundSocketTest, ConnectError) {
//
// Apple platforms don't allow binding multiple TCP sockets to the same port
// even with SO_REUSEADDR enabled.
-#if !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_IOS)
+#if !defined(OS_WIN) && !defined(OS_APPLE)
TEST_F(TCPBoundSocketTest, ListenError) {
// Bind a socket.
mojo::Remote<mojom::TCPBoundSocket> bound_socket1;
@@ -285,7 +285,7 @@ TEST_F(TCPBoundSocketTest, ListenError) {
EXPECT_TRUE(result == net::ERR_ADDRESS_IN_USE ||
result == net::ERR_INVALID_ARGUMENT);
}
-#endif // !defined(OS_WIN) && !defined(OS_MACOSX) && !defined(OS_IOS)
+#endif // !defined(OS_WIN) && !defined(OS_APPLE)
// Test the case bind succeeds, and transfer some data.
TEST_F(TCPBoundSocketTest, ReadWrite) {
diff --git a/chromium/services/network/tcp_socket_unittest.cc b/chromium/services/network/tcp_socket_unittest.cc
index b0be79ae427..9e65857c518 100644
--- a/chromium/services/network/tcp_socket_unittest.cc
+++ b/chromium/services/network/tcp_socket_unittest.cc
@@ -38,7 +38,7 @@
#include "services/network/tcp_server_socket.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
@@ -575,7 +575,7 @@ TEST_F(TCPSocketTest, SocketClosed) {
int result = observer()->WaitForWriteError();
bool result_ok = result == net::ERR_CONNECTION_RESET ||
result == net::ERR_CONNECTION_ABORTED;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
// On some macOS kernels, send() on a closing TCP socket can return
// EPROTOTYPE, which is unknown to the net stack and gets mapped to
// net::ERR_FAILED.
diff --git a/chromium/services/network/throttling/throttling_network_interceptor.cc b/chromium/services/network/throttling/throttling_network_interceptor.cc
index 203d6d37de0..4a83c2b57e3 100644
--- a/chromium/services/network/throttling/throttling_network_interceptor.cc
+++ b/chromium/services/network/throttling/throttling_network_interceptor.cc
@@ -18,16 +18,11 @@ namespace network {
namespace {
-int64_t kPacketSize = 1500;
+constexpr int64_t kPacketSize = 1500;
base::TimeDelta CalculateTickLength(double throughput) {
- if (!throughput)
- return base::TimeDelta::FromMicroseconds(1);
- int64_t us_tick_length = (1000000L * kPacketSize) / throughput;
- DCHECK(us_tick_length != 0);
- if (us_tick_length == 0)
- us_tick_length = 1;
- return base::TimeDelta::FromMicroseconds(us_tick_length);
+ return throughput ? base::TimeDelta::FromSecondsD(kPacketSize / throughput)
+ : base::TimeDelta::FromMicroseconds(1);
}
} // namespace
@@ -109,7 +104,7 @@ uint64_t ThrottlingNetworkInterceptor::UpdateThrottledRecords(
return last_tick;
}
- int64_t new_tick = (now - offset_) / tick_length;
+ int64_t new_tick = (now - offset_).IntDiv(tick_length);
int64_t ticks = new_tick - last_tick;
int64_t length = records->size();
diff --git a/chromium/services/network/throttling/throttling_network_transaction.cc b/chromium/services/network/throttling/throttling_network_transaction.cc
index 75b96109880..589ec4723e0 100644
--- a/chromium/services/network/throttling/throttling_network_transaction.cc
+++ b/chromium/services/network/throttling/throttling_network_transaction.cc
@@ -274,8 +274,8 @@ void ThrottlingNetworkTransaction::SetWebSocketHandshakeStreamCreateHelper(
}
void ThrottlingNetworkTransaction::SetBeforeNetworkStartCallback(
- const BeforeNetworkStartCallback& callback) {
- network_transaction_->SetBeforeNetworkStartCallback(callback);
+ BeforeNetworkStartCallback callback) {
+ network_transaction_->SetBeforeNetworkStartCallback(std::move(callback));
}
void ThrottlingNetworkTransaction::SetRequestHeadersCallback(
@@ -288,6 +288,11 @@ void ThrottlingNetworkTransaction::SetResponseHeadersCallback(
network_transaction_->SetResponseHeadersCallback(std::move(callback));
}
+void ThrottlingNetworkTransaction::SetConnectedCallback(
+ const ConnectedCallback& callback) {
+ network_transaction_->SetConnectedCallback(callback);
+}
+
int ThrottlingNetworkTransaction::ResumeNetworkStart() {
if (CheckFailed())
return net::ERR_INTERNET_DISCONNECTED;
diff --git a/chromium/services/network/throttling/throttling_network_transaction.h b/chromium/services/network/throttling/throttling_network_transaction.h
index d5a4da0b40e..a9adb443fc5 100644
--- a/chromium/services/network/throttling/throttling_network_transaction.h
+++ b/chromium/services/network/throttling/throttling_network_transaction.h
@@ -78,7 +78,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) ThrottlingNetworkTransaction
void SetWebSocketHandshakeStreamCreateHelper(
net::WebSocketHandshakeStreamBase::CreateHelper* create_helper) override;
void SetBeforeNetworkStartCallback(
- const BeforeNetworkStartCallback& callback) override;
+ BeforeNetworkStartCallback callback) override;
+ void SetConnectedCallback(const ConnectedCallback& callback) override;
void SetRequestHeadersCallback(net::RequestHeadersCallback callback) override;
void SetResponseHeadersCallback(
net::ResponseHeadersCallback callback) override;
diff --git a/chromium/services/network/tls_socket_factory.cc b/chromium/services/network/tls_socket_factory.cc
index 7f7dd14fc8b..dd9f19903ed 100644
--- a/chromium/services/network/tls_socket_factory.cc
+++ b/chromium/services/network/tls_socket_factory.cc
@@ -51,7 +51,8 @@ TLSSocketFactory::TLSSocketFactory(
url_request_context->transport_security_state(),
url_request_context->cert_transparency_verifier(),
url_request_context->ct_policy_enforcer(),
- nullptr /* Disables SSL session caching */),
+ nullptr /* Disables SSL session caching */,
+ url_request_context->sct_auditing_delegate()),
client_socket_factory_(nullptr),
ssl_config_service_(url_request_context->ssl_config_service()) {
if (http_context) {
@@ -132,7 +133,8 @@ void TLSSocketFactory::CreateTLSClientSocket(
no_verification_transport_security_state_.get(),
no_verification_cert_transparency_verifier_.get(),
no_verification_ct_policy_enforcer_.get(),
- nullptr /* no session cache */);
+ nullptr /* no session cache */,
+ nullptr /* disable sct auditing */);
}
ssl_client_context = no_verification_ssl_client_context_.get();
send_ssl_info = true;
diff --git a/chromium/services/network/trust_tokens/BUILD.gn b/chromium/services/network/trust_tokens/BUILD.gn
index 2e105004a31..93b85014834 100644
--- a/chromium/services/network/trust_tokens/BUILD.gn
+++ b/chromium/services/network/trust_tokens/BUILD.gn
@@ -162,6 +162,7 @@ source_set("tests") {
":trust_tokens",
"//base",
"//base/test:test_support",
+ "//base/util/ranges",
"//components/cbor",
"//components/sqlite_proto",
"//net",
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 908d96fd0eb..d89947bb068 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
@@ -85,7 +85,7 @@ TEST(SQLiteTrustTokenPersister, PutReinitializeAndGet) {
// database asynchronously, so as not to leak after the test concludes.
env.RunUntilIdle();
- base::DeleteFile(temp_path, false);
+ base::DeleteFile(temp_path);
}
// Ensure that it's possible to create a Trust Tokens persister on top of a
diff --git a/chromium/services/network/trust_tokens/trust_token_key_commitments.cc b/chromium/services/network/trust_tokens/trust_token_key_commitments.cc
index e762e32fb0b..4b50e745c68 100644
--- a/chromium/services/network/trust_tokens/trust_token_key_commitments.cc
+++ b/chromium/services/network/trust_tokens/trust_token_key_commitments.cc
@@ -36,10 +36,10 @@ ParseCommitmentsFromCommandLine() {
raw_commitments)) {
return std::move(*parsed);
} else {
- // Crash loudly here because the user presumably only provides key
+ // Complain loudly here because the user presumably only provides key
// commitments through the command line out of a desire to _use_ the key
// commitments.
- LOG(FATAL)
+ LOG(ERROR)
<< "Couldn't parse Trust Tokens key commitments from the command line: "
<< raw_commitments;
}
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 130509bbee4..9ba6d9d3070 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
@@ -127,20 +127,29 @@ void TrustTokenRequestHelperFactory::ConstructHelperUsingStore(
}
case mojom::TrustTokenOperationType::kSigning: {
- base::Optional<SuitableTrustTokenOrigin> maybe_issuer;
- if (params->issuer) {
- maybe_issuer =
- SuitableTrustTokenOrigin::Create(std::move(*params->issuer));
- }
-
- if (!maybe_issuer) {
- LogOutcome(net_log, "Missing/unsuitable 'issuer' parameter");
+ if (params->issuers.empty()) {
+ LogOutcome(net_log, "Empty 'issuers' parameter");
std::move(done).Run(mojom::TrustTokenOperationStatus::kInvalidArgument);
return;
}
+ std::vector<SuitableTrustTokenOrigin> issuers;
+ for (url::Origin& potentially_unsuitable_issuer : params->issuers) {
+ base::Optional<SuitableTrustTokenOrigin> maybe_issuer =
+ SuitableTrustTokenOrigin::Create(
+ std::move(potentially_unsuitable_issuer));
+ if (!maybe_issuer) {
+ LogOutcome(net_log, "Unsuitable issuer in 'issuers' parameter");
+ std::move(done).Run(
+ mojom::TrustTokenOperationStatus::kInvalidArgument);
+ return;
+ }
+
+ issuers.emplace_back(std::move(*maybe_issuer));
+ }
+
TrustTokenRequestSigningHelper::Params signing_params(
- std::move(*maybe_issuer), top_frame_origin,
+ std::move(issuers), top_frame_origin,
std::move(params->additional_signed_headers),
params->include_timestamp_header, params->sign_request_data,
params->possibly_unsafe_additional_signing_data);
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 10c2b2cbb41..8fa823a05b0 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
@@ -54,8 +54,8 @@ class TrustTokenRequestHelperFactoryTest : public ::testing::Test {
TrustTokenRequestHelperFactoryTest() {
suitable_request_ = CreateSuitableRequest();
suitable_params_ = mojom::TrustTokenParams::New();
- suitable_params_->issuer =
- url::Origin::Create(GURL("https://issuer.example"));
+ suitable_params_->issuers.push_back(
+ url::Origin::Create(GURL("https://issuer.example")));
}
protected:
@@ -146,21 +146,22 @@ TEST_F(TrustTokenRequestHelperFactoryTest, ForbiddenHeaders) {
}
TEST_F(TrustTokenRequestHelperFactoryTest,
- CreatingSigningHelperRequiresSuitableIssuer) {
+ CreatingSigningHelperRequiresSuitableIssuers) {
auto request = CreateSuitableRequest();
auto params = suitable_params().Clone();
params->type = mojom::TrustTokenOperationType::kSigning;
- params->issuer.reset();
+ params->issuers.clear();
EXPECT_EQ(CreateHelperAndWaitForResult(*request, *params).status(),
mojom::TrustTokenOperationStatus::kInvalidArgument);
- params->issuer = UnsuitableUntrustworthyOrigin();
+ params->issuers.push_back(UnsuitableUntrustworthyOrigin());
EXPECT_EQ(CreateHelperAndWaitForResult(*request, *params).status(),
mojom::TrustTokenOperationStatus::kInvalidArgument);
- params->issuer = UnsuitableNonHttpNonHttpsOrigin();
+ params->issuers.clear();
+ params->issuers.push_back(UnsuitableNonHttpNonHttpsOrigin());
EXPECT_EQ(CreateHelperAndWaitForResult(*request, *params).status(),
mojom::TrustTokenOperationStatus::kInvalidArgument);
}
diff --git a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc
index 49ac06d0aea..d4dcbaaa7b3 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_issuance_helper.cc
@@ -104,9 +104,6 @@ void TrustTokenRequestIssuanceHelper::Begin(
net::URLRequest* request,
base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) {
DCHECK(request);
- DCHECK(!request->initiator() ||
- IsOriginPotentiallyTrustworthy(*request->initiator()))
- << *request->initiator();
net_log_.BeginEvent(
net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_ISSUANCE);
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 7799e2af869..df04c1c6924 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
@@ -7,6 +7,7 @@
#include <memory>
#include "base/callback.h"
+#include "base/no_destructor.h"
#include "base/test/task_environment.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.h"
diff --git a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc
index 2578edaf0ee..db260dd5887 100644
--- a/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc
+++ b/chromium/services/network/trust_tokens/trust_token_request_redemption_helper.cc
@@ -73,9 +73,6 @@ void TrustTokenRequestRedemptionHelper::Begin(
net::URLRequest* request,
base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) {
DCHECK(request);
- DCHECK(!request->initiator() ||
- IsOriginPotentiallyTrustworthy(*request->initiator()))
- << *request->initiator();
net_log_.BeginEvent(
net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_REDEMPTION);
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 87661babf5c..88888c91ea7 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
@@ -7,6 +7,7 @@
#include <memory>
#include "base/callback.h"
+#include "base/no_destructor.h"
#include "base/test/task_environment.h"
#include "net/base/load_flags.h"
#include "net/base/request_priority.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 5a185ef4261..f5d2d7201d7 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
@@ -44,6 +44,7 @@ void LogOutcome(const net::NetLogWithSource& log, base::StringPiece outcome) {
}
} // namespace
+
namespace internal {
// Parse the Signed-Headers input header as a Structured Headers Draft 15 list
@@ -91,12 +92,14 @@ namespace {
using Params = TrustTokenRequestSigningHelper::Params;
-// Constants for keys and values in the Sec-Signature header:
+// Constants for keys and values in the generated headers:
const char kSignatureHeaderSignRequestDataIncludeValue[] = "include";
const char kSignatureHeaderSignRequestDataHeadersOnlyValue[] = "headers-only";
+const char kSignatureHeaderSignaturesKey[] = "signatures";
const char kSignatureHeaderSignRequestDataKey[] = "sign-request-data";
const char kSignatureHeaderPublicKeyKey[] = "public-key";
const char kSignatureHeaderSignatureKey[] = "sig";
+const char kRedemptionRecordHeaderRedemptionRecordKey[] = "redemption-record";
std::vector<std::string> Lowercase(std::vector<std::string> in) {
for (std::string& str : in) {
@@ -181,12 +184,37 @@ GetHeadersToSignAndUpdateSignedHeadersHeader(
}
void AttachSignedRedemptionRecordHeader(net::URLRequest* request,
- const std::string& value) {
+ std::string value) {
request->SetExtraRequestHeaderByName(
kTrustTokensRequestHeaderSecSignedRedemptionRecord, value,
/*overwrite=*/true);
}
+// Builds a Trust Tokens signed redemption record header, which is logically an
+// issuer-to-SRR map but implemented as a Structured Headers Draft 15
+// parameterized list (essentially a list where each member has an associated
+// dictionary).
+base::Optional<std::string> ConstructSignedRedemptionRecordHeader(
+ const base::flat_map<SuitableTrustTokenOrigin,
+ SignedTrustTokenRedemptionRecord>&
+ records_per_issuer) {
+ net::structured_headers::List header_items;
+
+ for (const auto& issuer_and_record : records_per_issuer) {
+ net::structured_headers::Item issuer_item(
+ issuer_and_record.first.Serialize(),
+ net::structured_headers::Item::ItemType::kStringType);
+ net::structured_headers::Item redemption_record_item(
+ issuer_and_record.second.body(),
+ net::structured_headers::Item::ItemType::kByteSequenceType);
+ header_items.emplace_back(net::structured_headers::ParameterizedMember(
+ std::move(issuer_item), {{kRedemptionRecordHeaderRedemptionRecordKey,
+ std::move(redemption_record_item)}}));
+ }
+
+ return net::structured_headers::SerializeList(std::move(header_items));
+}
+
} // namespace
TrustTokenRequestSigningHelper::TrustTokenRequestSigningHelper(
@@ -204,13 +232,13 @@ TrustTokenRequestSigningHelper::TrustTokenRequestSigningHelper(
TrustTokenRequestSigningHelper::~TrustTokenRequestSigningHelper() = default;
Params::Params(
- SuitableTrustTokenOrigin issuer,
+ std::vector<SuitableTrustTokenOrigin> issuers,
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)),
+ : issuers(std::move(issuers)),
toplevel(std::move(toplevel)),
additional_headers_to_sign(std::move(additional_headers_to_sign)),
should_add_timestamp(should_add_timestamp),
@@ -220,7 +248,9 @@ Params::Params(
Params::Params(SuitableTrustTokenOrigin issuer,
SuitableTrustTokenOrigin toplevel)
- : issuer(std::move(issuer)), toplevel(std::move(toplevel)) {}
+ : toplevel(std::move(toplevel)) {
+ issuers.emplace_back(std::move(issuer));
+}
Params::~Params() = default;
Params::Params(const Params&) = default;
// The type alias causes a linter false positive.
@@ -234,9 +264,6 @@ void TrustTokenRequestSigningHelper::Begin(
net::URLRequest* request,
base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) {
DCHECK(request);
- DCHECK(!request->initiator() ||
- IsOriginPotentiallyTrustworthy(*request->initiator()))
- << *request->initiator();
#if DCHECK_IS_ON()
// Add some postcondition checking on return.
done = base::BindOnce(
@@ -270,22 +297,41 @@ void TrustTokenRequestSigningHelper::Begin(
net_log_.BeginEvent(
net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_SIGNING);
- // The comments below are the steps in the "Redemption record attachment and
- // request signing" pseudocode in https://bit.ly/trust-token-dd
+ // The numbered comments below are the steps in the "Redemption record
+ // attachment and request signing" pseudocode in https://bit.ly/trust-token-dd
- base::Optional<SignedTrustTokenRedemptionRecord> maybe_redemption_record =
- token_store_->RetrieveNonstaleRedemptionRecord(params_.issuer,
- params_.toplevel);
+ // (Because of the chracteristics of the protocol, this map is expected to
+ // have at most ~5 elements.)
+ base::flat_map<SuitableTrustTokenOrigin, SignedTrustTokenRedemptionRecord>
+ records_per_issuer;
- if (!maybe_redemption_record) {
+ // 1. For each issuer specified, search storage for a non-expired SRR
+ // corresponding to that issuer and the request’s initiating top-level origin.
+ for (const SuitableTrustTokenOrigin& issuer : params_.issuers) {
+ base::Optional<SignedTrustTokenRedemptionRecord> maybe_redemption_record =
+ token_store_->RetrieveNonstaleRedemptionRecord(issuer,
+ params_.toplevel);
+ if (!maybe_redemption_record)
+ continue;
+
+ records_per_issuer[issuer] = std::move(*maybe_redemption_record);
+ }
+
+ if (records_per_issuer.empty()) {
AttachSignedRedemptionRecordHeader(request, std::string());
- LogOutcome(net_log_, "No SRR for this (issuer, top-level context) pair");
+ LogOutcome(net_log_,
+ "No SRR for any of the given issuers, in the operation's "
+ "top-level context");
std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
return;
}
+ // 2.a. If the request’s additionalSigningData argument is nonempty, add a
+ // Sec-Trust-Tokens-Additional-Signing-Data header to the request with its
+ // value equal to that of the request’s additionalSigningData argument.
if (params_.possibly_unsafe_additional_signing_data) {
+ // 2.a.i. If it is longer than 2048 bytes, raise an error.
if (params_.possibly_unsafe_additional_signing_data->size() >
kTrustTokenAdditionalSigningDataMaxSizeBytes) {
LogOutcome(net_log_, "Overly long additionalSigningData");
@@ -295,6 +341,8 @@ void TrustTokenRequestSigningHelper::Begin(
return;
}
+ // 2.a.ii. If it is not a valid HTTP header value (contains \r, \n, or \0),
+ // raise an error.
if (!net::HttpUtil::IsValidHeaderValue(
*params_.possibly_unsafe_additional_signing_data)) {
LogOutcome(net_log_,
@@ -313,6 +361,9 @@ void TrustTokenRequestSigningHelper::Begin(
DCHECK(!request->extra_request_headers().HasHeader(
kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData));
+ // 2.a.iii. Add a Sec-Trust-Tokens-Additional-Signing-Data header to the
+ // request with its value equal to that of the request’s
+ // additionalSigningData argument.
request->SetExtraRequestHeaderByName(
kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData,
*params_.possibly_unsafe_additional_signing_data,
@@ -322,6 +373,11 @@ void TrustTokenRequestSigningHelper::Begin(
kTrustTokensRequestHeaderSecTrustTokensAdditionalSigningData);
}
+ // 2.b. Merge the additionalRequestHeaders Fetch parameter’s contents into the
+ // request’s Signed-Headers header (creating a header if previously absent).
+ // If the request has a Sec-Trust-Tokens-Additional-Signing-Data header,
+ // append “Sec-Trust-Tokens-Additional-Signing-Data” to the request’s
+ // Signed-Headers header.
base::Optional<std::vector<std::string>> maybe_headers_to_sign =
GetHeadersToSignAndUpdateSignedHeadersHeader(
request, params_.additional_headers_to_sign);
@@ -336,8 +392,24 @@ void TrustTokenRequestSigningHelper::Begin(
return;
}
- AttachSignedRedemptionRecordHeader(request, maybe_redemption_record->body());
+ // 2.c. Attach the SRRs in a Sec-Signed-Redemption-Record header.
+ if (base::Optional<std::string> maybe_signed_redemption_record_header =
+ ConstructSignedRedemptionRecordHeader(records_per_issuer)) {
+ AttachSignedRedemptionRecordHeader(
+ request, std::move(*maybe_signed_redemption_record_header));
+ } else {
+ AttachSignedRedemptionRecordHeader(request, std::string());
+ LogOutcome(
+ net_log_,
+ "Unexpected internal error serializing Sec-Signed-Redemption-Record"
+ " header.");
+ std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
+ return;
+ }
+
+ // 2.d. If specified by the request’s includeTimestampHeader parameter, add a
+ // Sec-Time header containing a high-resolution timestamp, encoded in ISO8601.
if (params_.should_add_timestamp) {
request->SetExtraRequestHeaderByName(kTrustTokensRequestHeaderSecTime,
base::TimeToISO8601(base::Time::Now()),
@@ -350,39 +422,58 @@ void TrustTokenRequestSigningHelper::Begin(
return;
}
- base::Optional<std::vector<uint8_t>> maybe_signature =
- GetSignature(request, *maybe_redemption_record, *maybe_headers_to_sign);
-
- if (!maybe_signature) {
- AttachSignedRedemptionRecordHeader(request, std::string());
- request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSecTime);
- request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSignedHeaders);
-
- LogOutcome(net_log_, "Internal error generating signature");
- std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
- return;
+ // 2.e. If the request’s signRequestData Fetch parameter is not “omit”, follow
+ // the steps in the Computing an outgoing request’s signatures section to add
+ // a Sec-Signature header containing, for each issuer, a signature over some
+ // of the request’s data (e.g. a subset of its headers) generated using a key
+ // bound to a prior redemption against that issuer.
+ base::flat_map<SuitableTrustTokenOrigin, std::vector<uint8_t>>
+ signatures_per_issuer;
+
+ for (const auto& issuer_and_record : records_per_issuer) {
+ if (base::Optional<std::vector<uint8_t>> maybe_signature = GetSignature(
+ request, issuer_and_record.second, *maybe_headers_to_sign)) {
+ signatures_per_issuer[issuer_and_record.first] =
+ std::move(*maybe_signature);
+ } else {
+ // Failure isn't likely and would mean that the signing key---which we
+ // generate ourselves, during redemption---somehow got corrupted, or there
+ // was some kind of internal error generating the signature in the
+ // underlying cryptography library.
+ net_log_.AddEntry(
+ net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_SIGNING,
+ net::NetLogEventPhase::NONE,
+ [&issuer_and_record](net::NetLogCaptureMode mode) {
+ base::Value ret(base::Value::Type::DICTIONARY);
+ ret.SetStringPath("failed_signing_params.issuer",
+ issuer_and_record.first.Serialize());
+ if (net::NetLogCaptureIncludesSensitive(mode)) {
+ ret.SetStringPath("failed_signing_params.key",
+ issuer_and_record.second.signing_key());
+ }
+ return ret;
+ });
+ }
}
- base::Optional<std::string> maybe_signature_header = BuildSignatureHeader(
- maybe_redemption_record->public_key(),
- base::StringPiece(reinterpret_cast<const char*>(maybe_signature->data()),
- maybe_signature->size()));
-
- // Error serializing the header. Not expected.
- if (!maybe_signature_header) {
+ if (base::Optional<std::string> maybe_signature_header =
+ BuildSignatureHeaderIfAtLeastOneSignatureIsPresent(
+ records_per_issuer, signatures_per_issuer)) {
+ request->SetExtraRequestHeaderByName(kTrustTokensRequestHeaderSecSignature,
+ std::move(*maybe_signature_header),
+ /*overwrite=*/true);
+ } else {
AttachSignedRedemptionRecordHeader(request, std::string());
request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSecTime);
request->RemoveRequestHeaderByName(kTrustTokensRequestHeaderSignedHeaders);
- LogOutcome(net_log_, "Internal error serializing signature header");
+ LogOutcome(net_log_,
+ "Internal error serializing signature header, or generating all "
+ "issuers' signatures failed.");
std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
return;
}
- request->SetExtraRequestHeaderByName(kTrustTokensRequestHeaderSecSignature,
- *maybe_signature_header,
- /*overwrite=*/true);
-
LogOutcome(net_log_, "Success");
std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
}
@@ -393,33 +484,79 @@ void TrustTokenRequestSigningHelper::Finalize(
return std::move(done).Run(mojom::TrustTokenOperationStatus::kOk);
}
-base::Optional<std::string>
-TrustTokenRequestSigningHelper::BuildSignatureHeader(
- base::StringPiece public_key,
- base::StringPiece signature) {
+namespace {
+
+// Given a redemption record and a signature bytestring, returns a {
+// "public-key": <public key>,
+// "sig": <signature>
+// }
+// nested map, corresponding to a single entry in the Sec-Signature header's
+// top-level list.
+net::structured_headers::Parameters ConstructKeyAndSignaturePair(
+ const SignedTrustTokenRedemptionRecord& redemption_record,
+ base::span<const uint8_t> signature_bytes) {
+ net::structured_headers::Item public_key(
+ redemption_record.public_key(),
+ net::structured_headers::Item::ItemType::kByteSequenceType);
+ net::structured_headers::Item signature(net::structured_headers::Item(
+ std::string(reinterpret_cast<const char*>(signature_bytes.data()),
+ signature_bytes.size()),
+ net::structured_headers::Item::ItemType::kByteSequenceType));
+
+ return {{kSignatureHeaderPublicKeyKey, std::move(public_key)},
+ {kSignatureHeaderSignatureKey, std::move(signature)}};
+}
+
+} // namespace
+
+base::Optional<std::string> TrustTokenRequestSigningHelper::
+ BuildSignatureHeaderIfAtLeastOneSignatureIsPresent(
+ const base::flat_map<SuitableTrustTokenOrigin,
+ SignedTrustTokenRedemptionRecord>&
+ records_per_issuer,
+ const base::flat_map<SuitableTrustTokenOrigin, std::vector<uint8_t>>&
+ signatures_per_issuer) {
+ if (signatures_per_issuer.empty())
+ return base::nullopt;
+
net::structured_headers::Dictionary header_items;
- header_items[kSignatureHeaderPublicKeyKey] =
- net::structured_headers::ParameterizedMember(
- net::structured_headers::Item(
- std::string(public_key),
- net::structured_headers::Item::ItemType::kByteSequenceType),
- {});
- header_items[kSignatureHeaderSignatureKey] =
+ std::vector<net::structured_headers::ParameterizedItem> keys_and_signatures;
+ for (const auto& kv : signatures_per_issuer) {
+ const SuitableTrustTokenOrigin& issuer = kv.first;
+ const std::vector<uint8_t>& signature = kv.second;
+
+ keys_and_signatures.emplace_back(net::structured_headers::ParameterizedItem(
+ net::structured_headers::Item(
+ issuer.Serialize(),
+ net::structured_headers::Item::ItemType::kStringType),
+ // records_per_issuer is guaranteed to have all of the keys that
+ // signatures_per_issuer does, so using |at| is safe:
+ ConstructKeyAndSignaturePair(records_per_issuer.at(issuer),
+ signature)));
+ }
+
+ header_items[kSignatureHeaderSignaturesKey] =
net::structured_headers::ParameterizedMember(
- net::structured_headers::Item(
- std::string(signature),
- net::structured_headers::Item::ItemType::kByteSequenceType),
- {});
+ std::move(keys_and_signatures),
+ net::structured_headers::Parameters());
// A value of kOmit denotes not wanting the request signed at all, so it'd be
// a caller error if we were trying to sign the request with it set.
DCHECK_NE(params_.sign_request_data, mojom::TrustTokenSignRequestData::kOmit);
- const char* sign_request_data_value =
- params_.sign_request_data == mojom::TrustTokenSignRequestData::kInclude
- ? kSignatureHeaderSignRequestDataIncludeValue
- : kSignatureHeaderSignRequestDataHeadersOnlyValue;
+ const char* sign_request_data_value = "";
+ switch (params_.sign_request_data) {
+ case mojom::TrustTokenSignRequestData::kInclude:
+ sign_request_data_value = kSignatureHeaderSignRequestDataIncludeValue;
+ break;
+ case mojom::TrustTokenSignRequestData::kHeadersOnly:
+ sign_request_data_value = kSignatureHeaderSignRequestDataHeadersOnlyValue;
+ break;
+ case mojom::TrustTokenSignRequestData::kOmit:
+ NOTREACHED(); // "omit" handled (far) above.
+ break;
+ }
header_items[kSignatureHeaderSignRequestDataKey] =
net::structured_headers::ParameterizedMember(
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 831ee3a68b4..16831045bc0 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
@@ -73,7 +73,7 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
struct Params {
// Refer to fields' comments for their semantics.
- Params(SuitableTrustTokenOrigin issuer,
+ Params(std::vector<SuitableTrustTokenOrigin> issuers,
SuitableTrustTokenOrigin toplevel,
std::vector<std::string> additional_headers_to_sign,
bool should_add_timestamp,
@@ -91,14 +91,14 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
Params(Params&&);
Params& operator=(Params&&);
- // |issuer| is the Trust Tokens issuer origin for which to retrieve a Signed
- // Redemption Record and matching signing key. This must be both (1) HTTP or
- // HTTPS and (2) "potentially trustworthy". This precondition is slightly
- // involved because there are two needs:
+ // |issuers| contains the Trust Tokens issuer origins for which to retrieve
+ // Signed Redemption Records and matching signing keys. These must be both
+ // (1) HTTP or HTTPS and (2) "potentially trustworthy". This precondition is
+ // slightly involved because there are two needs:
// 1. HTTP or HTTPS so that the scheme serializes in a sensible manner in
- // order to serve as a key for persisting state.
- // 2. potentially trustworthy origin to satisfy Web security requirements.
- SuitableTrustTokenOrigin issuer;
+ // order to serve as a key for persisting state,
+ // 2. potentially trustworthy to satisfy Web security requirements.
+ std::vector<SuitableTrustTokenOrigin> issuers;
// |toplevel| is the top-level origin of the initiating request. This must
// satisfy the same preconditions as |issuer|.
@@ -173,13 +173,13 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
TrustTokenRequestSigningHelper& operator=(
const TrustTokenRequestSigningHelper&) = delete;
- // Attempts to attach a Signed Redemption Record (SRR) corresponding
- // to |request|'s initiating top-level origin and the provided issuer origin.
+ // Attempts to attach Signed Redemption Records (SRRs) corresponding
+ // to |request|'s initiating top-level origin and the provided issuer origins.
//
// ATTACHING THE REDEMPTION RECORD:
- // In the case that an SRR is found and the requested headers to sign are
- // well-formed, attaches a Sec-Signed-Redemption-Record header
- // bearing the SRR and:
+ // In the case that an SRR is found for at least one provided issuer and the
+ // requested headers to sign are well-formed, attaches a
+ // Sec-Signed-Redemption-Record header bearing the SRRs and:
// 1. if the request is configured for adding a Trust Tokens timestamp,
// adds a timestamp header;
// 2. if the request is configured for signing, computes the request's
@@ -190,11 +190,12 @@ 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; or
+ // 2. none of the provided issuers has an SRR corresponding to this top-level
+ // origin in |token_store_|; or
// 3. an internal error occurs during signing or header serialization.
//
// POSTCONDITIONS:
- // - Always returns kOk. This is to avoid aborting a request entirely to a
+ // - Always returns kOk. This is to avoid aborting a request entirely due to a
// failure during signing; see the Trust Tokens design doc for more
// discussion.
// - On failure, the request will contain an empty
@@ -211,16 +212,28 @@ class TrustTokenRequestSigningHelper : public TrustTokenRequestHelper {
base::OnceCallback<void(mojom::TrustTokenOperationStatus)> done) override;
private:
- // Given (unencoded) bytestrings |public_key| and |signature|, returns the
+ // Given issuer-to-redemption-record and issuer-to-signature maps, returns a
// Trust Tokens signature header, a serialized Structured Headers Draft 15
- // dictionary looking roughly like (order not guaranteed):
- // public-key=:<base64(pk)>:,
- // sig=:<base64(signature)>:,
- // sign-request-data=include | headers-only
+ // dictionary with logical structure roughly
+ // "signatures": [
+ // (<issuer 1>, { "public-key": <public key>, "sig": <signature> }),
+ // …..
+ // (<issuer N>, { "public-key": <public key>, "sig": <signature> })
+ // ],
+ // "sign-request-data": include | headers-only
//
- // Returns nullopt on serialization error.
- base::Optional<std::string> BuildSignatureHeader(base::StringPiece public_key,
- base::StringPiece signature);
+ // Returns nullopt on serialization error, or if |signatures_per_issuer| is
+ // empty.
+ //
+ // REQUIRES: Every issuer in |signatures_per_issuer| must have a corresponding
+ // signed redemption record in |records_per_issuer|.
+ base::Optional<std::string>
+ BuildSignatureHeaderIfAtLeastOneSignatureIsPresent(
+ const base::flat_map<SuitableTrustTokenOrigin,
+ SignedTrustTokenRedemptionRecord>&
+ records_per_issuer,
+ const base::flat_map<SuitableTrustTokenOrigin, std::vector<uint8_t>>&
+ signatures_per_issuer);
// Returns a signature over |request|'s pertinent data (public key,
// user-specified headers and, possibly, destination URL), or nullopt in case
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 08a9bad1ae9..0270abe485d 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
@@ -18,11 +18,14 @@
#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
#include "base/time/time_to_iso8601.h"
+#include "base/util/ranges/algorithm.h"
#include "components/cbor/reader.h"
#include "components/cbor/values.h"
#include "components/cbor/writer.h"
#include "net/base/request_priority.h"
#include "net/http/structured_headers.h"
+#include "net/log/test_net_log.h"
+#include "net/log/test_net_log_util.h"
#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"
@@ -38,7 +41,6 @@
#include "url/gurl.h"
#include "url/origin.h"
-using ::testing::AnyOf;
using ::testing::IsEmpty;
using ::testing::Matches;
using ::testing::Not;
@@ -102,30 +104,35 @@ class FailingSigner : public TrustTokenRequestSigningHelper::Signer {
}
};
-// Reconstructs |request|'s canonical request data, extracts the signature from
+// Reconstructs |request|'s canonical request data, extracts the signatures from
// |request|'s Sec-Signature header, and uses the verification algorithm
// provided by the template parameter |Signer| to check that the Sec-Signature
-// header's contained signature verifies.
+// header's contained signatures verify.
template <typename Signer>
-void ReconstructSigningDataAndAssertSignatureVerifies(
- net::URLRequest* request) {
+void ReconstructSigningDataAndAssertSignaturesVerify(
+ net::URLRequest* request,
+ size_t num_expected_signatures) {
std::string error;
- bool success = test::ReconstructSigningDataAndVerifySignature(
+
+ std::map<std::string, std::string> verification_keys_per_issuer;
+ bool success = test::ReconstructSigningDataAndVerifySignatures(
request->url(), request->extra_request_headers(),
- base::BindOnce([](base::span<const uint8_t> data,
- base::span<const uint8_t> signature,
- base::span<const uint8_t> verification_key) {
+ base::BindRepeating([](base::span<const uint8_t> data,
+ base::span<const uint8_t> signature,
+ base::span<const uint8_t> verification_key) {
return Signer().Verify(data, signature, verification_key);
}),
- &error);
+ &error, &verification_keys_per_issuer);
ASSERT_TRUE(success) << error;
+ ASSERT_EQ(verification_keys_per_issuer.size(), num_expected_signatures);
}
-// Verifies that |request| has a Sec-Signature header with a "sig" field and
-// extracts the request's signature from this field.
-void AssertHasSignatureAndExtract(const net::URLRequest& request,
- std::string* signature_out) {
+// Verifies that |request| has a Sec-Signature header containing signatures and
+// extracts the signature for each issuer to |signatures_out|.
+void AssertHasSignaturesAndExtract(
+ const net::URLRequest& request,
+ std::map<std::string, std::string>* signatures_out) {
std::string signature_header;
ASSERT_TRUE(request.extra_request_headers().GetHeader("Sec-Signature",
&signature_header));
@@ -133,12 +140,22 @@ void AssertHasSignatureAndExtract(const net::URLRequest& request,
base::Optional<net::structured_headers::Dictionary> maybe_dictionary =
net::structured_headers::ParseDictionary(signature_header);
ASSERT_TRUE(maybe_dictionary);
- ASSERT_TRUE(maybe_dictionary->contains("sig"));
+ ASSERT_TRUE(maybe_dictionary->contains("signatures"));
+
+ for (auto& issuer_and_params : maybe_dictionary->at("signatures").member) {
+ net::structured_headers::Item& issuer_item = issuer_and_params.item;
+ ASSERT_TRUE(issuer_item.is_string());
+
+ auto signature_iterator = std::find_if(
+ issuer_and_params.params.begin(), issuer_and_params.params.end(),
+ [](auto& param) { return param.first == "sig"; });
- net::structured_headers::Item& sig_item =
- maybe_dictionary->at("sig").member.front().item;
- ASSERT_TRUE(sig_item.is_byte_sequence());
- *signature_out = sig_item.GetString();
+ ASSERT_TRUE(signature_iterator != issuer_and_params.params.end())
+ << "Missing signature";
+ ASSERT_TRUE(signature_iterator->second.is_byte_sequence());
+ signatures_out->emplace(issuer_item.GetString(),
+ signature_iterator->second.GetString());
+ }
}
// Assert that the given signing data is a concatenation of the domain separator
@@ -149,7 +166,7 @@ void AssertDecodesToCborAndExtractField(base::StringPiece signing_data,
base::StringPiece field_name,
std::string* field_value_out) {
base::Optional<cbor::Value> parsed = cbor::Reader::Read(base::as_bytes(
- // Skip over the "Trust Token v0" domain separator.
+ // Skip over the domain separator (e.g. "Trust Token v0").
base::make_span(signing_data)
.subspan(base::size(TrustTokenRequestSigningHelper::
kRequestSigningDomainSeparator))));
@@ -178,6 +195,13 @@ MATCHER_P2(Header,
return Matches(other_matcher)(header);
}
+SuitableTrustTokenOrigin CreateSuitableOriginOrDie(base::StringPiece spec) {
+ base::Optional<SuitableTrustTokenOrigin> maybe_origin =
+ SuitableTrustTokenOrigin::Create(GURL(spec));
+ CHECK(maybe_origin) << "Failed to create a SuitableTrustTokenOrigin!";
+ return *maybe_origin;
+}
+
} // namespace
TEST_F(TrustTokenRequestSigningHelperTest, WontSignIfNoRedemptionRecord) {
@@ -199,8 +223,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, WontSignIfNoRedemptionRecord) {
mojom::TrustTokenOperationStatus result =
ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
- // In failure cases, the signing helper should return kOk but attach an empty
- // SRR header.
+ // In failure cases---in particular, in this case where none of the provided
+ // issuers has a signed redemption record in storage---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("Sec-Signature")));
@@ -222,7 +247,8 @@ TEST_F(TrustTokenRequestSigningHelperTest, MergesHeaders) {
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
my_record.set_body("SRR body");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
@@ -266,7 +292,8 @@ TEST_F(TrustTokenRequestSigningHelperTest,
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
@@ -311,7 +338,8 @@ TEST_F(TrustTokenRequestSigningHelperTest,
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
@@ -349,7 +377,8 @@ TEST_F(TrustTokenRequestSigningHelperTestWithMockTime, ProvidesTimeHeader) {
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
my_record.set_body("look at me, I'm an SRR body");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
@@ -367,6 +396,9 @@ TEST_F(TrustTokenRequestSigningHelperTestWithMockTime, ProvidesTimeHeader) {
}
// Test SRR attachment without request signing:
+// - The two issuers with stored redemption records should appear in the header.
+// - A third issuer without a corresponding redemption record in storage
+// shouldn't appear in the header.
TEST_F(TrustTokenRequestSigningHelperTest,
RedemptionRecordAttachmentWithoutSigning) {
std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
@@ -376,11 +408,26 @@ TEST_F(TrustTokenRequestSigningHelperTest,
*SuitableTrustTokenOrigin::Create(GURL("https://toplevel.com")));
params.should_add_timestamp = true;
params.sign_request_data = mojom::TrustTokenSignRequestData::kOmit;
-
- SignedTrustTokenRedemptionRecord my_record;
- my_record.set_body("look at me! I'm a signed redemption record");
- my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ params.issuers.push_back(
+ *SuitableTrustTokenOrigin::Create(GURL("https://second-issuer.example")));
+
+ SignedTrustTokenRedemptionRecord first_issuer_record;
+ first_issuer_record.set_body("look at me! I'm a signed redemption record");
+ first_issuer_record.set_public_key("key");
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ first_issuer_record);
+
+ SignedTrustTokenRedemptionRecord second_issuer_record;
+ second_issuer_record.set_body(
+ "I'm another signed redemption record, distinct from the first");
+ second_issuer_record.set_public_key("some other key");
+ store->SetRedemptionRecord(params.issuers.back(), params.toplevel,
+ second_issuer_record);
+
+ // Attempting to sign with an issuer with no redemption record in storage
+ // should be fine, resulting in the issuer getting ignored.
+ params.issuers.push_back(
+ *SuitableTrustTokenOrigin::Create(GURL("https://third-issuer.example")));
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<IdentitySigner>(),
@@ -392,8 +439,23 @@ TEST_F(TrustTokenRequestSigningHelperTest,
ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
ASSERT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
- EXPECT_THAT(*my_request,
- Header("Sec-Signed-Redemption-Record", StrEq(my_record.body())));
+
+ std::string redemption_record_header;
+ ASSERT_TRUE(my_request->extra_request_headers().GetHeader(
+ "Sec-Signed-Redemption-Record", &redemption_record_header));
+ std::map<SuitableTrustTokenOrigin, std::string> redemption_records_per_issuer;
+ std::string error;
+ ASSERT_TRUE(test::ExtractRedemptionRecordsFromHeader(
+ redemption_record_header, &redemption_records_per_issuer, &error))
+ << error;
+
+ EXPECT_THAT(
+ redemption_records_per_issuer,
+ UnorderedElementsAre(
+ Pair(CreateSuitableOriginOrDie("https://issuer.com"),
+ StrEq(first_issuer_record.body())),
+ Pair(CreateSuitableOriginOrDie("https://second-issuer.example"),
+ StrEq(second_issuer_record.body()))));
EXPECT_THAT(*my_request, Header("Sec-Time"));
EXPECT_THAT(*my_request, Not(Header("Sec-Signature")));
}
@@ -410,11 +472,12 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyMinimal) {
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
my_record.set_body("look at me, I'm an SRR body");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
// Giving an IdentitySigner to |helper| will mean that |helper| should provide
// its entire signing data in the request's Sec-Signature header's "sig"
- // field. ReconstructSigningDataAndAssertSignatureVerifies then reproduces
+ // field. ReconstructSigningDataAndAssertSignaturesVerify then reproduces
// this canonical data's construction and checks that the reconstructed data
// matches what |helper| produced.
auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>();
@@ -430,11 +493,11 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyMinimal) {
EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
ASSERT_NO_FATAL_FAILURE(
- ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
- my_request.get()));
+ ReconstructSigningDataAndAssertSignaturesVerify<IdentitySigner>(
+ my_request.get(), /*num_expected_signatures=*/1));
}
-// Test a round-trip sign-and-verify with signed headers.
+// Test a round-trip sign-and-verify with signed headers and multiple issuers.
TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyWithHeaders) {
std::unique_ptr<TrustTokenStore> store = TrustTokenStore::CreateForTesting();
@@ -445,10 +508,18 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyWithHeaders) {
SignedTrustTokenRedemptionRecord record;
record.set_body("I am a signed token redemption record");
record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record);
params.additional_headers_to_sign =
std::vector<std::string>{"Sec-Signed-Redemption-Record"};
+ params.issuers.push_back(
+ *SuitableTrustTokenOrigin::Create(GURL("https://second-issuer.example")));
+ SignedTrustTokenRedemptionRecord other_record;
+ other_record.set_body("I am a different signed token redemption record");
+ other_record.set_public_key("some other key");
+ store->SetRedemptionRecord(params.issuers.back(), params.toplevel,
+ other_record);
+
auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>();
TrustTokenRequestSigningHelper helper(store.get(), std::move(params),
std::make_unique<IdentitySigner>(),
@@ -461,8 +532,8 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyWithHeaders) {
EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
ASSERT_NO_FATAL_FAILURE(
- ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
- my_request.get()));
+ ReconstructSigningDataAndAssertSignaturesVerify<IdentitySigner>(
+ my_request.get(), /*num_expected_signatures=*/2));
}
// Test a round-trip sign-and-verify with signed headers when adding a timestamp
@@ -480,7 +551,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyTimestampHeader) {
SignedTrustTokenRedemptionRecord record;
record.set_body("I am a signed token redemption record");
record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record);
auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>();
TrustTokenRequestSigningHelper helper(store.get(), std::move(params),
@@ -495,15 +566,17 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyTimestampHeader) {
EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
ASSERT_NO_FATAL_FAILURE(
- ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
- my_request.get()));
+ ReconstructSigningDataAndAssertSignaturesVerify<IdentitySigner>(
+ my_request.get(), /*num_expected_signatures=*/1));
- std::string signature_string;
+ // Because we're using an IdentitySigner, each signature will have value
+ // equal to the base64-encoded request signing data.
+ std::map<std::string, std::string> signatures;
ASSERT_NO_FATAL_FAILURE(
- AssertHasSignatureAndExtract(*my_request, &signature_string));
+ AssertHasSignaturesAndExtract(*my_request, &signatures));
std::string retrieved_timestamp;
ASSERT_NO_FATAL_FAILURE(AssertDecodesToCborAndExtractField(
- signature_string, "sec-time", &retrieved_timestamp));
+ signatures.begin()->second, "sec-time", &retrieved_timestamp));
}
// Test a round-trip sign-and-verify additionally signing over the destination
@@ -520,7 +593,7 @@ TEST_F(TrustTokenRequestSigningHelperTest,
SignedTrustTokenRedemptionRecord record;
record.set_body("I am a signed token redemption record");
record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record);
params.additional_headers_to_sign =
std::vector<std::string>{"Sec-Signed-Redemption-Record"};
@@ -536,23 +609,23 @@ TEST_F(TrustTokenRequestSigningHelperTest,
ExecuteBeginOperationAndWaitForResult(&helper, my_request.get());
// In addition to testing that the signing data equals
- // ReconstructSigningDataAndAssertSignatureVerifies's reconstruction of the
+ // ReconstructSigningDataAndAssertSignaturesVerify's reconstruction of the
// data, explicitly check that it contains a "destination" field with the
// right value.
EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
ASSERT_NO_FATAL_FAILURE(
- ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
- my_request.get()));
+ ReconstructSigningDataAndAssertSignaturesVerify<IdentitySigner>(
+ my_request.get(), /*num_expected_signatures=*/1));
- // Because we're using an IdentitySigner, |signature_string| will have value
+ // Because we're using an IdentitySigner, each signature will have value
// equal to the base64-encoded request signing data.
- std::string signature_string;
+ std::map<std::string, std::string> signatures;
ASSERT_NO_FATAL_FAILURE(
- AssertHasSignatureAndExtract(*my_request, &signature_string));
+ AssertHasSignaturesAndExtract(*my_request, &signatures));
std::string retrieved_url;
ASSERT_NO_FATAL_FAILURE(AssertDecodesToCborAndExtractField(
- signature_string, "destination", &retrieved_url));
+ signatures.begin()->second, "destination", &retrieved_url));
ASSERT_EQ(retrieved_url, "destination.com");
}
@@ -569,7 +642,9 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ my_record.set_signing_key("signing key");
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
params.should_add_timestamp = true;
params.additional_headers_to_sign =
@@ -577,9 +652,12 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
// FailingSigner will fail to sign the request, so we should see the operation
// fail.
+ net::RecordingTestNetLog net_log;
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FailingSigner>(),
- std::make_unique<TrustTokenRequestCanonicalizer>());
+ std::make_unique<TrustTokenRequestCanonicalizer>(),
+ net::NetLogWithSource::Make(&net_log,
+ net::NetLogSourceType::URL_REQUEST));
auto my_request = MakeURLRequest("https://destination.com/");
my_request->set_initiator(
@@ -592,6 +670,18 @@ TEST_F(TrustTokenRequestSigningHelperTest, CatchesSignatureFailure) {
EXPECT_THAT(*my_request, Not(Header("Sec-Time")));
EXPECT_THAT(*my_request, Not(Header("Sec-Signature")));
EXPECT_THAT(*my_request, Header("Sec-Signed-Redemption-Record", IsEmpty()));
+ EXPECT_TRUE(util::ranges::any_of(
+ net_log.GetEntriesWithType(
+ net::NetLogEventType::TRUST_TOKEN_OPERATION_BEGIN_SIGNING),
+ [](const net::NetLogEntry& entry) {
+ base::Optional<std::string> key = net::GetOptionalStringValueFromParams(
+ entry, "failed_signing_params.key");
+ base::Optional<std::string> issuer =
+ net::GetOptionalStringValueFromParams(
+ entry, "failed_signing_params.issuer");
+ return key && *key == "signing key" && issuer &&
+ *issuer == "https://issuer.com";
+ }));
}
// Test a round-trip sign-and-verify with signed headers when adding additional
@@ -609,7 +699,7 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyAdditionalSigningData) {
SignedTrustTokenRedemptionRecord record;
record.set_body("I am a signed token redemption record");
record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel, record);
auto canonicalizer = std::make_unique<TrustTokenRequestCanonicalizer>();
TrustTokenRequestSigningHelper helper(store.get(), std::move(params),
@@ -624,15 +714,17 @@ TEST_F(TrustTokenRequestSigningHelperTest, SignAndVerifyAdditionalSigningData) {
EXPECT_EQ(result, mojom::TrustTokenOperationStatus::kOk);
ASSERT_NO_FATAL_FAILURE(
- ReconstructSigningDataAndAssertSignatureVerifies<IdentitySigner>(
- my_request.get()));
+ ReconstructSigningDataAndAssertSignaturesVerify<IdentitySigner>(
+ my_request.get(), /*num_expected_signatures=*/1));
- std::string signature_string;
+ // Because we're using an IdentitySigner, each signature will have value
+ // equal to the base64-encoded request signing data.
+ std::map<std::string, std::string> signatures;
ASSERT_NO_FATAL_FAILURE(
- AssertHasSignatureAndExtract(*my_request, &signature_string));
+ AssertHasSignaturesAndExtract(*my_request, &signatures));
std::string retrieved_additional_signing_data;
ASSERT_NO_FATAL_FAILURE(AssertDecodesToCborAndExtractField(
- signature_string, "sec-trust-tokens-additional-signing-data",
+ signatures.begin()->second, "sec-trust-tokens-additional-signing-data",
&retrieved_additional_signing_data));
EXPECT_EQ(retrieved_additional_signing_data, "some additional data to sign");
@@ -651,7 +743,8 @@ TEST_F(TrustTokenRequestSigningHelperTest,
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
@@ -685,7 +778,8 @@ TEST_F(TrustTokenRequestSigningHelperTest,
SignedTrustTokenRedemptionRecord my_record;
my_record.set_public_key("key");
- store->SetRedemptionRecord(params.issuer, params.toplevel, my_record);
+ store->SetRedemptionRecord(params.issuers.front(), params.toplevel,
+ my_record);
TrustTokenRequestSigningHelper helper(
store.get(), std::move(params), std::make_unique<FakeSigner>(),
diff --git a/chromium/services/network/udp_socket_test_util.cc b/chromium/services/network/udp_socket_test_util.cc
deleted file mode 100644
index b05ada98a90..00000000000
--- a/chromium/services/network/udp_socket_test_util.cc
+++ /dev/null
@@ -1,202 +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/network/udp_socket_test_util.h"
-
-#include <utility>
-
-#include "base/run_loop.h"
-#include "base/test/bind_test_util.h"
-#include "net/traffic_annotation/network_traffic_annotation_test_helper.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace network {
-
-namespace test {
-
-UDPSocketTestHelper::UDPSocketTestHelper(mojo::Remote<mojom::UDPSocket>* socket)
- : socket_(socket) {}
-
-UDPSocketTestHelper::~UDPSocketTestHelper() {}
-
-int UDPSocketTestHelper::ConnectSync(const net::IPEndPoint& remote_addr,
- mojom::UDPSocketOptionsPtr options,
- net::IPEndPoint* local_addr_out) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->Connect(
- remote_addr, std::move(options),
- base::BindLambdaForTesting(
- [&](int result, const base::Optional<net::IPEndPoint>& local_addr) {
- net_error = result;
- if (local_addr) {
- *local_addr_out = local_addr.value();
- }
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::BindSync(const net::IPEndPoint& local_addr,
- mojom::UDPSocketOptionsPtr options,
- net::IPEndPoint* local_addr_out) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->Bind(
- local_addr, std::move(options),
- base::BindLambdaForTesting(
- [&](int result, const base::Optional<net::IPEndPoint>& local_addr) {
- net_error = result;
- if (local_addr) {
- *local_addr_out = local_addr.value();
- }
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::SendToSync(const net::IPEndPoint& remote_addr,
- const std::vector<uint8_t>& input) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->SendTo(
- remote_addr, input,
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::SendSync(const std::vector<uint8_t>& input) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->Send(
- input,
- net::MutableNetworkTrafficAnnotationTag(TRAFFIC_ANNOTATION_FOR_TESTS),
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::SetBroadcastSync(bool broadcast) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->SetBroadcast(broadcast,
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::SetSendBufferSizeSync(int send_buffer_size) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->SetSendBufferSize(send_buffer_size,
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::SetReceiveBufferSizeSync(int receive_buffer_size) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->SetReceiveBufferSize(
- receive_buffer_size, base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::JoinGroupSync(const net::IPAddress& group_address) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->JoinGroup(group_address,
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-int UDPSocketTestHelper::LeaveGroupSync(const net::IPAddress& group_address) {
- base::RunLoop run_loop;
- int net_error = net::ERR_FAILED;
- socket_->get()->LeaveGroup(group_address,
- base::BindLambdaForTesting([&](int result) {
- net_error = result;
- run_loop.Quit();
- }));
- run_loop.Run();
- return net_error;
-}
-
-UDPSocketListenerImpl::ReceivedResult::ReceivedResult(
- int net_error_arg,
- const base::Optional<net::IPEndPoint>& src_addr_arg,
- base::Optional<std::vector<uint8_t>> data_arg)
- : net_error(net_error_arg),
- src_addr(src_addr_arg),
- data(std::move(data_arg)) {}
-
-UDPSocketListenerImpl::ReceivedResult::ReceivedResult(
- const ReceivedResult& other) = default;
-
-UDPSocketListenerImpl::ReceivedResult::~ReceivedResult() {}
-
-UDPSocketListenerImpl::UDPSocketListenerImpl()
- : run_loop_(std::make_unique<base::RunLoop>()),
- expected_receive_count_(0) {}
-
-UDPSocketListenerImpl::~UDPSocketListenerImpl() {}
-
-void UDPSocketListenerImpl::WaitForReceivedResults(size_t count) {
- DCHECK_LE(results_.size(), count);
- DCHECK_EQ(0u, expected_receive_count_);
-
- if (results_.size() == count)
- return;
-
- expected_receive_count_ = count;
- run_loop_->Run();
- run_loop_ = std::make_unique<base::RunLoop>();
-}
-
-void UDPSocketListenerImpl::OnReceived(
- int32_t result,
- const base::Optional<net::IPEndPoint>& src_addr,
- base::Optional<base::span<const uint8_t>> data) {
- // OnReceive() API contracts specifies that this method will not be called
- // with a |result| that is > 0.
- DCHECK_GE(0, result);
- DCHECK(result < 0 || data);
-
- results_.emplace_back(result, src_addr,
- data ? base::make_optional(std::vector<uint8_t>(
- data.value().begin(), data.value().end()))
- : base::nullopt);
- if (results_.size() == expected_receive_count_) {
- expected_receive_count_ = 0;
- run_loop_->Quit();
- }
-}
-
-} // namespace test
-
-} // namespace network
diff --git a/chromium/services/network/udp_socket_test_util.h b/chromium/services/network/udp_socket_test_util.h
deleted file mode 100644
index a6134096955..00000000000
--- a/chromium/services/network/udp_socket_test_util.h
+++ /dev/null
@@ -1,88 +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_NETWORK_UDP_SOCKET_TEST_UTIL_H_
-#define SERVICES_NETWORK_UDP_SOCKET_TEST_UTIL_H_
-
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/containers/span.h"
-#include "base/macros.h"
-#include "base/optional.h"
-#include "base/run_loop.h"
-#include "mojo/public/cpp/bindings/remote.h"
-#include "net/base/ip_endpoint.h"
-#include "net/base/net_errors.h"
-#include "services/network/public/mojom/udp_socket.mojom.h"
-
-namespace network {
-
-namespace test {
-
-// Helper functions to invoke the corresponding mojo APIs and wait for
-// completion.
-class UDPSocketTestHelper {
- public:
- explicit UDPSocketTestHelper(mojo::Remote<mojom::UDPSocket>* socket);
- ~UDPSocketTestHelper();
- int ConnectSync(const net::IPEndPoint& remote_addr,
- mojom::UDPSocketOptionsPtr options,
- net::IPEndPoint* local_addr_out);
- int BindSync(const net::IPEndPoint& local_addr,
- mojom::UDPSocketOptionsPtr options,
- net::IPEndPoint* local_addr_out);
- int SendToSync(const net::IPEndPoint& remote_addr,
- const std::vector<uint8_t>& input);
- int SendSync(const std::vector<uint8_t>& input);
- int SetBroadcastSync(bool broadcast);
- int SetSendBufferSizeSync(int send_buffer_size);
- int SetReceiveBufferSizeSync(int receive_buffer_size);
- int JoinGroupSync(const net::IPAddress& group_address);
- int LeaveGroupSync(const net::IPAddress& group_address);
-
- private:
- mojo::Remote<mojom::UDPSocket>* socket_;
-};
-
-// An implementation of mojom::UDPSocketListener that records received results.
-class UDPSocketListenerImpl : public mojom::UDPSocketListener {
- public:
- struct ReceivedResult {
- ReceivedResult(int net_error_arg,
- const base::Optional<net::IPEndPoint>& src_addr_arg,
- base::Optional<std::vector<uint8_t>> data_arg);
- ReceivedResult(const ReceivedResult& other);
- ~ReceivedResult();
-
- int net_error;
- base::Optional<net::IPEndPoint> src_addr;
- base::Optional<std::vector<uint8_t>> data;
- };
-
- UDPSocketListenerImpl();
- ~UDPSocketListenerImpl() override;
-
- const std::vector<ReceivedResult>& results() const { return results_; }
-
- void WaitForReceivedResults(size_t count);
-
- private:
- void OnReceived(int32_t result,
- const base::Optional<net::IPEndPoint>& src_addr,
- base::Optional<base::span<const uint8_t>> data) override;
- std::unique_ptr<base::RunLoop> run_loop_;
- std::vector<ReceivedResult> results_;
- size_t expected_receive_count_;
-
- DISALLOW_COPY_AND_ASSIGN(UDPSocketListenerImpl);
-};
-
-} // namespace test
-
-} // namespace network
-
-#endif // SERVICES_NETWORK_UDP_SOCKET_TEST_UTIL_H_
diff --git a/chromium/services/network/udp_socket_unittest.cc b/chromium/services/network/udp_socket_unittest.cc
index 8601d120fe0..6c180f8f335 100644
--- a/chromium/services/network/udp_socket_unittest.cc
+++ b/chromium/services/network/udp_socket_unittest.cc
@@ -26,7 +26,7 @@
#include "net/url_request/url_request_test_util.h"
#include "services/network/public/mojom/udp_socket.mojom.h"
#include "services/network/socket_factory.h"
-#include "services/network/udp_socket_test_util.h"
+#include "services/network/test/udp_socket_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
diff --git a/chromium/services/network/url_loader.cc b/chromium/services/network/url_loader.cc
index 9d2d455613f..0c19f0441db 100644
--- a/chromium/services/network/url_loader.cc
+++ b/chromium/services/network/url_loader.cc
@@ -28,10 +28,10 @@
#include "base/trace_event/trace_event.h"
#include "mojo/public/cpp/system/simple_watcher.h"
#include "net/base/elements_upload_data_stream.h"
-#include "net/base/ip_endpoint.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/mime_sniffer.h"
+#include "net/base/transport_info.h"
#include "net/base/upload_bytes_element_reader.h"
#include "net/base/upload_file_element_reader.h"
#include "net/cookies/canonical_cookie.h"
@@ -41,9 +41,11 @@
#include "net/ssl/ssl_connection_status_flags.h"
#include "net/ssl/ssl_private_key.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
+#include "net/url_request/redirect_info.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "services/network/chunked_data_pipe_upload_data_stream.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
#include "services/network/data_pipe_element_reader.h"
#include "services/network/network_usage_accumulator.h"
#include "services/network/origin_policy/origin_policy_constants.h"
@@ -52,6 +54,7 @@
#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/ip_address_space_util.h"
#include "services/network/public/cpp/net_adapters.h"
#include "services/network/public/cpp/network_switches.h"
#include "services/network/public/cpp/origin_policy.h"
@@ -207,12 +210,14 @@ std::unique_ptr<net::UploadDataStream> CreateUploadDataStream(
std::vector<base::File>& opened_files,
base::SequencedTaskRunner* file_task_runner) {
// In the case of a chunked upload, there will just be one element.
- if (body->elements()->size() == 1 &&
- body->elements()->begin()->type() ==
- network::mojom::DataElementType::kChunkedDataPipe) {
- return std::make_unique<ChunkedDataPipeUploadDataStream>(
- body, const_cast<DataElement&>(body->elements()->front())
- .ReleaseChunkedDataPipeGetter());
+ if (body->elements()->size() == 1) {
+ network::mojom::DataElementType type = body->elements()->begin()->type();
+ if (type == network::mojom::DataElementType::kChunkedDataPipe ||
+ type == network::mojom::DataElementType::kReadOnceStream) {
+ return std::make_unique<ChunkedDataPipeUploadDataStream>(
+ body,
+ body->elements_mutable()->begin()->ReleaseChunkedDataPipeGetter());
+ }
}
auto opened_file = opened_files.begin();
@@ -241,7 +246,8 @@ std::unique_ptr<net::UploadDataStream> CreateUploadDataStream(
body, element.CloneDataPipeGetter()));
break;
}
- case network::mojom::DataElementType::kChunkedDataPipe: {
+ case network::mojom::DataElementType::kChunkedDataPipe:
+ case network::mojom::DataElementType::kReadOnceStream: {
// This shouldn't happen, as the traits logic should ensure that if
// there's a chunked pipe, there's one and only one element.
NOTREACHED();
@@ -594,7 +600,7 @@ URLLoader::URLLoader(
is_nocors_corb_excluded_request_ =
request.corb_excluded && request.mode == mojom::RequestMode::kNoCors &&
- CrossOriginReadBlocking::ShouldAllowForPlugin(
+ CrossOriginReadBlockingExceptionForPlugin::ShouldAllowForPlugin(
factory_params_->process_id);
request_mode_ = request.mode;
if (request.trusted_params) {
@@ -612,7 +618,7 @@ URLLoader::URLLoader(
if (request.update_first_party_url_on_redirect) {
url_request_->set_first_party_url_policy(
- net::URLRequest::UPDATE_FIRST_PARTY_URL_ON_REDIRECT);
+ net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT);
}
url_request_->SetLoadFlags(request.load_flags);
@@ -979,6 +985,65 @@ void URLLoader::ResumeReadingBodyFromNet() {
}
}
+int URLLoader::CanConnectToRemoteEndpoint(
+ const net::TransportInfo& info) const {
+ const mojom::IPAddressSpace remote_address_space =
+ IPAddressToIPAddressSpace(info.endpoint.address());
+ if (options_ & mojom::kURLLoadOptionBlockLocalRequest &&
+ IsLessPublicAddressSpace(remote_address_space,
+ network::mojom::IPAddressSpace::kPublic)) {
+ DVLOG(1) << "CORS-RFC1918 check: failed due to loader options.";
+ return net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST;
+ }
+
+ const mojom::ClientSecurityStatePtr& security_state =
+ factory_params_->client_security_state;
+ if (!security_state) {
+ DVLOG(1) << "CORS-RFC1918 check: skipped, missing client security state.";
+ return net::OK;
+ }
+
+ DVLOG(1) << "CORS-RFC1918 check: running against client security state = { "
+ << "is_web_secure_context: " << security_state->is_web_secure_context
+ << ", ip_address_space: " << security_state->ip_address_space
+ << ", private_network_request_policy: "
+ << security_state->private_network_request_policy << " }.";
+
+ // We use a switch statement to force this code to be amended when values are
+ // added to the PrivateNetworkRequestPolicy enum.
+ switch (security_state->private_network_request_policy) {
+ case mojom::PrivateNetworkRequestPolicy::kAllow:
+ break;
+ case mojom::PrivateNetworkRequestPolicy::kBlockFromInsecureToMorePrivate:
+ // We block requests from insecure contexts to resources in IP address
+ // spaces more private than that of the initiator. This prevents malicious
+ // insecure public websites from making requests to someone's printer, for
+ // example.
+ if (!security_state->is_web_secure_context &&
+ IsLessPublicAddressSpace(remote_address_space,
+ security_state->ip_address_space)) {
+ DVLOG(1) << "CORS-RFC1918 check: "
+ "failed, blocking insecure private network request.";
+ return net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST;
+ }
+ }
+
+ DVLOG(1) << "CORS-RFC1918 check: success.";
+ return net::OK;
+}
+
+int URLLoader::OnConnected(net::URLRequest* url_request,
+ const net::TransportInfo& info) {
+ DCHECK_EQ(url_request, url_request_.get());
+
+ DVLOG(1) << "Connection obtained for URL request to " << url_request->url()
+ << ": " << info;
+
+ // Now that the request endpoint's address has been resolved, check if
+ // this request should be blocked by CORS-RFC1918 rules.
+ return CanConnectToRemoteEndpoint(info);
+}
+
void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) {
@@ -1015,7 +1080,7 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
CrossOriginResourcePolicy::IsBlocked(
url_request_->url(), url_request_->original_url(),
url_request_->initiator(), *response, request_mode_,
- factory_params_->request_initiator_site_lock,
+ factory_params_->request_initiator_origin_lock,
cross_origin_embedder_policy, coep_reporter_)) {
CompleteBlockedResponse(net::ERR_BLOCKED_BY_RESPONSE, false,
blocked_reason);
@@ -1035,22 +1100,13 @@ void URLLoader::OnReceivedRedirect(net::URLRequest* url_request,
// 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)
+ if (elements->size() != 1u)
return false;
- return elements->at(0).type() == mojom::DataElementType::kChunkedDataPipe;
+ return elements->front().type() == mojom::DataElementType::kReadOnceStream;
}
void URLLoader::OnAuthRequired(net::URLRequest* url_request,
@@ -1153,6 +1209,44 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
return;
}
+ response_ = network::mojom::URLResponseHead::New();
+ PopulateResourceResponse(
+ url_request_.get(), is_load_timing_enabled_,
+ options_ & mojom::kURLLoadOptionSendSSLInfoWithResponse, response_.get());
+ if (report_raw_headers_) {
+ response_->raw_request_response_info = BuildRawRequestResponseInfo(
+ *url_request_, raw_request_headers_, raw_response_headers_.get());
+ raw_request_headers_ = net::HttpRawRequestHeaders();
+ raw_response_headers_ = nullptr;
+ }
+
+ // Parse and remove the Trust Tokens response headers, if any are expected,
+ // potentially failing the request if an error occurs.
+ if (trust_token_helper_) {
+ trust_token_helper_->Finalize(
+ response_.get(),
+ base::BindOnce(&URLLoader::OnDoneFinalizingTrustTokenOperation,
+ weak_ptr_factory_.GetWeakPtr()));
+ // |this| may have been deleted.
+ return;
+ }
+
+ ContinueOnResponseStarted();
+}
+
+void URLLoader::OnDoneFinalizingTrustTokenOperation(
+ mojom::TrustTokenOperationStatus status) {
+ trust_token_status_ = status;
+
+ if (status != mojom::TrustTokenOperationStatus::kOk) {
+ NotifyCompleted(net::ERR_TRUST_TOKEN_OPERATION_FAILED);
+ // |this| may have been deleted.
+ return;
+ }
+ ContinueOnResponseStarted();
+}
+
+void URLLoader::ContinueOnResponseStarted() {
MojoCreateDataPipeOptions options;
options.struct_size = sizeof(MojoCreateDataPipeOptions);
options.flags = MOJO_CREATE_DATA_PIPE_FLAG_NONE;
@@ -1178,17 +1272,6 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
upload_progress_tracker_ = nullptr;
}
- response_ = network::mojom::URLResponseHead::New();
- PopulateResourceResponse(
- url_request_.get(), is_load_timing_enabled_,
- options_ & mojom::kURLLoadOptionSendSSLInfoWithResponse, response_.get());
- if (report_raw_headers_) {
- response_->raw_request_response_info = BuildRawRequestResponseInfo(
- *url_request_, raw_request_headers_, raw_response_headers_.get());
- raw_request_headers_ = net::HttpRawRequestHeaders();
- raw_response_headers_ = nullptr;
- }
-
peer_closed_handle_watcher_.Watch(
response_body_stream_.get(), MOJO_HANDLE_SIGNAL_PEER_CLOSED,
base::BindRepeating(&URLLoader::OnResponseBodyStreamConsumerClosed,
@@ -1210,7 +1293,7 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
CrossOriginResourcePolicy::IsBlocked(
url_request_->url(), url_request_->original_url(),
url_request_->initiator(), *response_, request_mode_,
- factory_params_->request_initiator_site_lock,
+ factory_params_->request_initiator_origin_lock,
cross_origin_embedder_policy, coep_reporter_)) {
CompleteBlockedResponse(net::ERR_BLOCKED_BY_RESPONSE, false,
blocked_reason);
@@ -1218,34 +1301,6 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
return;
}
- // Parse and remove the Trust Tokens response headers, if any are expected,
- // potentially failing the request if an error occurs.
- if (trust_token_helper_) {
- trust_token_helper_->Finalize(
- response_.get(),
- base::BindOnce(
- [](base::WeakPtr<URLLoader> loader, net::URLRequest* request,
- int net_error, mojom::TrustTokenOperationStatus status) {
- if (!loader)
- return;
- if (status != mojom::TrustTokenOperationStatus::kOk) {
- loader->trust_token_status_ = status;
- loader->NotifyCompleted(net::ERR_TRUST_TOKEN_OPERATION_FAILED);
- // |loader| may have been deleted.
- return;
- }
- loader->ContinueOnResponseStarted(request, net_error);
- },
- weak_ptr_factory_.GetWeakPtr(), url_request, net_error));
- // |this| may have been deleted.
- return;
- }
-
- ContinueOnResponseStarted(url_request, net_error);
-}
-
-void URLLoader::ContinueOnResponseStarted(net::URLRequest* url_request,
- int net_error) {
// Figure out if we need to sniff (for MIME type detection or for Cross-Origin
// Read Blocking / CORB).
if (factory_params_->is_corb_enabled && !is_nocors_corb_excluded_request_) {
@@ -1255,7 +1310,7 @@ void URLLoader::ContinueOnResponseStarted(net::URLRequest* url_request,
corb_analyzer_ =
std::make_unique<CrossOriginReadBlocking::ResponseAnalyzer>(
url_request_->url(), url_request_->initiator(), *response_,
- factory_params_->request_initiator_site_lock, request_mode_,
+ factory_params_->request_initiator_origin_lock, request_mode_,
isolated_world_origin_, network_service_client_);
is_more_corb_sniffing_needed_ = corb_analyzer_->needs_sniffing();
if (corb_analyzer_->ShouldBlock()) {
@@ -1302,8 +1357,8 @@ void URLLoader::ContinueOnResponseStarted(net::URLRequest* url_request,
// request of the original URL.
net::IsolationInfo isolation_info = net::IsolationInfo::Create(
net::IsolationInfo::RedirectMode::kUpdateNothing,
- url_request->isolation_info().top_frame_origin().value(),
- url_request->isolation_info().frame_origin().value(),
+ url_request_->isolation_info().top_frame_origin().value(),
+ url_request_->isolation_info().frame_origin().value(),
net::SiteForCookies());
origin_policy_manager_->RetrieveOriginPolicy(
url::Origin::Create(url_request_->url()), isolation_info,
@@ -1794,14 +1849,13 @@ void URLLoader::SetRawRequestHeadersAndNotify(
}
if (cookie_observer_) {
- net::CookieStatusList reported_cookies;
+ net::CookieAccessResultList reported_cookies;
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_with_access_result.cookie,
- cookie_with_access_result.access_result.status});
+ reported_cookies.push_back({cookie_with_access_result.cookie,
+ cookie_with_access_result.access_result});
}
}
@@ -2009,13 +2063,15 @@ void URLLoader::ReportFlaggedResponseCookies() {
}
if (cookie_observer_) {
- net::CookieStatusList reported_cookies;
- for (const auto& cookie_line_and_status :
+ net::CookieAccessResultList reported_cookies;
+ for (const auto& cookie_line_and_access_result :
url_request_->maybe_stored_cookies()) {
- if (ShouldNotifyAboutCookie(cookie_line_and_status.status) &&
- cookie_line_and_status.cookie) {
- reported_cookies.push_back({cookie_line_and_status.cookie.value(),
- cookie_line_and_status.status});
+ if (ShouldNotifyAboutCookie(
+ cookie_line_and_access_result.access_result.status) &&
+ cookie_line_and_access_result.cookie) {
+ reported_cookies.push_back(
+ {cookie_line_and_access_result.cookie.value(),
+ cookie_line_and_access_result.access_result});
}
}
diff --git a/chromium/services/network/url_loader.h b/chromium/services/network/url_loader.h
index 33e6b100ef3..a624b8c43f4 100644
--- a/chromium/services/network/url_loader.h
+++ b/chromium/services/network/url_loader.h
@@ -27,9 +27,9 @@
#include "net/http/http_raw_request_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#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/cross_origin_read_blocking.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,6 +46,9 @@
namespace net {
class HttpResponseHeaders;
+class IPEndPoint;
+struct RedirectInfo;
+struct TransportInfo;
class URLRequestContext;
} // namespace net
@@ -133,6 +136,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void ResumeReadingBodyFromNet() override;
// net::URLRequest::Delegate implementation:
+ int OnConnected(net::URLRequest* url_request,
+ const net::TransportInfo& info) override;
void OnReceivedRedirect(net::URLRequest* url_request,
const net::RedirectInfo& redirect_info,
bool* defer_redirect) override;
@@ -265,7 +270,15 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
// - receive the result in OnDoneBeginningTrustTokenOperation;
// - if successful, ScheduleStart; if there was an error, fail.
//
- // (Inbound, response handling just takes a synchronous Finalize call.)
+ // Inbound control flow:
+ //
+ // Start in OnResponseStarted
+ // - If there are no Trust Tokens parameters, proceed to
+ // ContinueOnResponseStarted.
+ // - Otherwise:
+ // - execute TrustTokenRequestHelper::Finalize against the helper;
+ // - receive the result in OnDoneFinalizingTrusttokenOperation;
+ // - if successful, ContinueOnResponseStarted; if there was an error, fail.
void BeginTrustTokenOperationIfNecessaryAndThenScheduleStart(
const ResourceRequest& request);
void OnDoneConstructingTrustTokenHelper(
@@ -273,9 +286,11 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
TrustTokenStatusOrRequestHelper status_or_helper);
void OnDoneBeginningTrustTokenOperation(
mojom::TrustTokenOperationStatus status);
+ void OnDoneFinalizingTrustTokenOperation(
+ mojom::TrustTokenOperationStatus status);
// Continuation of |OnResponseStarted| after possibly asynchronously
// concluding the request's Trust Tokens operation.
- void ContinueOnResponseStarted(net::URLRequest* url_request, int net_error);
+ void ContinueOnResponseStarted();
void ScheduleStart();
void ReadMore();
@@ -330,6 +345,16 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) URLLoader
void StartReading();
void OnOriginPolicyManagerRetrieveDone(const OriginPolicy& origin_policy);
+ // Checks if the request initiator should be allowed to make requests to the
+ // remote endpoint, as described in |info|.
+ //
+ // Returns a net error code.
+ //
+ // See the CORS-RFC1918 spec: https://wicg.github.io/cors-rfc1918.
+ //
+ // Helper for OnConnected().
+ int CanConnectToRemoteEndpoint(const net::TransportInfo& info) const;
+
net::URLRequestContext* url_request_context_;
mojom::NetworkServiceClient* network_service_client_;
mojom::NetworkContextClient* network_context_client_;
diff --git a/chromium/services/network/url_loader_factory.cc b/chromium/services/network/url_loader_factory.cc
index c8f02a3760f..75ae8488efa 100644
--- a/chromium/services/network/url_loader_factory.cc
+++ b/chromium/services/network/url_loader_factory.cc
@@ -215,22 +215,6 @@ void URLLoaderFactory::CreateLoaderAndStart(
return;
}
- if (url_request.trust_token_params && !context_->trust_token_store()) {
- mojo::ReportBadMessage(
- "Got a request with Trust Tokens parameters with Trust tokens "
- "disabled.");
- return;
- }
-
- if (url_request.trust_token_params && url_request.request_initiator &&
- !IsOriginPotentiallyTrustworthy(*url_request.request_initiator)) {
- mojo::ReportBadMessage(
- "Got a request with Trust Tokens parameters from an insecure context, "
- "but Trust Tokens operations may only be executed from secure "
- "contexts.");
- return;
- }
-
std::unique_ptr<TrustTokenRequestHelperFactory> trust_token_factory;
if (url_request.trust_token_params) {
trust_token_factory = std::make_unique<TrustTokenRequestHelperFactory>(
diff --git a/chromium/services/network/url_loader_unittest.cc b/chromium/services/network/url_loader_unittest.cc
index dc8375fd926..72b18010175 100644
--- a/chromium/services/network/url_loader_unittest.cc
+++ b/chromium/services/network/url_loader_unittest.cc
@@ -43,12 +43,15 @@
#include "net/base/escape.h"
#include "net/base/features.h"
#include "net/base/io_buffer.h"
+#include "net/base/ip_endpoint.h"
#include "net/base/isolation_info.h"
#include "net/base/load_flags.h"
#include "net/base/mime_sniffer.h"
#include "net/base/net_errors.h"
+#include "net/base/transport_info.h"
#include "net/cert/internal/parse_name.h"
#include "net/cert/test_root_certs.h"
+#include "net/cookies/cookie_access_result.h"
#include "net/cookies/cookie_change_dispatcher.h"
#include "net/cookies/cookie_inclusion_status.h"
#include "net/cookies/cookie_util.h"
@@ -60,6 +63,7 @@
#include "net/test/embedded_test_server/controllable_http_response.h"
#include "net/test/embedded_test_server/embedded_test_server.h"
#include "net/test/embedded_test_server/http_response.h"
+#include "net/test/gtest_util.h"
#include "net/test/quic_simple_test_server.h"
#include "net/test/test_data_directory.h"
#include "net/test/url_request/url_request_failed_job.h"
@@ -70,13 +74,14 @@
#include "net/url_request/url_request_filter.h"
#include "net/url_request/url_request_interceptor.h"
#include "net/url_request/url_request_job.h"
-#include "net/url_request/url_request_status.h"
#include "net/url_request/url_request_test_job.h"
#include "net/url_request/url_request_test_util.h"
+#include "services/network/cross_origin_read_blocking_exception_for_plugin.h"
#include "services/network/public/cpp/features.h"
#include "services/network/public/cpp/resource_request.h"
#include "services/network/public/mojom/cookie_access_observer.mojom-forward.h"
#include "services/network/public/mojom/cookie_access_observer.mojom.h"
+#include "services/network/public/mojom/ip_address_space.mojom.h"
#include "services/network/public/mojom/origin_policy_manager.mojom.h"
#include "services/network/public/mojom/trust_tokens.mojom-shared.h"
#include "services/network/public/mojom/url_loader.mojom.h"
@@ -99,7 +104,10 @@ namespace network {
namespace {
+using ::net::test::IsError;
+using ::net::test::IsOk;
using ::testing::Optional;
+using ::testing::ValuesIn;
// Returns a URLLoader::DeleteCallback that destroys |url_loader| and quits
// |run_loop| when invoked. Tests must wait on the RunLoop to ensure nothing is
@@ -379,6 +387,89 @@ class SimulatedCacheInterceptor : public net::URLRequestInterceptor {
DISALLOW_COPY_AND_ASSIGN(SimulatedCacheInterceptor);
};
+// Fakes the TransportInfo passed to URLRequest::Delegate::OnConnected().
+class URLRequestFakeTransportInfoJob : public net::URLRequestJob {
+ public:
+ // |transport_info| is subsequently passed to the OnConnected() callback.
+ URLRequestFakeTransportInfoJob(net::URLRequest* request,
+ net::NetworkDelegate* network_delegate,
+ const net::TransportInfo& transport_info)
+ : URLRequestJob(request, network_delegate),
+ transport_info_(transport_info) {}
+
+ URLRequestFakeTransportInfoJob(const URLRequestFakeTransportInfoJob&) =
+ delete;
+ URLRequestFakeTransportInfoJob& operator=(
+ const URLRequestFakeTransportInfoJob&) = delete;
+
+ // net::URLRequestJob implementation:
+ void Start() override {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&URLRequestFakeTransportInfoJob::StartAsync,
+ weak_factory_.GetWeakPtr()));
+ }
+
+ int ReadRawData(net::IOBuffer* buf, int buf_size) override { return 0; }
+
+ private:
+ ~URLRequestFakeTransportInfoJob() override = default;
+
+ void StartAsync() {
+ const int result = NotifyConnected(transport_info_);
+ if (result != net::OK) {
+ NotifyStartError(result);
+ return;
+ }
+
+ NotifyHeadersComplete();
+ }
+
+ // The fake transport info we pass to OnConnected().
+ const net::TransportInfo transport_info_;
+
+ base::WeakPtrFactory<URLRequestFakeTransportInfoJob> weak_factory_{this};
+};
+
+// Intercepts URLRequestJob creation to a specific URL. All requests to this
+// URL will report being connected with a fake TransportInfo struct.
+class FakeTransportInfoInterceptor : public net::URLRequestInterceptor {
+ public:
+ // All intercepted requests will claim to be connected via |transport_info|.
+ explicit FakeTransportInfoInterceptor(
+ const net::TransportInfo& transport_info)
+ : transport_info_(transport_info) {}
+
+ ~FakeTransportInfoInterceptor() override = default;
+
+ FakeTransportInfoInterceptor(const FakeTransportInfoInterceptor&) = delete;
+ FakeTransportInfoInterceptor& operator=(const FakeTransportInfoInterceptor&) =
+ delete;
+
+ // URLRequestInterceptor implementation:
+ net::URLRequestJob* MaybeInterceptRequest(
+ net::URLRequest* request,
+ net::NetworkDelegate* network_delegate) const override {
+ // NOTE: We cannot use make_unique() because
+ // URLRequestFakeTransportInfoJob's destructor is private, which prevents
+ // use of unique_ptr.
+ return new URLRequestFakeTransportInfoJob(request, network_delegate,
+ transport_info_);
+ }
+
+ private:
+ const net::TransportInfo transport_info_;
+};
+
+// Returns a maximally-restrictive security state for use in tests.
+mojom::ClientSecurityStatePtr NewSecurityState() {
+ auto result = mojom::ClientSecurityState::New();
+ result->is_web_secure_context = false;
+ result->private_network_request_policy =
+ mojom::PrivateNetworkRequestPolicy::kBlockFromInsecureToMorePrivate;
+ result->ip_address_space = mojom::IPAddressSpace::kUnknown;
+ return result;
+}
+
// Returns whether monitoring was successfully set up. If yes,
// StopMonitorBodyReadFromNetBeforePausedHistogram() needs to be called later to
// stop monitoring.
@@ -491,9 +582,12 @@ class URLLoaderTest : public testing::Test {
base::RunLoop delete_run_loop;
mojo::Remote<mojom::URLLoader> loader;
std::unique_ptr<URLLoader> url_loader;
- static mojom::URLLoaderFactoryParams params;
+
+ mojom::URLLoaderFactoryParams params;
params.process_id = mojom::kBrowserProcessId;
params.is_corb_enabled = false;
+ params.client_security_state.Swap(&client_security_state_);
+
url::Origin origin = url::Origin::Create(url);
params.isolation_info =
net::IsolationInfo::CreateForInternalRequest(origin);
@@ -668,6 +762,9 @@ class URLLoaderTest : public testing::Test {
DCHECK(!ran_);
expect_redirect_ = true;
}
+ void set_client_security_state(mojom::ClientSecurityStatePtr state) {
+ client_security_state_ = std::move(state);
+ }
void set_request_body(scoped_refptr<ResourceRequestBody> request_body) {
request_body_ = request_body;
}
@@ -791,6 +888,7 @@ class URLLoaderTest : public testing::Test {
bool send_ssl_with_response_ = false;
bool send_ssl_for_cert_error_ = false;
bool expect_redirect_ = false;
+ mojom::ClientSecurityStatePtr client_security_state_;
scoped_refptr<ResourceRequestBody> request_body_;
// Used to ensure that methods are called either before or after a request is
@@ -838,6 +936,307 @@ TEST_F(URLLoaderTest, SSLSentOnlyWhenRequested) {
ASSERT_FALSE(!!ssl_info());
}
+// This test verifies that when the URLLoaderFactory's parameters are missing
+// a client security state, requests to local network resources are authorized.
+TEST_F(URLLoaderTest, MissingClientSecurityStateIsOk) {
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+// These tests verify that requests from an secure page to an IP in the
+// "local" address space are never blocked.
+
+TEST_F(URLLoaderTest, SecureUnknownToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = true;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, SecurePublicToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = true;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, SecurePrivateToLocalIsBlocked) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = true;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, SecureLocalToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = true;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+// These tests verify that requests from any page to an IP in the "local"
+// address space are never blocked when the request policy is kAllow.
+
+TEST_F(URLLoaderTest, PolicyIsAllowUnknownToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->private_network_request_policy =
+ mojom::PrivateNetworkRequestPolicy::kAllow;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, PolicyIsAllowPublicToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->private_network_request_policy =
+ mojom::PrivateNetworkRequestPolicy::kAllow;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, PolicyIsAllowPrivateToLocalIsBlocked) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->private_network_request_policy =
+ mojom::PrivateNetworkRequestPolicy::kAllow;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+TEST_F(URLLoaderTest, PolicyIsAllowLocalToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->private_network_request_policy =
+ mojom::PrivateNetworkRequestPolicy::kAllow;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+// These tests verify that requests from an insecure page to an IP in the
+// "local" address space are blocked unless the page came from the same address
+// space. In practice, the local address space contains only localhost.
+//
+// NOTE: These tests exercise the same codepath as
+// URLLoaderFakeTransportInfoTest below, except they use real URLRequestJob and
+// HttpTransaction implementations for higher confidence in the correctness of
+// the whole stack. OTOH, using an embedded test server prevents us from mocking
+// out the endpoint IP address.
+
+TEST_F(URLLoaderTest, InsecureRequestToLocalResource) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = false;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kUnknown;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")),
+ IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST));
+}
+
+TEST_F(URLLoaderTest, InsecurePublicToLocalIsBlocked) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = false;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPublic;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")),
+ IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST));
+}
+
+TEST_F(URLLoaderTest, InsecurePrivateToLocalIsBlocked) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = false;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kPrivate;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")),
+ IsError(net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST));
+}
+
+TEST_F(URLLoaderTest, InsecureLocalToLocalIsOk) {
+ auto client_security_state = NewSecurityState();
+ client_security_state->is_web_secure_context = false;
+ client_security_state->ip_address_space = mojom::IPAddressSpace::kLocal;
+ set_client_security_state(std::move(client_security_state));
+
+ EXPECT_THAT(Load(test_server()->GetURL("/empty.html")), IsOk());
+}
+
+// Bundles together the inputs to a parameterized private network request test.
+struct URLLoaderFakeTransportInfoTestParams {
+ // The address space of the client.
+ mojom::IPAddressSpace client_address_space;
+
+ // The address space of the endpoint serving the request.
+ mojom::IPAddressSpace endpoint_address_space;
+
+ // The expected request result.
+ int expected_result;
+};
+
+// For clarity when debugging parameterized test failures.
+std::ostream& operator<<(std::ostream& out,
+ const URLLoaderFakeTransportInfoTestParams& params) {
+ return out << "{ client_address_space: " << params.client_address_space
+ << ", endpoint_address_space: " << params.endpoint_address_space
+ << ", expected_result: "
+ << net::ErrorToString(params.expected_result) << " }";
+}
+
+class URLLoaderFakeTransportInfoTest
+ : public URLLoaderTest,
+ public testing::WithParamInterface<URLLoaderFakeTransportInfoTestParams> {
+ protected:
+ // Returns an address in the given IP address space.
+ static net::IPAddress FakeAddress(mojom::IPAddressSpace space) {
+ switch (space) {
+ case mojom::IPAddressSpace::kUnknown:
+ return net::IPAddress();
+ case mojom::IPAddressSpace::kPublic:
+ return net::IPAddress(42, 0, 1, 2);
+ case mojom::IPAddressSpace::kPrivate:
+ return net::IPAddress(10, 0, 1, 2);
+ case mojom::IPAddressSpace::kLocal:
+ return net::IPAddress::IPv4Localhost();
+ }
+ }
+
+ // Returns an endpoint in the given IP address space.
+ static net::IPEndPoint FakeEndpoint(mojom::IPAddressSpace space) {
+ return net::IPEndPoint(FakeAddress(space), 80);
+ }
+
+ // Returns a transport info with an endpoint in the given IP address space.
+ static net::TransportInfo FakeTransportInfo(mojom::IPAddressSpace space) {
+ return net::TransportInfo(net::TransportType::kDirect, FakeEndpoint(space));
+ }
+};
+
+// This test verifies that requests made from insecure contexts are handled
+// appropriately when they go from a less-private address space to a
+// more-private address space or not. The test is parameterized by
+// (client address space, server address space, expected result) tuple.
+TEST_P(URLLoaderFakeTransportInfoTest, PrivateNetworkRequestLoadsCorrectly) {
+ const auto params = GetParam();
+
+ auto client_security_state = NewSecurityState();
+ client_security_state->ip_address_space = params.client_address_space;
+ set_client_security_state(std::move(client_security_state));
+
+ const GURL url("http://fake-endpoint");
+
+ net::URLRequestFilter::GetInstance()->AddUrlInterceptor(
+ url, std::make_unique<FakeTransportInfoInterceptor>(
+ FakeTransportInfo(params.endpoint_address_space)));
+
+ // Despite its name, IsError(OK) asserts that the matched value is OK.
+ EXPECT_THAT(Load(url), IsError(params.expected_result));
+}
+
+// Lists all combinations we want to test in URLLoaderFakeTransportInfoTest.
+constexpr URLLoaderFakeTransportInfoTestParams
+ kURLLoaderFakeTransportInfoTestParamsList[] = {
+ // Client: kUnknown
+ {
+ mojom::IPAddressSpace::kUnknown,
+ mojom::IPAddressSpace::kUnknown,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kUnknown,
+ mojom::IPAddressSpace::kPublic,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kUnknown,
+ mojom::IPAddressSpace::kPrivate,
+ net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST,
+ },
+ {
+ mojom::IPAddressSpace::kUnknown,
+ mojom::IPAddressSpace::kLocal,
+ net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST,
+ },
+ // Client: kPublic
+ {
+ mojom::IPAddressSpace::kPublic,
+ mojom::IPAddressSpace::kUnknown,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPublic,
+ mojom::IPAddressSpace::kPublic,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPublic,
+ mojom::IPAddressSpace::kPrivate,
+ net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST,
+ },
+ {
+ mojom::IPAddressSpace::kPublic,
+ mojom::IPAddressSpace::kLocal,
+ net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST,
+ },
+ // Client: kPrivate
+ {
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kUnknown,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kPublic,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kPrivate,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kPrivate,
+ mojom::IPAddressSpace::kLocal,
+ net::ERR_INSECURE_PRIVATE_NETWORK_REQUEST,
+ },
+ // Client: kLocal
+ {
+ mojom::IPAddressSpace::kLocal,
+ mojom::IPAddressSpace::kUnknown,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kLocal,
+ mojom::IPAddressSpace::kPublic,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kLocal,
+ mojom::IPAddressSpace::kPrivate,
+ net::OK,
+ },
+ {
+ mojom::IPAddressSpace::kLocal,
+ mojom::IPAddressSpace::kLocal,
+ net::OK,
+ },
+};
+
+INSTANTIATE_TEST_SUITE_P(Parameterized,
+ URLLoaderFakeTransportInfoTest,
+ ValuesIn(kURLLoaderFakeTransportInfoTestParamsList));
+
// Tests that auth challenge info is present on the response when a request
// receives an authentication challenge.
TEST_F(URLLoaderTest, AuthChallengeInfo) {
@@ -1874,6 +2273,62 @@ TEST_F(URLLoaderTest, UploadChunkedDataPipe) {
EXPECT_EQ(net::OK, client()->completion_status().error_code);
}
+// Tests a request body with ReadOnceStream.
+TEST_F(URLLoaderTest, UploadReadOnceStream) {
+ const std::string kRequestBody = "Request Body";
+
+ TestChunkedDataPipeGetter data_pipe_getter;
+
+ ResourceRequest request =
+ CreateResourceRequest("POST", test_server()->GetURL("/echo"));
+ request.request_body = base::MakeRefCounted<ResourceRequestBody>();
+ request.request_body->SetToReadOnceStream(
+ data_pipe_getter.GetDataPipeGetterRemote());
+
+ base::HistogramTester tester;
+ std::string histogram_allowh1("Net.Fetch.UploadStreamingProtocolAllowH1");
+ std::string histogram_notallowh1(
+ "Net.Fetch.UploadStreamingProtocolNotAllowH1");
+ tester.ExpectTotalCount(histogram_allowh1, 0);
+ tester.ExpectTotalCount(histogram_notallowh1, 0);
+
+ base::RunLoop delete_run_loop;
+ mojo::Remote<mojom::URLLoader> loader;
+ std::unique_ptr<URLLoader> url_loader;
+ mojom::URLLoaderFactoryParams params;
+ params.process_id = mojom::kBrowserProcessId;
+ params.is_corb_enabled = false;
+ url_loader = std::make_unique<URLLoader>(
+ context(), nullptr /* network_service_client */,
+ nullptr /* network_context_client */,
+ DeleteLoaderCallback(&delete_run_loop, &url_loader),
+ loader.BindNewPipeAndPassReceiver(), 0, request, client()->CreateRemote(),
+ /*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 */,
+ mojo::NullRemote() /* cookie_observer */);
+
+ mojom::ChunkedDataPipeGetter::GetSizeCallback get_size_callback =
+ data_pipe_getter.WaitForGetSize();
+ mojo::BlockingCopyFromString(kRequestBody,
+ data_pipe_getter.WaitForStartReading());
+ std::move(get_size_callback).Run(net::OK, kRequestBody.size());
+ delete_run_loop.Run();
+ client()->RunUntilComplete();
+
+ EXPECT_EQ(kRequestBody, ReadBody());
+ EXPECT_EQ(net::OK, client()->completion_status().error_code);
+
+ tester.ExpectTotalCount(histogram_allowh1, 1);
+ // From ReportFetchUploadStreamingUMA()
+ constexpr int kHTTP1_1 = 0;
+ tester.ExpectBucketCount(histogram_allowh1, kHTTP1_1, 1);
+ tester.ExpectTotalCount(histogram_notallowh1, 0);
+}
+
// Tests that SSLInfo is not attached to OnComplete messages when there is no
// certificate error.
TEST_F(URLLoaderTest, NoSSLInfoWithoutCertificateError) {
@@ -2630,13 +3085,13 @@ class MockCookieObserver : public network::mojom::CookieAccessObserver {
struct CookieDetails {
CookieDetails(const mojom::CookieAccessDetailsPtr& details,
- const net::CookieWithStatus cookie)
+ const net::CookieWithAccessResult cookie)
: type(details->type),
name(cookie.cookie.Name()),
value(cookie.cookie.Value()),
- is_include(cookie.status.IsInclude()),
+ is_include(cookie.access_result.status.IsInclude()),
url(details->url),
- status(cookie.status) {}
+ status(cookie.access_result.status) {}
CookieDetails(CookieAccessType type,
std::string name,
@@ -2734,12 +3189,12 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
int32_t process_id,
int32_t routing_id,
const std::string& devtools_request_id,
- const net::CookieAndLineStatusList& cookies_with_status,
+ const net::CookieAndLineAccessResultList& cookies_with_access_result,
std::vector<network::mojom::HttpRawHeaderPairPtr> headers,
const base::Optional<std::string>& raw_response_headers) override {
raw_response_cookies_.insert(raw_response_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;
@@ -2774,7 +3229,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
EXPECT_EQ(goal, raw_request_cookies_.size());
}
- const net::CookieAndLineStatusList& raw_response_cookies() const {
+ const net::CookieAndLineAccessResultList& raw_response_cookies() const {
return raw_response_cookies_;
}
@@ -2789,7 +3244,7 @@ class MockNetworkServiceClient : public TestNetworkServiceClient {
}
private:
- net::CookieAndLineStatusList raw_response_cookies_;
+ net::CookieAndLineAccessResultList raw_response_cookies_;
base::OnceClosure wait_for_raw_response_;
size_t wait_for_raw_response_goal_ = 0u;
std::string devtools_request_id_;
@@ -3238,7 +3693,7 @@ TEST_F(URLLoaderTest, CorbExcludedWithNoCors) {
std::unique_ptr<URLLoader> url_loader;
mojom::URLLoaderFactoryParams params;
params.process_id = 123;
- CrossOriginReadBlocking::AddExceptionForPlugin(123);
+ CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(123);
url_loader = std::make_unique<URLLoader>(
context(), nullptr /* network_service_client */,
nullptr /* network_context_client */,
@@ -3262,13 +3717,14 @@ TEST_F(URLLoaderTest, CorbExcludedWithNoCors) {
// The request body is allowed through because CORB isn't applied.
ASSERT_NE(std::string(), body);
- CrossOriginReadBlocking::RemoveExceptionForPlugin(123);
+ CrossOriginReadBlockingExceptionForPlugin::RemoveExceptionForPlugin(123);
}
// This simulates a renderer that pretends to be proxying requests for Flash
// (when browser didn't actually confirm that Flash is hosted by the given
-// process via CrossOriginReadBlocking::AddExceptionForPlugin). We should still
-// apply CORB in this case.
+// process via
+// CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin). We should
+// still apply CORB in this case.
TEST_F(URLLoaderTest, CorbEffectiveWithNoCorsWhenNoActualPlugin) {
int kResourceType = 1;
ResourceRequest request =
@@ -3283,8 +3739,9 @@ TEST_F(URLLoaderTest, CorbEffectiveWithNoCorsWhenNoActualPlugin) {
std::unique_ptr<URLLoader> url_loader;
mojom::URLLoaderFactoryParams params;
params.process_id = 234;
- // No call to CrossOriginReadBlocking::AddExceptionForPlugin(123) - this is
- // what we primarily want to cover in this test.
+ // No call to
+ // CrossOriginReadBlockingExceptionForPlugin::AddExceptionForPlugin(123) -
+ // this is what we primarily want to cover in this test.
url_loader = std::make_unique<URLLoader>(
context(), nullptr /* network_service_client */,
nullptr /* network_context_client */,
@@ -4338,8 +4795,8 @@ TEST_F(URLLoaderTest, RawResponseCookies) {
network_service_client.raw_response_cookies()[0].cookie->Name());
EXPECT_EQ("b",
network_service_client.raw_response_cookies()[0].cookie->Value());
- EXPECT_TRUE(
- network_service_client.raw_response_cookies()[0].status.IsInclude());
+ EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+ .access_result.status.IsInclude());
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
@@ -4387,7 +4844,7 @@ TEST_F(URLLoaderTest, RawResponseCookiesInvalid) {
EXPECT_FALSE(network_service_client.raw_response_cookies()[0].cookie);
EXPECT_TRUE(
network_service_client.raw_response_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
+ .access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE}));
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
@@ -4443,8 +4900,8 @@ TEST_F(URLLoaderTest, RawResponseCookiesRedirect) {
network_service_client.raw_response_cookies()[0].cookie->Name());
EXPECT_EQ("true",
network_service_client.raw_response_cookies()[0].cookie->Value());
- EXPECT_TRUE(
- network_service_client.raw_response_cookies()[0].status.IsInclude());
+ EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+ .access_result.status.IsInclude());
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4491,7 +4948,7 @@ TEST_F(URLLoaderTest, RawResponseCookiesRedirect) {
EXPECT_TRUE(
network_service_client.raw_response_cookies()[0].cookie->IsSecure());
EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
+ .access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
}
}
@@ -4538,8 +4995,8 @@ TEST_F(URLLoaderTest, RawResponseCookiesAuth) {
network_service_client.raw_response_cookies()[0].cookie->Name());
EXPECT_EQ("true",
network_service_client.raw_response_cookies()[0].cookie->Value());
- EXPECT_TRUE(
- network_service_client.raw_response_cookies()[0].status.IsInclude());
+ EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
+ .access_result.status.IsInclude());
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
}
@@ -4584,7 +5041,7 @@ TEST_F(URLLoaderTest, RawResponseCookiesAuth) {
EXPECT_TRUE(
network_service_client.raw_response_cookies()[0].cookie->IsSecure());
EXPECT_TRUE(network_service_client.raw_response_cookies()[0]
- .status.HasExactlyExclusionReasonsForTesting(
+ .access_result.status.HasExactlyExclusionReasonsForTesting(
{net::CookieInclusionStatus::EXCLUDE_SECURE_ONLY}));
EXPECT_EQ("TEST", network_service_client.devtools_request_id());
diff --git a/chromium/services/network/websocket.cc b/chromium/services/network/websocket.cc
index dcf9d7ccb77..0b013c409b1 100644
--- a/chromium/services/network/websocket.cc
+++ b/chromium/services/network/websocket.cc
@@ -11,6 +11,7 @@
#include "base/bind.h"
#include "base/bind_helpers.h"
+#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/location.h"
#include "base/logging.h"
@@ -185,7 +186,9 @@ void WebSocket::WebSocketEventHandler::OnAddChannelResponse(
<< " extensions=\"" << extensions << "\"";
impl_->handshake_succeeded_ = true;
- impl_->pending_connection_tracker_.OnCompleteHandshake();
+ if (impl_->pending_connection_tracker_) {
+ impl_->pending_connection_tracker_->OnCompleteHandshake();
+ }
base::CommandLine* const command_line =
base::CommandLine::ForCurrentProcess();
@@ -390,11 +393,13 @@ WebSocket::WebSocket(
int32_t frame_id,
const url::Origin& origin,
uint32_t options,
+ net::NetworkTrafficAnnotationTag traffic_annotation,
HasRawHeadersAccess has_raw_headers_access,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
- WebSocketThrottler::PendingConnection pending_connection_tracker,
+ base::Optional<WebSocketThrottler::PendingConnection>
+ pending_connection_tracker,
DataPipeUseTracker data_pipe_use_tracker,
base::TimeDelta delay)
: factory_(factory),
@@ -404,6 +409,7 @@ WebSocket::WebSocket(
pending_connection_tracker_(std::move(pending_connection_tracker)),
delay_(delay),
options_(options),
+ traffic_annotation_(traffic_annotation),
child_id_(child_id),
frame_id_(frame_id),
origin_(std::move(origin)),
@@ -423,6 +429,8 @@ WebSocket::WebSocket(
// |isolation_info| must not be empty.
DCHECK(!factory_->GetURLRequestContext()->require_network_isolation_key() ||
!isolation_info.IsEmpty());
+ // |delay| should be zero if this connection is not throttled.
+ DCHECK(pending_connection_tracker.has_value() || delay.is_zero());
if (auth_handler_) {
// Make sure the request dies if |auth_handler_| has an error, otherwise
// requests can hang.
@@ -603,7 +611,7 @@ void WebSocket::AddChannel(
}
channel_->SendAddChannelRequest(socket_url, requested_protocols, origin_,
site_for_cookies, isolation_info,
- headers_to_pass);
+ headers_to_pass, traffic_annotation_);
}
void WebSocket::OnWritable(MojoResult result,
diff --git a/chromium/services/network/websocket.h b/chromium/services/network/websocket.h
index 4d4f3ef8c08..b487133bd86 100644
--- a/chromium/services/network/websocket.h
+++ b/chromium/services/network/websocket.h
@@ -22,6 +22,7 @@
#include "base/util/type_safety/strong_alias.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "net/websockets/websocket_event_interface.h"
#include "services/network/network_service.h"
#include "services/network/public/mojom/network_context.mojom.h"
@@ -64,11 +65,13 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
int32_t render_frame_id,
const url::Origin& origin,
uint32_t options,
+ net::NetworkTrafficAnnotationTag traffic_annotation,
HasRawHeadersAccess has_raw_cookie_access,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client,
- WebSocketThrottler::PendingConnection pending_connection_tracker,
+ base::Optional<WebSocketThrottler::PendingConnection>
+ pending_connection_tracker,
DataPipeUseTracker,
base::TimeDelta delay);
~WebSocket() override;
@@ -79,8 +82,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
void StartReceiving() override;
void StartClosingHandshake(uint16_t code, const std::string& reason) override;
- bool handshake_succeeded() const { return handshake_succeeded_; }
-
// Whether to allow sending/setting cookies during WebSocket handshakes for
// |url|. This decision is based on the |options_| and |origin_| this
// WebSocket was created with.
@@ -183,7 +184,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
mojo::Remote<mojom::AuthenticationHandler> auth_handler_;
mojo::Remote<mojom::TrustedHeaderClient> header_client_;
- WebSocketThrottler::PendingConnection pending_connection_tracker_;
+ base::Optional<WebSocketThrottler::PendingConnection>
+ pending_connection_tracker_;
// The channel we use to send events to the network.
std::unique_ptr<net::WebSocketChannel> channel_;
@@ -193,6 +195,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
const uint32_t options_;
+ const net::NetworkTrafficAnnotationTag traffic_annotation_;
+
const int32_t child_id_;
const int32_t frame_id_;
@@ -202,8 +206,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocket : public mojom::WebSocket {
// For 3rd-party cookie permission checking.
net::SiteForCookies site_for_cookies_;
- // handshake_succeeded_ is used by WebSocketManager to manage counters for
- // per-renderer WebSocket throttling.
bool handshake_succeeded_ = false;
const HasRawHeadersAccess has_raw_headers_access_;
diff --git a/chromium/services/network/websocket_factory.cc b/chromium/services/network/websocket_factory.cc
index 597b4bcfdc6..f5525ded93b 100644
--- a/chromium/services/network/websocket_factory.cc
+++ b/chromium/services/network/websocket_factory.cc
@@ -8,6 +8,7 @@
#include "mojo/public/cpp/bindings/message.h"
#include "net/base/isolation_info.h"
#include "net/base/url_util.h"
+#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/network_context.h"
#include "services/network/network_service.h"
#include "services/network/public/mojom/network_context.mojom.h"
@@ -36,6 +37,7 @@ void WebSocketFactory::CreateWebSocket(
int32_t render_frame_id,
const url::Origin& origin,
uint32_t options,
+ net::NetworkTrafficAnnotationTag traffic_annotation,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client) {
@@ -61,8 +63,9 @@ void WebSocketFactory::CreateWebSocket(
connections_.insert(std::make_unique<WebSocket>(
this, url, requested_protocols, site_for_cookies, isolation_info,
std::move(additional_headers), process_id, render_frame_id, origin,
- options, has_raw_headers_access, std::move(handshake_client),
- std::move(auth_handler), std::move(header_client),
+ options, traffic_annotation, 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/network/websocket_factory.h b/chromium/services/network/websocket_factory.h
index 3a652f82515..87af5ae218c 100644
--- a/chromium/services/network/websocket_factory.h
+++ b/chromium/services/network/websocket_factory.h
@@ -22,6 +22,7 @@ namespace net {
class IsolationInfo;
class SiteForCookies;
class SSLInfo;
+struct NetworkTrafficAnnotationTag;
} // namespace net
namespace url {
@@ -48,6 +49,7 @@ class WebSocketFactory final {
int32_t render_frame_id,
const url::Origin& origin,
uint32_t options,
+ net::NetworkTrafficAnnotationTag traffic_annotation,
mojo::PendingRemote<mojom::WebSocketHandshakeClient> handshake_client,
mojo::PendingRemote<mojom::AuthenticationHandler> auth_handler,
mojo::PendingRemote<mojom::TrustedHeaderClient> header_client);
diff --git a/chromium/services/network/websocket_throttler.cc b/chromium/services/network/websocket_throttler.cc
index d3809825556..8cc1ecfb6c9 100644
--- a/chromium/services/network/websocket_throttler.cc
+++ b/chromium/services/network/websocket_throttler.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include "base/rand_util.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
namespace network {
@@ -93,8 +94,13 @@ base::TimeDelta WebSocketThrottler::CalculateDelay(int process_id) const {
return it->second->CalculateDelay();
}
-WebSocketThrottler::PendingConnection
+base::Optional<WebSocketThrottler::PendingConnection>
WebSocketThrottler::IssuePendingConnectionTracker(int process_id) {
+ if (process_id == mojom::kBrowserProcessId) {
+ // The browser process is not throttled.
+ return base::nullopt;
+ }
+
auto it = per_process_throttlers_.find(process_id);
if (it == per_process_throttlers_.end()) {
it = per_process_throttlers_
diff --git a/chromium/services/network/websocket_throttler.h b/chromium/services/network/websocket_throttler.h
index 510c0575f4c..0226aacce0c 100644
--- a/chromium/services/network/websocket_throttler.h
+++ b/chromium/services/network/websocket_throttler.h
@@ -11,6 +11,7 @@
#include "base/component_export.h"
#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
#include "base/time/time.h"
#include "base/timer/timer.h"
@@ -103,8 +104,6 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketPerProcessThrottler final {
// This class is for throttling WebSocket connections. WebSocketThrottler is
// a set of per-renderer throttlers.
-// This class is only used in the network service. content::WebSocketManager
-// uses WebSocketPerProcessThrottler directly.
class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketThrottler final {
public:
using PendingConnection = WebSocketPerProcessThrottler::PendingConnection;
@@ -119,8 +118,10 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) WebSocketThrottler final {
base::TimeDelta CalculateDelay(int process_id) const;
// Returns a pending connection for |process_id|. This function can be called
- // only when |HasTooManyPendingConnections(process_id)| is false.
- PendingConnection IssuePendingConnectionTracker(int process_id);
+ // only when |HasTooManyPendingConnections(process_id)| is false. May return
+ // |base::nullopt| if |process_id| is not throttled.
+ base::Optional<PendingConnection> IssuePendingConnectionTracker(
+ int process_id);
size_t GetSizeForTesting() const { return per_process_throttlers_.size(); }
diff --git a/chromium/services/network/websocket_throttler_unittest.cc b/chromium/services/network/websocket_throttler_unittest.cc
index 0d8b3326f8e..725a8e0b7e1 100644
--- a/chromium/services/network/websocket_throttler_unittest.cc
+++ b/chromium/services/network/websocket_throttler_unittest.cc
@@ -8,6 +8,7 @@
#include "base/optional.h"
#include "base/test/task_environment.h"
+#include "services/network/public/mojom/network_context.mojom-forward.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace network {
@@ -322,23 +323,35 @@ TEST_F(WebSocketThrottlerTest, TooManyPendingConnections) {
for (int i = 0; i < limit - 1; ++i) {
ASSERT_FALSE(throttler.HasTooManyPendingConnections(process1));
ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
- trackers.push_back(throttler.IssuePendingConnectionTracker(process1));
- trackers.push_back(throttler.IssuePendingConnectionTracker(process2));
+ trackers.push_back(
+ std::move(throttler.IssuePendingConnectionTracker(process1).value()));
+ trackers.push_back(
+ std::move(throttler.IssuePendingConnectionTracker(process2).value()));
}
EXPECT_EQ(2u, throttler.GetSizeForTesting());
ASSERT_FALSE(throttler.HasTooManyPendingConnections(process1));
ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
- trackers.push_back(throttler.IssuePendingConnectionTracker(process1));
+ trackers.push_back(
+ std::move(throttler.IssuePendingConnectionTracker(process1).value()));
ASSERT_TRUE(throttler.HasTooManyPendingConnections(process1));
ASSERT_FALSE(throttler.HasTooManyPendingConnections(process2));
- trackers.push_back(throttler.IssuePendingConnectionTracker(process2));
+ trackers.push_back(
+ std::move(throttler.IssuePendingConnectionTracker(process2).value()));
ASSERT_TRUE(throttler.HasTooManyPendingConnections(process1));
ASSERT_TRUE(throttler.HasTooManyPendingConnections(process2));
}
+TEST_F(WebSocketThrottlerTest, BrowserProcessNotThrottled) {
+ WebSocketThrottler throttler;
+ ASSERT_FALSE(
+ throttler.HasTooManyPendingConnections(mojom::kBrowserProcessId));
+ ASSERT_FALSE(throttler.IssuePendingConnectionTracker(mojom::kBrowserProcessId)
+ .has_value());
+}
+
} // namespace
} // namespace network
diff --git a/chromium/services/preferences/tracked/BUILD.gn b/chromium/services/preferences/tracked/BUILD.gn
index 6802e27ffdd..ccd24350291 100644
--- a/chromium/services/preferences/tracked/BUILD.gn
+++ b/chromium/services/preferences/tracked/BUILD.gn
@@ -59,7 +59,7 @@ source_set("tracked") {
]
if (is_mac) {
- libs = [ "IOKit.framework" ]
+ frameworks = [ "IOKit.framework" ]
}
}
diff --git a/chromium/services/preferences/tracked/device_id_unittest.cc b/chromium/services/preferences/tracked/device_id_unittest.cc
index 297cf42e618..11c16b44ab6 100644
--- a/chromium/services/preferences/tracked/device_id_unittest.cc
+++ b/chromium/services/preferences/tracked/device_id_unittest.cc
@@ -12,7 +12,7 @@ TEST(GetDeterministicMachineSpecificIdTest, IsDeterministic) {
std::string second_machine_id;
const MachineIdStatus kExpectedStatus =
-#if defined(OS_WIN) || (defined(OS_MACOSX) && !defined(OS_IOS))
+#if defined(OS_WIN) || defined(OS_MAC)
MachineIdStatus::SUCCESS;
#else
MachineIdStatus::NOT_IMPLEMENTED;
diff --git a/chromium/services/proxy_resolver/public/cpp/OWNERS b/chromium/services/proxy_resolver/public/cpp/OWNERS
index 59d61d1933d..d5fefd82012 100644
--- a/chromium/services/proxy_resolver/public/cpp/OWNERS
+++ b/chromium/services/proxy_resolver/public/cpp/OWNERS
@@ -1,8 +1,2 @@
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
-per-file manifest.cc=set noparent
-per-file manifest.cc=file://ipc/SECURITY_OWNERS
-per-file manifest.h=set noparent
-per-file manifest.h=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h b/chromium/services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h
index 5dfd827b4ab..8ca2bbfc8ea 100644
--- a/chromium/services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h
+++ b/chromium/services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h
@@ -8,7 +8,7 @@
#include "base/strings/string_piece.h"
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "net/proxy_resolution/proxy_resolve_dns_operation.h"
-#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom-shared.h"
namespace mojo {
diff --git a/chromium/services/proxy_resolver/public/cpp/proxy_resolver.typemap b/chromium/services/proxy_resolver/public/cpp/proxy_resolver.typemap
deleted file mode 100644
index db1f4b0ea80..00000000000
--- a/chromium/services/proxy_resolver/public/cpp/proxy_resolver.typemap
+++ /dev/null
@@ -1,27 +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.
-
-mojom = "//services/proxy_resolver/public/mojom/proxy_resolver.mojom"
-public_headers = [
- "//net/base/proxy_server.h",
- "//net/proxy_resolution/proxy_info.h",
- "//net/proxy_resolution/proxy_resolve_dns_operation.h",
-]
-traits_headers = [
- "//services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h",
- "//services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h",
-]
-sources = [
- "//services/proxy_resolver/public/cpp/mojo_host_mojom_traits.cc",
- "//services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.cc",
-]
-type_mappings = [
- "proxy_resolver.mojom.HostResolveOperation=::net::ProxyResolveDnsOperation",
- "proxy_resolver.mojom.ProxyInfo=::net::ProxyInfo",
- "proxy_resolver.mojom.ProxyServer=::net::ProxyServer",
- "proxy_resolver.mojom.ProxyServer::Scheme=::net::ProxyScheme",
-]
-public_deps = [
- "//net",
-]
diff --git a/chromium/services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h b/chromium/services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h
index 4c434c4b417..32ab0c7709d 100644
--- a/chromium/services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h
+++ b/chromium/services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h
@@ -12,7 +12,7 @@
#include "net/base/proxy_server.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_list.h"
-#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
+#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom-shared.h"
namespace net {
class ProxyInfo;
diff --git a/chromium/services/proxy_resolver/public/cpp/typemaps.gni b/chromium/services/proxy_resolver/public/cpp/typemaps.gni
deleted file mode 100644
index babbad449ce..00000000000
--- a/chromium/services/proxy_resolver/public/cpp/typemaps.gni
+++ /dev/null
@@ -1,5 +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.
-
-typemaps = [ "//services/proxy_resolver/public/cpp/proxy_resolver.typemap" ]
diff --git a/chromium/services/proxy_resolver/public/mojom/BUILD.gn b/chromium/services/proxy_resolver/public/mojom/BUILD.gn
index d82c4009965..77790f8e173 100644
--- a/chromium/services/proxy_resolver/public/mojom/BUILD.gn
+++ b/chromium/services/proxy_resolver/public/mojom/BUILD.gn
@@ -18,4 +18,38 @@ mojom("mojom") {
export_define_blink = "BLINK_PLATFORM_IMPLEMENTATION=1"
export_header_blink = "third_party/blink/public/platform/web_common.h"
}
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "proxy_resolver.mojom.HostResolveOperation"
+ cpp = "::net::ProxyResolveDnsOperation"
+ },
+
+ {
+ mojom = "proxy_resolver.mojom.ProxyInfo"
+ cpp = "::net::ProxyInfo"
+ },
+
+ {
+ mojom = "proxy_resolver.mojom.ProxyServer"
+ cpp = "::net::ProxyServer"
+ },
+
+ {
+ mojom = "proxy_resolver.mojom.ProxyServer::Scheme"
+ cpp = "::net::ProxyScheme"
+ },
+ ]
+ traits_headers = [
+ "//services/proxy_resolver/public/cpp/mojo_host_mojom_traits.h",
+ "//services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.h",
+ ]
+ traits_sources = [
+ "//services/proxy_resolver/public/cpp/mojo_host_mojom_traits.cc",
+ "//services/proxy_resolver/public/cpp/proxy_resolver_mojom_traits.cc",
+ ]
+ },
+ ]
}
diff --git a/chromium/services/resource_coordinator/BUILD.gn b/chromium/services/resource_coordinator/BUILD.gn
index cc38677069d..fb47a3d1911 100644
--- a/chromium/services/resource_coordinator/BUILD.gn
+++ b/chromium/services/resource_coordinator/BUILD.gn
@@ -15,6 +15,8 @@ source_set("lib") {
"memory_instrumentation/graph.h",
"memory_instrumentation/graph_processor.cc",
"memory_instrumentation/graph_processor.h",
+ "memory_instrumentation/memory_dump_map_converter.cc",
+ "memory_instrumentation/memory_dump_map_converter.h",
"memory_instrumentation/queued_request.cc",
"memory_instrumentation/queued_request.h",
"memory_instrumentation/queued_request_dispatcher.cc",
@@ -44,6 +46,7 @@ source_set("tests") {
"memory_instrumentation/coordinator_impl_unittest.cc",
"memory_instrumentation/graph_processor_unittest.cc",
"memory_instrumentation/graph_unittest.cc",
+ "memory_instrumentation/memory_dump_map_converter_unittest.cc",
"public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits_unittest.cc",
"public/cpp/memory_instrumentation/os_metrics_unittest.cc",
"public/cpp/memory_instrumentation/tracing_integration_unittest.cc",
diff --git a/chromium/services/resource_coordinator/DEPS b/chromium/services/resource_coordinator/DEPS
index 9765ce49d0f..7e714d03182 100644
--- a/chromium/services/resource_coordinator/DEPS
+++ b/chromium/services/resource_coordinator/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+components/ukm/test_ukm_recorder.h",
+ "+third_party/perfetto",
"+third_party/smhasher",
"+services/metrics/public",
]
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/OWNERS b/chromium/services/resource_coordinator/memory_instrumentation/OWNERS
index 62d73f2aea3..e13658dd0d4 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/OWNERS
+++ b/chromium/services/resource_coordinator/memory_instrumentation/OWNERS
@@ -1,3 +1,4 @@
hjd@chromium.org
primiano@chromium.org
+ssid@chromium.org
# COMPONENT: Internals>Instrumentation>Memory
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
index cbfa18439ce..37facb9f51b 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
+++ b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
@@ -29,7 +29,7 @@
#include "services/resource_coordinator/public/mojom/memory_instrumentation/constants.mojom.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
index 00ba4480852..ae218fdf6cf 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
+++ b/chromium/services/resource_coordinator/memory_instrumentation/coordinator_impl_unittest.cc
@@ -14,7 +14,6 @@
#include "base/time/time.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "build/build_config.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -443,7 +442,7 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
// This ifdef is here to match the sandboxing behavior of the client.
// On Linux, all memory dumps come from the browser client. On all other
// platforms, they are expected to come from each individual client.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
EXPECT_CALL(browser_client,
RequestOSMemoryDumpMock(
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
@@ -473,7 +472,7 @@ TEST_F(CoordinatorImplTest, TimeOutStuckChildMultiProcess) {
results[0] = FillRawOSDump(kRendererPid);
std::move(callback).Run(true, std::move(results));
}));
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
// Make the browser respond correctly but pretend the renderer is "stuck"
// by storing a callback.
@@ -620,7 +619,7 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
MemoryAllocatorDump::kUnitsBytes, 1024 * 2);
std::move(callback).Run(true, args.dump_guid, std::move(pmd));
}));
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
EXPECT_CALL(browser_client,
RequestOSMemoryDumpMock(_, AllOf(Contains(1), Contains(2)), _))
.WillOnce(Invoke(
@@ -661,7 +660,7 @@ TEST_F(CoordinatorImplTest, GlobalMemoryDumpStruct) {
results[0]->resident_set_kb = 2;
std::move(callback).Run(true, std::move(results));
}));
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
MockGlobalMemoryDumpCallback callback;
EXPECT_CALL(callback, OnCall(true, NotNull()))
@@ -705,7 +704,7 @@ TEST_F(CoordinatorImplTest, VmRegionsForHeapProfiler) {
// This ifdef is here to match the sandboxing behavior of the client.
// On Linux, all memory dumps come from the browser client. On all other
// platforms, they are expected to come from each individual client.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
EXPECT_CALL(browser_client,
RequestOSMemoryDumpMock(
_, AllOf(Contains(kBrowserPid), Contains(kRendererPid)), _))
@@ -735,7 +734,7 @@ TEST_F(CoordinatorImplTest, VmRegionsForHeapProfiler) {
results[0] = FillRawOSDump(kRendererPid);
std::move(callback).Run(true, std::move(results));
}));
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
MockGetVmRegionsForHeapProfilerCallback callback;
EXPECT_CALL(callback, OnCall(_))
@@ -867,7 +866,7 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
// This ifdef is here to match the sandboxing behavior of the client.
// On Linux, all memory dumps come from the browser client. On all other
// platforms, they are expected to come from each individual client.
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
EXPECT_CALL(client_process_1, RequestOSMemoryDumpMock(_, _, _))
.WillOnce(Invoke(
[](mojom::MemoryMapOption, const std::vector<base::ProcessId>& pids,
@@ -915,7 +914,7 @@ TEST_F(CoordinatorImplTest, DumpByPidSuccess) {
results[0] = FillRawOSDump(kGpuPid);
std::move(callback).Run(true, std::move(results));
}));
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
base::RunLoop run_loop;
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.cc b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.cc
new file mode 100644
index 00000000000..e6c09f7a476
--- /dev/null
+++ b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.cc
@@ -0,0 +1,151 @@
+// 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/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h"
+
+#include <list>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/trace_event/process_memory_dump.h"
+#include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
+
+namespace memory_instrumentation {
+
+MemoryDumpMapConverter::MemoryDumpMapConverter() = default;
+MemoryDumpMapConverter::~MemoryDumpMapConverter() = default;
+
+perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap
+MemoryDumpMapConverter::Convert(const MemoryDumpMap& input) {
+ perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap output;
+
+ for (const auto& entry : input) {
+ const base::ProcessId process_id = entry.first;
+ const base::trace_event::ProcessMemoryDump* process_dump = entry.second;
+
+ if (process_dump == nullptr)
+ continue;
+
+ output.emplace(process_id, ConvertProcessMemoryDump(*process_dump));
+ }
+
+ return output;
+}
+
+std::unique_ptr<MemoryDumpMapConverter::PerfettoProcessMemoryNode>
+MemoryDumpMapConverter::ConvertProcessMemoryDump(
+ const base::trace_event::ProcessMemoryDump& input) {
+ const perfetto::trace_processor::LevelOfDetail level_of_detail =
+ ConvertLevelOfDetail(input.dump_args().level_of_detail);
+
+ MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap nodes_map =
+ ConvertAllocatorDumps(input);
+ MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
+ edges_map = ConvertAllocatorDumpEdges(input);
+
+ return std::make_unique<PerfettoProcessMemoryNode>(
+ level_of_detail, std::move(edges_map), std::move(nodes_map));
+}
+
+perfetto::trace_processor::LevelOfDetail
+MemoryDumpMapConverter::ConvertLevelOfDetail(
+ const base::trace_event::MemoryDumpLevelOfDetail& input) const {
+ switch (input) {
+ case base::trace_event::MemoryDumpLevelOfDetail::BACKGROUND:
+ return perfetto::trace_processor::LevelOfDetail::kBackground;
+ case base::trace_event::MemoryDumpLevelOfDetail::LIGHT:
+ return perfetto::trace_processor::LevelOfDetail::kLight;
+ case base::trace_event::MemoryDumpLevelOfDetail::DETAILED:
+ return perfetto::trace_processor::LevelOfDetail::kDetailed;
+ }
+ return perfetto::trace_processor::LevelOfDetail::kDetailed;
+}
+
+std::vector<perfetto::trace_processor::RawMemoryGraphNode::MemoryNodeEntry>
+MemoryDumpMapConverter::ConvertAllocatorDumpEntries(
+ const base::trace_event::MemoryAllocatorDump& input) const {
+ std::vector<perfetto::trace_processor::RawMemoryGraphNode::MemoryNodeEntry>
+ output;
+
+ for (const auto& entry : input.entries()) {
+ if (entry.entry_type ==
+ base::trace_event::MemoryAllocatorDump::Entry::kUint64) {
+ output.emplace_back(entry.name, entry.units, entry.value_uint64);
+ } else {
+ output.emplace_back(entry.name, entry.units, entry.value_string);
+ }
+ }
+ return output;
+}
+
+std::unique_ptr<perfetto::trace_processor::RawMemoryGraphNode>
+MemoryDumpMapConverter::ConvertMemoryAllocatorDump(
+ const base::trace_event::MemoryAllocatorDump& input) const {
+ auto output = std::make_unique<perfetto::trace_processor::RawMemoryGraphNode>(
+ input.absolute_name(), ConvertLevelOfDetail(input.level_of_detail()),
+ ConvertMemoryAllocatorDumpGuid(input.guid()),
+ ConvertAllocatorDumpEntries(input));
+
+ CopyAndConvertAllocatorDumpFlags(input, output.get());
+
+ return output;
+}
+
+void MemoryDumpMapConverter::CopyAndConvertAllocatorDumpFlags(
+ const base::trace_event::MemoryAllocatorDump& input,
+ perfetto::trace_processor::RawMemoryGraphNode* output) const {
+ output->clear_flags(output->flags());
+ output->set_flags(
+ input.flags() & base::trace_event::MemoryAllocatorDump::WEAK
+ ? perfetto::trace_processor::RawMemoryGraphNode::kWeak
+ : perfetto::trace_processor::RawMemoryGraphNode::kDefault);
+}
+
+MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap
+MemoryDumpMapConverter::ConvertAllocatorDumps(
+ const base::trace_event::ProcessMemoryDump& input) const {
+ MemoryDumpMapConverter::PerfettoProcessMemoryNode::MemoryNodesMap output;
+ for (const auto& entry : input.allocator_dumps()) {
+ const std::unique_ptr<base::trace_event::MemoryAllocatorDump>& dump =
+ entry.second;
+
+ output.emplace(entry.first, ConvertMemoryAllocatorDump(*dump));
+ }
+ return output;
+}
+
+MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
+MemoryDumpMapConverter::ConvertAllocatorDumpEdges(
+ const base::trace_event::ProcessMemoryDump& input) const {
+ MemoryDumpMapConverter::PerfettoProcessMemoryNode::AllocatorNodeEdgesMap
+ output;
+ for (const auto& entry : input.allocator_dumps_edges()) {
+ std::unique_ptr<perfetto::trace_processor::MemoryGraphEdge> edge =
+ ConvertAllocatorDumpEdge(entry.second);
+ const perfetto::trace_processor::MemoryAllocatorNodeId source =
+ edge->source;
+ output.emplace(source, std::move(edge));
+ }
+ return output;
+}
+
+std::unique_ptr<perfetto::trace_processor::MemoryGraphEdge>
+MemoryDumpMapConverter::ConvertAllocatorDumpEdge(
+ const base::trace_event::ProcessMemoryDump::MemoryAllocatorDumpEdge& input)
+ const {
+ return std::make_unique<perfetto::trace_processor::MemoryGraphEdge>(
+ ConvertMemoryAllocatorDumpGuid(input.source),
+ ConvertMemoryAllocatorDumpGuid(input.target), input.importance,
+ input.overridable);
+}
+
+perfetto::trace_processor::MemoryAllocatorNodeId
+MemoryDumpMapConverter::ConvertMemoryAllocatorDumpGuid(
+ const base::trace_event::MemoryAllocatorDumpGuid& input) const {
+ return perfetto::trace_processor::MemoryAllocatorNodeId(input.ToUint64());
+}
+
+} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h
new file mode 100644
index 00000000000..f01fa30f32f
--- /dev/null
+++ b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h
@@ -0,0 +1,83 @@
+// 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_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_MEMORY_DUMP_MAP_CONVERTER_H_
+#define SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_MEMORY_DUMP_MAP_CONVERTER_H_
+
+#include <list>
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "base/trace_event/process_memory_dump.h"
+#include "third_party/perfetto/include/perfetto/ext/trace_processor/importers/memory_tracker/graph_processor.h"
+
+namespace memory_instrumentation {
+
+// Converts the Chromium MemoryDumpMap to the corresponding defined in Perfetto
+// type RawMemoryNodeMap.
+//
+// Example usage:
+//
+// {
+// base::trace_event::ProcessMemoryDump pmd;
+//
+// MemoryDumpMapConverter converter;
+// perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap
+// perfettoNodeMap = converter.Convert(pmd);
+// }
+class MemoryDumpMapConverter {
+ public:
+ using MemoryDumpMap =
+ std::map<base::ProcessId, const base::trace_event::ProcessMemoryDump*>;
+
+ using PerfettoProcessMemoryNode =
+ perfetto::trace_processor::RawProcessMemoryNode;
+
+ MemoryDumpMapConverter();
+ ~MemoryDumpMapConverter();
+ MemoryDumpMapConverter(const MemoryDumpMapConverter&) = delete;
+ void operator=(const MemoryDumpMapConverter&) = delete;
+
+ perfetto::trace_processor::GraphProcessor::RawMemoryNodeMap Convert(
+ const MemoryDumpMap& input);
+
+ private:
+ std::unique_ptr<MemoryDumpMapConverter::PerfettoProcessMemoryNode>
+ ConvertProcessMemoryDump(const base::trace_event::ProcessMemoryDump& input);
+
+ perfetto::trace_processor::LevelOfDetail ConvertLevelOfDetail(
+ const base::trace_event::MemoryDumpLevelOfDetail& input) const;
+
+ PerfettoProcessMemoryNode::MemoryNodesMap ConvertAllocatorDumps(
+ const base::trace_event::ProcessMemoryDump& input) const;
+
+ std::unique_ptr<perfetto::trace_processor::RawMemoryGraphNode>
+ ConvertMemoryAllocatorDump(
+ const base::trace_event::MemoryAllocatorDump& input) const;
+
+ void CopyAndConvertAllocatorDumpFlags(
+ const base::trace_event::MemoryAllocatorDump& input,
+ perfetto::trace_processor::RawMemoryGraphNode* output) const;
+
+ std::vector<perfetto::trace_processor::RawMemoryGraphNode::MemoryNodeEntry>
+ ConvertAllocatorDumpEntries(
+ const base::trace_event::MemoryAllocatorDump& input) const;
+
+ PerfettoProcessMemoryNode::AllocatorNodeEdgesMap ConvertAllocatorDumpEdges(
+ const base::trace_event::ProcessMemoryDump& input) const;
+
+ std::unique_ptr<perfetto::trace_processor::MemoryGraphEdge>
+ ConvertAllocatorDumpEdge(
+ const base::trace_event::ProcessMemoryDump::MemoryAllocatorDumpEdge&
+ input) const;
+
+ perfetto::trace_processor::MemoryAllocatorNodeId
+ ConvertMemoryAllocatorDumpGuid(
+ const base::trace_event::MemoryAllocatorDumpGuid& input) const;
+};
+
+} // namespace memory_instrumentation
+
+#endif // SERVICES_RESOURCE_COORDINATOR_MEMORY_INSTRUMENTATION_MEMORY_DUMP_MAP_CONVERTER_H_
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter_unittest.cc b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter_unittest.cc
new file mode 100644
index 00000000000..bce58c22181
--- /dev/null
+++ b/chromium/services/resource_coordinator/memory_instrumentation/memory_dump_map_converter_unittest.cc
@@ -0,0 +1,86 @@
+// 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/resource_coordinator/memory_instrumentation/memory_dump_map_converter.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace memory_instrumentation {
+
+using base::trace_event::MemoryAllocatorDump;
+using base::trace_event::MemoryAllocatorDumpGuid;
+using base::trace_event::MemoryDumpArgs;
+using base::trace_event::MemoryDumpLevelOfDetail;
+using base::trace_event::ProcessMemoryDump;
+
+TEST(MemoryDumpMapConverter, Convert) {
+ MemoryDumpMapConverter::MemoryDumpMap process_dumps;
+
+ MemoryDumpArgs dump_args1 = {MemoryDumpLevelOfDetail::DETAILED};
+ ProcessMemoryDump pmd1(dump_args1);
+
+ auto* source1 = pmd1.CreateAllocatorDump("test1/test2/test3");
+ source1->AddScalar(MemoryAllocatorDump::kNameSize,
+ MemoryAllocatorDump::kUnitsBytes, 10);
+
+ auto* target1 = pmd1.CreateAllocatorDump("target1");
+ pmd1.AddOwnershipEdge(source1->guid(), target1->guid(), 10);
+
+ pmd1.CreateWeakSharedGlobalAllocatorDump(MemoryAllocatorDumpGuid(1));
+
+ process_dumps.emplace(1, &pmd1);
+
+ MemoryDumpArgs dump_args2 = {MemoryDumpLevelOfDetail::LIGHT};
+ ProcessMemoryDump pmd2(dump_args2);
+
+ auto* source2 = pmd2.CreateAllocatorDump("test1/test4/test5");
+ source2->AddScalar(MemoryAllocatorDump::kNameSize,
+ MemoryAllocatorDump::kUnitsObjects, 1);
+
+ process_dumps.emplace(2, &pmd2);
+
+ MemoryDumpMapConverter converter;
+ auto output_dump_map = converter.Convert(process_dumps);
+
+ ASSERT_EQ(output_dump_map.size(), 2uL);
+ ASSERT_NE(output_dump_map.find(1), output_dump_map.end());
+ ASSERT_EQ(output_dump_map[1]->allocator_nodes().size(), 3uL);
+ ASSERT_NE(output_dump_map[1]->allocator_nodes().find("test1/test2/test3"),
+ output_dump_map[1]->allocator_nodes().end());
+ {
+ const auto& dump =
+ *output_dump_map[1]->allocator_nodes().at("test1/test2/test3");
+
+ ASSERT_EQ(dump.entries().size(), 1uL);
+ const auto& entry = dump.entries()[0];
+ ASSERT_EQ(entry.entry_type, perfetto::trace_processor::RawMemoryGraphNode::
+ MemoryNodeEntry::kUint64);
+ ASSERT_EQ(entry.units, "bytes");
+ ASSERT_EQ(entry.value_uint64, 10uL);
+ }
+
+ ASSERT_NE(output_dump_map[1]->allocator_nodes().find("target1"),
+ output_dump_map[1]->allocator_nodes().end());
+ ASSERT_NE(output_dump_map[1]->allocator_nodes().find("global/1"),
+ output_dump_map[1]->allocator_nodes().end());
+
+ ASSERT_NE(output_dump_map.find(2), output_dump_map.end());
+ ASSERT_EQ(output_dump_map[2]->allocator_nodes().size(), 1uL);
+ ASSERT_NE(output_dump_map[2]->allocator_nodes().find("test1/test4/test5"),
+ output_dump_map[2]->allocator_nodes().end());
+
+ {
+ const auto& dump =
+ *output_dump_map[2]->allocator_nodes().at("test1/test4/test5");
+
+ ASSERT_EQ(dump.entries().size(), 1uL);
+ const auto& entry = dump.entries()[0];
+ ASSERT_EQ(entry.entry_type, perfetto::trace_processor::RawMemoryGraphNode::
+ MemoryNodeEntry::kUint64);
+ ASSERT_EQ(entry.units, "objects");
+ ASSERT_EQ(entry.value_uint64, 1uL);
+ }
+}
+
+} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
index 632e8da62e0..9810dcb1fb2 100644
--- a/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
+++ b/chromium/services/resource_coordinator/memory_instrumentation/queued_request_dispatcher.cc
@@ -21,7 +21,7 @@
#include "services/resource_coordinator/memory_instrumentation/switches.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/global_memory_dump.h"
-#if defined(OS_MACOSX) && !defined(OS_IOS)
+#if defined(OS_MAC)
#include "base/mac/mac_util.h"
#endif
@@ -43,11 +43,11 @@ namespace {
uint32_t CalculatePrivateFootprintKb(const mojom::RawOSMemDump& os_dump,
uint32_t shared_resident_kb) {
DCHECK(os_dump.platform_private_footprint);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
uint64_t rss_anon_bytes = os_dump.platform_private_footprint->rss_anon_bytes;
uint64_t vm_swap_bytes = os_dump.platform_private_footprint->vm_swap_bytes;
return (rss_anon_bytes + vm_swap_bytes) / 1024;
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
if (base::mac::IsAtLeastOS10_12()) {
uint64_t phys_footprint_bytes =
os_dump.platform_private_footprint->phys_footprint_bytes;
@@ -82,7 +82,7 @@ memory_instrumentation::mojom::OSMemDumpPtr CreatePublicOSDump(
os_dump->is_peak_rss_resettable = internal_os_dump.is_peak_rss_resettable;
os_dump->private_footprint_kb =
CalculatePrivateFootprintKb(internal_os_dump, shared_resident_kb);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
os_dump->private_footprint_swap_kb =
internal_os_dump.platform_private_footprint->vm_swap_bytes / 1024;
#endif
@@ -243,12 +243,12 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
// On most platforms each process can dump data about their own process
// so ask each process to do so Linux is special see below.
-#if !defined(OS_LINUX)
+#if !defined(OS_LINUX) && !defined(OS_CHROMEOS)
request->pending_responses.insert({client_info.pid, ResponseType::kOSDump});
client->RequestOSMemoryDump(request->memory_map_option(),
{base::kNullProcessId},
base::BindOnce(os_callback, client_info.pid));
-#endif // !defined(OS_LINUX)
+#endif // !defined(OS_LINUX) && !defined(OS_CHROMEOS)
// If we are in the single pid case, then we've already found the only
// process we're looking for.
@@ -258,7 +258,7 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
// In some cases, OS stats can only be dumped from a privileged process to
// get around to sandboxing/selinux restrictions (see crbug.com/461788).
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
std::vector<base::ProcessId> pids;
mojom::ClientProcess* browser_client = nullptr;
base::ProcessId browser_client_pid = base::kNullProcessId;
@@ -283,7 +283,7 @@ void QueuedRequestDispatcher::SetUpAndDispatch(
browser_client->RequestOSMemoryDump(request->memory_map_option(), pids,
std::move(callback));
}
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
// In this case, we have not found the pid we are looking for so increment
// the failed dump count and exit.
@@ -302,7 +302,7 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
const OsCallback& os_callback) {
// On Linux, OS stats can only be dumped from a privileged process to
// get around to sandboxing/selinux restrictions (see crbug.com/461788).
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
mojom::ClientProcess* browser_client = nullptr;
base::ProcessId browser_client_pid = 0;
for (const auto& client_info : clients) {
@@ -337,7 +337,7 @@ void QueuedRequestDispatcher::SetUpAndDispatchVmRegionRequest(
base::BindOnce(os_callback, client_info.pid));
}
}
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
}
// static
@@ -353,7 +353,7 @@ QueuedRequestDispatcher::FinalizeVmRegionRequest(
// each client process provides 1 OS dump, % the case where the client is
// disconnected mid dump.
OSMemDumpMap& extra_os_dumps = response.second.os_dumps;
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
for (auto& kv : extra_os_dumps) {
auto pid = kv.first == base::kNullProcessId ? original_pid : kv.first;
DCHECK(results.find(pid) == results.end());
@@ -414,7 +414,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
// crash). In the latter case (OS_LINUX) we expect the full map to come
// from the browser process response.
OSMemDumpMap& extra_os_dumps = response.second.os_dumps;
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
for (const auto& kv : extra_os_dumps) {
auto pid = kv.first == base::kNullProcessId ? original_pid : kv.first;
DCHECK_EQ(pid_to_os_dump[pid], nullptr);
@@ -475,7 +475,7 @@ void QueuedRequestDispatcher::Finalize(QueuedRequest* request,
mojom::OSMemDumpPtr os_dump = nullptr;
if (raw_os_dump) {
uint64_t shared_resident_kb = 0;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// The resident, anonymous shared memory for each process is only relevant
// on macOS.
const auto process_graph_it =
diff --git a/chromium/services/resource_coordinator/public/cpp/OWNERS b/chromium/services/resource_coordinator/public/cpp/OWNERS
index a605b82578c..4e0f5fdc988 100644
--- a/chromium/services/resource_coordinator/public/cpp/OWNERS
+++ b/chromium/services/resource_coordinator/public/cpp/OWNERS
@@ -1,7 +1 @@
per-file BUILD.gn=file://services/resource_coordinator/memory_instrumentation/OWNERS
-
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
-
-per-file *_mojom_traits*.*=set noparent
-per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
index a5521d03293..887892c3ef3 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/OWNERS
@@ -1,7 +1,4 @@
file://services/resource_coordinator/memory_instrumentation/OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
-
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
index b39166af6b2..b96cb6d7215 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
@@ -12,7 +12,6 @@
#include "base/synchronization/lock.h"
#include "base/trace_event/memory_dump_request_args.h"
#include "build/build_config.h"
-#include "mojo/public/cpp/bindings/interface_request.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h"
#include "services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.h"
@@ -141,7 +140,7 @@ void ClientProcessImpl::RequestOSMemoryDump(
args.pids = pids;
args.callback = std::move(callback);
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// If the most recent chrome memory dump hasn't finished, wait for that to
// finish.
if (most_recent_chrome_memory_dump_guid_.has_value()) {
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.typemap b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.typemap
deleted file mode 100644
index 421b6ee7f0b..00000000000
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.typemap
+++ /dev/null
@@ -1,30 +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.
-
-mojom = "//services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom"
-
-public_headers = [
- "//base/trace_event/memory_dump_request_args.h",
- "//base/trace_event/process_memory_dump.h",
- "//base/trace_event/memory_allocator_dump.h",
- "//base/trace_event/memory_dump_manager.h",
-]
-traits_headers = [ "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h" ]
-sources = [
- "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc",
- "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h",
-]
-deps = [
- "//base",
-]
-type_mappings = [
- "memory_instrumentation.mojom.DumpType=::base::trace_event::MemoryDumpType",
- "memory_instrumentation.mojom.LevelOfDetail=::base::trace_event::MemoryDumpLevelOfDetail",
- "memory_instrumentation.mojom.Determinism=::base::trace_event::MemoryDumpDeterminism",
- "memory_instrumentation.mojom.RequestArgs=::base::trace_event::MemoryDumpRequestArgs",
- "memory_instrumentation.mojom.RawAllocatorDumpEdge=::base::trace_event::ProcessMemoryDump::MemoryAllocatorDumpEdge",
- "memory_instrumentation.mojom.RawAllocatorDumpEntry=::base::trace_event::MemoryAllocatorDump::Entry[move_only]",
- "memory_instrumentation.mojom.RawAllocatorDump=::std::unique_ptr<::base::trace_event::MemoryAllocatorDump>[move_only]",
- "memory_instrumentation.mojom.RawProcessMemoryDump=::std::unique_ptr<::base::trace_event::ProcessMemoryDump>[move_only,nullable_is_same_type]",
-]
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc
index a7ab6f897af..56040f9e835 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc
@@ -4,6 +4,8 @@
#include "services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
+
namespace mojo {
// static
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h
index 6493feeb02d..44829fe9e12 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h
@@ -7,9 +7,11 @@
#include "base/component_export.h"
#include "base/process/process_handle.h"
+#include "base/trace_event/memory_allocator_dump.h"
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/memory_dump_request_args.h"
-#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom.h"
+#include "base/trace_event/process_memory_dump.h"
+#include "services/resource_coordinator/public/mojom/memory_instrumentation/memory_instrumentation.mojom-shared.h"
namespace mojo {
@@ -100,19 +102,19 @@ template <>
struct COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MOJOM) UnionTraits<
memory_instrumentation::mojom::RawAllocatorDumpEntryValueDataView,
base::trace_event::MemoryAllocatorDump::Entry> {
- static memory_instrumentation::mojom::RawAllocatorDumpEntryValue::Tag GetTag(
- const base::trace_event::MemoryAllocatorDump::Entry& args) {
+ static memory_instrumentation::mojom::RawAllocatorDumpEntryValueDataView::Tag
+ GetTag(const base::trace_event::MemoryAllocatorDump::Entry& args) {
switch (args.entry_type) {
case base::trace_event::MemoryAllocatorDump::Entry::EntryType::kUint64:
- return memory_instrumentation::mojom::RawAllocatorDumpEntryValue::Tag::
- VALUE_UINT64;
+ return memory_instrumentation::mojom::
+ RawAllocatorDumpEntryValueDataView::Tag::VALUE_UINT64;
case base::trace_event::MemoryAllocatorDump::Entry::EntryType::kString:
- return memory_instrumentation::mojom::RawAllocatorDumpEntryValue::Tag::
- VALUE_STRING;
+ return memory_instrumentation::mojom::
+ RawAllocatorDumpEntryValueDataView::Tag::VALUE_STRING;
}
NOTREACHED();
- return memory_instrumentation::mojom::RawAllocatorDumpEntryValue::Tag::
- VALUE_UINT64;
+ return memory_instrumentation::mojom::RawAllocatorDumpEntryValueDataView::
+ Tag::VALUE_UINT64;
}
static uint64_t value_uint64(
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
index 30cee82b9de..f8c11ab4dd8 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.cc
@@ -16,7 +16,7 @@ bool OSMetrics::FillProcessMemoryMaps(base::ProcessId pid,
std::vector<mojom::VmRegionPtr> results;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// On macOS, fetching all memory maps is very slow. See
// https://crbug.com/826913 and https://crbug.com/1035401.
results = GetProcessModules(pid);
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 1e95e345556..1fdd28fbef1 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
@@ -19,18 +19,35 @@ FORWARD_DECLARE_TEST(ProfilingJsonExporterTest, MemoryMaps);
namespace memory_instrumentation {
+// This class provides synchronous access to memory metrics for a process with a
+// given |pid|. These interfaces have platform-specific restrictions:
+// * On Android, due to sandboxing restrictions, processes can only access
+// memory metrics for themselves. Thus |pid| must be equal to getpid().
+// * On Linux, due to sandboxing restrictions, only the privileged browser
+// process has access to memory metrics for sandboxed child processes.
+// * On Fuchsia, due to the API expecting a ProcessId rather than a
+// ProcessHandle, processes can only access memory metrics for themselves or
+// for children of base::GetDefaultJob().
+//
+// These restrictions mean that any code that wishes to be cross-platform
+// compatible cannot synchronously obtain memory metrics for a |pid|. Instead,
+// it must use the async MemoryInstrumentation methods.
class COMPONENT_EXPORT(
RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION) OSMetrics {
public:
+ // Fills |dump| with memory information about |pid|. See class comments for
+ // restrictions on |pid|. |dump.platform_private_footprint| must be allocated
+ // before calling this function. If |pid| is null, the pid of the current
+ // process is used
static bool FillOSMemoryDump(base::ProcessId pid, mojom::RawOSMemDump* dump);
static bool FillProcessMemoryMaps(base::ProcessId,
mojom::MemoryMapOption,
mojom::RawOSMemDump*);
static std::vector<mojom::VmRegionPtr> GetProcessMemoryMaps(base::ProcessId);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
static void SetProcSmapsForTesting(FILE*);
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
private:
FRIEND_TEST_ALL_PREFIXES(OSMetricsTest, ParseProcSmaps);
@@ -40,11 +57,11 @@ class COMPONENT_EXPORT(
FRIEND_TEST_ALL_PREFIXES(heap_profiling::ProfilingJsonExporterTest,
MemoryMaps);
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
static std::vector<mojom::VmRegionPtr> GetProcessModules(base::ProcessId);
#endif
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
// 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.
@@ -79,7 +96,7 @@ class COMPONENT_EXPORT(
// TODO(chiniforooshan): move to /base/process/process_metrics_linux.cc after
// making sure that peak RSS is useful.
static size_t GetPeakResidentSetSize(base::ProcessId pid);
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
};
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
index 4a946b9427f..42d7d8622a5 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_fuchsia.cc
@@ -4,6 +4,15 @@
#include "services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics.h"
+#include "base/process/process.h"
+#include "base/process/process_handle.h"
+
+#include <lib/zx/job.h>
+#include <lib/zx/object.h>
+#include <lib/zx/process.h>
+#include <zircon/limits.h>
+#include <zircon/status.h>
+#include <zircon/syscalls.h>
#include <vector>
namespace memory_instrumentation {
@@ -11,9 +20,25 @@ namespace memory_instrumentation {
// static
bool OSMetrics::FillOSMemoryDump(base::ProcessId pid,
mojom::RawOSMemDump* dump) {
- // TODO(fuchsia): Implement this. See crbug.com/750948
- NOTIMPLEMENTED();
- return false;
+ base::Process process = pid == base::kNullProcessId
+ ? base::Process::Current()
+ : base::Process::Open(pid);
+ zx::unowned<zx::process> zx_process(process.Handle());
+ zx_info_task_stats_t info;
+ zx_status_t status = zx_process->get_info(ZX_INFO_TASK_STATS, &info,
+ sizeof(info), nullptr, nullptr);
+ if (status != ZX_OK) {
+ return false;
+ }
+
+ size_t rss_bytes = info.mem_private_bytes + info.mem_shared_bytes;
+ size_t rss_anon_bytes = info.mem_private_bytes;
+
+ dump->resident_set_kb = rss_bytes / 1024;
+ dump->platform_private_footprint->rss_anon_bytes = rss_anon_bytes;
+ // Fuchsia has no swap.
+ dump->platform_private_footprint->vm_swap_bytes = 0;
+ return true;
}
// static
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
index 589a3a3fd06..f08b8507d0a 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/os_metrics_unittest.cc
@@ -12,7 +12,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include <libgen.h>
#include <mach-o/dyld.h>
#endif
@@ -22,13 +22,13 @@
#include <windows.h>
#endif
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
#include <sys/mman.h>
#endif
namespace memory_instrumentation {
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
namespace {
const char kTestSmaps1[] =
"00400000-004be000 r-xp 00000000 fc:01 1234 /file/1\n"
@@ -128,7 +128,7 @@ void CreateTempFileWithContents(const char* contents, base::ScopedFILE* file) {
}
} // namespace
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
TEST(OSMetricsTest, GivesNonZeroResults) {
base::ProcessId pid = base::kNullProcessId;
@@ -136,16 +136,17 @@ TEST(OSMetricsTest, GivesNonZeroResults) {
dump.platform_private_footprint = mojom::PlatformPrivateFootprint::New();
EXPECT_TRUE(OSMetrics::FillOSMemoryDump(pid, &dump));
EXPECT_TRUE(dump.platform_private_footprint);
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
+ defined(OS_FUCHSIA)
EXPECT_GT(dump.platform_private_footprint->rss_anon_bytes, 0u);
#elif defined(OS_WIN)
EXPECT_GT(dump.platform_private_footprint->private_bytes, 0u);
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
EXPECT_GT(dump.platform_private_footprint->internal_bytes, 0u);
#endif
}
-#if defined(OS_LINUX) || defined(OS_ANDROID)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
TEST(OSMetricsTest, ParseProcSmaps) {
const uint32_t kProtR = mojom::VmRegion::kProtectionFlagsRead;
const uint32_t kProtW = mojom::VmRegion::kProtectionFlagsWrite;
@@ -252,7 +253,7 @@ TEST(OSMetricsTest, GetMappedAndResidentPages) {
EXPECT_EQ(pages == accessed_pages_set, true);
}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
#if defined(OS_WIN)
void DummyFunction() {}
@@ -305,7 +306,7 @@ TEST(OSMetricsTest, TestWinModuleReading) {
}
#endif // defined(OS_WIN)
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
namespace {
void CheckMachORegions(const std::vector<mojom::VmRegionPtr>& maps) {
@@ -346,6 +347,6 @@ TEST(OSMetricsTest, DISABLED_TestMachOReading) {
maps = OSMetrics::GetProcessModules(base::kNullProcessId);
CheckMachORegions(maps);
}
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_MAC)
} // namespace memory_instrumentation
diff --git a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
index 03b977fdd87..221956c6306 100644
--- a/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
+++ b/chromium/services/resource_coordinator/public/cpp/memory_instrumentation/tracing_observer.cc
@@ -204,7 +204,7 @@ void TracingObserver::MemoryMapsAsValueInto(
is_argument_filtering_enabled));
// The following stats are only well defined on Linux-derived OSes.
-#if !defined(OS_MACOSX) && !defined(OS_WIN)
+#if !defined(OS_MAC) && !defined(OS_WIN)
value->BeginDictionary("bs"); // byte stats
value->SetString(
"pss",
diff --git a/chromium/services/resource_coordinator/public/cpp/typemaps.gni b/chromium/services/resource_coordinator/public/cpp/typemaps.gni
deleted file mode 100644
index e6ac78fe325..00000000000
--- a/chromium/services/resource_coordinator/public/cpp/typemaps.gni
+++ /dev/null
@@ -1,5 +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.
-
-typemaps = [ "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.typemap" ]
diff --git a/chromium/services/resource_coordinator/public/mojom/BUILD.gn b/chromium/services/resource_coordinator/public/mojom/BUILD.gn
index 91170ef50f3..ec433ce1e59 100644
--- a/chromium/services/resource_coordinator/public/mojom/BUILD.gn
+++ b/chromium/services/resource_coordinator/public/mojom/BUILD.gn
@@ -20,7 +20,54 @@ mojom_component("mojom") {
]
enabled_features = []
- if (is_linux || is_android) {
+ if (is_linux || is_chromeos || is_android) {
enabled_features += [ "private_swap_info" ]
}
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "memory_instrumentation.mojom.DumpType"
+ cpp = "::base::trace_event::MemoryDumpType"
+ },
+ {
+ mojom = "memory_instrumentation.mojom.LevelOfDetail"
+ cpp = "::base::trace_event::MemoryDumpLevelOfDetail"
+ },
+ {
+ mojom = "memory_instrumentation.mojom.Determinism"
+ cpp = "::base::trace_event::MemoryDumpDeterminism"
+ },
+ {
+ mojom = "memory_instrumentation.mojom.RequestArgs"
+ cpp = "::base::trace_event::MemoryDumpRequestArgs"
+ },
+ {
+ mojom = "memory_instrumentation.mojom.RawAllocatorDumpEdge"
+ cpp =
+ "::base::trace_event::ProcessMemoryDump::MemoryAllocatorDumpEdge"
+ },
+ {
+ mojom = "memory_instrumentation.mojom.RawAllocatorDumpEntry"
+ cpp = "::base::trace_event::MemoryAllocatorDump::Entry"
+ move_only = true
+ },
+ {
+ mojom = "memory_instrumentation.mojom.RawAllocatorDump"
+ cpp = "::std::unique_ptr<::base::trace_event::MemoryAllocatorDump>"
+ move_only = true
+ },
+ {
+ mojom = "memory_instrumentation.mojom.RawProcessMemoryDump"
+ cpp = "::std::unique_ptr<::base::trace_event::ProcessMemoryDump>"
+ move_only = true
+ nullable_is_same_type = true
+ },
+ ]
+ traits_headers = [ "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.h" ]
+ traits_sources = [ "//services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation_mojom_traits.cc" ]
+ traits_public_deps = [ "//base" ]
+ },
+ ]
}
diff --git a/chromium/services/service_manager/BUILD.gn b/chromium/services/service_manager/BUILD.gn
index 25d7a7c9e7c..7de1fb1d77f 100644
--- a/chromium/services/service_manager/BUILD.gn
+++ b/chromium/services/service_manager/BUILD.gn
@@ -48,9 +48,9 @@ source_set("service_manager") {
public_deps = [
"//base",
"//mojo/public/cpp/bindings",
+ "//sandbox/policy",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
- "//services/service_manager/sandbox",
]
if (!is_ios) {
@@ -65,7 +65,7 @@ source_set("service_manager") {
]
}
- if (is_linux) {
+ if (is_linux || is_chromeos) {
deps += [ "//sandbox/linux:sandbox_services" ]
}
}
diff --git a/chromium/services/service_manager/embedder/BUILD.gn b/chromium/services/service_manager/embedder/BUILD.gn
index 6d28466ba7f..fbbf2166aae 100644
--- a/chromium/services/service_manager/embedder/BUILD.gn
+++ b/chromium/services/service_manager/embedder/BUILD.gn
@@ -30,7 +30,7 @@ if (!is_ios) {
"mac_init.mm",
]
- libs = [ "Foundation.framework" ]
+ frameworks = [ "Foundation.framework" ]
}
deps = [
@@ -58,7 +58,7 @@ if (!is_ios) {
deps += [ "//ui/base" ]
}
- if (is_linux) {
+ if (is_linux || is_chromeos) {
deps += [ ":set_process_title_linux" ]
}
@@ -79,7 +79,7 @@ source_set("embedder_result_codes") {
sources = [ "result_codes.h" ]
}
-if (is_linux) {
+if (is_linux || is_chromeos) {
source_set("set_process_title_linux") {
public = [ "set_process_title_linux.h" ]
sources = [ "set_process_title_linux.cc" ]
diff --git a/chromium/services/service_manager/embedder/main.cc b/chromium/services/service_manager/embedder/main.cc
index d277d1eea17..607618c0fad 100644
--- a/chromium/services/service_manager/embedder/main.cc
+++ b/chromium/services/service_manager/embedder/main.cc
@@ -33,6 +33,7 @@
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "mojo/public/cpp/base/shared_memory_utils.h"
+#include "sandbox/policy/sandbox_type.h"
#include "services/service_manager/embedder/main_delegate.h"
#include "services/service_manager/embedder/process_type.h"
#include "services/service_manager/embedder/set_process_title.h"
@@ -41,7 +42,6 @@
#include "services/service_manager/public/cpp/service.h"
#include "services/service_manager/public/cpp/service_executable/service_executable_environment.h"
#include "services/service_manager/public/cpp/service_executable/switches.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
#include "ui/base/ui_base_switches.h"
@@ -62,14 +62,14 @@
#include "base/posix/global_descriptors.h"
#endif
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include "base/mac/scoped_nsautorelease_pool.h"
#include "services/service_manager/embedder/mac_init.h"
#if BUILDFLAG(USE_ALLOCATOR_SHIM)
#include "base/allocator/allocator_shim.h"
#endif
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_MAC)
namespace service_manager {
@@ -257,7 +257,7 @@ int Main(const MainParams& params) {
int exit_code = -1;
base::debug::GlobalActivityTracker* tracker = nullptr;
ProcessType process_type = delegate->OverrideProcessType();
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
std::unique_ptr<base::mac::ScopedNSAutoreleasePool> autorelease_pool;
#endif
@@ -270,12 +270,12 @@ int Main(const MainParams& params) {
#endif
if (!is_initialized) {
is_initialized = true;
-#if defined(OS_MACOSX) && BUILDFLAG(USE_ALLOCATOR_SHIM)
+#if defined(OS_MAC) && BUILDFLAG(USE_ALLOCATOR_SHIM)
base::allocator::InitializeAllocatorShim();
#endif
base::EnableTerminationOnOutOfMemory();
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
// The various desktop environments set this environment variable that
// allows the dbus client library to connect directly to the bus. When this
// variable is not set (test environments like xvfb-run), the dbus client
@@ -344,7 +344,7 @@ int Main(const MainParams& params) {
MainDelegate::InitializeParams init_params;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// We need this pool for all the objects created before we get to the event
// loop, but we don't want to leave them hanging around until the app quits.
// Each "main" needs to flush this pool right before it goes into its main
@@ -386,9 +386,9 @@ int Main(const MainParams& params) {
// Note #2: some platforms can directly allocated shared memory in a
// sandboxed process. The defines below must be in sync with the
// implementation of mojo::NodeController::CreateSharedBuffer().
-#if !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
- if (service_manager::IsUnsandboxedSandboxType(
- service_manager::SandboxTypeFromCommandLine(command_line))) {
+#if !defined(OS_MAC) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
+ if (sandbox::policy::IsUnsandboxedSandboxType(
+ sandbox::policy::SandboxTypeFromCommandLine(command_line))) {
// Unsandboxed processes don't need shared memory brokering... because
// they're not sandboxed.
} else if (mojo_config.force_direct_shared_memory_allocation) {
@@ -402,7 +402,7 @@ int Main(const MainParams& params) {
// allocate shared memory.
mojo::SharedMemoryUtils::InstallBaseHooks();
}
-#endif // !defined(OS_MACOSX) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
+#endif // !defined(OS_MAC) && !defined(OS_NACL_SFI) && !defined(OS_FUCHSIA)
#if defined(OS_WIN)
// Route stdio to parent console (if any) or create one.
@@ -465,7 +465,7 @@ int Main(const MainParams& params) {
}
}
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
autorelease_pool.reset();
#endif
diff --git a/chromium/services/service_manager/embedder/main_delegate.h b/chromium/services/service_manager/embedder/main_delegate.h
index abced50cb03..fc3d4538059 100644
--- a/chromium/services/service_manager/embedder/main_delegate.h
+++ b/chromium/services/service_manager/embedder/main_delegate.h
@@ -36,7 +36,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_EMBEDDER) MainDelegate {
public:
// Extra parameters passed to MainDelegate::Initialize.
struct InitializeParams {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
// The outermost autorelease pool, allocated by internal service manager
// logic. This is guaranteed to live throughout the extent of Run().
base::mac::ScopedNSAutoreleasePool* autorelease_pool = nullptr;
diff --git a/chromium/services/service_manager/embedder/set_process_title.cc b/chromium/services/service_manager/embedder/set_process_title.cc
index 1dc53b847ef..a2ced5316c7 100644
--- a/chromium/services/service_manager/embedder/set_process_title.cc
+++ b/chromium/services/service_manager/embedder/set_process_title.cc
@@ -2,13 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+// Define _GNU_SOURCE to ensure that <errno.h> defines
+// program_invocation_short_name. Keep this at the top of the file since some
+// system headers might include <errno.h> and the header could be skipped on
+// subsequent includes.
+#if (defined(OS_LINUX) || defined(OS_CHROMEOS)) && !defined(_GNU_SOURCE)
+#define _GNU_SOURCE
+#endif
+
#include "services/service_manager/embedder/set_process_title.h"
#include <stddef.h>
#include "build/build_config.h"
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_SOLARIS)
+#if defined(OS_POSIX) && !defined(OS_MAC) && !defined(OS_SOLARIS)
#include <limits.h>
#include <stdlib.h>
#include <unistd.h>
@@ -16,9 +24,10 @@
#include <string>
#include "base/command_line.h"
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_SOLARIS)
+#endif // defined(OS_POSIX) && !defined(OS_MAC) && !defined(OS_SOLARIS)
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
+#include <errno.h> // Get program_invocation_short_name declaration.
#include <sys/prctl.h>
#include "base/files/file_path.h"
@@ -28,12 +37,12 @@
#include "base/threading/platform_thread.h"
// Linux/glibc doesn't natively have setproctitle().
#include "services/service_manager/embedder/set_process_title_linux.h"
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
namespace service_manager {
// TODO(jrg): Find out if setproctitle or equivalent is available on Android.
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_SOLARIS) && \
+#if defined(OS_POSIX) && !defined(OS_MAC) && !defined(OS_SOLARIS) && \
!defined(OS_ANDROID) && !defined(OS_FUCHSIA)
void SetProcessTitleFromCommandLine(const char** main_argv) {
@@ -43,7 +52,7 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
std::string title;
bool have_argv0 = false;
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
DCHECK_EQ(base::PlatformThread::CurrentId(), getpid());
if (main_argv)
@@ -64,13 +73,19 @@ void SetProcessTitleFromCommandLine(const char** main_argv) {
if (base::EndsWith(title, kDeletedSuffix, base::CompareCase::SENSITIVE))
title.resize(title.size() - kDeletedSuffix.size());
+ base::FilePath::StringType base_name =
+ base::FilePath(title).BaseName().value();
// PR_SET_NAME is available in Linux 2.6.9 and newer.
// When available at run time, this sets the short process name that shows
// when the full command line is not being displayed in most process
// listings.
- prctl(PR_SET_NAME, base::FilePath(title).BaseName().value().c_str());
+ prctl(PR_SET_NAME, base_name.c_str());
+
+ // This prevents program_invocation_short_name from being broken by
+ // setproctitle().
+ program_invocation_short_name = strdup(base_name.c_str());
}
-#endif // defined(OS_LINUX)
+#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
const base::CommandLine* command_line =
base::CommandLine::ForCurrentProcess();
diff --git a/chromium/services/service_manager/public/cpp/BUILD.gn b/chromium/services/service_manager/public/cpp/BUILD.gn
index e7d0f383a25..5220a379e5f 100644
--- a/chromium/services/service_manager/public/cpp/BUILD.gn
+++ b/chromium/services/service_manager/public/cpp/BUILD.gn
@@ -25,11 +25,11 @@ component("cpp") {
"manifest_builder.h",
"service.cc",
"service.h",
- "service_binding.cc",
- "service_binding.h",
"service_context_ref.h",
"service_keepalive.cc",
"service_keepalive.h",
+ "service_receiver.cc",
+ "service_receiver.h",
"standalone_connector_impl.cc",
"standalone_connector_impl.h",
]
diff --git a/chromium/services/service_manager/public/cpp/OWNERS b/chromium/services/service_manager/public/cpp/OWNERS
index 7aebc8abbf8..d5fefd82012 100644
--- a/chromium/services/service_manager/public/cpp/OWNERS
+++ b/chromium/services/service_manager/public/cpp/OWNERS
@@ -1,4 +1,2 @@
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/service_manager/public/cpp/bind_source_info.typemap b/chromium/services/service_manager/public/cpp/bind_source_info.typemap
deleted file mode 100644
index 120f6d9dc07..00000000000
--- a/chromium/services/service_manager/public/cpp/bind_source_info.typemap
+++ /dev/null
@@ -1,14 +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.
-
-mojom = "//services/service_manager/public/mojom/service.mojom"
-public_headers = [ "//services/service_manager/public/cpp/bind_source_info.h" ]
-traits_headers =
- [ "//services/service_manager/public/cpp/bind_source_info_mojom_traits.h" ]
-public_deps = [
- "//services/service_manager/public/cpp:cpp_types",
-]
-
-type_mappings =
- [ "service_manager.mojom.BindSourceInfo=::service_manager::BindSourceInfo" ]
diff --git a/chromium/services/service_manager/public/cpp/bind_source_info_mojom_traits.h b/chromium/services/service_manager/public/cpp/bind_source_info_mojom_traits.h
index 9f57eec34b6..744fb6895b5 100644
--- a/chromium/services/service_manager/public/cpp/bind_source_info_mojom_traits.h
+++ b/chromium/services/service_manager/public/cpp/bind_source_info_mojom_traits.h
@@ -6,13 +6,15 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_BIND_SOURCE_INFO_MOJOM_TRAITS_H_
#include "services/service_manager/public/cpp/bind_source_info.h"
-#include "services/service_manager/public/mojom/service.mojom.h"
+#include "services/service_manager/public/cpp/identity_mojom_traits.h"
+#include "services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h"
+#include "services/service_manager/public/mojom/service.mojom-shared.h"
namespace mojo {
template <>
struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
- StructTraits<service_manager::mojom::BindSourceInfo::DataView,
+ StructTraits<service_manager::mojom::BindSourceInfoDataView,
service_manager::BindSourceInfo> {
static const service_manager::Identity& identity(
const service_manager::BindSourceInfo& source) {
diff --git a/chromium/services/service_manager/public/cpp/identity.typemap b/chromium/services/service_manager/public/cpp/identity.typemap
deleted file mode 100644
index 6fb23dc509d..00000000000
--- a/chromium/services/service_manager/public/cpp/identity.typemap
+++ /dev/null
@@ -1,14 +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.
-
-mojom = "//services/service_manager/public/mojom/connector.mojom"
-public_headers = [ "//services/service_manager/public/cpp/identity.h" ]
-traits_headers =
- [ "//services/service_manager/public/cpp/identity_mojom_traits.h" ]
-public_deps = [
- "//services/service_manager/public/cpp:cpp_types",
- "//services/service_manager/public/cpp:mojom_traits",
-]
-
-type_mappings = [ "service_manager.mojom.Identity=::service_manager::Identity" ]
diff --git a/chromium/services/service_manager/public/cpp/interface_provider_spec.typemap b/chromium/services/service_manager/public/cpp/interface_provider_spec.typemap
deleted file mode 100644
index 72f0278bb34..00000000000
--- a/chromium/services/service_manager/public/cpp/interface_provider_spec.typemap
+++ /dev/null
@@ -1,17 +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.
-
-mojom = "//services/service_manager/public/mojom/interface_provider_spec.mojom"
-public_headers =
- [ "//services/service_manager/public/cpp/interface_provider_spec.h" ]
-traits_headers = [ "//services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h" ]
-public_deps = [
- "//services/service_manager/public/cpp:cpp_types",
-]
-
-type_mappings = [
- "service_manager.mojom.InterfaceProviderSpec=::service_manager::InterfaceProviderSpec",
- "service_manager.mojom.InterfaceSet=::service_manager::InterfaceSet",
- "service_manager.mojom.CapabilitySet=::service_manager::CapabilitySet",
-]
diff --git a/chromium/services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h b/chromium/services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h
index e7c8a8feaed..b996bc7b001 100644
--- a/chromium/services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h
+++ b/chromium/services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h
@@ -6,13 +6,13 @@
#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_INTERFACE_PROVIDER_SPEC_MOJOM_TRAITS_H_
#include "services/service_manager/public/cpp/interface_provider_spec.h"
-#include "services/service_manager/public/mojom/interface_provider_spec.mojom.h"
+#include "services/service_manager/public/mojom/interface_provider_spec.mojom-shared.h"
namespace mojo {
template <>
struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
- StructTraits<service_manager::mojom::InterfaceProviderSpec::DataView,
+ StructTraits<service_manager::mojom::InterfaceProviderSpecDataView,
service_manager::InterfaceProviderSpec> {
static const std::map<service_manager::Capability,
service_manager::InterfaceSet>&
@@ -32,7 +32,7 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
template <>
struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
- StructTraits<service_manager::mojom::InterfaceSet::DataView,
+ StructTraits<service_manager::mojom::InterfaceSetDataView,
service_manager::InterfaceSet> {
static std::vector<std::string> interfaces(
const service_manager::InterfaceSet& spec) {
@@ -57,7 +57,7 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
template <>
struct COMPONENT_EXPORT(SERVICE_MANAGER_MOJOM)
- StructTraits<service_manager::mojom::CapabilitySet::DataView,
+ StructTraits<service_manager::mojom::CapabilitySetDataView,
service_manager::CapabilitySet> {
static std::vector<std::string> capabilities(
const service_manager::CapabilitySet& spec) {
diff --git a/chromium/services/service_manager/public/cpp/manifest.h b/chromium/services/service_manager/public/cpp/manifest.h
index 586441b2826..b731d58022e 100644
--- a/chromium/services/service_manager/public/cpp/manifest.h
+++ b/chromium/services/service_manager/public/cpp/manifest.h
@@ -93,7 +93,8 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Manifest {
// binary (for example Chromium, or any Content embedder), and the embedder
// handles requests for new instances of the service via
// ServiceProcess::Delegate::RunService(). The service will always run in
- // a child process sandboxed according to SandboxType (see Options below).
+ // a child process sandboxed according to sandbox::policy::SandboxType (see
+ // Options below).
kOutOfProcessBuiltin,
// The service is launched out-of-process from a standalone service
@@ -102,7 +103,8 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Manifest {
// "${service_name}.service.exe" on Windows).
//
// Proper sandboxing is currently not supported for standalone service
- // executables, so SandboxType (see Options below) is ignored. This renders
+ // executables, so sandbox::policy::SandboxType (see Options below) is
+ // ignored. This renders
// standalone service executables generally unsuitable for production
// environments.
kStandaloneExecutable,
@@ -151,7 +153,8 @@ struct COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Manifest {
// if |execution_mode| is |kOutOfProcessBuiltin| or
// |kStandaloneExecutable|.
//
- // TODO(https://crbug.com/915806): Make this field a SandboxType enum.
+ // TODO(https://crbug.com/915806): Make this field a
+ // sandbox::policy::SandboxType enum.
std::string sandbox_type{"utility"};
};
diff --git a/chromium/services/service_manager/public/cpp/service.h b/chromium/services/service_manager/public/cpp/service.h
index 9316c3aa4b1..38fb7950b51 100644
--- a/chromium/services/service_manager/public/cpp/service.h
+++ b/chromium/services/service_manager/public/cpp/service.h
@@ -32,7 +32,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) Service {
// default implementation of |OnDisconnected()|.
//
// This should really only be called on a Service instance that has a bound
- // connection to the Service Manager, e.g. a functioning ServiceBinding. If
+ // connection to the Service Manager, e.g. a functioning ServiceReceiver. If
// the service never calls |Terminate()|, it will effectively leak.
//
// If |callback| is non-null, it will be invoked after |service| is destroyed.
diff --git a/chromium/services/service_manager/public/cpp/service_executable/BUILD.gn b/chromium/services/service_manager/public/cpp/service_executable/BUILD.gn
index d62e2b37543..4c1c4969ef6 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/BUILD.gn
+++ b/chromium/services/service_manager/public/cpp/service_executable/BUILD.gn
@@ -13,8 +13,8 @@ source_set("support") {
"//mojo/core/embedder",
"//mojo/public/cpp/platform",
"//mojo/public/cpp/system",
+ "//sandbox/policy",
"//services/service_manager/public/cpp",
- "//services/service_manager/sandbox",
]
public_deps = [
@@ -22,7 +22,7 @@ source_set("support") {
"//services/service_manager/public/mojom",
]
- if (is_linux) {
+ if (is_linux || is_chromeos) {
deps += [
"//sandbox/linux:sandbox",
"//sandbox/linux:sandbox_services",
diff --git a/chromium/services/service_manager/public/cpp/service_executable/main.cc b/chromium/services/service_manager/public/cpp/service_executable/main.cc
index 5cec8822602..e760c26199a 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/main.cc
+++ b/chromium/services/service_manager/public/cpp/service_executable/main.cc
@@ -23,7 +23,7 @@
#include "services/service_manager/public/cpp/service_executable/service_main.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include "base/mac/bundle_locations.h"
#endif
diff --git a/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc b/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
index 7d660a916fb..8d99a8e2773 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
+++ b/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.cc
@@ -6,48 +6,49 @@
#include "base/check.h"
#include "base/command_line.h"
-#include "base/message_loop/message_loop_current.h"
#include "base/message_loop/message_pump_type.h"
#include "base/synchronization/waitable_event.h"
+#include "base/task/current_thread.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "build/build_config.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/invitation.h"
#include "mojo/public/cpp/system/message_pipe.h"
+#include "sandbox/policy/sandbox.h"
+#include "sandbox/policy/switches.h"
#include "services/service_manager/public/cpp/service_executable/switches.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "services/service_manager/sandbox/switches.h"
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "base/rand_util.h"
#include "base/system/sys_info.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
+#include "sandbox/policy/linux/sandbox_linux.h"
#endif
namespace service_manager {
ServiceExecutableEnvironment::ServiceExecutableEnvironment()
: ipc_thread_("IPC Thread") {
- DCHECK(!base::MessageLoopCurrent::Get());
+ DCHECK(!base::CurrentThread::Get());
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
const base::CommandLine& command_line =
*base::CommandLine::ForCurrentProcess();
- if (command_line.HasSwitch(switches::kServiceSandboxType)) {
+ if (command_line.HasSwitch(sandbox::policy::switches::kServiceSandboxType)) {
// Warm parts of base in the copy of base in the mojo runner.
base::RandUint64();
base::SysInfo::AmountOfPhysicalMemory();
base::SysInfo::NumberOfProcessors();
// Repeat steps normally performed by the zygote.
- SandboxLinux::Options sandbox_options;
+ sandbox::policy::SandboxLinux::Options sandbox_options;
sandbox_options.engage_namespace_sandbox = true;
- Sandbox::Initialize(
- UtilitySandboxTypeFromString(
- command_line.GetSwitchValueASCII(switches::kServiceSandboxType)),
- SandboxLinux::PreSandboxHook(), sandbox_options);
+ sandbox::policy::Sandbox::Initialize(
+ sandbox::policy::UtilitySandboxTypeFromString(
+ command_line.GetSwitchValueASCII(
+ sandbox::policy::switches::kServiceSandboxType)),
+ sandbox::policy::SandboxLinux::PreSandboxHook(), sandbox_options);
}
#endif
@@ -64,12 +65,12 @@ ServiceExecutableEnvironment::ServiceExecutableEnvironment()
ServiceExecutableEnvironment::~ServiceExecutableEnvironment() = default;
-mojom::ServiceRequest
+mojo::PendingReceiver<mojom::Service>
ServiceExecutableEnvironment::TakeServiceRequestFromCommandLine() {
auto invitation = mojo::IncomingInvitation::Accept(
mojo::PlatformChannel::RecoverPassedEndpointFromCommandLine(
*base::CommandLine::ForCurrentProcess()));
- return mojom::ServiceRequest(invitation.ExtractMessagePipe(
+ return mojo::PendingReceiver<mojom::Service>(invitation.ExtractMessagePipe(
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
switches::kServiceRequestAttachmentName)));
}
diff --git a/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h b/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h
index f5265705ed0..0183aa0d2da 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h
+++ b/chromium/services/service_manager/public/cpp/service_executable/service_executable_environment.h
@@ -9,6 +9,7 @@
#include "base/optional.h"
#include "base/threading/thread.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
+#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "services/service_manager/public/mojom/service.mojom.h"
namespace service_manager {
@@ -32,7 +33,7 @@ class ServiceExecutableEnvironment {
// Returns a ServiceRequest which should be passed to the Service
// implementation which will run within the extent of this environment.
- mojom::ServiceRequest TakeServiceRequestFromCommandLine();
+ mojo::PendingReceiver<mojom::Service> TakeServiceRequestFromCommandLine();
private:
base::Thread ipc_thread_;
diff --git a/chromium/services/service_manager/public/cpp/service_executable/service_main.h b/chromium/services/service_manager/public/cpp/service_executable/service_main.h
index cdf2dc0e46b..534a1274cd5 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/service_main.h
+++ b/chromium/services/service_manager/public/cpp/service_executable/service_main.h
@@ -10,6 +10,7 @@
// Service executables linking against the
// "//services/service_manager/public/cpp/service_executable:main" target must
// implement this function as their entry point.
-void ServiceMain(service_manager::mojom::ServiceRequest request);
+void ServiceMain(
+ mojo::PendingReceiver<service_manager::mojom::Service> receiver);
#endif // SERVICES_SERVICE_MANAGER_PUBLIC_CPP_STANDALONE_SERVICE_SERVICE_MAIN_H_
diff --git a/chromium/services/service_manager/public/cpp/service_executable/switches.cc b/chromium/services/service_manager/public/cpp/service_executable/switches.cc
index 9a84d6c9faa..88be354d542 100644
--- a/chromium/services/service_manager/public/cpp/service_executable/switches.cc
+++ b/chromium/services/service_manager/public/cpp/service_executable/switches.cc
@@ -12,8 +12,9 @@ namespace switches {
// different services.
const char kServiceName[] = "service-name";
-// The name of the |service_manager::mojom::ServiceRequest| message pipe handle
-// that is attached to the incoming Mojo invitation received by the service.
+// The name of the |mojo::PendingReceiver<service_manager::mojom::Service>|
+// message pipe handle that is attached to the incoming Mojo invitation received
+// by the service.
const char kServiceRequestAttachmentName[] = "service-request-attachment-name";
} // namespace switches
diff --git a/chromium/services/service_manager/public/cpp/service_filter.typemap b/chromium/services/service_manager/public/cpp/service_filter.typemap
deleted file mode 100644
index 1b30da43555..00000000000
--- a/chromium/services/service_manager/public/cpp/service_filter.typemap
+++ /dev/null
@@ -1,14 +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.
-
-mojom = "//services/service_manager/public/mojom/service_filter.mojom"
-public_headers = [ "//services/service_manager/public/cpp/service_filter.h" ]
-traits_headers =
- [ "//services/service_manager/public/cpp/service_filter_mojom_traits.h" ]
-public_deps = [
- "//services/service_manager/public/cpp:cpp_types",
- "//services/service_manager/public/cpp:mojom_traits",
-]
-type_mappings =
- [ "service_manager.mojom.ServiceFilter=::service_manager::ServiceFilter" ]
diff --git a/chromium/services/service_manager/public/cpp/service_keepalive.cc b/chromium/services/service_manager/public/cpp/service_keepalive.cc
index a4e53956313..0e02994a207 100644
--- a/chromium/services/service_manager/public/cpp/service_keepalive.cc
+++ b/chromium/services/service_manager/public/cpp/service_keepalive.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/task/post_task.h"
-#include "services/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/public/cpp/service_receiver.h"
namespace service_manager {
@@ -56,9 +56,9 @@ class ServiceKeepaliveRefImpl : public ServiceKeepaliveRef {
DISALLOW_COPY_AND_ASSIGN(ServiceKeepaliveRefImpl);
};
-ServiceKeepalive::ServiceKeepalive(ServiceBinding* binding,
+ServiceKeepalive::ServiceKeepalive(ServiceReceiver* receiver,
base::Optional<base::TimeDelta> idle_timeout)
- : binding_(binding), idle_timeout_(idle_timeout) {}
+ : receiver_(receiver), idle_timeout_(idle_timeout) {}
ServiceKeepalive::~ServiceKeepalive() = default;
@@ -111,10 +111,10 @@ void ServiceKeepalive::OnTimerExpired() {
for (auto& observer : observers_)
observer.OnIdleTimeout();
- // NOTE: We allow for a null |binding_| because it's convenient in some
+ // NOTE: We allow for a null |receiver_| because it's convenient in some
// testing scenarios and adds no real complexity to this implementation.
- if (binding_)
- binding_->RequestClose();
+ if (receiver_)
+ receiver_->RequestClose();
}
} // namespace service_manager
diff --git a/chromium/services/service_manager/public/cpp/service_keepalive.h b/chromium/services/service_manager/public/cpp/service_keepalive.h
index 6a1488993d7..70ab6ff9964 100644
--- a/chromium/services/service_manager/public/cpp/service_keepalive.h
+++ b/chromium/services/service_manager/public/cpp/service_keepalive.h
@@ -15,12 +15,12 @@
namespace service_manager {
-class ServiceBinding;
+class ServiceReceiver;
class ServiceKeepaliveRef;
// Service implementations are responsible for managing their own lifetime and
-// as such are expected to call |ServiceBinding::RequestClose()| on their own
-// ServiceBinding when they are no longer in use by any clients and otherwise
+// as such are expected to call |ServiceReceiver::RequestClose()| on their own
+// ServiceReceiver when they are no longer in use by any clients and otherwise
// have no reason to keep running (e.g. no active UI visible).
//
// ServiceKeepalive helps Service implementations accomplish this by vending
@@ -32,7 +32,7 @@ class ServiceKeepaliveRef;
// If the ServiceKeepalive's number of living ServiceKeepaliveRef instances goes
// to zero, the service is considered idle. If the ServiceKeepalive is
// configured with an idle timeout, it will automatically invoke
-// |ServiceBinding::RequestClose()| on its associated ServiceBinding once the
+// |ServiceReceiver::RequestClose()| on its associated ServiceReceiver once the
// service has remained idle for that continuous duration.
//
// Services can use this mechanism to vend ServiceKeepaliveRefs to various parts
@@ -55,10 +55,10 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceKeepalive {
};
// Constructs a ServiceKeepalive to control the lifetime behavior of
- // |*binding|. Note that if either |binding| or |idle_timeout| is null, this
+ // |*receiver|. Note that if either |receiver| or |idle_timeout| is null, this
// object will not do any automatic lifetime management and will instead only
// maintain an internal ref-count which the consumer can query.
- ServiceKeepalive(ServiceBinding* binding,
+ ServiceKeepalive(ServiceReceiver* receiver,
base::Optional<base::TimeDelta> idle_timeout);
~ServiceKeepalive();
@@ -82,7 +82,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceKeepalive {
void OnTimerExpired();
- ServiceBinding* const binding_;
+ ServiceReceiver* const receiver_;
const base::Optional<base::TimeDelta> idle_timeout_;
base::Optional<base::OneShotTimer> idle_timer_;
base::ObserverList<Observer> observers_;
@@ -93,7 +93,7 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceKeepalive {
};
// Objects which can be created by a |ServiceKeepalive| and cloned from each
-// other. The ServiceBinding referenced by a ServiceKeepalive is considered
+// other. The ServiceReceiver referenced by a ServiceKeepalive is considered
// active as long as one of these objects exists and is associated with that
// ServiceKeepalive.
class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceKeepaliveRef {
diff --git a/chromium/services/service_manager/public/cpp/service_binding.cc b/chromium/services/service_manager/public/cpp/service_receiver.cc
index 83ba0279530..18ac3893fa5 100644
--- a/chromium/services/service_manager/public/cpp/service_binding.cc
+++ b/chromium/services/service_manager/public/cpp/service_receiver.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/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/public/cpp/service_receiver.h"
#include <utility>
@@ -14,35 +14,35 @@
namespace service_manager {
-ServiceBinding::ServiceBinding(service_manager::Service* service)
+ServiceReceiver::ServiceReceiver(service_manager::Service* service)
: service_(service) {
DCHECK(service_);
}
-ServiceBinding::ServiceBinding(service_manager::Service* service,
- mojo::PendingReceiver<mojom::Service> receiver)
- : ServiceBinding(service) {
+ServiceReceiver::ServiceReceiver(service_manager::Service* service,
+ mojo::PendingReceiver<mojom::Service> receiver)
+ : ServiceReceiver(service) {
if (receiver.is_valid())
Bind(std::move(receiver));
}
-ServiceBinding::~ServiceBinding() = default;
+ServiceReceiver::~ServiceReceiver() = default;
-Connector* ServiceBinding::GetConnector() {
+Connector* ServiceReceiver::GetConnector() {
if (!connector_)
connector_ = Connector::Create(&pending_connector_receiver_);
return connector_.get();
}
-void ServiceBinding::Bind(mojo::PendingReceiver<mojom::Service> receiver) {
+void ServiceReceiver::Bind(mojo::PendingReceiver<mojom::Service> receiver) {
DCHECK(!is_bound());
receiver_.Bind(std::move(receiver));
receiver_.set_disconnect_handler(base::BindOnce(
- &ServiceBinding::OnConnectionError, base::Unretained(this)));
+ &ServiceReceiver::OnConnectionError, base::Unretained(this)));
}
-void ServiceBinding::RequestClose() {
- // We allow for innoccuous RequestClose() calls on unbound ServiceBindings.
+void ServiceReceiver::RequestClose() {
+ // We allow for innoccuous RequestClose() calls on unbound ServiceReceivers.
// This may occur e.g. when running a service in-process.
if (!is_bound())
return;
@@ -58,19 +58,19 @@ void ServiceBinding::RequestClose() {
}
}
-void ServiceBinding::Close() {
+void ServiceReceiver::Close() {
DCHECK(is_bound());
receiver_.reset();
service_control_.reset();
connector_.reset();
}
-void ServiceBinding::OnConnectionError() {
+void ServiceReceiver::OnConnectionError() {
service_->OnDisconnected();
}
-void ServiceBinding::OnStart(const Identity& identity,
- OnStartCallback callback) {
+void ServiceReceiver::OnStart(const Identity& identity,
+ OnStartCallback callback) {
identity_ = identity;
if (!pending_connector_receiver_.is_valid())
@@ -85,7 +85,7 @@ void ServiceBinding::OnStart(const Identity& identity,
service_control_->RequestQuit();
}
-void ServiceBinding::OnBindInterface(
+void ServiceReceiver::OnBindInterface(
const BindSourceInfo& source_info,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle interface_pipe,
@@ -96,7 +96,7 @@ void ServiceBinding::OnBindInterface(
service_->OnConnect(source_info, interface_name, std::move(interface_pipe));
}
-void ServiceBinding::CreatePackagedServiceInstance(
+void ServiceReceiver::CreatePackagedServiceInstance(
const Identity& identity,
mojo::PendingReceiver<mojom::Service> receiver,
mojo::PendingRemote<mojom::ProcessMetadata> metadata) {
diff --git a/chromium/services/service_manager/public/cpp/service_binding.h b/chromium/services/service_manager/public/cpp/service_receiver.h
index 6a2f6c6f14e..c80300876f1 100644
--- a/chromium/services/service_manager/public/cpp/service_binding.h
+++ b/chromium/services/service_manager/public/cpp/service_receiver.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_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_BINDING_H_
-#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_BINDING_H_
+#ifndef SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_RECEIVER_H_
+#define SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_RECEIVER_H_
#include <memory>
@@ -30,13 +30,14 @@ class Service;
// implementation, while also exposing a working Connector interface the service
// can use to make outgoing interface requests.
//
-// A ServiceBinding is considered to be "bound" after |Bind()| is invoked with a
-// valid Service receiver (or the equivalent constructor is used -- see below).
-// Upon connection error or an explicit call to |Close()|, the ServiceBinding
-// will be considered "unbound" until another call to |Bind()| is made.
+// A ServiceReceiver is considered to be "bound" after |Bind()| is invoked with
+// a valid Service receiver (or the equivalent constructor is used -- see
+// below). Upon connection error or an explicit call to |Close()|, the
+// ServiceReceiver will be considered "unbound" until another call to |Bind()|
+// is made.
//
-// NOTE: A well-behaved service should aim to always close its ServiceBinding
-// gracefully by calling |RequestClose()|. Closing a ServiceBinding abruptly
+// NOTE: A well-behaved service should aim to always close its ServiceReceiver
+// gracefully by calling |RequestClose()|. Closing a ServiceReceiver abruptly
// (by either destroying it or explicitly calling |Close()|) introduces inherent
// flakiness into the system unless the Service's |OnDisconnected()| has already
// been invoked, because otherwise the Service Manager may have in-flight
@@ -44,45 +45,45 @@ class Service;
// dropped to the dismay of the service instance which issued them. Exceptions
// can reasonably be made for system-wide shutdown situations where even the
// Service Manager itself will be imminently torn down.
-class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceBinding
+class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceReceiver
: public mojom::Service {
public:
- // Creates a new ServiceBinding bound to |service|. The service will not
+ // Creates a new ServiceReceiver bound to |service|. The service will not
// receive any Service interface calls until |Bind()| is called, but its
// |connector()| is usable immediately upon construction.
//
- // |service| is not owned and must outlive this ServiceBinding.
- explicit ServiceBinding(service_manager::Service* service);
+ // |service| is not owned and must outlive this ServiceReceiver.
+ explicit ServiceReceiver(service_manager::Service* service);
// Same as above, but behaves as if |Bind(receiver)| is also called
// immediately after construction. See below.
- ServiceBinding(service_manager::Service* service,
- mojo::PendingReceiver<mojom::Service> receiver);
+ ServiceReceiver(service_manager::Service* service,
+ mojo::PendingReceiver<mojom::Service> receiver);
- ~ServiceBinding() override;
+ ~ServiceReceiver() override;
bool is_bound() const { return receiver_.is_bound(); }
const Identity& identity() const { return identity_; }
// Returns a usable Connector which can make outgoing interface requests
- // identifying as the service to which this ServiceBinding is bound.
+ // identifying as the service to which this ServiceReceiver is bound.
Connector* GetConnector();
- // Binds this ServiceBinding to a new Service receiver. Once a ServiceBinding
- // is bound, its target Service will begin receiving Service events. The
- // order of events received is:
+ // Binds this ServiceReceiver to a new Service receiver. Once a
+ // ServiceReceiver is bound, its target Service will begin receiving Service
+ // events. The order of events received is:
//
// - OnStart() exactly once
// - OnIdentityKnown() exactly once
// - OnBindInterface() zero or more times
//
// The target Service will be able to receive these events until this
- // ServiceBinding is either unbound or destroyed.
+ // ServiceReceiver is either unbound or destroyed.
//
// If |receiver| is invalid, this call does nothing.
//
- // Must only be called on an unbound ServiceBinding.
+ // Must only be called on an unbound ServiceReceiver.
void Bind(mojo::PendingReceiver<mojom::Service> receiver);
// Asks the Service Manager nicely if it's OK for this service instance to
@@ -90,16 +91,16 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceBinding
// binding's connection, ultimately triggering an |OnDisconnected()| call on
// the bound Service object.
//
- // Must only be called on a bound ServiceBinding.
+ // Must only be called on a bound ServiceReceiver.
void RequestClose();
// Immediately severs the connection to the Service Manager. No further
- // incoming interface requests will be received until this ServiceBinding is
+ // incoming interface requests will be received until this ServiceReceiver is
// bound again. Always prefer |RequestClose()| under normal circumstances,
// unless |OnDisconnected()| has already been invoked on the Service. See the
// note in the class documentation above regarding graceful binding closure.
//
- // Must only be called on a bound ServiceBinding.
+ // Must only be called on a bound ServiceReceiver.
void Close();
private:
@@ -118,13 +119,13 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceBinding
// The Service instance to which all incoming events from the Service Manager
// should be directed. Typically this is the object which owns this
- // ServiceBinding.
+ // ServiceReceiver.
service_manager::Service* const service_;
// A pending Connector request which will eventually be passed to the Service
- // Manager. Created preemptively by every unbound ServiceBinding so that
+ // Manager. Created preemptively by every unbound ServiceReceiver so that
// |connector()| may begin pipelining outgoing requests even before the
- // ServiceBinding is bound to a Service receiver.
+ // ServiceReceiver is bound to a Service receiver.
mojo::PendingReceiver<mojom::Connector> pending_connector_receiver_;
mojo::Receiver<mojom::Service> receiver_{this};
@@ -136,13 +137,13 @@ class COMPONENT_EXPORT(SERVICE_MANAGER_CPP) ServiceBinding
mojo::AssociatedRemote<mojom::ServiceControl> service_control_;
// Tracks whether |RequestClose()| has been called at least once prior to
- // receiving |OnStart()| on a bound ServiceBinding. This ensures that the
+ // receiving |OnStart()| on a bound ServiceReceiver. This ensures that the
// closure request is actually issued once |OnStart()| is invoked.
bool request_closure_on_start_ = false;
- DISALLOW_COPY_AND_ASSIGN(ServiceBinding);
+ DISALLOW_COPY_AND_ASSIGN(ServiceReceiver);
};
} // namespace service_manager
-#endif // SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_CONTEXT_H_
+#endif // SERVICES_SERVICE_MANAGER_PUBLIC_CPP_SERVICE_RECEIVER_H_
diff --git a/chromium/services/service_manager/public/cpp/typemaps.gni b/chromium/services/service_manager/public/cpp/typemaps.gni
deleted file mode 100644
index b4f38a3bf1e..00000000000
--- a/chromium/services/service_manager/public/cpp/typemaps.gni
+++ /dev/null
@@ -1,6 +0,0 @@
-typemaps = [
- "//services/service_manager/public/cpp/bind_source_info.typemap",
- "//services/service_manager/public/cpp/identity.typemap",
- "//services/service_manager/public/cpp/interface_provider_spec.typemap",
- "//services/service_manager/public/cpp/service_filter.typemap",
-]
diff --git a/chromium/services/service_manager/public/mojom/BUILD.gn b/chromium/services/service_manager/public/mojom/BUILD.gn
index a9e2eca0163..b7f9ae5291b 100644
--- a/chromium/services/service_manager/public/mojom/BUILD.gn
+++ b/chromium/services/service_manager/public/mojom/BUILD.gn
@@ -23,6 +23,72 @@ mojom_component("mojom") {
":constants",
"//mojo/public/mojom/base",
]
+
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "service_manager.mojom.BindSourceInfo"
+ cpp = "::service_manager::BindSourceInfo"
+ },
+ ]
+ traits_headers = [
+ "//services/service_manager/public/cpp/bind_source_info_mojom_traits.h",
+ ]
+ traits_public_deps = [
+ "//services/service_manager/public/cpp:cpp_types",
+ "//services/service_manager/public/cpp:mojom_traits",
+ ]
+ },
+ {
+ types = [
+ {
+ mojom = "service_manager.mojom.Identity"
+ cpp = "::service_manager::Identity"
+ },
+ ]
+ traits_headers =
+ [ "//services/service_manager/public/cpp/identity_mojom_traits.h" ]
+ traits_public_deps = [
+ "//services/service_manager/public/cpp:cpp_types",
+ "//services/service_manager/public/cpp:mojom_traits",
+ ]
+ },
+ {
+ types = [
+ {
+ mojom = "service_manager.mojom.InterfaceProviderSpec"
+ cpp = "::service_manager::InterfaceProviderSpec"
+ },
+ {
+ mojom = "service_manager.mojom.InterfaceSet"
+ cpp = "::service_manager::InterfaceSet"
+ },
+ {
+ mojom = "service_manager.mojom.CapabilitySet"
+ cpp = "::service_manager::CapabilitySet"
+ },
+ ]
+ traits_headers = [ "//services/service_manager/public/cpp/interface_provider_spec_mojom_traits.h" ]
+ traits_public_deps = [ "//services/service_manager/public/cpp:cpp_types" ]
+ },
+ {
+ types = [
+ {
+ mojom = "service_manager.mojom.ServiceFilter"
+ cpp = "::service_manager::ServiceFilter"
+ },
+ ]
+
+ traits_headers = [
+ "//services/service_manager/public/cpp/service_filter_mojom_traits.h",
+ ]
+ traits_public_deps = [
+ "//services/service_manager/public/cpp:cpp_types",
+ "//services/service_manager/public/cpp:mojom_traits",
+ ]
+ },
+ ]
}
mojom_component("constants") {
diff --git a/chromium/services/service_manager/sandbox/BUILD.gn b/chromium/services/service_manager/sandbox/BUILD.gn
deleted file mode 100644
index 21749ad3322..00000000000
--- a/chromium/services/service_manager/sandbox/BUILD.gn
+++ /dev/null
@@ -1,144 +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.
-
-import("//build/buildflag_header.gni")
-import("//build/config/chromecast_build.gni")
-import("//build/config/sanitizers/sanitizers.gni")
-
-component("sandbox") {
- sources = [
- "export.h",
- "features.cc",
- "features.h",
- "sandbox.cc",
- "sandbox.h",
- "sandbox_delegate.h",
- "sandbox_type.cc",
- "sandbox_type.h",
- "switches.cc",
- "switches.h",
- ]
- defines = [ "SERVICE_MANAGER_SANDBOX_IMPL" ]
- public_deps = [ "//services/service_manager/embedder:embedder_switches" ]
- deps = [
- ":sanitizer_buildflags",
- "//base",
- "//sandbox:common",
- ]
- if (is_linux) {
- sources += [
- "linux/bpf_audio_policy_linux.cc",
- "linux/bpf_audio_policy_linux.h",
- "linux/bpf_base_policy_linux.cc",
- "linux/bpf_base_policy_linux.h",
- "linux/bpf_broker_policy_linux.cc",
- "linux/bpf_broker_policy_linux.h",
- "linux/bpf_cdm_policy_linux.cc",
- "linux/bpf_cdm_policy_linux.h",
- "linux/bpf_cros_amd_gpu_policy_linux.cc",
- "linux/bpf_cros_amd_gpu_policy_linux.h",
- "linux/bpf_cros_arm_gpu_policy_linux.cc",
- "linux/bpf_cros_arm_gpu_policy_linux.h",
- "linux/bpf_gpu_policy_linux.cc",
- "linux/bpf_gpu_policy_linux.h",
- "linux/bpf_network_policy_linux.cc",
- "linux/bpf_network_policy_linux.h",
- "linux/bpf_ppapi_policy_linux.cc",
- "linux/bpf_ppapi_policy_linux.h",
- "linux/bpf_print_compositor_policy_linux.cc",
- "linux/bpf_print_compositor_policy_linux.h",
- "linux/bpf_renderer_policy_linux.cc",
- "linux/bpf_renderer_policy_linux.h",
- "linux/bpf_sharing_service_policy_linux.cc",
- "linux/bpf_sharing_service_policy_linux.h",
- "linux/bpf_speech_recognition_policy_linux.cc",
- "linux/bpf_speech_recognition_policy_linux.h",
- "linux/bpf_utility_policy_linux.cc",
- "linux/bpf_utility_policy_linux.h",
- "linux/sandbox_debug_handling_linux.cc",
- "linux/sandbox_debug_handling_linux.h",
- "linux/sandbox_linux.cc",
- "linux/sandbox_linux.h",
- "linux/sandbox_seccomp_bpf_linux.cc",
- "linux/sandbox_seccomp_bpf_linux.h",
- ]
- configs += [
- "//media:media_config",
- "//media/audio:platform_config",
- ]
- deps += [
- ":chromecast_sandbox_whitelist_buildflags",
- "//sandbox:sandbox_buildflags",
- "//sandbox/linux:sandbox_services",
- "//sandbox/linux:seccomp_bpf",
- "//sandbox/linux:suid_sandbox_client",
- ]
- }
- if (is_chromeos) {
- 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) {
- sources += [
- "mac/sandbox_mac.h",
- "mac/sandbox_mac.mm",
- ]
- deps += [ "//sandbox/mac:seatbelt" ]
- public_deps += [ "mac:packaged_sb_files" ]
- libs = [
- "AppKit.framework",
- "CoreFoundation.framework",
- "CoreGraphics.framework",
- "Foundation.framework",
- "IOSurface.framework",
- ]
- }
- if (is_win) {
- sources += [
- "win/sandbox_diagnostics.cc",
- "win/sandbox_diagnostics.h",
- "win/sandbox_win.cc",
- "win/sandbox_win.h",
- ]
- deps += [ "//sandbox/win:sandbox" ]
- }
- if (is_fuchsia) {
- sources += [
- "fuchsia/sandbox_policy_fuchsia.cc",
- "fuchsia/sandbox_policy_fuchsia.h",
- ]
-
- public_deps += [
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.io",
- "//third_party/fuchsia-sdk/sdk/pkg/fidl",
- "//third_party/fuchsia-sdk/sdk/pkg/zx",
- ]
-
- deps += [
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.camera3",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.fonts",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.intl",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.logger",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.mediacodec",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.net",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.netstack",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.sysmem",
- "//third_party/fuchsia-sdk/sdk/fidl/fuchsia.ui.scenic",
- ]
- }
-}
-
-buildflag_header("sanitizer_buildflags") {
- header = "sanitizer_buildflags.h"
- flags = [ "USING_SANITIZER=$using_sanitizer" ]
-}
-
-buildflag_header("chromecast_sandbox_whitelist_buildflags") {
- header = "chromecast_sandbox_whitelist_buildflags.h"
- flags = [ "ENABLE_CHROMECAST_GPU_SANDBOX_WHITELIST=$is_chromecast" ]
-}
diff --git a/chromium/services/service_manager/sandbox/DEPS b/chromium/services/service_manager/sandbox/DEPS
deleted file mode 100644
index 804a308655f..00000000000
--- a/chromium/services/service_manager/sandbox/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+sandbox/constants.h",
- "+sandbox",
-]
diff --git a/chromium/services/service_manager/sandbox/OWNERS b/chromium/services/service_manager/sandbox/OWNERS
deleted file mode 100644
index e02183bdf41..00000000000
--- a/chromium/services/service_manager/sandbox/OWNERS
+++ /dev/null
@@ -1,4 +0,0 @@
-set noparent
-file://sandbox/OWNERS
-# COMPONENT: Internals>Sandbox
-# TEAM: security-dev@chromium.org
diff --git a/chromium/services/service_manager/sandbox/export.h b/chromium/services/service_manager/sandbox/export.h
deleted file mode 100644
index 29fa29dfda1..00000000000
--- a/chromium/services/service_manager/sandbox/export.h
+++ /dev/null
@@ -1,29 +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_SANDBOX_EXPORT_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_EXPORT_H_
-
-#if defined(COMPONENT_BUILD)
-#if defined(WIN32)
-
-#if defined(SERVICE_MANAGER_SANDBOX_IMPL)
-#define SERVICE_MANAGER_SANDBOX_EXPORT __declspec(dllexport)
-#else
-#define SERVICE_MANAGER_SANDBOX_EXPORT __declspec(dllimport)
-#endif // defined(SERVICE_MANAGER_SANDBOX_IMPL)
-
-#else // defined(WIN32)
-#if defined(SERVICE_MANAGER_SANDBOX_IMPL)
-#define SERVICE_MANAGER_SANDBOX_EXPORT __attribute__((visibility("default")))
-#else
-#define SERVICE_MANAGER_SANDBOX_EXPORT
-#endif // defined(SERVICE_MANAGER_SANDBOX_IMPL)
-#endif
-
-#else // defined(COMPONENT_BUILD)
-#define SERVICE_MANAGER_SANDBOX_EXPORT
-#endif
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_EXPORT_H_
diff --git a/chromium/services/service_manager/sandbox/features.cc b/chromium/services/service_manager/sandbox/features.cc
deleted file mode 100644
index c29946b6eb8..00000000000
--- a/chromium/services/service_manager/sandbox/features.cc
+++ /dev/null
@@ -1,52 +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/sandbox/features.h"
-
-#include "build/build_config.h"
-
-namespace service_manager {
-namespace features {
-
-// Enables audio service sandbox.
-// (Only causes an effect when feature kAudioServiceOutOfProcess is enabled.)
-const base::Feature kAudioServiceSandbox {
- "AudioServiceSandbox",
-#if defined(OS_WIN) || defined(OS_MACOSX)
- base::FEATURE_ENABLED_BY_DEFAULT
-#else
- base::FEATURE_DISABLED_BY_DEFAULT
-#endif // defined(OS_WIN) || defined(OS_MACOSX)
-};
-
-#if !defined(OS_MACOSX)
-// Enables network service sandbox.
-// (Only causes an effect when feature kNetworkService is enabled.)
-const base::Feature kNetworkServiceSandbox {
- "NetworkServiceSandbox",
- base::FEATURE_DISABLED_BY_DEFAULT
-};
-#endif // !defined(OS_MACOSX)
-
-#if defined(OS_WIN)
-// Emergency "off switch" for new Windows sandbox security mitigation,
-// sandbox::MITIGATION_EXTENSION_POINT_DISABLE.
-const base::Feature kWinSboxDisableExtensionPoints{
- "WinSboxDisableExtensionPoint", base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Enables GPU AppContainer sandbox on Windows.
-const base::Feature kGpuAppContainer{"GpuAppContainer",
- base::FEATURE_DISABLED_BY_DEFAULT};
-
-// Enables GPU Low Privilege AppContainer when combined with kGpuAppContainer.
-const base::Feature kGpuLPAC{"GpuLPAC", base::FEATURE_ENABLED_BY_DEFAULT};
-#endif // defined(OS_WIN)
-
-#if !defined(OS_ANDROID)
-// Controls whether the isolated XR service is sandboxed.
-const base::Feature kXRSandbox{"XRSandbox", base::FEATURE_ENABLED_BY_DEFAULT};
-#endif // !defined(OS_ANDROID)
-
-} // namespace features
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/features.h b/chromium/services/service_manager/sandbox/features.h
deleted file mode 100644
index 86735e2330d..00000000000
--- a/chromium/services/service_manager/sandbox/features.h
+++ /dev/null
@@ -1,39 +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.
-
-// This file defines all the public base::FeatureList features for the content
-// module.
-
-#ifndef SERVICES_SERVICE_MANAGER_SANDBOX_FEATURES_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_FEATURES_H_
-
-#include "base/feature_list.h"
-#include "build/build_config.h"
-#include "services/service_manager/sandbox/export.h"
-
-namespace service_manager {
-namespace features {
-
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature kAudioServiceSandbox;
-
-#if !defined(OS_MACOSX)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature
- kNetworkServiceSandbox;
-#endif
-
-#if defined(OS_WIN)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature
- kWinSboxDisableExtensionPoints;
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature kGpuAppContainer;
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature kGpuLPAC;
-#endif // defined(OS_WIN)
-
-#if !defined(OS_ANDROID)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const base::Feature kXRSandbox;
-#endif // !defined(OS_ANDROID)
-
-} // namespace features
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_FEATURES_H_
diff --git a/chromium/services/service_manager/sandbox/fuchsia/OWNERS b/chromium/services/service_manager/sandbox/fuchsia/OWNERS
deleted file mode 100644
index 7632a21d130..00000000000
--- a/chromium/services/service_manager/sandbox/fuchsia/OWNERS
+++ /dev/null
@@ -1 +0,0 @@
-file://fuchsia/SECURITY_OWNERS
diff --git a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc b/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
deleted file mode 100644
index 0d178b90d10..00000000000
--- a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.cc
+++ /dev/null
@@ -1,284 +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/sandbox/fuchsia/sandbox_policy_fuchsia.h"
-
-#include <lib/fdio/spawn.h>
-#include <stdio.h>
-#include <zircon/processargs.h>
-#include <zircon/syscalls/policy.h>
-
-#include <fuchsia/camera3/cpp/fidl.h>
-#include <fuchsia/fonts/cpp/fidl.h>
-#include <fuchsia/intl/cpp/fidl.h>
-#include <fuchsia/logger/cpp/fidl.h>
-#include <fuchsia/mediacodec/cpp/fidl.h>
-#include <fuchsia/net/cpp/fidl.h>
-#include <fuchsia/netstack/cpp/fidl.h>
-#include <fuchsia/sysmem/cpp/fidl.h>
-#include <fuchsia/ui/scenic/cpp/fidl.h>
-#include <lib/sys/cpp/component_context.h>
-#include <lib/sys/cpp/service_directory.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/base_paths_fuchsia.h"
-#include "base/command_line.h"
-#include "base/containers/span.h"
-#include "base/files/file_util.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"
-#include "base/threading/thread_task_runner_handle.h"
-#include "services/service_manager/sandbox/switches.h"
-
-namespace service_manager {
-namespace {
-
-enum SandboxFeature {
- // Clones the job. This is required to start new processes (to make it useful
- // the process will also need access to the fuchsia.process.Launcher service).
- kCloneJob = 1 << 0,
-
- // Provides access to resources required by Vulkan.
- kProvideVulkanResources = 1 << 1,
-
- // Read only access to /config/ssl, which contains root certs info.
- kProvideSslConfig = 1 << 2,
-
- // Uses a service directory channel that is explicitly passed by the caller
- // instead of automatically connecting to the service directory of the current
- // process' namespace. Intended for use by SandboxType::kWebContext.
- kUseServiceDirectoryOverride = 1 << 3,
-
- // Allows the process to use the ambient mark-vmo-as-executable capability.
- kAmbientMarkVmoAsExecutable = 1 << 4,
-};
-
-struct SandboxConfig {
- base::span<const char* const> services;
- uint32_t features;
-};
-
-constexpr SandboxConfig kWebContextConfig = {
- // Services directory is passed by calling SetServiceDirectory().
- base::span<const char* const>(),
-
- // Context processes only actually use the kUseServiceDirectoryOverride
- // and kCloneJob |features| themselves. However, they must be granted
- // all of the other features to delegate to child processes.
- kCloneJob | kProvideVulkanResources | kProvideSslConfig |
- kAmbientMarkVmoAsExecutable | kUseServiceDirectoryOverride,
-};
-
-constexpr SandboxConfig kGpuConfig = {
- base::make_span((const char* const[]){
- fuchsia::sysmem::Allocator::Name_,
- "fuchsia.vulkan.loader.Loader",
- fuchsia::ui::scenic::Scenic::Name_,
- }),
- kProvideVulkanResources,
-};
-
-constexpr SandboxConfig kNetworkConfig = {
- base::make_span((const char* const[]){
- fuchsia::net::NameLookup::Name_,
- fuchsia::netstack::Netstack::Name_,
- "fuchsia.posix.socket.Provider",
- }),
- kProvideSslConfig,
-};
-
-constexpr SandboxConfig kRendererConfig = {
- base::make_span((const char* const[]){
- fuchsia::fonts::Provider::Name_,
- fuchsia::mediacodec::CodecFactory::Name_,
- fuchsia::sysmem::Allocator::Name_,
- }),
- kAmbientMarkVmoAsExecutable,
-};
-
-constexpr SandboxConfig kVideoCaptureConfig = {
- base::make_span((const char* const[]){
- fuchsia::camera3::DeviceWatcher::Name_,
- fuchsia::sysmem::Allocator::Name_,
- }),
- 0,
-};
-
-// No-access-to-anything.
-constexpr SandboxConfig kEmptySandboxConfig = {
- base::span<const char* const>(),
- 0,
-};
-
-const SandboxConfig* GetConfigForSandboxType(SandboxType type) {
- switch (type) {
- case SandboxType::kNoSandbox:
- return nullptr;
- case SandboxType::kGpu:
- return &kGpuConfig;
- case SandboxType::kNetwork:
- return &kNetworkConfig;
- case SandboxType::kRenderer:
- return &kRendererConfig;
- case SandboxType::kWebContext:
- return &kWebContextConfig;
- case SandboxType::kVideoCapture:
- return &kVideoCaptureConfig;
- // Remaining types receive no-access-to-anything.
- case SandboxType::kAudio:
- case SandboxType::kCdm:
- case SandboxType::kPpapi:
- case SandboxType::kPrintCompositor:
- case SandboxType::kSharingService:
- case SandboxType::kSpeechRecognition:
- case SandboxType::kUtility:
- return &kEmptySandboxConfig;
- }
-}
-
-// Services that are passed to all processes.
-constexpr base::span<const char* const> kDefaultServices = base::make_span(
- (const char* const[]){fuchsia::intl::PropertyProvider::Name_,
- fuchsia::logger::LogSink::Name_});
-
-} // namespace
-
-SandboxPolicyFuchsia::SandboxPolicyFuchsia(service_manager::SandboxType type) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- service_manager::switches::kNoSandbox)) {
- type_ = service_manager::SandboxType::kNoSandbox;
- } else {
- type_ = type;
- }
- // If we need to pass some services for the given sandbox type then create
- // |sandbox_directory_| and initialize it with the corresponding list of
- // services. FilteredServiceDirectory must be initialized on a thread that has
- // async_dispatcher.
- const SandboxConfig* config = GetConfigForSandboxType(type_);
- if (config && !(config->features & kUseServiceDirectoryOverride)) {
- service_directory_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- service_directory_ =
- std::make_unique<base::fuchsia::FilteredServiceDirectory>(
- base::ComponentContextForProcess()->svc().get());
- for (const char* service_name : kDefaultServices) {
- service_directory_->AddService(service_name);
- }
- for (const char* service_name : config->services) {
- service_directory_->AddService(service_name);
- }
- // Bind the service directory and store the client channel for
- // UpdateLaunchOptionsForSandbox()'s use.
- service_directory_->ConnectClient(service_directory_client_.NewRequest());
- CHECK(service_directory_client_);
- }
-}
-
-SandboxPolicyFuchsia::~SandboxPolicyFuchsia() {
- if (service_directory_) {
- service_directory_task_runner_->DeleteSoon(FROM_HERE,
- std::move(service_directory_));
- }
-}
-
-void SandboxPolicyFuchsia::SetServiceDirectory(
- fidl::InterfaceHandle<::fuchsia::io::Directory> service_directory_client) {
- DCHECK(GetConfigForSandboxType(type_)->features &
- kUseServiceDirectoryOverride);
- DCHECK(!service_directory_client_);
-
- service_directory_client_ = std::move(service_directory_client);
-}
-
-void SandboxPolicyFuchsia::UpdateLaunchOptionsForSandbox(
- base::LaunchOptions* options) {
-
- // Always clone stderr to get logs output.
- options->fds_to_remap.push_back(std::make_pair(STDERR_FILENO, STDERR_FILENO));
- options->fds_to_remap.push_back(std::make_pair(STDOUT_FILENO, STDOUT_FILENO));
-
- if (type_ == service_manager::SandboxType::kNoSandbox) {
- options->spawn_flags = FDIO_SPAWN_CLONE_NAMESPACE | FDIO_SPAWN_CLONE_JOB;
- options->clear_environment = false;
- return;
- }
-
- // Map /pkg (read-only files deployed from the package) into the child's
- // namespace.
- base::FilePath package_root;
- base::PathService::Get(base::DIR_ASSETS, &package_root);
- options->paths_to_clone.push_back(package_root);
-
- // If /config/data/tzdata/icu/ exists then it contains up-to-date timezone
- // data which should be provided to all sub-processes, for consistency.
- const auto kIcuTimezoneDataPath = base::FilePath("/config/data/tzdata/icu");
- static bool icu_timezone_data_exists = base::PathExists(kIcuTimezoneDataPath);
- if (icu_timezone_data_exists)
- options->paths_to_clone.push_back(kIcuTimezoneDataPath);
-
- // Clear environmental variables to better isolate the child from
- // this process.
- options->clear_environment = true;
-
- // Don't clone anything by default.
- options->spawn_flags = 0;
-
- // Must get a config here as --no-sandbox bails out earlier.
- const SandboxConfig* config = GetConfigForSandboxType(type_);
- CHECK(config);
-
- if (config->features & kCloneJob)
- options->spawn_flags |= FDIO_SPAWN_CLONE_JOB;
-
- if (config->features & kProvideSslConfig)
- options->paths_to_clone.push_back(base::FilePath("/config/ssl"));
-
- if (config->features & kProvideVulkanResources) {
- // /dev/class/gpu and /config/vulkan/icd.d are to used configure and
- // access the GPU.
- options->paths_to_clone.push_back(base::FilePath("/dev/class/gpu"));
- const auto vulkan_icd_path = base::FilePath("/config/vulkan/icd.d");
- if (base::PathExists(vulkan_icd_path))
- options->paths_to_clone.push_back(vulkan_icd_path);
-
- // /dev/class/goldfish-pipe, /dev/class/goldfish-address-space and
- // /dev/class/goldfish-control are used for Fuchsia Emulator.
- options->paths_to_clone.insert(
- options->paths_to_clone.end(),
- {base::FilePath("/dev/class/goldfish-pipe"),
- base::FilePath("/dev/class/goldfish-control"),
- base::FilePath("/dev/class/goldfish-address-space")});
- }
-
- // If the process needs access to any services then transfer the
- // |service_directory_client_| handle for it to mount at "/svc".
- if (service_directory_client_) {
- options->paths_to_transfer.push_back(base::PathToTransfer{
- base::FilePath("/svc"),
- service_directory_client_.TakeChannel().release()});
- }
-
- // Isolate the child process from the call by launching it in its own job.
- zx_status_t status = zx::job::create(*base::GetDefaultJob(), 0, &job_);
- ZX_CHECK(status == ZX_OK, status) << "zx_job_create";
- options->job_handle = job_.get();
-
- // Do not allow ambient VMO mark-as-executable capability to be inherited
- // by processes that do not need to JIT (i.e. do not run V8/WASM).
- if (!(config->features & kAmbientMarkVmoAsExecutable)) {
- zx_policy_basic_v2_t deny_ambient_mark_vmo_exec{
- ZX_POL_AMBIENT_MARK_VMO_EXEC, ZX_POL_ACTION_KILL, ZX_POL_OVERRIDE_DENY};
- status = job_.set_policy(ZX_JOB_POL_RELATIVE, ZX_JOB_POL_BASIC_V2,
- &deny_ambient_mark_vmo_exec, 1);
- ZX_CHECK(status == ZX_OK, status) << "zx_job_set_policy";
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h b/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h
deleted file mode 100644
index 7811581aba7..00000000000
--- a/chromium/services/service_manager/sandbox/fuchsia/sandbox_policy_fuchsia.h
+++ /dev/null
@@ -1,62 +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_SANDBOX_FUCHSIA_SANDBOX_POLICY_FUCHSIA_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_FUCHSIA_SANDBOX_POLICY_FUCHSIA_H_
-
-#include <fuchsia/io/cpp/fidl.h>
-#include <lib/fidl/cpp/interface_handle.h>
-#include <lib/zx/job.h>
-
-#include "base/memory/ref_counted.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-namespace base {
-struct LaunchOptions;
-class SequencedTaskRunner;
-
-namespace fuchsia {
-class FilteredServiceDirectory;
-} // namespace fuchsia
-
-} // namespace base
-
-namespace service_manager {
-
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxPolicyFuchsia {
- public:
- // Must be called on the IO thread.
- explicit SandboxPolicyFuchsia(service_manager::SandboxType type);
- ~SandboxPolicyFuchsia();
-
- // Sets the service directory to pass to the child process when launching it.
- // This is only supported for SandboxType::kWebContext processes. If this is
- // not called for a WEB_CONTEXT process then it will receive no services.
- void SetServiceDirectory(
- fidl::InterfaceHandle<::fuchsia::io::Directory> service_directory_client);
-
- // Modifies the process launch |options| to achieve the level of
- // isolation appropriate for current the sandbox type. The caller may then add
- // any descriptors or handles afterward to grant additional capabilities
- // to the new process.
- void UpdateLaunchOptionsForSandbox(base::LaunchOptions* options);
-
- private:
- service_manager::SandboxType type_;
-
- // Services directory used for the /svc namespace of the child process.
- std::unique_ptr<base::fuchsia::FilteredServiceDirectory> service_directory_;
- fidl::InterfaceHandle<::fuchsia::io::Directory> service_directory_client_;
- scoped_refptr<base::SequencedTaskRunner> service_directory_task_runner_;
-
- // Job in which the child process is launched.
- zx::job job_;
-
- DISALLOW_COPY_AND_ASSIGN(SandboxPolicyFuchsia);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_FUCHSIA_SANDBOX_POLICY_FUCHSIA_H_
diff --git a/chromium/services/service_manager/sandbox/linux/OWNERS b/chromium/services/service_manager/sandbox/linux/OWNERS
deleted file mode 100644
index 57df6dc7ec4..00000000000
--- a/chromium/services/service_manager/sandbox/linux/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-file://sandbox/linux/OWNERS
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.cc
deleted file mode 100644
index dca79767558..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.cc
+++ /dev/null
@@ -1,138 +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.
-
-#include "services/service_manager/sandbox/linux/bpf_audio_policy_linux.h"
-
-#include <sys/socket.h>
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/services/syscall_wrappers.h"
-#include "sandbox/linux/syscall_broker/broker_process.h"
-#include "sandbox/linux/system_headers/linux_futex.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::Arg;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::If;
-using sandbox::bpf_dsl::ResultExpr;
-using sandbox::bpf_dsl::Trap;
-using sandbox::syscall_broker::BrokerProcess;
-
-namespace service_manager {
-
-AudioProcessPolicy::AudioProcessPolicy() = default;
-
-AudioProcessPolicy::~AudioProcessPolicy() = default;
-
-ResultExpr AudioProcessPolicy::EvaluateSyscall(int system_call_number) const {
- switch (system_call_number) {
-#if defined(__NR_connect)
- case __NR_connect:
-#endif
-#if defined(__NR_ftruncate)
- case __NR_ftruncate:
-#endif
-#if defined(__NR_ftruncate64)
- case __NR_ftruncate64:
-#endif
-#if defined(__NR_fallocate)
- case __NR_fallocate:
-#endif
-#if defined(__NR_getdents)
- case __NR_getdents:
-#endif
-#if defined(__NR_getpeername)
- case __NR_getpeername:
-#endif
-#if defined(__NR_getsockopt)
- case __NR_getsockopt:
-#endif
-#if defined(__NR_getsockname)
- case __NR_getsockname:
-#endif
-#if defined(__NR_ioctl)
- case __NR_ioctl:
-#endif
-#if defined(__NR_memfd_create)
- case __NR_memfd_create:
-#endif
-#if defined(__NR_pwrite)
- case __NR_pwrite:
-#endif
-#if defined(__NR_pwrite64)
- case __NR_pwrite64:
-#endif
-#if defined(__NR_sched_setscheduler)
- case __NR_sched_setscheduler:
-#endif
-#if defined(__NR_setsockopt)
- case __NR_setsockopt:
-#endif
-#if defined(__NR_uname)
- case __NR_uname:
-#endif
- return Allow();
-#if defined(__NR_futex)
- case __NR_futex: {
- const Arg<int> op(1);
-#if defined(USE_PULSEAUDIO)
- return Switch(op & ~FUTEX_PRIVATE_FLAG)
- .SANDBOX_BPF_DSL_CASES(
- (FUTEX_CMP_REQUEUE, FUTEX_LOCK_PI, FUTEX_UNLOCK_PI, FUTEX_WAIT,
- FUTEX_WAIT_BITSET, FUTEX_WAKE),
- Allow())
- .Default(Error(EPERM));
-#else
- return sandbox::RestrictFutex();
-#endif
- }
-#endif
-#if defined(__NR_kill)
- case __NR_kill: {
- // man kill says:
- // "If sig is 0, then no signal is sent, but existence and permission
- // checks are still performed; this can be used to check for the
- // existence of a process ID or process group ID that the caller is
- // permitted to signal."
- //
- // This seems to be tripping up at least ESET's NOD32 anti-virus, causing
- // an unnecessary crash in the audio process. See: http://crbug.com/904787
- const Arg<pid_t> pid(0);
- const Arg<int> sig(1);
- return If(pid == sandbox::sys_getpid(), Allow())
- .ElseIf(sig == 0, Error(EPERM))
- .Else(sandbox::CrashSIGSYSKill());
- }
-#endif
-#if defined(__NR_socket)
- case __NR_socket: {
- const Arg<int> domain(0);
- return If(domain == AF_UNIX, Allow()).Else(Error(EPERM));
- }
-#endif
- default:
-#if defined(__x86_64__)
- if (sandbox::SyscallSets::IsSystemVSemaphores(system_call_number) ||
- sandbox::SyscallSets::IsSystemVSharedMemory(system_call_number)) {
- return Allow();
- }
-#elif defined(__i386__)
- if (sandbox::SyscallSets::IsSystemVIpc(system_call_number))
- return Allow();
-#endif
-
- auto* broker_process = SandboxLinux::GetInstance()->broker_process();
- if (broker_process->IsSyscallAllowed(system_call_number))
- return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
-
- return BPFBasePolicy::EvaluateSyscall(system_call_number);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.h
deleted file mode 100644
index afbab1f9e8c..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_audio_policy_linux.h
+++ /dev/null
@@ -1,28 +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.
-
-#ifndef SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_AUDIO_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_AUDIO_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 AudioProcessPolicy : public BPFBasePolicy {
- public:
- AudioProcessPolicy();
- ~AudioProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(AudioProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_AUDIO_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.cc
deleted file mode 100644
index 687f648aa79..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.cc
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright 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.
-
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-#include <errno.h>
-
-#include "base/check.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-namespace {
-
-// The errno used for denied file system access system calls, such as open(2).
-static const int kFSDeniedErrno = EPERM;
-
-} // namespace.
-
-BPFBasePolicy::BPFBasePolicy()
- : baseline_policy_(new sandbox::BaselinePolicy(kFSDeniedErrno)) {}
-BPFBasePolicy::~BPFBasePolicy() {}
-
-ResultExpr BPFBasePolicy::EvaluateSyscall(int system_call_number) const {
- DCHECK(baseline_policy_);
-
- // set_robust_list(2) is part of the futex(2) infrastructure.
- // Chrome on Linux/Chrome OS will call set_robust_list(2) frequently.
- // The baseline policy will EPERM set_robust_list(2), but on systems with
- // SECCOMP logs enabled in auditd this will cause a ton of logspam.
- // If we're not blocking the entire futex(2) infrastructure, we should allow
- // set_robust_list(2) and quiet the logspam.
- if (system_call_number == __NR_set_robust_list) {
- return Allow();
- }
-
- return baseline_policy_->EvaluateSyscall(system_call_number);
-}
-
-ResultExpr BPFBasePolicy::InvalidSyscall() const {
- DCHECK(baseline_policy_);
- return baseline_policy_->InvalidSyscall();
-}
-
-int BPFBasePolicy::GetFSDeniedErrno() {
- return kFSDeniedErrno;
-}
-
-} // namespace service_manager.
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.h
deleted file mode 100644
index 8cae3526097..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_base_policy_linux.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright 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_SANDBOX_LINUX_BPF_BASE_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_BASE_POLICY_LINUX_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl_forward.h"
-#include "sandbox/linux/bpf_dsl/policy.h"
-#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
-#include "services/service_manager/sandbox/export.h"
-
-namespace service_manager {
-
-// The "baseline" BPF policy. Any other seccomp-bpf policy should inherit
-// from it.
-// It implements the main Policy interface. Due to its nature
-// as a "kernel attack surface reduction" layer, it's implementation-defined.
-class SERVICE_MANAGER_SANDBOX_EXPORT BPFBasePolicy
- : public sandbox::bpf_dsl::Policy {
- public:
- BPFBasePolicy();
- ~BPFBasePolicy() override;
-
- // sandbox::bpf_dsl::Policy:
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
- sandbox::bpf_dsl::ResultExpr InvalidSyscall() const override;
-
- // Get the errno(3) to return for filesystem errors.
- static int GetFSDeniedErrno();
-
- pid_t GetPolicyPid() const { return baseline_policy_->policy_pid(); }
-
- private:
- // Compose the BaselinePolicy from sandbox/.
- std::unique_ptr<sandbox::BaselinePolicy> baseline_policy_;
- DISALLOW_COPY_AND_ASSIGN(BPFBasePolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_BASE_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.cc
deleted file mode 100644
index 68af74e1fba..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.cc
+++ /dev/null
@@ -1,149 +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/sandbox/linux/bpf_broker_policy_linux.h"
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-BrokerProcessPolicy::BrokerProcessPolicy(
- const sandbox::syscall_broker::BrokerCommandSet& allowed_command_set)
- : allowed_command_set_(allowed_command_set) {}
-
-BrokerProcessPolicy::~BrokerProcessPolicy() {}
-
-ResultExpr BrokerProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
-#if defined(__NR_access)
- case __NR_access:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_ACCESS))
- return Allow();
- break;
-#endif
-#if defined(__NR_faccessat)
- case __NR_faccessat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_ACCESS))
- return Allow();
- break;
-#endif
-#if defined(__NR_mkdir)
- case __NR_mkdir:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_MKDIR))
- return Allow();
- break;
-#endif
-#if defined(__NR_mkdirat)
- case __NR_mkdirat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_MKDIR))
- return Allow();
- break;
-#endif
-#if defined(__NR_open)
- case __NR_open:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_OPEN))
- return Allow();
- break;
-#endif
-#if defined(__NR_openat)
- case __NR_openat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_OPEN))
- return Allow();
- break;
-#endif
-#if defined(__NR_rename)
- case __NR_rename:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_RENAME))
- return Allow();
- break;
-#endif
-#if defined(__NR_renameat)
- case __NR_renameat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_RENAME))
- return Allow();
- break;
-#endif
-#if defined(__NR_stat)
- case __NR_stat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_stat64)
- case __NR_stat64:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_lstat)
- case __NR_lstat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_lstat64)
- case __NR_lstat64:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_fstatat)
- case __NR_fstatat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_newfstatat)
- case __NR_newfstatat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_STAT))
- return Allow();
- break;
-#endif
-#if defined(__NR_readlink)
- case __NR_readlink:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_READLINK))
- return Allow();
- break;
-#endif
-#if defined(__NR_readlinkat)
- case __NR_readlinkat:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_READLINK))
- return Allow();
- break;
-#endif
-#if defined(__NR_rmdir)
- case __NR_rmdir:
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_RMDIR))
- return Allow();
- break;
-#endif
-#if defined(__NR_unlink)
- case __NR_unlink:
- // NOTE: Open() uses unlink() to make "temporary" files.
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_OPEN) ||
- allowed_command_set_.test(sandbox::syscall_broker::COMMAND_UNLINK)) {
- return Allow();
- }
- break;
-#endif
-#if defined(__NR_unlinkat)
- case __NR_unlinkat:
- // NOTE: Open() uses unlink() to make "temporary" files.
- if (allowed_command_set_.test(sandbox::syscall_broker::COMMAND_OPEN) ||
- allowed_command_set_.test(sandbox::syscall_broker::COMMAND_UNLINK)) {
- return Allow();
- }
- break;
-#endif
- default:
- break;
- }
- return BPFBasePolicy::EvaluateSyscall(sysno);
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.h
deleted file mode 100644
index 8299a3a3b06..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_broker_policy_linux.h
+++ /dev/null
@@ -1,35 +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_SANDBOX_LINUX_BPF_BROKER_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_BROKER_POLICY_LINUX_H_
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/syscall_broker/broker_command.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// A broker policy is one for a privileged syscall broker that allows
-// access, open, openat, and (in the non-Chrome OS case) unlink.
-class SERVICE_MANAGER_SANDBOX_EXPORT BrokerProcessPolicy
- : public BPFBasePolicy {
- public:
- explicit BrokerProcessPolicy(
- const sandbox::syscall_broker::BrokerCommandSet& allowed_command_set);
- ~BrokerProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- const sandbox::syscall_broker::BrokerCommandSet allowed_command_set_;
-
- DISALLOW_COPY_AND_ASSIGN(BrokerProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_BROKER_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.cc
deleted file mode 100644
index 9d39e5d5de4..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.cc
+++ /dev/null
@@ -1,56 +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/sandbox/linux/bpf_cdm_policy_linux.h"
-
-#include <errno.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-CdmProcessPolicy::CdmProcessPolicy() {}
-CdmProcessPolicy::~CdmProcessPolicy() {}
-
-ResultExpr CdmProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- case __NR_ioctl:
- return sandbox::RestrictIoctl();
- // Allow the system calls below.
- case __NR_fdatasync:
- case __NR_fsync:
- case __NR_ftruncate:
- case __NR_fallocate:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // https://crbug.com/546204
- case __NR_pwrite64:
- case __NR_sysinfo:
- case __NR_times:
- case __NR_uname:
- return Allow();
- case __NR_sched_getaffinity:
- return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
- default:
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.h
deleted file mode 100644
index ea07367a600..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cdm_policy_linux.h
+++ /dev/null
@@ -1,28 +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_SANDBOX_LINUX_BPF_CDM_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CDM_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// This policy can be used by the process hosting a Content Decryption Module.
-class CdmProcessPolicy : public BPFBasePolicy {
- public:
- CdmProcessPolicy();
- ~CdmProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CdmProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CDM_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.cc
deleted file mode 100644
index 56233eeace4..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/kcmp.h>
-#include <sys/socket.h>
-
-// Some arch's (arm64 for instance) unistd.h don't pull in symbols used here
-// unless these are defined.
-#define __ARCH_WANT_SYSCALL_NO_AT
-#define __ARCH_WANT_SYSCALL_DEPRECATED
-#include <unistd.h>
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-
-using sandbox::bpf_dsl::AllOf;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Arg;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::If;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-CrosAmdGpuProcessPolicy::CrosAmdGpuProcessPolicy() {}
-
-CrosAmdGpuProcessPolicy::~CrosAmdGpuProcessPolicy() {}
-
-ResultExpr CrosAmdGpuProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- case __NR_fstatfs:
- case __NR_sched_setscheduler:
- case __NR_sysinfo:
- case __NR_uname:
-#if !defined(__aarch64__)
- case __NR_readlink:
- case __NR_stat:
-#endif
- return Allow();
-#if defined(__x86_64__)
- // Allow only AF_UNIX for |domain|.
- case __NR_socket:
- case __NR_socketpair: {
- const Arg<int> domain(0);
- return If(domain == AF_UNIX, Allow()).Else(Error(EPERM));
- }
-#endif
- case __NR_kcmp: {
- const Arg<int> pid1(0);
- const Arg<int> pid2(1);
- const Arg<int> type(2);
- const int policy_pid = GetPolicyPid();
- // Only allowed when comparing file handles for the calling thread.
- return If(AllOf(pid1 == policy_pid, pid2 == policy_pid,
- type == KCMP_FILE),
- Allow())
- .Else(Error(EPERM));
- }
- default:
- // Default to the generic GPU policy.
- return GpuProcessPolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h
deleted file mode 100644
index 23980dc67e2..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h
+++ /dev/null
@@ -1,30 +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_SANDBOX_LINUX_BPF_CROS_AMD_GPU_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CROS_AMD_GPU_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_gpu_policy_linux.h"
-
-namespace service_manager {
-
-// This policy is for AMD GPUs running on Chrome OS.
-class SERVICE_MANAGER_SANDBOX_EXPORT CrosAmdGpuProcessPolicy
- : public GpuProcessPolicy {
- public:
- CrosAmdGpuProcessPolicy();
- ~CrosAmdGpuProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(CrosAmdGpuProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CROS_AMD_GPU_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.cc
deleted file mode 100644
index cecd679785f..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.cc
+++ /dev/null
@@ -1,67 +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.
-
-#include "services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h"
-
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h"
-
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Arg;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::If;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-CrosArmGpuProcessPolicy::CrosArmGpuProcessPolicy(bool allow_shmat)
-#if defined(__arm__) || defined(__aarch64__)
- : allow_shmat_(allow_shmat)
-#endif
-{
-}
-
-CrosArmGpuProcessPolicy::~CrosArmGpuProcessPolicy() {}
-
-ResultExpr CrosArmGpuProcessPolicy::EvaluateSyscall(int sysno) const {
-#if defined(__arm__) || defined(__aarch64__)
- if (allow_shmat_ && sysno == __NR_shmat)
- return Allow();
-#endif // defined(__arm__) || defined(__aarch64__)
-
- switch (sysno) {
-#if defined(__arm__) || defined(__aarch64__)
- // ARM GPU sandbox is started earlier so we need to allow networking
- // in the sandbox.
- case __NR_connect:
- case __NR_getpeername:
- case __NR_getsockname:
- case __NR_sysinfo:
- case __NR_uname:
- return Allow();
- // Allow only AF_UNIX for |domain|.
- case __NR_socket:
- case __NR_socketpair: {
- const Arg<int> domain(0);
- return If(domain == AF_UNIX, Allow()).Else(Error(EPERM));
- }
-#endif // defined(__arm__) || defined(__aarch64__)
- default:
- // Default to the generic GPU policy.
- return GpuProcessPolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h
deleted file mode 100644
index 36b8b9c9619..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 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_SANDBOX_LINUX_BPF_CROS_ARM_GPU_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CROS_ARM_GPU_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_gpu_policy_linux.h"
-
-namespace service_manager {
-
-// This policy is for Chrome OS ARM.
-class SERVICE_MANAGER_SANDBOX_EXPORT CrosArmGpuProcessPolicy
- : public GpuProcessPolicy {
- public:
- explicit CrosArmGpuProcessPolicy(bool allow_shmat);
- ~CrosArmGpuProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
-#if defined(__arm__) || defined(__aarch64__)
- const bool allow_shmat_; // Allow shmat(2).
-#endif
- DISALLOW_COPY_AND_ASSIGN(CrosArmGpuProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_CROS_ARM_GPU_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.cc
deleted file mode 100644
index d658059a294..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.cc
+++ /dev/null
@@ -1,93 +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.
-
-#include "services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/syscall_broker/broker_process.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::ResultExpr;
-using sandbox::bpf_dsl::Trap;
-using sandbox::syscall_broker::BrokerProcess;
-
-namespace service_manager {
-
-GpuProcessPolicy::GpuProcessPolicy() {}
-
-GpuProcessPolicy::~GpuProcessPolicy() {}
-
-// Main policy for x86_64/i386. Extended by CrosArmGpuProcessPolicy.
-ResultExpr GpuProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
-#if defined(OS_CHROMEOS)
- case __NR_memfd_create:
-#else // !defined(OS_CHROMEOS)
- case __NR_fallocate:
-#endif // defined(OS_CHROMEOS)
- case __NR_ftruncate:
-#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
- case __NR_ftruncate64:
-#endif
-#if !defined(__aarch64__)
- case __NR_getdents:
-#endif
- case __NR_getdents64:
- case __NR_ioctl:
- return Allow();
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__)
- // The Nvidia driver uses flags not in the baseline policy
- // (MAP_LOCKED | MAP_EXECUTABLE | MAP_32BIT)
- case __NR_mmap:
-#endif
- // We also hit this on the linux_chromeos bot but don't yet know what
- // weird flags were involved.
- case __NR_mprotect:
- // TODO(jln): restrict prctl.
- case __NR_prctl:
- case __NR_sysinfo:
- case __NR_uname: // https://crbug.com/1075934
- return Allow();
- case __NR_sched_getaffinity:
- case __NR_sched_setaffinity:
- return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
- case __NR_prlimit64:
- return sandbox::RestrictPrlimit64(GetPolicyPid());
- default:
- if (SyscallSets::IsEventFd(sysno))
- return Allow();
-
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_X11)
- if (SyscallSets::IsSystemVSharedMemory(sysno))
- return Allow();
-#endif
-
- auto* broker_process = SandboxLinux::GetInstance()->broker_process();
- if (broker_process->IsSyscallAllowed(sysno)) {
- return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
- }
-
- // Default on the baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h
deleted file mode 100644
index c1091816681..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 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_SANDBOX_LINUX_BPF_GPU_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_GPU_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 GpuProcessPolicy : public BPFBasePolicy {
- public:
- GpuProcessPolicy();
- ~GpuProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(GpuProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_GPU_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.cc
deleted file mode 100644
index a3f79ee6370..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.cc
+++ /dev/null
@@ -1,49 +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.
-
-#include "services/service_manager/sandbox/linux/bpf_ime_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 {
-
-ImeProcessPolicy::ImeProcessPolicy() {}
-
-ImeProcessPolicy::~ImeProcessPolicy() {}
-
-ResultExpr ImeProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
-#if defined(__NR_uname)
- case __NR_uname:
-#endif
-#if defined(__NR_clock_gettime)
- case __NR_clock_gettime:
-#endif
- return Allow();
-// https://crbug.com/991435
-#if defined(__NR_getrusage)
- case __NR_getrusage:
- return sandbox::RestrictGetrusage();
-#endif
- default:
- 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_ime_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.h
deleted file mode 100644
index d9a8cd36522..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_ime_policy_linux.h
+++ /dev/null
@@ -1,27 +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.
-
-#ifndef SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_IME_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_IME_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 ImeProcessPolicy : public BPFBasePolicy {
- public:
- ImeProcessPolicy();
- ~ImeProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(int sysno) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ImeProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_IME_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.cc
deleted file mode 100644
index 201a6b371c0..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.cc
+++ /dev/null
@@ -1,44 +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/sandbox/linux/bpf_network_policy_linux.h"
-
-#include <fcntl.h>
-#include <unistd.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/syscall_broker/broker_file_permission.h"
-#include "sandbox/linux/syscall_broker/broker_process.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_seccomp_bpf_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 {
-
-NetworkProcessPolicy::NetworkProcessPolicy() {}
-
-NetworkProcessPolicy::~NetworkProcessPolicy() {}
-
-ResultExpr NetworkProcessPolicy::EvaluateSyscall(int sysno) const {
- auto* broker_process = SandboxLinux::GetInstance()->broker_process();
- if (broker_process->IsSyscallAllowed(sysno)) {
- return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
- }
-
- // TODO(tsepez): FIX this.
- return Allow();
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.h
deleted file mode 100644
index f5322058f05..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_network_policy_linux.h
+++ /dev/null
@@ -1,29 +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_SANDBOX_LINUX_BPF_NETWORK_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_NETWORK_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 NetworkProcessPolicy
- : public BPFBasePolicy {
- public:
- NetworkProcessPolicy();
- ~NetworkProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NetworkProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_NETWORK_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.cc
deleted file mode 100644
index 7e9c64ddb57..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright 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.
-
-#include "services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h"
-
-#include <errno.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-PpapiProcessPolicy::PpapiProcessPolicy() {}
-PpapiProcessPolicy::~PpapiProcessPolicy() {}
-
-ResultExpr PpapiProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- // TODO(jln): restrict prctl.
- case __NR_prctl:
- case __NR_pwrite64:
- case __NR_sched_get_priority_max:
- case __NR_sched_get_priority_min:
- case __NR_sysinfo:
- case __NR_times:
- return Allow();
- case __NR_sched_getaffinity:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_setscheduler:
- return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
- case __NR_ioctl:
- return Error(ENOTTY); // Flash Access.
- default:
- // Default on the baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h
deleted file mode 100644
index 103b33e69e8..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 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_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// Policy for Pepper plugins such as Flash.
-class PpapiProcessPolicy : public BPFBasePolicy {
- public:
- PpapiProcessPolicy();
- ~PpapiProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PpapiProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_PPAPI_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.cc
deleted file mode 100644
index df978881f80..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.cc
+++ /dev/null
@@ -1,54 +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/sandbox/linux/bpf_print_compositor_policy_linux.h"
-
-#include <errno.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-PrintCompositorProcessPolicy::PrintCompositorProcessPolicy() {}
-PrintCompositorProcessPolicy::~PrintCompositorProcessPolicy() {}
-
-ResultExpr PrintCompositorProcessPolicy::EvaluateSyscall(int sysno) const {
- // TODO(weili): the current set of policy is exactly same as utility process
- // policy. Check whether we can trim further.
- switch (sysno) {
- case __NR_ioctl:
- return sandbox::RestrictIoctl();
- // Allow the system calls below.
- case __NR_fdatasync:
- case __NR_fsync:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // https://crbug.com/546204
- case __NR_pwrite64:
- case __NR_sysinfo:
- case __NR_times:
- case __NR_uname:
- return Allow();
- default:
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.h
deleted file mode 100644
index f6617c35027..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.h
+++ /dev/null
@@ -1,28 +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_SANDBOX_LINUX_BPF_PRINT_COMPOSITOR_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_PRINT_COMPOSITOR_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// This policy can be used by print compositor utility processes.
-class PrintCompositorProcessPolicy : public BPFBasePolicy {
- public:
- PrintCompositorProcessPolicy();
- ~PrintCompositorProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PrintCompositorProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_PRINT_COMPOSITOR_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc
deleted file mode 100644
index a85c0ea8678..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.cc
+++ /dev/null
@@ -1,111 +0,0 @@
-// Copyright 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.
-
-#include "services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h"
-
-#include <errno.h>
-#include <sys/ioctl.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-// TODO(vignatti): replace the local definitions below with #include
-// <linux/dma-buf.h> once kernel version 4.6 becomes widely used.
-#include <linux/types.h>
-
-struct local_dma_buf_sync {
- __u64 flags;
-};
-#define LOCAL_DMA_BUF_BASE 'b'
-#define LOCAL_DMA_BUF_IOCTL_SYNC \
- _IOW(LOCAL_DMA_BUF_BASE, 0, struct local_dma_buf_sync)
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Arg;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-namespace {
-
-ResultExpr RestrictIoctl() {
- const Arg<unsigned long> request(1);
- return Switch(request)
- .SANDBOX_BPF_DSL_CASES((static_cast<unsigned long>(TCGETS), FIONREAD),
- Allow())
- .SANDBOX_BPF_DSL_CASES(
- (static_cast<unsigned long>(LOCAL_DMA_BUF_IOCTL_SYNC)), Allow())
- .Default(sandbox::CrashSIGSYSIoctl());
-}
-
-} // namespace
-
-RendererProcessPolicy::RendererProcessPolicy() {}
-RendererProcessPolicy::~RendererProcessPolicy() {}
-
-ResultExpr RendererProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- // The baseline policy allows __NR_clock_gettime. Allow
- // clock_getres() for V8. crbug.com/329053.
- case __NR_clock_getres:
- return sandbox::RestrictClockID();
- case __NR_ioctl:
- return RestrictIoctl();
- // Allow the system calls below.
- case __NR_fdatasync:
- case __NR_fsync:
- case __NR_ftruncate:
-#if defined(__i386__) || defined(__arm__) || \
- (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
- case __NR_ftruncate64:
-#endif
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
- case __NR_getrlimit:
- case __NR_setrlimit:
-// We allow setrlimit to dynamically adjust the address space limit as
-// needed for WebAssembly memory objects (https://crbug.com/750378). Even
-// with setrlimit being allowed, we cannot raise rlim_max once it's
-// lowered. Thus we generally have the same protection because we normally
-// set rlim_max and rlim_cur together.
-//
-// See SandboxLinux::LimitAddressSpace() in
-// services/service_manager/sandbox/linux/sandbox_linux.cc and
-// ArrayBufferContents::ReserveMemory,
-// ArrayBufferContents::ReleaseReservedMemory in
-// third_party/WebKit/Source/platform/wtf/typed_arrays/ArrayBufferContents.cpp.
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // See crbug.com/149834.
- case __NR_pwrite64:
- case __NR_sched_get_priority_max:
- case __NR_sched_get_priority_min:
- case __NR_sysinfo:
- case __NR_times:
- case __NR_uname:
- return Allow();
- case __NR_sched_getaffinity:
- case __NR_sched_getparam:
- case __NR_sched_getscheduler:
- case __NR_sched_setscheduler:
- return sandbox::RestrictSchedTarget(GetPolicyPid(), sysno);
- case __NR_prlimit64:
- // See crbug.com/662450 and setrlimit comment above.
- return sandbox::RestrictPrlimit(GetPolicyPid());
- default:
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h
deleted file mode 100644
index 86c514240d9..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 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_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// This policy can be used by both renderer and worker processes.
-class RendererProcessPolicy : public BPFBasePolicy {
- public:
- RendererProcessPolicy();
- ~RendererProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RendererProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_RENDERER_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.cc
deleted file mode 100644
index 483c1c644a0..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-// 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_sharing_service_policy_linux.h"
-
-#include <errno.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-ResultExpr SharingServiceProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- case __NR_ioctl:
- return sandbox::RestrictIoctl();
- // Allow the system calls below.
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // https://crbug.com/546204
- case __NR_pwrite64:
- case __NR_times:
- return Allow();
- default:
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.h
deleted file mode 100644
index 4b62254012c..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// 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_SHARING_SERVICE_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_SHARING_SERVICE_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// This policy can be used by the Sharing service to host WebRTC.
-class SharingServiceProcessPolicy : public BPFBasePolicy {
- public:
- SharingServiceProcessPolicy() = default;
- ~SharingServiceProcessPolicy() override = default;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- SharingServiceProcessPolicy(const SharingServiceProcessPolicy&) = delete;
- SharingServiceProcessPolicy& operator=(const SharingServiceProcessPolicy&) =
- delete;
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.cc
deleted file mode 100644
index d1eb78d5be0..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.cc
+++ /dev/null
@@ -1,47 +0,0 @@
-// 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_speech_recognition_policy_linux.h"
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.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 {
-
-SpeechRecognitionProcessPolicy::SpeechRecognitionProcessPolicy() = default;
-SpeechRecognitionProcessPolicy::~SpeechRecognitionProcessPolicy() = default;
-
-ResultExpr SpeechRecognitionProcessPolicy::EvaluateSyscall(
- int system_call_number) const {
- switch (system_call_number) {
-#if defined(__NR_eventfd2)
- case __NR_eventfd2:
- return Allow();
-#endif
-#if defined(__NR_getdents64)
- case __NR_getdents64:
- return Allow();
-#endif
-#if defined(__NR_getdents)
- case __NR_getdents:
- return Allow();
-#endif
- default:
- auto* broker_process = SandboxLinux::GetInstance()->broker_process();
- if (broker_process->IsSyscallAllowed(system_call_number))
- return Trap(BrokerProcess::SIGSYS_Handler, broker_process);
-
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(system_call_number);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.h
deleted file mode 100644
index b12bc82755c..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.h
+++ /dev/null
@@ -1,31 +0,0 @@
-// 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_SPEECH_RECOGNITION_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_SPEECH_RECOGNITION_POLICY_LINUX_H_
-
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// The process policy for the sandboxed utility process that loads the Speech
-// On-Device API (SODA). This policy allows the syscalls used by the libsoda.so
-// binary to transcribe audio into text.
-class SERVICE_MANAGER_SANDBOX_EXPORT SpeechRecognitionProcessPolicy
- : public BPFBasePolicy {
- public:
- SpeechRecognitionProcessPolicy();
- ~SpeechRecognitionProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SpeechRecognitionProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_SPEECH_RECOGNITION_POLICY_LINUX_H_
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
deleted file mode 100644
index 812072395ec..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.cc
+++ /dev/null
@@ -1,34 +0,0 @@
-// 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
deleted file mode 100644
index a562a68cfce..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_tts_policy_linux.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// 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/bpf_utility_policy_linux.cc b/chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc
deleted file mode 100644
index 192081eead3..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.cc
+++ /dev/null
@@ -1,55 +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/sandbox/linux/bpf_utility_policy_linux.h"
-
-#include <errno.h>
-
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::Error;
-using sandbox::bpf_dsl::ResultExpr;
-
-namespace service_manager {
-
-UtilityProcessPolicy::UtilityProcessPolicy() {}
-UtilityProcessPolicy::~UtilityProcessPolicy() {}
-
-ResultExpr UtilityProcessPolicy::EvaluateSyscall(int sysno) const {
- switch (sysno) {
- case __NR_ioctl:
- return sandbox::RestrictIoctl();
- case __NR_prlimit64:
- // Restrict prlimit() to reference only the calling process.
- return sandbox::RestrictPrlimitToGetrlimit(GetPolicyPid());
- // Allow the system calls below.
- case __NR_fdatasync:
- case __NR_fsync:
-#if defined(__i386__) || defined(__x86_64__) || defined(__mips__) || \
- defined(__aarch64__)
- case __NR_getrlimit:
-#endif
-#if defined(__i386__) || defined(__arm__)
- case __NR_ugetrlimit:
-#endif
- case __NR_mremap: // https://crbug.com/546204
- case __NR_pwrite64:
- case __NR_sysinfo:
- case __NR_times:
- case __NR_uname:
- return Allow();
- default:
- // Default on the content baseline policy.
- return BPFBasePolicy::EvaluateSyscall(sysno);
- }
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.h b/chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.h
deleted file mode 100644
index 34fa171c3a1..00000000000
--- a/chromium/services/service_manager/sandbox/linux/bpf_utility_policy_linux.h
+++ /dev/null
@@ -1,28 +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_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-
-namespace service_manager {
-
-// This policy can be used by utility processes.
-class UtilityProcessPolicy : public BPFBasePolicy {
- public:
- UtilityProcessPolicy();
- ~UtilityProcessPolicy() override;
-
- sandbox::bpf_dsl::ResultExpr EvaluateSyscall(
- int system_call_number) const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(UtilityProcessPolicy);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_BPF_UTILITY_POLICY_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.cc b/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.cc
deleted file mode 100644
index f435ccb4714..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.cc
+++ /dev/null
@@ -1,79 +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/sandbox/linux/sandbox_debug_handling_linux.h"
-
-#include <errno.h>
-#include <signal.h>
-#include <stddef.h>
-#include <sys/prctl.h>
-#include <unistd.h>
-
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/safe_sprintf.h"
-#include "services/service_manager/sandbox/switches.h"
-
-namespace service_manager {
-
-namespace {
-
-void DoChrootSignalHandler(int) {
- const int old_errno = errno;
- const char kFirstMessage[] = "Chroot signal handler called.\n";
- ignore_result(write(STDERR_FILENO, kFirstMessage, sizeof(kFirstMessage) - 1));
-
- const int chroot_ret = chroot("/");
-
- char kSecondMessage[100];
- const ssize_t printed = base::strings::SafeSPrintf(
- kSecondMessage, "chroot() returned %d. Errno is %d.\n", chroot_ret,
- errno);
- if (printed > 0 && printed < static_cast<ssize_t>(sizeof(kSecondMessage))) {
- ignore_result(write(STDERR_FILENO, kSecondMessage, printed));
- }
- errno = old_errno;
-}
-
-// This is a quick hack to allow testing sandbox crash reports in production
-// binaries.
-// This installs a signal handler for SIGUSR2 that performs a chroot().
-// In most of our BPF policies, it is a "watched" system call which will
-// trigger a SIGSYS signal whose handler will crash.
-// This has been added during the investigation of https://crbug.com/415842.
-void InstallCrashTestHandler() {
- struct sigaction act = {};
- act.sa_handler = DoChrootSignalHandler;
- CHECK_EQ(0, sigemptyset(&act.sa_mask));
- act.sa_flags = 0;
-
- PCHECK(0 == sigaction(SIGUSR2, &act, NULL));
-}
-
-bool IsSandboxDebuggingEnabled() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- service_manager::switches::kAllowSandboxDebugging);
-}
-
-} // namespace
-
-// static
-bool SandboxDebugHandling::SetDumpableStatusAndHandlers() {
- if (IsSandboxDebuggingEnabled()) {
- // If sandbox debugging is allowed, install a handler for sandbox-related
- // crash testing.
- InstallCrashTestHandler();
- return true;
- }
-
- if (prctl(PR_SET_DUMPABLE, 0) != 0) {
- PLOG(ERROR) << "Failed to set non-dumpable flag";
- return false;
- }
-
- return prctl(PR_GET_DUMPABLE) == 0;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h b/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h
deleted file mode 100644
index 17018f2665c..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_debug_handling_linux.h
+++ /dev/null
@@ -1,26 +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_SANDBOX_LINUX_SANDBOX_DEBUG_HANDLING_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_DEBUG_HANDLING_LINUX_H_
-
-#include "base/macros.h"
-#include "services/service_manager/sandbox/export.h"
-
-namespace service_manager {
-
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxDebugHandling {
- public:
- // Depending on the command line, set the current process as
- // non dumpable. Also set any signal handlers for sandbox
- // debugging.
- static bool SetDumpableStatusAndHandlers();
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxDebugHandling);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_DEBUG_HANDLING_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_linux.cc b/chromium/services/service_manager/sandbox/linux/sandbox_linux.cc
deleted file mode 100644
index 3848ab4916e..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_linux.cc
+++ /dev/null
@@ -1,563 +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/sandbox/linux/sandbox_linux.h"
-
-#include <dirent.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <limits>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/singleton.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/system/sys_info.h"
-#include "base/time/time.h"
-#include "build/build_config.h"
-#include "sandbox/constants.h"
-#include "sandbox/linux/services/credentials.h"
-#include "sandbox/linux/services/libc_interceptor.h"
-#include "sandbox/linux/services/namespace_sandbox.h"
-#include "sandbox/linux/services/proc_util.h"
-#include "sandbox/linux/services/resource_limits.h"
-#include "sandbox/linux/services/thread_helpers.h"
-#include "sandbox/linux/services/yama.h"
-#include "sandbox/linux/suid/client/setuid_sandbox_client.h"
-#include "sandbox/linux/syscall_broker/broker_command.h"
-#include "sandbox/linux/syscall_broker/broker_process.h"
-#include "sandbox/sandbox_buildflags.h"
-#include "services/service_manager/sandbox/linux/bpf_broker_policy_linux.h"
-#include "services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h"
-#include "services/service_manager/sandbox/sandbox.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-#include "services/service_manager/sandbox/switches.h"
-
-#if BUILDFLAG(USING_SANITIZER)
-#include <sanitizer/common_interface_defs.h>
-#endif
-
-using sandbox::Yama;
-
-namespace service_manager {
-
-namespace {
-
-void LogSandboxStarted(const std::string& sandbox_name) {
- const std::string process_type =
- base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kProcessType);
- const std::string activated_sandbox =
- "Activated " + sandbox_name +
- " sandbox for process type: " + process_type + ".";
- VLOG(1) << activated_sandbox;
-}
-
-bool IsRunningTSAN() {
-#if defined(THREAD_SANITIZER)
- return true;
-#else
- return false;
-#endif
-}
-
-// Get a file descriptor to /proc. Either duplicate |proc_fd| or try to open
-// it by using the filesystem directly.
-// TODO(jln): get rid of this ugly interface.
-base::ScopedFD OpenProc(int proc_fd) {
- int ret_proc_fd = -1;
- if (proc_fd >= 0) {
- // If a handle to /proc is available, use it. This allows to bypass file
- // system restrictions.
- ret_proc_fd =
- HANDLE_EINTR(openat(proc_fd, ".", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- } else {
- // Otherwise, make an attempt to access the file system directly.
- ret_proc_fd = HANDLE_EINTR(
- openat(AT_FDCWD, "/proc/", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
- }
- DCHECK_LE(0, ret_proc_fd);
- return base::ScopedFD(ret_proc_fd);
-}
-
-bool UpdateProcessTypeAndEnableSandbox(
- SandboxLinux::PreSandboxHook broker_side_hook,
- SandboxLinux::Options options,
- sandbox::syscall_broker::BrokerCommandSet allowed_command_set) {
- base::CommandLine::StringVector exec =
- base::CommandLine::ForCurrentProcess()->GetArgs();
- base::CommandLine::Reset();
- base::CommandLine::Init(0, nullptr);
- base::CommandLine::ForCurrentProcess()->InitFromArgv(exec);
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- std::string new_process_type =
- command_line->GetSwitchValueASCII(switches::kProcessType);
- if (!new_process_type.empty()) {
- new_process_type.append("-broker");
- } else {
- new_process_type = "broker";
- }
-
- VLOG(3) << "UpdateProcessTypeAndEnableSandbox: Updating process type to "
- << new_process_type;
- command_line->AppendSwitchASCII(switches::kProcessType, new_process_type);
-
- if (broker_side_hook)
- CHECK(std::move(broker_side_hook).Run(options));
-
- return SandboxSeccompBPF::StartSandboxWithExternalPolicy(
- std::make_unique<BrokerProcessPolicy>(allowed_command_set),
- base::ScopedFD());
-}
-
-} // namespace
-
-SandboxLinux::SandboxLinux()
- : proc_fd_(-1),
- seccomp_bpf_started_(false),
- sandbox_status_flags_(kInvalid),
- pre_initialized_(false),
- seccomp_bpf_supported_(false),
- seccomp_bpf_with_tsync_supported_(false),
- yama_is_enforcing_(false),
- initialize_sandbox_ran_(false),
- setuid_sandbox_client_(sandbox::SetuidSandboxClient::Create()),
- broker_process_(nullptr) {
- if (!setuid_sandbox_client_) {
- LOG(FATAL) << "Failed to instantiate the setuid sandbox client.";
- }
-#if BUILDFLAG(USING_SANITIZER)
- sanitizer_args_ = std::make_unique<__sanitizer_sandbox_arguments>();
- *sanitizer_args_ = {0};
-#endif
-}
-
-SandboxLinux::~SandboxLinux() {
- if (pre_initialized_) {
- CHECK(initialize_sandbox_ran_);
- }
-}
-
-SandboxLinux* SandboxLinux::GetInstance() {
- SandboxLinux* instance = base::Singleton<SandboxLinux>::get();
- CHECK(instance);
- return instance;
-}
-
-void SandboxLinux::PreinitializeSandbox() {
- CHECK(!pre_initialized_);
- seccomp_bpf_supported_ = false;
-#if BUILDFLAG(USING_SANITIZER)
- // Sanitizers need to open some resources before the sandbox is enabled.
- // This should not fork, not launch threads, not open a directory.
- __sanitizer_sandbox_on_notify(sanitizer_args());
- sanitizer_args_.reset();
-#endif
-
- // Open proc_fd_. It would break the security of the setuid sandbox if it was
- // not closed.
- // If SandboxLinux::PreinitializeSandbox() runs, InitializeSandbox() must run
- // as well.
- proc_fd_ = HANDLE_EINTR(open("/proc", O_DIRECTORY | O_RDONLY | O_CLOEXEC));
- CHECK_GE(proc_fd_, 0);
- // We "pre-warm" the code that detects supports for seccomp BPF.
- if (SandboxSeccompBPF::IsSeccompBPFDesired()) {
- if (!SandboxSeccompBPF::SupportsSandbox()) {
- VLOG(1) << "Lacking support for seccomp-bpf sandbox.";
- } else {
- seccomp_bpf_supported_ = true;
- }
-
- if (SandboxSeccompBPF::SupportsSandboxWithTsync()) {
- seccomp_bpf_with_tsync_supported_ = true;
- }
- }
-
- // Yama is a "global", system-level status. We assume it will not regress
- // after startup.
- const int yama_status = Yama::GetStatus();
- yama_is_enforcing_ = (yama_status & Yama::STATUS_PRESENT) &&
- (yama_status & Yama::STATUS_ENFORCING);
- pre_initialized_ = true;
-}
-
-void SandboxLinux::EngageNamespaceSandbox(bool from_zygote) {
- CHECK(EngageNamespaceSandboxInternal(from_zygote));
-}
-
-bool SandboxLinux::EngageNamespaceSandboxIfPossible() {
- return EngageNamespaceSandboxInternal(false /* from_zygote */);
-}
-
-std::vector<int> SandboxLinux::GetFileDescriptorsToClose() {
- std::vector<int> fds;
- if (proc_fd_ >= 0) {
- fds.push_back(proc_fd_);
- }
- return fds;
-}
-
-int SandboxLinux::GetStatus() {
- if (!pre_initialized_) {
- return 0;
- }
- if (sandbox_status_flags_ == kInvalid) {
- // Initialize sandbox_status_flags_.
- sandbox_status_flags_ = 0;
- if (setuid_sandbox_client_->IsSandboxed()) {
- sandbox_status_flags_ |= kSUID;
- if (setuid_sandbox_client_->IsInNewPIDNamespace())
- sandbox_status_flags_ |= kPIDNS;
- if (setuid_sandbox_client_->IsInNewNETNamespace())
- sandbox_status_flags_ |= kNetNS;
- } else if (sandbox::NamespaceSandbox::InNewUserNamespace()) {
- sandbox_status_flags_ |= kUserNS;
- if (sandbox::NamespaceSandbox::InNewPidNamespace())
- sandbox_status_flags_ |= kPIDNS;
- if (sandbox::NamespaceSandbox::InNewNetNamespace())
- sandbox_status_flags_ |= kNetNS;
- }
-
- // We report whether the sandbox will be activated when renderers, workers
- // and PPAPI plugins go through sandbox initialization.
- if (seccomp_bpf_supported()) {
- sandbox_status_flags_ |= kSeccompBPF;
- }
-
- if (seccomp_bpf_with_tsync_supported()) {
- sandbox_status_flags_ |= kSeccompTSYNC;
- }
-
- if (yama_is_enforcing_) {
- sandbox_status_flags_ |= kYama;
- }
- }
-
- return sandbox_status_flags_;
-}
-
-// Threads are counted via /proc/self/task. This is a little hairy because of
-// PID namespaces and existing sandboxes, so "self" must really be used instead
-// of using the pid.
-bool SandboxLinux::IsSingleThreaded() const {
- base::ScopedFD proc_fd(OpenProc(proc_fd_));
-
- CHECK(proc_fd.is_valid()) << "Could not count threads, the sandbox was not "
- << "pre-initialized properly.";
-
- const bool is_single_threaded =
- sandbox::ThreadHelpers::IsSingleThreaded(proc_fd.get());
-
- return is_single_threaded;
-}
-
-bool SandboxLinux::seccomp_bpf_started() const {
- return seccomp_bpf_started_;
-}
-
-sandbox::SetuidSandboxClient* SandboxLinux::setuid_sandbox_client() const {
- return setuid_sandbox_client_.get();
-}
-
-// For seccomp-bpf, we use the SandboxSeccompBPF class.
-bool SandboxLinux::StartSeccompBPF(SandboxType sandbox_type,
- PreSandboxHook hook,
- const Options& options) {
- CHECK(!seccomp_bpf_started_);
- CHECK(pre_initialized_);
-#if BUILDFLAG(USE_SECCOMP_BPF)
- if (!seccomp_bpf_supported())
- return false;
-
- if (IsUnsandboxedSandboxType(sandbox_type) ||
- !SandboxSeccompBPF::IsSeccompBPFDesired() ||
- !SandboxSeccompBPF::SupportsSandbox()) {
- return true;
- }
-
- if (hook)
- CHECK(std::move(hook).Run(options));
-
- // If we allow threads *and* have multiple threads, try to use TSYNC.
- sandbox::SandboxBPF::SeccompLevel seccomp_level =
- options.allow_threads_during_sandbox_init && !IsSingleThreaded()
- ? sandbox::SandboxBPF::SeccompLevel::MULTI_THREADED
- : sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED;
-
- // If the kernel supports the sandbox, and if the command line says we
- // should enable it, enable it or die.
- std::unique_ptr<BPFBasePolicy> policy =
- SandboxSeccompBPF::PolicyForSandboxType(sandbox_type, options);
- SandboxSeccompBPF::StartSandboxWithExternalPolicy(
- std::move(policy), OpenProc(proc_fd_), seccomp_level);
- SandboxSeccompBPF::RunSandboxSanityChecks(sandbox_type, options);
- seccomp_bpf_started_ = true;
- LogSandboxStarted("seccomp-bpf");
- return true;
-#else
- return false;
-#endif
-}
-
-bool SandboxLinux::InitializeSandbox(SandboxType sandbox_type,
- SandboxLinux::PreSandboxHook hook,
- const Options& options) {
- DCHECK(!initialize_sandbox_ran_);
- initialize_sandbox_ran_ = true;
-
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- const std::string process_type =
- command_line->GetSwitchValueASCII(switches::kProcessType);
-
- // We need to make absolutely sure that our sandbox is "sealed" before
- // returning.
- // Unretained() since the current object is a Singleton.
- base::ScopedClosureRunner sandbox_sealer(
- base::BindOnce(&SandboxLinux::SealSandbox, base::Unretained(this)));
- // Make sure that this function enables sandboxes as promised by GetStatus().
- // Unretained() since the current object is a Singleton.
- base::ScopedClosureRunner sandbox_promise_keeper(
- base::BindOnce(&SandboxLinux::CheckForBrokenPromises,
- base::Unretained(this), sandbox_type));
-
- const bool has_threads = !IsSingleThreaded();
-
- // For now, restrict the |options.allow_threads_during_sandbox_init| option to
- // the GPU process
- DCHECK(process_type == switches::kGpuProcess ||
- !options.allow_threads_during_sandbox_init);
- if (has_threads && !options.allow_threads_during_sandbox_init) {
- std::string error_message =
- "InitializeSandbox() called with multiple threads in process " +
- process_type + ".";
- // TSAN starts a helper thread, so we don't start the sandbox and don't
- // even report an error about it.
- if (IsRunningTSAN())
- return false;
-
- // The GPU process is allowed to call InitializeSandbox() with threads.
- bool sandbox_failure_fatal = process_type != switches::kGpuProcess;
- // This can be disabled with the '--gpu-sandbox-failures-fatal' flag.
- // Setting the flag with no value or any value different than 'yes' or 'no'
- // is equal to setting '--gpu-sandbox-failures-fatal=yes'.
- if (process_type == switches::kGpuProcess &&
- command_line->HasSwitch(switches::kGpuSandboxFailuresFatal)) {
- const std::string switch_value =
- command_line->GetSwitchValueASCII(switches::kGpuSandboxFailuresFatal);
- sandbox_failure_fatal = switch_value != "no";
- }
-
- if (sandbox_failure_fatal) {
- error_message += " Try waiting for /proc to be updated.";
- LOG(ERROR) << error_message;
- // This will return if /proc/self eventually reports this process is
- // single-threaded, or crash if it does not after a number of retries.
- sandbox::ThreadHelpers::AssertSingleThreaded();
- } else {
- LOG(ERROR) << error_message;
- return false;
- }
- }
-
- // At this point we are either single threaded, or we won't be engaging the
- // semantic layer of the sandbox and we won't care if there are file
- // descriptors left open.
-
- // Pre-initialize if not already done.
- if (!pre_initialized_)
- PreinitializeSandbox();
-
- // Turn on the namespace sandbox if our caller wants it (and the zygote hasn't
- // done so already).
- if (options.engage_namespace_sandbox)
- EngageNamespaceSandbox(false /* from_zygote */);
-
- // Check for open directories, which can break the semantic sandbox layer. In
- // some cases the caller doesn't want to enable the semantic sandbox layer,
- // and this CHECK should be skipped. In this case, the caller should unset
- // |options.check_for_open_directories|.
- CHECK(!options.check_for_open_directories || !HasOpenDirectories())
- << "InitializeSandbox() called after unexpected directories have been "
- << "opened. This breaks the security of the setuid sandbox.";
-
- sandbox::InitLibcLocaltimeFunctions();
-
- // Attempt to limit the future size of the address space of the process.
- // Fine to call with multiple threads as we don't use RLIMIT_STACK.
- int error = 0;
- const bool limited_as = LimitAddressSpace(&error);
- if (error) {
- // Restore errno. Internally to |LimitAddressSpace|, the errno due to
- // setrlimit may be lost.
- errno = error;
- PCHECK(limited_as);
- }
-
- return StartSeccompBPF(sandbox_type, std::move(hook), options);
-}
-
-void SandboxLinux::StopThread(base::Thread* thread) {
- DCHECK(thread);
- StopThreadAndEnsureNotCounted(thread);
-}
-
-bool SandboxLinux::seccomp_bpf_supported() const {
- CHECK(pre_initialized_);
- return seccomp_bpf_supported_;
-}
-
-bool SandboxLinux::seccomp_bpf_with_tsync_supported() const {
- CHECK(pre_initialized_);
- return seccomp_bpf_with_tsync_supported_;
-}
-
-rlim_t GetProcessDataSizeLimit(SandboxType sandbox_type) {
-#if defined(ARCH_CPU_64_BITS)
- if (sandbox_type == SandboxType::kGpu ||
- sandbox_type == SandboxType::kRenderer) {
- // Allow the GPU/RENDERER process's sandbox to access more physical memory
- // if it's available on the system.
- constexpr rlim_t GB = 1024 * 1024 * 1024;
- const rlim_t physical_memory = base::SysInfo::AmountOfPhysicalMemory();
- if (physical_memory > 16 * GB) {
- return 16 * GB;
- } else if (physical_memory > 8 * GB) {
- return 8 * GB;
- }
- }
-#endif
-
- return static_cast<rlim_t>(sandbox::kDataSizeLimit);
-}
-
-bool SandboxLinux::LimitAddressSpace(int* error) {
-#if !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) && \
- !defined(THREAD_SANITIZER) && !defined(LEAK_SANITIZER)
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- SandboxType sandbox_type = SandboxTypeFromCommandLine(*command_line);
- if (sandbox_type == SandboxType::kNoSandbox) {
- return false;
- }
-
- // Unfortunately, it does not appear possible to set RLIMIT_AS such that it
- // will both (a) be high enough to support V8's and WebAssembly's address
- // space requirements while also (b) being low enough to mitigate exploits
- // using integer overflows that require large allocations, heap spray, or
- // other memory-hungry attack modes.
-
- rlim_t process_data_size_limit = GetProcessDataSizeLimit(sandbox_type);
- // Fine to call with multiple threads as we don't use RLIMIT_STACK.
- *error = sandbox::ResourceLimits::Lower(RLIMIT_DATA, process_data_size_limit);
-
- // Cache the resource limit before turning on the sandbox.
- base::SysInfo::AmountOfVirtualMemory();
-
- return *error == 0;
-#else
- base::SysInfo::AmountOfVirtualMemory();
- return false;
-#endif // !defined(ADDRESS_SANITIZER) && !defined(MEMORY_SANITIZER) &&
- // !defined(THREAD_SANITIZER) && !defined(LEAK_SANITIZER)
-}
-
-void SandboxLinux::StartBrokerProcess(
- const sandbox::syscall_broker::BrokerCommandSet& allowed_command_set,
- std::vector<sandbox::syscall_broker::BrokerFilePermission> permissions,
- PreSandboxHook broker_side_hook,
- const Options& options) {
- // Leaked at shutdown, so use bare |new|.
- broker_process_ = new sandbox::syscall_broker::BrokerProcess(
- BPFBasePolicy::GetFSDeniedErrno(), allowed_command_set, permissions);
-
- // The initialization callback will perform generic initialization and then
- // call broker_sandboxer_callback.
- CHECK(broker_process_->Init(base::BindOnce(&UpdateProcessTypeAndEnableSandbox,
- std::move(broker_side_hook),
- options, allowed_command_set)));
-}
-
-bool SandboxLinux::HasOpenDirectories() const {
- return sandbox::ProcUtil::HasOpenDirectory(proc_fd_);
-}
-
-void SandboxLinux::SealSandbox() {
- if (proc_fd_ >= 0) {
- int ret = IGNORE_EINTR(close(proc_fd_));
- CHECK_EQ(0, ret);
- proc_fd_ = -1;
- }
-}
-
-void SandboxLinux::CheckForBrokenPromises(SandboxType sandbox_type) {
- if (sandbox_type != SandboxType::kRenderer &&
- sandbox_type != SandboxType::kPpapi) {
- return;
- }
- // Make sure that any promise made with GetStatus() wasn't broken.
- bool promised_seccomp_bpf_would_start =
- (sandbox_status_flags_ != kInvalid) && (GetStatus() & kSeccompBPF);
- CHECK(!promised_seccomp_bpf_would_start || seccomp_bpf_started_);
-}
-
-void SandboxLinux::StopThreadAndEnsureNotCounted(base::Thread* thread) const {
- DCHECK(thread);
- base::ScopedFD proc_fd(OpenProc(proc_fd_));
- PCHECK(proc_fd.is_valid());
- CHECK(
- sandbox::ThreadHelpers::StopThreadAndWatchProcFS(proc_fd.get(), thread));
-}
-
-bool SandboxLinux::EngageNamespaceSandboxInternal(bool from_zygote) {
- CHECK(pre_initialized_);
- CHECK(IsSingleThreaded())
- << "The process cannot have multiple threads when engaging the namespace "
- "sandbox, because the thread engaging the sandbox cannot ensure that "
- "other threads close all their open directories.";
-
- if (from_zygote) {
- // Check being in a new PID namespace created by the namespace sandbox and
- // being the init process.
- CHECK(sandbox::NamespaceSandbox::InNewPidNamespace());
- const pid_t pid = getpid();
- CHECK_EQ(1, pid);
- }
-
- // After we successfully move to a new user ns, we don't allow this function
- // to fail.
- if (!sandbox::Credentials::MoveToNewUserNS()) {
- return false;
- }
-
- // Note: this requires SealSandbox() to be called later in this process to be
- // safe, as this class is keeping a file descriptor to /proc/.
- CHECK(sandbox::Credentials::DropFileSystemAccess(proc_fd_));
-
- // Now we drop all capabilities that we can. In the zygote process, we need
- // to keep CAP_SYS_ADMIN, to place each child in its own PID namespace
- // later on.
- std::vector<sandbox::Credentials::Capability> caps;
- if (from_zygote) {
- caps.push_back(sandbox::Credentials::Capability::SYS_ADMIN);
- }
- CHECK(sandbox::Credentials::SetCapabilities(proc_fd_, caps));
- return true;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_linux.h b/chromium/services/service_manager/sandbox/linux/sandbox_linux.h
deleted file mode 100644
index 6a17f9edb63..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_linux.h
+++ /dev/null
@@ -1,297 +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_SANDBOX_LINUX_SANDBOX_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_LINUX_H_
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/check_op.h"
-#include "base/macros.h"
-#include "base/posix/global_descriptors.h"
-#include "sandbox/linux/syscall_broker/broker_command.h"
-#include "sandbox/linux/syscall_broker/broker_file_permission.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-#include "services/service_manager/sandbox/sanitizer_buildflags.h"
-
-#if BUILDFLAG(USING_SANITIZER)
-#include <sanitizer/common_interface_defs.h>
-#endif
-
-namespace base {
-template <typename T>
-struct DefaultSingletonTraits;
-class Thread;
-} // namespace base
-
-namespace sandbox {
-namespace syscall_broker {
-class BrokerProcess;
-} // namespace syscall_broker
-class SetuidSandboxClient;
-} // namespace sandbox
-
-namespace service_manager {
-
-// A singleton class to represent and change our sandboxing state for the
-// three main Linux sandboxes.
-// The sandboxing model allows using two layers of sandboxing. The first layer
-// can be implemented either with unprivileged namespaces or with the setuid
-// sandbox. This class provides a way to engage the namespace sandbox, but does
-// not deal with the legacy setuid sandbox directly.
-// The second layer is mainly based on seccomp-bpf and is engaged with
-// InitializeSandbox(). InitializeSandbox() is also responsible for "sealing"
-// the first layer of sandboxing. That is, InitializeSandbox must always be
-// called to have any meaningful sandboxing at all.
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxLinux {
- public:
- // This is a list of sandbox IPC methods which the renderer may send to the
- // sandbox host. See
- // https://chromium.googlesource.com/chromium/src/+/master/docs/linux/sandbox_ipc.md
- // This isn't the full list, values < 32 are reserved for methods called from
- // Skia, and values < 64 are reserved for libc_interceptor.cc.
- enum LinuxSandboxIPCMethods {
- DEPRECATED_METHOD_GET_FALLBACK_FONT_FOR_CHAR = 64,
- DEPRECATED_METHOD_GET_CHILD_WITH_INODE,
- DEPRECATED_METHOD_GET_STYLE_FOR_STRIKE,
- METHOD_MAKE_SHARED_MEMORY_SEGMENT,
- DEPRECATED_METHOD_MATCH_WITH_FALLBACK,
- };
-
- // These form a bitmask which describes the conditions of the Linux sandbox.
- // Note: this doesn't strictly give you the current status, it states
- // what will be enabled when the relevant processes are initialized.
- enum Status {
- // SUID sandbox active.
- kSUID = 1 << 0,
-
- // Sandbox is using a new PID namespace.
- kPIDNS = 1 << 1,
-
- // Sandbox is using a new network namespace.
- kNetNS = 1 << 2,
-
- // seccomp-bpf sandbox active.
- kSeccompBPF = 1 << 3,
-
- // The Yama LSM module is present and enforcing.
- kYama = 1 << 4,
-
- // seccomp-bpf sandbox is active and the kernel supports TSYNC.
- kSeccompTSYNC = 1 << 5,
-
- // User namespace sandbox active.
- kUserNS = 1 << 6,
-
- // A flag that denotes an invalid sandbox status.
- kInvalid = 1 << 31,
- };
-
- // SandboxLinux Options are a superset of SandboxSecompBPF Options.
- struct Options : public SandboxSeccompBPF::Options {
- // When running with a zygote, the namespace sandbox will have already
- // been engaged prior to initializing SandboxLinux itself, and need not
- // be done so again. Set to true to indicate that there isn't a zygote
- // for this process and the step is to be performed here explicitly.
- bool engage_namespace_sandbox = false;
-
- // Allow starting the sandbox with multiple threads already running. This
- // will enable TSYNC for seccomp-BPF, which syncs the seccomp-BPF policy
- // across all running threads.
- bool allow_threads_during_sandbox_init = false;
-
- // Enables the CHECK for open directories. The open directory check is only
- // useful for the chroot jail (from the semantic layer of the sandbox), and
- // can safely be disabled if we are only enabling the seccomp-BPF layer.
- bool check_for_open_directories = true;
- };
-
- // Callers can provide this hook to run code right before the policy
- // is passed to the BPF compiler and the sandbox is engaged. If
- // pre_sandbox_hook() returns true, the sandbox will be engaged
- // afterwards, otherwise the process is terminated.
- using PreSandboxHook = base::OnceCallback<bool(Options)>;
-
- // Get our singleton instance.
- static SandboxLinux* GetInstance();
-
- // Do some initialization that can only be done before any of the sandboxes
- // are enabled. If using the setuid sandbox, this should be called manually
- // before the setuid sandbox is engaged.
- // Security: When this runs, it is imperative that either InitializeSandbox()
- // runs as well or that all file descriptors returned in
- // GetFileDescriptorsToClose() get closed.
- // Otherwise file descriptors that bypass the security of the setuid sandbox
- // would be kept open. One must be particularly careful if a process performs
- // a fork().
- void PreinitializeSandbox();
-
- // Check that the current process is the init process of a new PID
- // namespace and then proceed to drop access to the file system by using
- // a new unprivileged namespace. This is a layer-1 sandbox.
- // In order for this sandbox to be effective, it must be "sealed" by calling
- // InitializeSandbox().
- // Terminates the process in case the sandboxing operations cannot complete
- // successfully.
- void EngageNamespaceSandbox(bool from_zygote);
-
- // Performs the same actions as EngageNamespaceSandbox, but is allowed to
- // to fail. This is useful when sandboxed non-renderer processes could
- // benefit from extra sandboxing but is not strictly required on systems that
- // don't support unprivileged user namespaces.
- // Zygote should use EngageNamespaceSandbox instead.
- bool EngageNamespaceSandboxIfPossible();
-
- // Return a list of file descriptors to close if PreinitializeSandbox() ran
- // but InitializeSandbox() won't. Avoid using.
- // TODO(jln): get rid of this hack.
- std::vector<int> GetFileDescriptorsToClose();
-
- // Seal an eventual layer-1 sandbox and initialize the layer-2 sandbox with
- // an adequate policy depending on the process type and command line
- // arguments.
- // Currently the layer-2 sandbox is composed of seccomp-bpf and address space
- // limitations.
- // This function should only be called without any thread running.
- bool InitializeSandbox(SandboxType sandbox_type,
- PreSandboxHook hook,
- const Options& options);
-
- // Stop |thread| in a way that can be trusted by the sandbox.
- void StopThread(base::Thread* thread);
-
- // Returns the status of the renderer, worker and ppapi sandbox. Can only
- // be queried after going through PreinitializeSandbox(). This is a bitmask
- // and uses the constants defined in "enum Status" above. Since the
- // status needs to be provided before the sandboxes are actually started,
- // this returns what will actually happen once InitializeSandbox()
- // is called from inside these processes.
- int GetStatus();
-
- // Returns true if the current process is single-threaded or if the number
- // of threads cannot be determined.
- bool IsSingleThreaded() const;
-
- // Returns true if we started Seccomp BPF.
- bool seccomp_bpf_started() const;
-
- // Simple accessor for our instance of the setuid sandbox. Will never return
- // NULL.
- // There is no StartSetuidSandbox(), the SetuidSandboxClient instance should
- // be used directly.
- sandbox::SetuidSandboxClient* setuid_sandbox_client() const;
-
- // Check the policy and eventually start the seccomp-bpf sandbox. Fine to be
- // called with threads, as long as
- // |options.allow_threads_during_sandbox_init| is true and the kernel
- // supports seccomp's TSYNC feature. If TSYNC is not available we treat
- // multiple threads as a fatal error.
- bool StartSeccompBPF(service_manager::SandboxType sandbox_type,
- PreSandboxHook hook,
- const Options& options);
-
- // Limit the address space of the current process (and its children) to make
- // some vulnerabilities harder to exploit. Writes the errno due to setrlimit
- // (including 0 if no error) into |error|.
- bool LimitAddressSpace(int* error);
-
- // Returns a file descriptor to proc. The file descriptor is no longer valid
- // after the sandbox has been sealed.
- int proc_fd() const {
- DCHECK_NE(-1, proc_fd_);
- return proc_fd_;
- }
-
-#if BUILDFLAG(USING_SANITIZER)
- __sanitizer_sandbox_arguments* sanitizer_args() const {
- return sanitizer_args_.get();
- }
-#endif
-
- // A BrokerProcess is a helper that is started before the sandbox is engaged,
- // typically from a pre-sandbox hook, that will serve requests to access
- // files over an IPC channel. The client of this runs from a SIGSYS handler
- // triggered by the seccomp-bpf sandbox.
- // |client_sandbox_policy| is the policy being run by the client, and is
- // used to derive the equivalent broker-side policy.
- // |broker_side_hook| is an alternate pre-sandbox hook to be run before the
- // broker itself gets sandboxed, to which the broker side policy and
- // |options| are passed.
- // Crashes the process if the broker can not be started since continuation
- // is impossible (and presumably unsafe).
- // This should never be destroyed, as after the sandbox is started it is
- // vital to the process.
- void StartBrokerProcess(
- const sandbox::syscall_broker::BrokerCommandSet& allowed_command_set,
- std::vector<sandbox::syscall_broker::BrokerFilePermission> permissions,
- PreSandboxHook broker_side_hook,
- const Options& options);
-
- sandbox::syscall_broker::BrokerProcess* broker_process() const {
- return broker_process_;
- }
-
- private:
- friend struct base::DefaultSingletonTraits<SandboxLinux>;
-
- SandboxLinux();
- ~SandboxLinux();
-
- // We must have been pre_initialized_ before using these.
- bool seccomp_bpf_supported() const;
- bool seccomp_bpf_with_tsync_supported() const;
-
- // Returns true if it can be determined that the current process has open
- // directories that are not managed by the SandboxLinux class. This would
- // be a vulnerability as it would allow to bypass the setuid sandbox.
- bool HasOpenDirectories() const;
-
- // The last part of the initialization is to make sure any temporary "hole"
- // in the sandbox is closed. For now, this consists of closing proc_fd_.
- void SealSandbox();
-
- // GetStatus() makes promises as to how the sandbox will behave. This
- // checks that no promises have been broken.
- void CheckForBrokenPromises(service_manager::SandboxType sandbox_type);
-
- // Stop |thread| and make sure it does not appear in /proc/self/tasks/
- // anymore.
- void StopThreadAndEnsureNotCounted(base::Thread* thread) const;
-
- // Engages the namespace sandbox as described for EngageNamespaceSandbox.
- // Returns false if it fails to transition to a new user namespace, but
- // after transitioning to a new user namespace we don't allow this function
- // to fail.
- bool EngageNamespaceSandboxInternal(bool from_zygote);
-
- // A file descriptor to /proc. It's dangerous to have it around as it could
- // allow for sandbox bypasses. It needs to be closed before we consider
- // ourselves sandboxed.
- int proc_fd_;
-
- bool seccomp_bpf_started_;
- // The value returned by GetStatus(). Gets computed once and then cached.
- int sandbox_status_flags_;
- // Did PreinitializeSandbox() run?
- bool pre_initialized_;
- bool seccomp_bpf_supported_; // Accurate if pre_initialized_.
- bool seccomp_bpf_with_tsync_supported_; // Accurate if pre_initialized_.
- bool yama_is_enforcing_; // Accurate if pre_initialized_.
- bool initialize_sandbox_ran_; // InitializeSandbox() was called.
- std::unique_ptr<sandbox::SetuidSandboxClient> setuid_sandbox_client_;
-#if BUILDFLAG(USING_SANITIZER)
- std::unique_ptr<__sanitizer_sandbox_arguments> sanitizer_args_;
-#endif
- sandbox::syscall_broker::BrokerProcess* broker_process_; // Leaked as global.
-
- DISALLOW_COPY_AND_ASSIGN(SandboxLinux);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_LINUX_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
deleted file mode 100644
index 1c16d68df91..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.cc
+++ /dev/null
@@ -1,282 +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/sandbox/linux/sandbox_seccomp_bpf_linux.h"
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <memory>
-#include <utility>
-
-#include "base/check_op.h"
-#include "base/command_line.h"
-#include "base/macros.h"
-#include "base/notreached.h"
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/bpf_dsl.h"
-#include "sandbox/linux/bpf_dsl/trap_registry.h"
-#include "sandbox/sandbox_buildflags.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-#include "services/service_manager/sandbox/switches.h"
-
-#if BUILDFLAG(USE_SECCOMP_BPF)
-
-#include "base/files/scoped_file.h"
-#include "base/posix/eintr_wrapper.h"
-#include "sandbox/linux/seccomp-bpf-helpers/baseline_policy.h"
-#include "sandbox/linux/seccomp-bpf-helpers/sigsys_handlers.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_parameters_restrictions.h"
-#include "sandbox/linux/seccomp-bpf-helpers/syscall_sets.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "sandbox/linux/system_headers/linux_syscalls.h"
-#include "services/service_manager/sandbox/linux/bpf_audio_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_cdm_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_cros_amd_gpu_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_cros_arm_gpu_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_gpu_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_network_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_ppapi_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_print_compositor_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_renderer_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_sharing_service_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_speech_recognition_policy_linux.h"
-#include "services/service_manager/sandbox/linux/bpf_utility_policy_linux.h"
-
-#if !defined(OS_NACL_NONSFI)
-#include "services/service_manager/sandbox/chromecast_sandbox_whitelist_buildflags.h"
-#endif // !defined(OS_NACL_NONSFI)
-
-#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;
-using sandbox::SandboxBPF;
-using sandbox::SyscallSets;
-using sandbox::bpf_dsl::Allow;
-using sandbox::bpf_dsl::ResultExpr;
-
-#else // BUILDFLAG(USE_SECCOMP_BPF)
-
-// Make sure that seccomp-bpf does not get disabled by mistake. Also make sure
-// that we think twice about this when adding a new architecture.
-#if !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_MIPS64EL)
-#error "Seccomp-bpf disabled on supported architecture!"
-#endif // !defined(ARCH_CPU_ARM64) && !defined(ARCH_CPU_MIPS64EL)
-
-#endif // BUILDFLAG(USE_SECCOMP_BPF)
-
-namespace service_manager {
-
-#if BUILDFLAG(USE_SECCOMP_BPF)
-namespace {
-
-#if !defined(OS_NACL_NONSFI)
-
-// nacl_helper needs to be tiny and includes only part of content/
-// in its dependencies. Make sure to not link things that are not needed.
-#if !defined(IN_NACL_HELPER)
-inline bool IsChromeOS() {
-#if defined(OS_CHROMEOS)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool UseChromecastSandboxWhitelist() {
-#if BUILDFLAG(ENABLE_CHROMECAST_GPU_SANDBOX_WHITELIST)
- return true;
-#else
- return false;
-#endif
-}
-
-inline bool IsArchitectureArm() {
-#if defined(ARCH_CPU_ARM_FAMILY)
- return true;
-#else
- return false;
-#endif
-}
-
-std::unique_ptr<BPFBasePolicy> GetGpuProcessSandbox(
- bool use_amd_specific_policies) {
- if (IsChromeOS() || UseChromecastSandboxWhitelist()) {
- if (IsArchitectureArm()) {
- return std::make_unique<CrosArmGpuProcessPolicy>(
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kGpuSandboxAllowSysVShm));
- }
- if (use_amd_specific_policies)
- return std::make_unique<CrosAmdGpuProcessPolicy>();
- }
- return std::make_unique<GpuProcessPolicy>();
-}
-#endif // !defined(IN_NACL_HELPER)
-#endif // !defined(OS_NACL_NONSFI)
-
-} // namespace
-
-#endif // USE_SECCOMP_BPF
-
-// Is seccomp BPF globally enabled?
-bool SandboxSeccompBPF::IsSeccompBPFDesired() {
-#if BUILDFLAG(USE_SECCOMP_BPF)
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- return !command_line.HasSwitch(switches::kNoSandbox) &&
- !command_line.HasSwitch(switches::kDisableSeccompFilterSandbox);
-#else
- return false;
-#endif // USE_SECCOMP_BPF
-}
-
-bool SandboxSeccompBPF::SupportsSandbox() {
-#if BUILDFLAG(USE_SECCOMP_BPF)
- return SandboxBPF::SupportsSeccompSandbox(
- SandboxBPF::SeccompLevel::SINGLE_THREADED);
-#else
- return false;
-#endif
-}
-
-#if !defined(OS_NACL_NONSFI)
-
-bool SandboxSeccompBPF::SupportsSandboxWithTsync() {
-#if BUILDFLAG(USE_SECCOMP_BPF)
- return SandboxBPF::SupportsSeccompSandbox(
- SandboxBPF::SeccompLevel::MULTI_THREADED);
-#else
- return false;
-#endif
-}
-
-std::unique_ptr<BPFBasePolicy> SandboxSeccompBPF::PolicyForSandboxType(
- SandboxType sandbox_type,
- const SandboxSeccompBPF::Options& options) {
- switch (sandbox_type) {
- case SandboxType::kGpu:
- return GetGpuProcessSandbox(options.use_amd_specific_policies);
- case SandboxType::kRenderer:
- return std::make_unique<RendererProcessPolicy>();
- case SandboxType::kPpapi:
- return std::make_unique<PpapiProcessPolicy>();
- case SandboxType::kUtility:
- return std::make_unique<UtilityProcessPolicy>();
- case SandboxType::kCdm:
- return std::make_unique<CdmProcessPolicy>();
- case SandboxType::kPrintCompositor:
- return std::make_unique<PrintCompositorProcessPolicy>();
- case SandboxType::kNetwork:
- return std::make_unique<NetworkProcessPolicy>();
- case SandboxType::kAudio:
- return std::make_unique<AudioProcessPolicy>();
- case SandboxType::kSharingService:
- return std::make_unique<SharingServiceProcessPolicy>();
- case SandboxType::kSpeechRecognition:
- return std::make_unique<SpeechRecognitionProcessPolicy>();
-#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:
- case SandboxType::kVideoCapture:
- NOTREACHED();
- return nullptr;
- }
-}
-
-// If a BPF policy is engaged for |process_type|, run a few sanity checks.
-void SandboxSeccompBPF::RunSandboxSanityChecks(
- SandboxType sandbox_type,
- const SandboxSeccompBPF::Options& options) {
- switch (sandbox_type) {
- case SandboxType::kRenderer:
- case SandboxType::kGpu:
- case SandboxType::kPpapi:
- case SandboxType::kPrintCompositor:
- case SandboxType::kCdm: {
- int syscall_ret;
- errno = 0;
-
- // Without the sandbox, this would EBADF.
- syscall_ret = fchmod(-1, 07777);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(EPERM, errno);
-
-// Run most of the sanity checks only in DEBUG mode to avoid a perf.
-// impact.
-#if !defined(NDEBUG)
- // open() must be restricted.
- syscall_ret = open("/etc/passwd", O_RDONLY);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(BPFBasePolicy::GetFSDeniedErrno(), errno);
-
- // We should never allow the creation of netlink sockets.
- syscall_ret = socket(AF_NETLINK, SOCK_DGRAM, 0);
- CHECK_EQ(-1, syscall_ret);
- CHECK_EQ(EPERM, errno);
-#endif // !defined(NDEBUG)
- } break;
-#if defined(OS_CHROMEOS)
- case SandboxType::kIme:
- case SandboxType::kTts:
-#endif // defined(OS_CHROMEOS)
- case SandboxType::kAudio:
- case SandboxType::kSharingService:
- case SandboxType::kSpeechRecognition:
- case SandboxType::kNetwork:
- case SandboxType::kUtility:
- case SandboxType::kNoSandbox:
- case SandboxType::kVideoCapture:
- case SandboxType::kZygoteIntermediateSandbox:
- // Otherwise, no checks required.
- break;
- }
-}
-#endif // !defined(OS_NACL_NONSFI)
-
-bool SandboxSeccompBPF::StartSandboxWithExternalPolicy(
- std::unique_ptr<sandbox::bpf_dsl::Policy> policy,
- base::ScopedFD proc_fd,
- sandbox::SandboxBPF::SeccompLevel seccomp_level) {
-#if BUILDFLAG(USE_SECCOMP_BPF)
- if (IsSeccompBPFDesired() && SupportsSandbox()) {
- CHECK(policy);
- // Starting the sandbox is a one-way operation. The kernel doesn't allow
- // us to unload a sandbox policy after it has been started. Nonetheless,
- // in order to make the use of the "Sandbox" object easier, we allow for
- // the object to be destroyed after the sandbox has been started. Note that
- // doing so does not stop the sandbox.
- SandboxBPF sandbox(std::move(policy));
- sandbox.SetProcFd(std::move(proc_fd));
- CHECK(sandbox.StartSandbox(seccomp_level));
- return true;
- }
-#endif // BUILDFLAG(USE_SECCOMP_BPF)
- return false;
-}
-
-#if !defined(OS_NACL_NONSFI)
-std::unique_ptr<sandbox::bpf_dsl::Policy>
-SandboxSeccompBPF::GetBaselinePolicy() {
-#if BUILDFLAG(USE_SECCOMP_BPF)
- return std::make_unique<BaselinePolicy>();
-#else
- return nullptr;
-#endif // BUILDFLAG(USE_SECCOMP_BPF)
-}
-#endif // !defined(OS_NACL_NONSFI)
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h b/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h
deleted file mode 100644
index e9f1688c080..00000000000
--- a/chromium/services/service_manager/sandbox/linux/sandbox_seccomp_bpf_linux.h
+++ /dev/null
@@ -1,78 +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_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
-
-#include <memory>
-
-#include "base/callback.h"
-#include "base/files/scoped_file.h"
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "sandbox/linux/bpf_dsl/policy.h"
-#include "sandbox/linux/seccomp-bpf/sandbox_bpf.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/linux/bpf_base_policy_linux.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-namespace service_manager {
-
-// This class has two main sets of APIs. One can be used to start the sandbox
-// for internal content process types, the other is indirectly exposed as
-// a public content/ API and uses a supplied policy.
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxSeccompBPF {
- public:
- struct Options {
- bool use_amd_specific_policies = false; // For ChromiumOS.
- bool use_intel_specific_policies = false; // For ChromiumOS.
-
- // Options for GPU's PreSandboxHook.
- bool accelerated_video_decode_enabled = false;
- bool accelerated_video_encode_enabled = false;
- };
-
- // This is the API to enable a seccomp-bpf sandbox for content/
- // process-types:
- // Is the sandbox globally enabled, can anything use it at all ?
- // This looks at global command line flags to see if the sandbox
- // should be enabled at all.
- static bool IsSeccompBPFDesired();
-
- // Check if the kernel supports seccomp-bpf.
- static bool SupportsSandbox();
-
-#if !defined(OS_NACL_NONSFI)
- // Check if the kernel supports TSYNC (thread synchronization) with seccomp.
- static bool SupportsSandboxWithTsync();
-
- // Return a policy suitable for use with StartSandboxWithExternalPolicy.
- static std::unique_ptr<BPFBasePolicy> PolicyForSandboxType(
- SandboxType sandbox_type,
- const SandboxSeccompBPF::Options& options);
-
- // Prove that the sandbox was engaged by the StartSandbox() call. Crashes
- // the process if the sandbox failed to engage.
- static void RunSandboxSanityChecks(SandboxType sandbox_type,
- const SandboxSeccompBPF::Options& options);
-#endif // !defined(OS_NACL_NONSFI)
-
- // This is the API to enable a seccomp-bpf sandbox by using an
- // external policy.
- static bool StartSandboxWithExternalPolicy(
- std::unique_ptr<sandbox::bpf_dsl::Policy> policy,
- base::ScopedFD proc_fd,
- sandbox::SandboxBPF::SeccompLevel seccomp_level =
- sandbox::SandboxBPF::SeccompLevel::SINGLE_THREADED);
-
- // The "baseline" policy can be a useful base to build a sandbox policy.
- static std::unique_ptr<sandbox::bpf_dsl::Policy> GetBaselinePolicy();
-
- private:
- DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxSeccompBPF);
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_LINUX_SANDBOX_SECCOMP_BPF_LINUX_H_
diff --git a/chromium/services/service_manager/sandbox/mac/BUILD.gn b/chromium/services/service_manager/sandbox/mac/BUILD.gn
deleted file mode 100644
index 6bb2025f321..00000000000
--- a/chromium/services/service_manager/sandbox/mac/BUILD.gn
+++ /dev/null
@@ -1,34 +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.
-
-action_foreach("package_sb_files") {
- script = "package_sb_file.py"
- sources = [
- "audio.sb",
- "cdm.sb",
- "common.sb",
- "gpu.sb",
- "gpu_v2.sb",
- "nacl_loader.sb",
- "network.sb",
- "ppapi.sb",
- "print_compositor.sb",
- "renderer.sb",
- "utility.sb",
- ]
- outputs = [
- "$target_gen_dir/{{source_name_part}}.sb.h",
- "$target_gen_dir/{{source_name_part}}.sb.cc",
- ]
- args = [
- "{{source}}",
- rebase_path(target_gen_dir, root_build_dir),
- ]
-}
-
-source_set("packaged_sb_files") {
- sources = get_target_outputs(":package_sb_files")
- defines = [ "SERVICE_MANAGER_SANDBOX_IMPL" ]
- deps = [ ":package_sb_files" ]
-}
diff --git a/chromium/services/service_manager/sandbox/mac/DEPS b/chromium/services/service_manager/sandbox/mac/DEPS
deleted file mode 100644
index 88962cb8c01..00000000000
--- a/chromium/services/service_manager/sandbox/mac/DEPS
+++ /dev/null
@@ -1,3 +0,0 @@
-include_rules = [
- "+sandbox/mac",
-]
diff --git a/chromium/services/service_manager/sandbox/mac/OWNERS b/chromium/services/service_manager/sandbox/mac/OWNERS
deleted file mode 100644
index cf797b66465..00000000000
--- a/chromium/services/service_manager/sandbox/mac/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-file://sandbox/mac/OWNERS
diff --git a/chromium/services/service_manager/sandbox/mac/audio.sb b/chromium/services/service_manager/sandbox/mac/audio.sb
deleted file mode 100644
index 2379adcb114..00000000000
--- a/chromium/services/service_manager/sandbox/mac/audio.sb
+++ /dev/null
@@ -1,67 +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.
-
-; --- The contents of common.sb implicitly included here. ---
-
-; File access.
-(allow file-read*
- (path (user-homedir-path "/Library/Caches/com.apple.coreaudio.components.plist"))
- (regex (user-homedir-path #"/Library/Preferences/com.apple.coreaudio.*"))
- (subpath "/Library/Audio/Plug-Ins")
- (subpath "/Library/QuickTime")
- (subpath "/System/Library/Components")
- (subpath "/System/Library/Extensions")
- (subpath (user-homedir-path "/Library/Audio/Plug-Ins"))
-)
-
-(allow device-microphone)
-
-(allow iokit-open
- (iokit-user-client-class "IOAudioControlUserClient")
- (iokit-user-client-class "IOAudioEngineUserClient")
-)
-
-(allow ipc-posix-shm-read* ipc-posix-shm-write-data
- (ipc-posix-name-regex #"^AudioIO"))
-
-; Mach IPC.
-(allow mach-lookup
- (global-name "com.apple.audio.SystemSoundServer-OSX")
- (global-name "com.apple.audio.VDCAssistant")
- (global-name "com.apple.audio.audiohald")
- (global-name "com.apple.audio.coreaudiod")
-)
-
-(if (>= os-version 1013)
- (allow mach-lookup
- (global-name "com.apple.audio.AudioComponentRegistrar")
- (xpc-service-name "com.apple.audio.SandboxHelper")
- ))
-
-; sysctls.
-(allow sysctl-read
- (sysctl-name "hw.optional.avx1_0")
- (sysctl-name "hw.optional.avx2_0")
- (sysctl-name "hw.optional.sse2")
- (sysctl-name "hw.optional.sse3")
- (sysctl-name "hw.optional.sse4_1")
- (sysctl-name "hw.optional.sse4_2")
-)
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls-debug)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))
- (allow syscall-unix
- (syscall-number SYS_csrctl)
- (syscall-number SYS_mlock)
- (syscall-number SYS_poll)
- (syscall-number SYS_proc_rlimit_control)
- (syscall-number SYS_psynch_cvbroad)
- (syscall-number SYS_psynch_cvwait)
- (syscall-number SYS_setsockopt)
- (syscall-number SYS_socketpair)
- (syscall-number SYS_work_interval_ctl)
- (syscall-number SYS_write)
-)))
diff --git a/chromium/services/service_manager/sandbox/mac/cdm.sb b/chromium/services/service_manager/sandbox/mac/cdm.sb
deleted file mode 100644
index 015d18fc119..00000000000
--- a/chromium/services/service_manager/sandbox/mac/cdm.sb
+++ /dev/null
@@ -1,16 +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.
-
-; *** The contents of common.sb are implicitly included here. ***
-
-; Allow preloading of the CDM using seatbelt extension.
-(allow file-read* (extension "com.apple.app-sandbox.read"))
-
-; mach IPC
-(allow mach-lookup (global-name "com.apple.windowserver.active"))
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls-debug)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))))
diff --git a/chromium/services/service_manager/sandbox/mac/common.sb b/chromium/services/service_manager/sandbox/mac/common.sb
deleted file mode 100644
index e15e9d97c52..00000000000
--- a/chromium/services/service_manager/sandbox/mac/common.sb
+++ /dev/null
@@ -1,298 +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.
-(version 1)
-
-; Helper function to check if a param is set to true.
-(define (param-true? str) (string=? (param str) "TRUE"))
-
-; Helper function to determine if a parameter is defined or not.
-(define (param-defined? str) (string? (param str)))
-
-; Define constants for all of the parameter strings passed in.
-(define browser-pid "BROWSER_PID")
-(define bundle-id "BUNDLE_ID")
-(define bundle-path "BUNDLE_PATH")
-(define component-path "COMPONENT_PATH")
-(define current-pid "CURRENT_PID")
-(define disable-sandbox-denial-logging "DISABLE_SANDBOX_DENIAL_LOGGING")
-(define enable-logging "ENABLE_LOGGING")
-(define executable-path "EXECUTABLE_PATH")
-(define homedir-as-literal "USER_HOMEDIR_AS_LITERAL")
-(define log-file-path "LOG_FILE_PATH")
-(define os-version (string->number (param "OS_VERSION")))
-(define darwin-user-cache-dir "DARWIN_USER_CACHE_DIR")
-(define darwin-user-dir "DARWIN_USER_DIR")
-(define darwin-user-temp-dir "DARWIN_USER_TEMP_DIR")
-; There are two separate flags for syscall filtering to allow it
-; to be rolled out to one process type at a time, while still allowing
-; local development.
-(define filter-syscalls "FILTER_SYSCALLS")
-(define filter-syscalls-debug "FILTER_SYSCALLS_DEBUG")
-
-; Backwards compatibility for 10.10.
-(if (not (defined? 'path))
- (define path literal))
-; Backwards compatibility for 10.11.
-(if (not (defined? 'iokit-registry-entry-class))
- (define iokit-registry-entry-class iokit-user-client-class))
-
-; --enable-sandbox-logging causes the sandbox to log failures to the syslog.
-(if (param-true? disable-sandbox-denial-logging)
- (deny default (with no-log))
- (deny default))
-
-(if (param-true? enable-logging) (debug deny))
-
-; Allow sending signals to self - https://crbug.com/20370
-(allow signal (target self))
-
-; Consumes a subpath and appends it to the user's homedir path.
-(define (user-homedir-path subpath)
- (string-append (param homedir-as-literal) subpath))
-
-; A function that specific profiles (i.e. renderer) can call to allow
-; font rendering.
-(define (allow-font-access)
- (begin
- (allow file-read-data
- (subpath "/Library/Fonts")
- (subpath "/System/Library/Fonts")
- (subpath (user-homedir-path "/Library/Fonts"))
- )
- (allow mach-lookup
- ; https://crbug.com/756145, https://crbug.com/786615
- (global-name "com.apple.FontObjectsServer")
- (global-name "com.apple.fonts")
- )
- (if (< os-version 1012)
- (allow mach-lookup (global-name "com.apple.FontServer")))
- ; To allow accessing downloaded and other hidden fonts in
- ; /System/Library/Asssets/com_apple_MobileAsset_Font*.
- ; (https://crbug.com/662686)
- (allow file-read* (extension "com.apple.app-sandbox.read"))))
-
-; Reads of signed Mach-O blobs created by the CVMS server.
-; https://crbug.com/850021
-(define (allow-cvms-blobs)
- (if (>= os-version 1014)
- (begin
- (allow file-read* file-write-unlink
- (prefix "/private/tmp/cvmsCodeSignObj"))
- (allow file-read*
- (extension "com.apple.cvms.kernel")
- (prefix "/private/var/db/CVMS/cvmsCodeSignObj"))
-)))
-
-; Allow logging for all processes.
-(allow file-write*
- (require-all
- (path (param log-file-path))
- (vnode-type REGULAR-FILE)))
-
-; Allow component builds to work.
-(if (param-defined? component-path)
- (allow file-read* (subpath (param component-path))))
-
-(allow process-exec (path (param executable-path)))
-(allow file-read* (path (param executable-path)))
-
-; The browser exposes Mach services at "bundle-id.service-name.browser-pid".
-; This macro is a helper for doing the string concatenation.
-(define (browser-service-name service-name)
- (global-name (string-append (param bundle-id)
- "." service-name "."
- (param browser-pid))))
-
-(allow mach-lookup
- (browser-service-name "MachPortRendezvousServer")
-)
-
-; Allow realpath() to work.
-(allow file-read-metadata (subpath "/"))
-
-; All processes can read the bundle contents.
-(allow file-read* (subpath (param bundle-path)))
-
-; Allow reads of system libraries and frameworks.
-(allow file-read*
- (subpath "/System/Library/CoreServices/CoreTypes.bundle")
- (subpath "/System/Library/CoreServices/SystemVersion.bundle")
- (subpath "/System/Library/Frameworks")
- (subpath "/System/Library/Preferences/Logging")
- (subpath "/System/Library/PrivateFrameworks")
- (subpath "/usr/lib")
-)
-
-; Reads from /etc.
-; This is read by CFPrefs calling getpwuid in a loop. libinfo then fails to
-; contact any of the opendirectoryd mach services, and falls back to
-; the /etc/passwd file for the user info. The access is OK because
-; no actual password hashes are in /etc/passwd anymore.
-(allow file-read-data (path "/private/etc/passwd"))
-
-; Access to /dev.
-(allow file-ioctl file-read-data file-write-data
- (require-all
- (path "/dev/dtracehelper")
- (vnode-type CHARACTER-DEVICE)))
-
-(allow file-read-data
- (path "/dev/null")
- (path "/dev/random")
- (path "/dev/urandom")
-)
-
-(if (>= os-version 1013)
- (begin (allow file-read* (subpath "/private/var/db/timezone"))
- (allow file-read-data (subpath "/usr/share/zoneinfo.default"))))
-
-(if (< os-version 1013)
- (allow file-read-data (subpath "/usr/share/zoneinfo")))
-
-; Reads from /Library.
-(allow file-read-data
- (path "/Library/Preferences/.GlobalPreferences.plist")
-)
-
-; Reads from /System.
-(allow file-read-data
- (path "/System/Library/CoreServices/SystemVersion.plist")
- (path "/System/Library/CoreServices/checkfixlist")
-)
-
-; Reads from /usr.
-(allow file-read-data
- (subpath "/usr/share/icu")
-)
-
-; Access to the home directory.
-(allow file-read-data
- (path (string-append (user-homedir-path "/Library/Preferences/") (param bundle-id) ".plist"))
- (path (user-homedir-path "/Library/Preferences/.GlobalPreferences.plist"))
- (regex (user-homedir-path #"/Library/Preferences/ByHost/.GlobalPreferences.*"))
- (path (user-homedir-path "/Library/Preferences/com.apple.LaunchServices/com.apple.launchservices.secure.plist"))
-)
-
-; Mach IPC needed by all Chromium Helper instances.
-(allow mach-lookup
- (global-name "com.apple.logd") ; https://crbug.com/792229
- (global-name "com.apple.system.logger")
- (global-name "com.apple.system.opendirectoryd.libinfo") ; https://crbug.com/792228
-)
-
-; sysctls permitted.
-(allow sysctl-read
- (sysctl-name "hw.activecpu")
- (sysctl-name "hw.busfrequency_compat")
- (sysctl-name "hw.byteorder")
- (sysctl-name "hw.cachelinesize_compat")
- (sysctl-name "hw.cpufrequency_compat")
- (sysctl-name "hw.cputype")
- (sysctl-name "hw.logicalcpu_max")
- (sysctl-name "hw.machine")
- (sysctl-name "hw.ncpu")
- (sysctl-name "hw.pagesize_compat")
- (sysctl-name "hw.physicalcpu_max")
- (sysctl-name "hw.tbfrequency_compat")
- (sysctl-name "hw.vectorunit")
- (sysctl-name "kern.hostname")
- (sysctl-name "kern.maxfilesperproc")
- (sysctl-name "kern.osrelease")
- (sysctl-name "kern.ostype")
- (sysctl-name "kern.osvariant_status")
- (sysctl-name "kern.osversion")
- (sysctl-name "kern.usrstack64")
- (sysctl-name "kern.version")
- (sysctl-name "sysctl.proc_cputype")
- (sysctl-name (string-append "kern.proc.pid." (param current-pid)))
-)
-
-(allow network-outbound
- (literal "/private/var/run/asl_input")
- (literal "/private/var/run/syslog")
-)
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls)
- (when (defined? 'syscall-unix)
- (allow syscall-unix
- (syscall-number SYS___disable_threadsignal)
- (syscall-number SYS___mac_syscall)
- (syscall-number SYS___pthread_kill)
- (syscall-number SYS___pthread_markcancel)
- (syscall-number SYS___pthread_sigmask)
- (syscall-number SYS___semwait_signal)
- (syscall-number SYS___semwait_signal_nocancel)
- (syscall-number SYS_access)
- (syscall-number SYS_bsdthread_create)
- (syscall-number SYS_bsdthread_ctl)
- (syscall-number SYS_bsdthread_register)
- (syscall-number SYS_bsdthread_terminate)
- (syscall-number SYS_close)
- (syscall-number SYS_close_nocancel)
- (syscall-number SYS_csops_audittoken)
- (syscall-number SYS_exit)
- (syscall-number SYS_fcntl)
- (syscall-number SYS_fileport_makefd)
- (syscall-number SYS_fileport_makeport)
- (syscall-number SYS_fstat64)
- (syscall-number SYS_fstatat64)
- (syscall-number SYS_fstatfs64)
- (syscall-number SYS_getattrlist)
- (syscall-number SYS_getattrlistbulk)
- (syscall-number SYS_getaudit_addr)
- (syscall-number SYS_getdirentries64)
- (syscall-number SYS_geteuid)
- (syscall-number SYS_getgid)
- (syscall-number SYS_gethostuuid)
- (syscall-number SYS_getpid)
- (syscall-number SYS_getppid)
- (syscall-number SYS_getpriority)
- (syscall-number SYS_getrlimit)
- (syscall-number SYS_gettimeofday)
- (syscall-number SYS_getuid)
- (syscall-number SYS_ioctl)
- (syscall-number SYS_issetugid)
- (syscall-number SYS_kdebug_trace64)
- (syscall-number SYS_kevent64)
- (syscall-number SYS_kevent_id)
- (syscall-number SYS_kevent_qos)
- (syscall-number SYS_kqueue)
- (syscall-number SYS_lstat64)
- (syscall-number SYS_madvise)
- (syscall-number SYS_mmap)
- (syscall-number SYS_mprotect)
- (syscall-number SYS_munmap)
- (syscall-number SYS_open)
- (syscall-number SYS_open_dprotected_np)
- (syscall-number SYS_open_nocancel)
- (syscall-number SYS_pread)
- (syscall-number SYS_proc_info)
- (syscall-number SYS_psynch_mutexdrop)
- (syscall-number SYS_psynch_mutexwait)
- (syscall-number SYS_psynch_rw_downgrade)
- (syscall-number SYS_psynch_rw_longrdlock)
- (syscall-number SYS_psynch_rw_rdlock)
- (syscall-number SYS_psynch_rw_unlock)
- (syscall-number SYS_psynch_rw_unlock2)
- (syscall-number SYS_psynch_rw_upgrade)
- (syscall-number SYS_psynch_rw_wrlock)
- (syscall-number SYS_psynch_rw_yieldwrlock)
- (syscall-number SYS_read)
- (syscall-number SYS_read_nocancel)
- (syscall-number SYS_readlink)
- (syscall-number SYS_shm_open)
- (syscall-number SYS_sigaction)
- (syscall-number SYS_sigprocmask)
- (syscall-number SYS_sigreturn)
- (syscall-number SYS_stat64)
- (syscall-number SYS_statfs64)
- (syscall-number SYS_sysctl)
- (syscall-number SYS_sysctlbyname)
- (syscall-number SYS_thread_selfid)
- (syscall-number SYS_ulock_wait)
- (syscall-number SYS_ulock_wake)
- (syscall-number SYS_workq_kernreturn)
- (syscall-number SYS_workq_open)
-)))
diff --git a/chromium/services/service_manager/sandbox/mac/gpu.sb b/chromium/services/service_manager/sandbox/mac/gpu.sb
deleted file mode 100644
index c02bbd5c18f..00000000000
--- a/chromium/services/service_manager/sandbox/mac/gpu.sb
+++ /dev/null
@@ -1,99 +0,0 @@
-;;
-;; Copyright (c) 2011 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.
-;;
-
-; *** The contents of the V1 sandbox common.sb are below. ***
-
-(version 1)
-
-; Helper function to check if a param is set to true.
-(define (param-true? str) (string=? (param str) "TRUE"))
-
-; Helper function to determine if a parameter is defined or not.
-(define (param-defined? str) (string? (param str)))
-
-; Define constants for all of the parameter strings passed in.
-(define bundle-version-path "BUNDLE_VERSION_PATH")
-(define disable-sandbox-denial-logging "DISABLE_SANDBOX_DENIAL_LOGGING")
-(define enable-logging "ENABLE_LOGGING")
-(define homedir-as-literal "USER_HOMEDIR_AS_LITERAL")
-(define elcap-or-later "ELCAP_OR_LATER")
-(define macos-1013 "MACOS_1013")
-(define field-trial-server-name "FIELD_TRIAL_SERVER_NAME")
-
-; Backwards compatibility for 10.9
-(if (not (defined? 'path))
- (define path literal))
-(if (not (defined? 'iokit-registry-entry-class))
- (define iokit-registry-entry-class iokit-user-client-class))
-
-; Consumes a subpath and appends it to the user's homedir path.
-(define (user-homedir-path subpath)
- (string-append (param homedir-as-literal) subpath))
-
-; (path) is not supported until 10.10.
-; TODO(kerrnel): remove this when 10.9 is no longer supported.
-(define (path x) (literal x))
-
-; DISABLE_SANDBOX_DENIAL_LOGGING turns off log messages in the system log.
-(if (param-true? disable-sandbox-denial-logging)
- (deny default (with no-log))
- (deny default))
-
-; Support for programmatically enabling verbose debugging.
-(if (param-true? enable-logging) (debug deny))
-
-(allow mach-lookup (global-name (param field-trial-server-name)))
-
-; Allow sending signals to self - https://crbug.com/20370
-(allow signal (target self))
-
-; Needed for full-page-zoomed controls - https://crbug.com/11325
-(allow sysctl-read)
-
-; Loading System Libraries.
-(allow file-read*
- (subpath "/System/Library/Frameworks")
- (subpath "/System/Library/PrivateFrameworks")
- (subpath "/System/Library/CoreServices"))
-
-(allow ipc-posix-shm)
-
-; Allow direct access to /dev/urandom, similar to Linux/POSIX, to allow
-; third party code (eg: bits of Adobe Flash and NSS) to function properly.
-(allow file-read-data file-read-metadata (literal "/dev/urandom"))
-
-; *** The contents of the V1 sandbox gpu.sb are below. ***
-
-; Allow communication between the GPU process and the UI server.
-(allow mach-lookup (global-name "com.apple.tsm.uiserver"))
-
-(allow file-read-metadata (literal "/"))
-
-; Needed for WebGL - crbug.com/75343
-(allow iokit-open
- (iokit-connection "IOAccelerator")
- (iokit-user-client-class "IOAccelerationUserClient")
- (iokit-user-client-class "IOFramebufferSharedUserClient")
- (iokit-user-client-class "AppleGraphicsControlClient")
- (iokit-user-client-class "AGPMClient")
- (iokit-user-client-class "IOHIDParamUserClient")
- (iokit-user-client-class "RootDomainUserClient")
- (iokit-user-client-class "IOSurfaceRootUserClient")
- (iokit-user-client-class "IOSurfaceSendRight"))
-
-; https://crbug.com/515280
-(if (param-true? elcap-or-later)
- (allow file-read* (subpath "/System/Library/Extensions")))
-
-; Needed for VideoToolbox usage - https://crbug.com/767037
-(allow mach-lookup (global-name "com.apple.coremedia.videodecoder"))
-
-; Needed for 10.14.5+ - https://crbug.com/957217
-(if (defined? 'xpc-service-name)
- (allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService")))
-
-; Needed for GPU process to fallback to SwiftShader - https://crbug.com/897914
-(allow file-read-data file-read-metadata (subpath (param bundle-version-path)))
diff --git a/chromium/services/service_manager/sandbox/mac/gpu_v2.sb b/chromium/services/service_manager/sandbox/mac/gpu_v2.sb
deleted file mode 100644
index 66f1bf89cca..00000000000
--- a/chromium/services/service_manager/sandbox/mac/gpu_v2.sb
+++ /dev/null
@@ -1,116 +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.
-
-; --- The contents of common.sb implicitly included here. ---
-
-; Allow cf prefs to work.
-(allow user-preference-read)
-
-(allow-cvms-blobs)
-
-(allow ipc-posix-shm)
-
-; Allow communication between the GPU process and the UI server.
-(allow mach-lookup
- (global-name "com.apple.bsd.dirhelper")
- (global-name "com.apple.cfprefsd.agent")
- (global-name "com.apple.cfprefsd.daemon")
- (global-name "com.apple.CoreServices.coreservicesd")
- (global-name "com.apple.coreservices.launchservicesd")
- (global-name "com.apple.cvmsServ")
- (global-name "com.apple.gpumemd.source")
- (global-name "com.apple.lsd.mapdb")
- (global-name "com.apple.lsd.modifydb")
- (global-name "com.apple.powerlog.plxpclogger.xpc")
- (global-name "com.apple.PowerManagement.control")
- (global-name "com.apple.SecurityServer")
- (global-name "com.apple.system.notification_center")
- (global-name "com.apple.tsm.uiserver")
- (global-name "com.apple.windowserver.active")
-)
-
-; Needed for metal decoding - https://crbug.com/957217
-(if (>= os-version 1014)
- (allow mach-lookup (xpc-service-name "com.apple.MTLCompilerService"))
-)
-
-; Needed for WebGL - https://crbug.com/75343
-(allow iokit-open
- (iokit-connection "IOAccelerator")
- (iokit-user-client-class "AGPMClient")
- (iokit-user-client-class "AppleGraphicsControlClient")
- (iokit-user-client-class "AppleGraphicsPolicyClient")
- (iokit-user-client-class "AppleIntelMEUserClient")
- (iokit-user-client-class "AppleMGPUPowerControlClient")
- (iokit-user-client-class "AppleSNBFBUserClient")
- (iokit-user-client-class "IOAccelerationUserClient")
- (iokit-user-client-class "IOFramebufferSharedUserClient")
- (iokit-user-client-class "IOHIDParamUserClient")
- (iokit-user-client-class "IOSurfaceRootUserClient")
- (iokit-user-client-class "IOSurfaceSendRight")
- (iokit-user-client-class "RootDomainUserClient")
-)
-
-(allow iokit-set-properties
- (require-all (iokit-connection "IODisplay")
- (require-any (iokit-property "brightness")
- (iokit-property "linear-brightness")
- (iokit-property "commit")
- (iokit-property "rgcs")
- (iokit-property "ggcs")
- (iokit-property "bgcs")
-)))
-
-(allow ipc-posix-shm-read-data
- (ipc-posix-name "apple.shm.notification_center"))
-
-; https://crbug.com/515280
-(if (>= os-version 1011)
- (allow file-read* (subpath "/System/Library/Extensions")))
-
-; Needed for VideoToolbox usage - https://crbug.com/767037
-(if (>= os-version 1013)
- (allow mach-lookup
- (xpc-service-name "com.apple.coremedia.videodecoder")
- (xpc-service-name "com.apple.coremedia.videoencoder")
- (xpc-service-name-regex #"\.apple-extension-service$")
-))
-
-(allow sysctl-read
- (sysctl-name "hw.logicalcpu_max")
- (sysctl-name "hw.model")
- (sysctl-name "kern.osvariant_status")
-)
-
-(allow file-read-data
- (path "/Library/MessageTracer/SubmitDiagInfo.default.domains.searchtree")
- (regex (user-homedir-path #"/Library/Preferences/ByHost/com.apple.AppleGVA.*"))
-)
-
-(allow file-read*
- (subpath "/Library/GPUBundles")
- (subpath "/Library/Video/Plug-Ins")
- (subpath "/System/Library/CoreServices/RawCamera.bundle")
- (subpath "/System/Library/Video/Plug-Ins")
-)
-
-; crbug.com/980134
-(allow file-read* file-write*
- (subpath (param darwin-user-cache-dir))
- (subpath (param darwin-user-dir))
- (subpath (param darwin-user-temp-dir))
-)
-
-(if (param-true? filter-syscalls-debug)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))
- (allow syscall-unix
- (syscall-number SYS_csrctl)
- (syscall-number SYS_getentropy)
- (syscall-number SYS_getxattr)
- (syscall-number SYS_kdebug_typefilter)
- (syscall-number SYS_sigaltstack)
- (syscall-number SYS_write)
- (syscall-number SYS_write_nocancel)
-)))
diff --git a/chromium/services/service_manager/sandbox/mac/nacl_loader.sb b/chromium/services/service_manager/sandbox/mac/nacl_loader.sb
deleted file mode 100644
index a5014f76413..00000000000
--- a/chromium/services/service_manager/sandbox/mac/nacl_loader.sb
+++ /dev/null
@@ -1,45 +0,0 @@
-;;
-;; Copyright (c) 2011 The Chromium Authors. All rights reserved.
-;; Use of this source code is governed by a BSD-style license that can be
-;; found in the LICENSE file.
-;;
-; This is the Sandbox configuration file used for safeguarding the user's
-; untrusted code within Native Client.
-;
-
-; *** The contents of common.sb are implicitly included here. ***
-
-; Allow a Native Client application to use semaphores, specifically
-; sem_init(), et.al.
-(allow ipc-posix-sem)
-
-(allow user-preference-read)
-
-(allow iokit-get-properties
- (iokit-registry-entry-class "IORegisterForSystemPower"))
-
-(allow iokit-open
- (iokit-user-client-class "IOSurfaceSendRight")
- (iokit-user-client-class "RootDomainUserClient")
-)
-
-(allow file-read-data
- (subpath "/usr/share/locale")
- ; e.g. ~/Library/Preferences/com.google.Chrome.plist
- (path (string-append
- (user-homedir-path "/Library/Preferences/")
- (param bundle-id)
- ".plist"))
-)
-
-(allow mach-lookup
- (global-name "com.apple.PowerManagement.control")
- (global-name "com.apple.system.notification_center")
-)
-
-(if (>= os-version 1014)
- (begin
- (allow sysctl-read (sysctl-name "kern.tcsm_enable"))
- (allow sysctl-write (sysctl-name "kern.tcsm_enable"))
- (allow sysctl-read (sysctl-name "kern.tcsm_available"))
-))
diff --git a/chromium/services/service_manager/sandbox/mac/network.sb b/chromium/services/service_manager/sandbox/mac/network.sb
deleted file mode 100644
index 9107f3704ba..00000000000
--- a/chromium/services/service_manager/sandbox/mac/network.sb
+++ /dev/null
@@ -1,124 +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.
-
-; --- The contents of common.sb implicitly included here. ---
-
-; Injected parameters.
-(define network-service-storage-paths-count "NETWORK_SERVICE_STORAGE_PATHS_COUNT")
-(define network-service-storage-path-n "NETWORK_SERVICE_STORAGE_PATH_")
-(define network-service-test-certs-dir "NETWORK_SERVICE_TEST_CERTS_DIR")
-
-; Allow access to the [0,N) storage location paths.
-(let ((count (string->number (param network-service-storage-paths-count))))
- (let loop ((i 0))
- (if (< i count)
- (begin
- (allow file* (subpath
- (param (string-append network-service-storage-path-n (number->string i)))))
- (loop (+ i 1))))))
-
-; DNS configuration watcher entries. This is a nesty mess of symlinks.
-(allow file-read*
- (path "/")
- (path "/etc")
- (path "/etc/hosts")
- (path "/etc/resolv.conf")
- (path "/private")
- (path "/private/etc")
- (path "/private/etc/hosts")
- (path "/private/etc/resolv.conf")
- (path "/private/var")
- (path "/private/var/run")
- (path "/private/var/run/resolv.conf")
- (path "/var")
- (path "/var/run")
-)
-
-; Local preferences.
-(allow file-read*
- (path (user-homedir-path (string-append "/Library/Preferences/" (param bundle-id) ".plist")))
-)
-
-; Certificate databases.
-(allow file-read*
- (path "/Library/Preferences/com.apple.security.plist")
- ; https://crbug.com/1024000
- (path (user-homedir-path "/Library/Preferences/com.apple.security.revocation.plist"))
- (subpath "/Library/Keychains")
- (subpath "/System/Library/Keychains")
- (subpath "/System/Library/Security")
- (subpath "/private/var/db/mds")
- (subpath (user-homedir-path "/Library/Keychains"))
-)
-(allow file-read* file-write*
- (subpath (param darwin-user-cache-dir))
- (subpath (param darwin-user-temp-dir))
-)
-(if (param-defined? network-service-test-certs-dir)
- (allow file-read* (subpath (param network-service-test-certs-dir))))
-
-; Network socket access.
-(allow network-outbound
- (control-name "com.apple.netsrc")
- (literal "/private/var/run/mDNSResponder")
- (remote tcp)
- (remote udp)
-)
-(allow network-bind network-inbound
- (local tcp)
- (local udp)
-)
-
-; DNS resolution.
-(allow system-socket
- (require-all (socket-domain AF_SYSTEM)
- (socket-protocol 2)) ; SYSPROTO_CONTROL
- (socket-domain AF_ROUTE)
-)
-
-; Distributed notifications memory.
-(allow ipc-posix-shm-read-data
- (ipc-posix-name "apple.shm.notification_center")
-)
-
-; Notification data from the security server database.
-(allow ipc-posix-shm
- (ipc-posix-name "com.apple.AppleDatabaseChanged")
-)
-
-(allow mach-lookup
- ; Set backup exclusion on cache files.
- (global-name "com.apple.backupd.sandbox.xpc")
-
- ; Used to look up the _CS_DARWIN_USER_CACHE_DIR in the sandbox.
- (global-name "com.apple.bsd.dirhelper")
- (global-name "com.apple.system.opendirectoryd.membership")
-
- ; Allow notifications of DNS changes.
- (global-name "com.apple.system.notification_center")
-
- ; Communicate with the security server for TLS certificate information.
- (global-name "com.apple.SecurityServer")
- (global-name "com.apple.networkd") ; https://crbug.com/1024000
- (global-name "com.apple.ocspd")
- (global-name "com.apple.trustd.agent")
-
- ; Read network configuration.
- (global-name "com.apple.SystemConfiguration.DNSConfiguration")
- (global-name "com.apple.SystemConfiguration.configd")
-)
-
-(allow sysctl-read
- (sysctl-name-regex #"^net.routetable")
-)
-
-; Kerberos support. This should be removed after GSS is moved out of the
-; network service. https://crbug.com/1017830
-(allow mach-lookup
- (global-name "org.h5l.kcm")
-)
-(allow file-read*
- (path "/private/etc/krb5.conf")
- (subpath "/System/Library/KerberosPlugins/KerberosFrameworkPlugins")
-)
diff --git a/chromium/services/service_manager/sandbox/mac/package_sb_file.py b/chromium/services/service_manager/sandbox/mac/package_sb_file.py
deleted file mode 100755
index 098d689a6c6..00000000000
--- a/chromium/services/service_manager/sandbox/mac/package_sb_file.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python
-# 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.
-
-import os
-import sys
-
-"""Pack MacOS sandbox seatbelt .sb files as C-style strings, escaping
-quotes and backslashes as needed.
-"""
-
-header = '// Generated by package_sb_file.py. Do not edit !!!\n\n'
-namespace = 'namespace service_manager {\n\n'
-namespace_end = '\n} // namespace service_manager\n'
-h_include = '#include "services/service_manager/sandbox/export.h"\n'
-h_definition = ('SERVICE_MANAGER_SANDBOX_EXPORT\n' +
- 'extern const char kSeatbeltPolicyString_%s[];\n\n')
-cc_include = '#include "services/service_manager/sandbox/mac/%s.sb.h"\n'
-cc_definition = 'const char kSeatbeltPolicyString_%s[] = \n'
-cc_definition_end = '"";\n' # Add "" so the definition has some content
- # (the empty string) if the sb file is empty.
-
-def escape_for_c(line):
- if line and line[0] == ';':
- return ''
- return line.replace('\\', '\\\\').replace('\"', '\\\"')
-
-def pack_file(argv):
- if len(argv) != 2:
- print >> sys.stderr, 'usage: package_sb_file.py input_filename output_dir'
- return 1
- input_filename = argv[0]
- output_directory = argv[1]
- input_basename = os.path.basename(input_filename)
- (module_name, module_ext) = os.path.splitext(input_basename)
- output_h_file = output_directory + '/' + input_basename + '.h'
- output_cc_file = output_directory + '/' + input_basename + '.cc'
- try:
- with open(input_filename, 'rb') as infile:
- with open(output_h_file, 'wb') as outfile:
- outfile.write(header)
- outfile.write(h_include)
- outfile.write(namespace)
- outfile.write(h_definition % module_name)
- outfile.write(namespace_end)
- with open(output_cc_file, 'wb') as outfile:
- outfile.write(header)
- outfile.write(cc_include % module_name)
- outfile.write(namespace)
- outfile.write(cc_definition % module_name)
- for line in infile:
- escaped_line = escape_for_c(line.rstrip())
- if escaped_line:
- outfile.write(' "' + escaped_line + '\\n"\n')
- outfile.write(cc_definition_end)
- outfile.write(namespace_end)
- except IOError:
- print >> sys.stderr, 'Failed to process %s' % input_filename
- return 1
- return 0
-
-if __name__ == '__main__':
- sys.exit(pack_file(sys.argv[1:]))
diff --git a/chromium/services/service_manager/sandbox/mac/ppapi.sb b/chromium/services/service_manager/sandbox/mac/ppapi.sb
deleted file mode 100644
index 6c0ca29e1f3..00000000000
--- a/chromium/services/service_manager/sandbox/mac/ppapi.sb
+++ /dev/null
@@ -1,49 +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.
-
-; --- The contents of common.sb implicitly included here. ---
-
-; Params specific to ppapi.
-(define ppapi-plugin-0 "PPAPI_PATH_0")
-(define ppapi-plugin-1 "PPAPI_PATH_1")
-(define ppapi-plugin-2 "PPAPI_PATH_2")
-(define ppapi-plugin-3 "PPAPI_PATH_3")
-(define ppapi-plugin-4 "PPAPI_PATH_4")
-
-; Needed for Fonts.
-(allow-font-access)
-
-; Mach lookups.
-(allow mach-lookup
- (global-name "com.apple.windowserver.active")
-)
-
-; IOKit
-(allow iokit-open
- (iokit-registry-entry-class "IOSurfaceRootUserClient")
-)
-
-; Reads from home dir.
-(allow file-read-data
- (path (user-homedir-path "/Library/Preferences/com.apple.universalaccess.plist"))
-)
-
-; Reads from /System.
-(allow file-read-data
- (path "/System/Library/Colors/System.clr/System.clr")
- (subpath "/System/Library/ColorSync/Profiles") ; https://crbug.com/822218
- (subpath "/System/Library/CoreServices/SystemAppearance.bundle")
-)
-
-; Allow the ppapi plugin binaries to be loaded.
-(if (param-defined? ppapi-plugin-0)
- (allow file-read-data (subpath (param ppapi-plugin-0))))
-(if (param-defined? ppapi-plugin-1)
- (allow file-read-data (subpath (param ppapi-plugin-1))))
-(if (param-defined? ppapi-plugin-2)
- (allow file-read-data (subpath (param ppapi-plugin-2))))
-(if (param-defined? ppapi-plugin-3)
- (allow file-read-data (subpath (param ppapi-plugin-3))))
-(if (param-defined? ppapi-plugin-4)
- (allow file-read-data (subpath (param ppapi-plugin-4))))
diff --git a/chromium/services/service_manager/sandbox/mac/print_compositor.sb b/chromium/services/service_manager/sandbox/mac/print_compositor.sb
deleted file mode 100644
index a8287999a5a..00000000000
--- a/chromium/services/service_manager/sandbox/mac/print_compositor.sb
+++ /dev/null
@@ -1,33 +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.
-;;
-; This is the sandbox configuration file used for safeguarding the print
-; compositor service which is used for compositing web contents printed from
-; different renderer processes.
-;
-; This configuration locks everything down, except font accesses.
-;
-
-; *** The contents of common.sb are implicitly included here. ***
-
-; Needed for Fonts.
-(allow-font-access)
-
-; Reads from /System.
-(allow file-read-data
- (subpath "/System/Library/ColorSync/Profiles") ; https://crbug.com/822218
-)
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls-debug)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))
- (allow syscall-unix
- (syscall-number SYS_fsgetpath)
- (syscall-number SYS_getfsstat64)
- (syscall-number SYS_mkdir)
- (syscall-number SYS_pathconf)
- (syscall-number SYS_sigaltstack)
- (syscall-number SYS_write)
-)))
diff --git a/chromium/services/service_manager/sandbox/mac/renderer.sb b/chromium/services/service_manager/sandbox/mac/renderer.sb
deleted file mode 100644
index 5071b8ce7ee..00000000000
--- a/chromium/services/service_manager/sandbox/mac/renderer.sb
+++ /dev/null
@@ -1,193 +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.
-
-; --- The contents of common.sb implicitly included here. ---
-
-; Put the denials first.
-; crbug.com/799149: These operations are allowed by default.
-(if (>= os-version 1013)
- (if (param-true? disable-sandbox-denial-logging)
- (deny iokit-get-properties process-info* nvram* (with no-log))
- (deny iokit-get-properties process-info* nvram*)
-))
-
-; Allow cf prefs to work.
-(allow user-preference-read)
-
-; process-info
-(if (>= os-version 1013)
- (begin
- (allow process-info-pidinfo)
- (allow process-info-setcontrol (target self))
-))
-
-; File reads.
-; Reads from the home directory.
-(allow file-read-data
- (path (user-homedir-path "/.CFUserTextEncoding"))
- (path (user-homedir-path "/Library/Preferences/com.apple.universalaccess.plist"))
-)
-
-; Reads of /dev devices.
-(allow file-read-data
- (path "/dev/autofs_nowait")
- (path "/dev/fd")
-)
-
-(allow-cvms-blobs)
-
-(allow file-write-data
- (require-all
- (path "/dev/null")
- (vnode-type CHARACTER-DEVICE)))
-
-; Needed for Fonts.
-(allow-font-access)
-
-; Reads from /System.
-(allow file-read-data
- (path "/System/Library/CoreServices/CoreTypes.bundle/Contents/Library/AppExceptions.bundle/Exceptions.plist")
- (path "/System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/Exceptions.plist")
- (path "/System/Library/Preferences/Logging/Subsystems/com.apple.SkyLight.plist")
- (subpath "/System/Library/ColorSync/Profiles")
- (subpath "/System/Library/CoreServices/SystemAppearance.bundle")
- (subpath "/System/Library/CoreServices/SystemVersion.bundle")
- (subpath "/System/Library/Extensions") ; https://crbug.com/847518
- (subpath "/System/Library/LinguisticData")
-)
-
-; Reads from /Library.
-(allow file-read-data
- (subpath "/Library/GPUBundles") ; https://crbug.com/850021
-)
-
-; IOKit
-(allow iokit-open
- (iokit-registry-entry-class "IOSurfaceRootUserClient")
- (iokit-registry-entry-class "RootDomainUserClient")
- (iokit-user-client-class "IOSurfaceSendRight")
-)
-
-; POSIX IPC
-(allow ipc-posix-shm-read-data
- (ipc-posix-name "apple.cfprefs.317580v1")
- (ipc-posix-name "apple.cfprefs.daemonv1")
- (ipc-posix-name "apple.shm.notification_center") ; https://crbug.com/792217
-)
-
-; mach IPC
-(allow mach-lookup
- (global-name "com.apple.cvmsServ") ; https://crbug.com/850021
- (global-name "com.apple.distributed_notifications@Uv3") ; https://crbug.com/792257
- (global-name "com.apple.lsd.mapdb")
- (global-name "com.apple.system.notification_center") ; https://crbug.com/792217
-)
-
-; IOKit properties.
-(if (>= os-version 1013)
- (allow iokit-get-properties
- (iokit-property "CaseSensitive")
- (iokit-property "CoreStorage Encrypted")
- (iokit-property "Ejectable")
- (iokit-property "Encrypted")
- (iokit-property "IOClassNameOverride")
- (iokit-property "IOMediaIcon")
- (iokit-property "Product Identification")
- (iokit-property "Protocol Characteristics")
- (iokit-property "Removable")
- (iokit-property "image-encrypted")
-))
-
-; For V8 to use in thread calculations.
-(if (>= os-version 1014)
- (begin
- (allow sysctl-read (sysctl-name "kern.tcsm_enable"))
- (allow sysctl-write (sysctl-name "kern.tcsm_enable"))
- (allow sysctl-read (sysctl-name "kern.tcsm_available"))
-))
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))
- (allow syscall-unix
- (syscall-number SYS_change_fdguard_np)
- (syscall-number SYS_chdir)
- (syscall-number SYS_chmod)
- (syscall-number SYS_csops)
- (syscall-number SYS_csrctl)
- (syscall-number SYS_dup)
- (syscall-number SYS_dup2)
- (syscall-number SYS_fchmod)
- (syscall-number SYS_fcntl_nocancel)
- (syscall-number SYS_fgetxattr)
- (syscall-number SYS_fileport_makefd)
- (syscall-number SYS_fileport_makeport)
- (syscall-number SYS_flock)
- (syscall-number SYS_fsetattrlist)
- (syscall-number SYS_fsgetpath)
- (syscall-number SYS_fsync)
- (syscall-number SYS_ftruncate)
- (syscall-number SYS_getegid)
- (syscall-number SYS_getentropy)
- (syscall-number SYS_getfsstat64)
- (syscall-number SYS_getrusage)
- (syscall-number SYS_getsockopt)
- (syscall-number SYS_gettid)
- (syscall-number SYS_getxattr)
- (syscall-number SYS_guarded_close_np)
- (syscall-number SYS_guarded_open_np)
- (syscall-number SYS_guarded_pwrite_np)
- (syscall-number SYS_kdebug_trace)
- (syscall-number SYS_kdebug_typefilter)
- (syscall-number SYS_listxattr)
- (syscall-number SYS_lseek)
- (syscall-number SYS_memorystatus_control)
- (syscall-number SYS_mkdir)
- (syscall-number SYS_mkdirat)
- (syscall-number SYS_mlock)
- (syscall-number SYS_msync)
- (syscall-number SYS_munlock)
- (syscall-number SYS_necp_client_action)
- (syscall-number SYS_necp_open)
- (syscall-number SYS_openat)
- (syscall-number SYS_openat_nocancel)
- (syscall-number SYS_pathconf)
- (syscall-number SYS_pipe)
- (syscall-number SYS_pread_nocancel)
- (syscall-number SYS_proc_rlimit_control)
- (syscall-number SYS_process_policy)
- (syscall-number SYS_psynch_cvbroad)
- (syscall-number SYS_psynch_cvclrprepost)
- (syscall-number SYS_psynch_cvsignal)
- (syscall-number SYS_psynch_cvwait)
- (syscall-number SYS_psynch_rw_unlock)
- (syscall-number SYS_psynch_rw_wrlock)
- (syscall-number SYS_pwrite)
- (syscall-number SYS_quotactl)
- (syscall-number SYS_recvfrom_nocancel)
- (syscall-number SYS_rename)
- (syscall-number SYS_rmdir)
- (syscall-number SYS_select)
- (syscall-number SYS_select_nocancel)
- (syscall-number SYS_sem_close)
- (syscall-number SYS_sem_open)
- (syscall-number SYS_sem_post)
- (syscall-number SYS_sem_wait)
- (syscall-number SYS_sendmsg_nocancel)
- (syscall-number SYS_sendto)
- (syscall-number SYS_sendto_nocancel)
- (syscall-number SYS_setpriority)
- (syscall-number SYS_setrlimit)
- (syscall-number SYS_setsockopt)
- (syscall-number SYS_shared_region_check_np)
- (syscall-number SYS_shutdown)
- (syscall-number SYS_sigaltstack)
- (syscall-number SYS_umask)
- (syscall-number SYS_unlink)
- (syscall-number SYS_work_interval_ctl)
- (syscall-number SYS_write)
- (syscall-number SYS_write_nocancel)
- (syscall-number SYS_writev)
-)))
diff --git a/chromium/services/service_manager/sandbox/mac/sandbox_mac.h b/chromium/services/service_manager/sandbox/mac/sandbox_mac.h
deleted file mode 100644
index dd2d9e1b1a4..00000000000
--- a/chromium/services/service_manager/sandbox/mac/sandbox_mac.h
+++ /dev/null
@@ -1,72 +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 SERVICE_MANAGER_SANDBOX_MAC_SANDBOX_MAC_H_
-#define SERVICE_MANAGER_SANDBOX_MAC_SANDBOX_MAC_H_
-
-#include "base/gtest_prod_util.h"
-#include "base/macros.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-namespace base {
-class FilePath;
-}
-
-namespace service_manager {
-
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxMac {
- public:
- // Warm up System APIs that empirically need to be accessed before the
- // sandbox is turned on. |sandbox_type| is the type of sandbox to warm up.
- // Valid |sandbox_type| values are defined by the enum SandboxType, or can be
- // defined by the embedder via
- // ContentClient::GetSandboxProfileForProcessType().
- static void Warmup(SandboxType sandbox_type);
-
- // Turns on the OS X sandbox for this process.
- // |sandbox_type| - type of Sandbox to use. See SandboxWarmup() for legal
- // values.
- //
- // Returns true on success, false if an error occurred enabling the sandbox.
- static bool Enable(SandboxType sandbox_type);
-
- // Convert provided path into a "canonical" path matching what the Sandbox
- // expects i.e. one without symlinks.
- // This path is not necessarily unique e.g. in the face of hardlinks.
- static base::FilePath GetCanonicalPath(const base::FilePath& path);
-
- // Returns the sandbox profile string for a given sandbox type.
- // It CHECKs that the sandbox profile is a valid type, so it always returns a
- // valid result, or crashes.
- static std::string GetSandboxProfile(SandboxType sandbox_type);
-
- static const char* kSandboxBrowserPID;
- static const char* kSandboxBundlePath;
- static const char* kSandboxChromeBundleId;
- static const char* kSandboxComponentPath;
- static const char* kSandboxDisableDenialLogging;
- static const char* kSandboxEnableLogging;
- static const char* kSandboxHomedirAsLiteral;
- static const char* kSandboxLoggingPathAsLiteral;
- static const char* kSandboxOSVersion;
-
- // TODO(kerrnel): this is only for the legacy sandbox.
- static const char* kSandboxElCapOrLater;
- static const char* kSandboxMacOS1013;
- static const char* kSandboxFieldTrialSeverName;
-
- static const char* kSandboxBundleVersionPath;
-
- private:
- FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, StringEscape);
- FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, RegexEscape);
- FRIEND_TEST_ALL_PREFIXES(MacDirAccessSandboxTest, SandboxAccess);
-
- DISALLOW_IMPLICIT_CONSTRUCTORS(SandboxMac);
-};
-
-} // namespace service_manager
-
-#endif // SERVICE_MANAGER_SANDBOX_MAC_SANDBOX_MAC_H_
diff --git a/chromium/services/service_manager/sandbox/mac/sandbox_mac.mm b/chromium/services/service_manager/sandbox/mac/sandbox_mac.mm
deleted file mode 100644
index 511d7edb0c2..00000000000
--- a/chromium/services/service_manager/sandbox/mac/sandbox_mac.mm
+++ /dev/null
@@ -1,272 +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/sandbox/mac/sandbox_mac.h"
-
-#import <Cocoa/Cocoa.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <CoreFoundation/CFTimeZone.h>
-#include <signal.h>
-#include <sys/param.h>
-
-#include <algorithm>
-#include <iterator>
-#include <map>
-#include <string>
-
-#include "base/command_line.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/mac/bundle_locations.h"
-#include "base/mac/foundation_util.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/mach_port_rendezvous.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/mac/scoped_nsobject.h"
-#include "base/rand_util.h"
-#include "base/stl_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_split.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/system/sys_info.h"
-#include "sandbox/mac/sandbox_compiler.h"
-#include "services/service_manager/sandbox/mac/audio.sb.h"
-#include "services/service_manager/sandbox/mac/cdm.sb.h"
-#include "services/service_manager/sandbox/mac/common.sb.h"
-#include "services/service_manager/sandbox/mac/gpu.sb.h"
-#include "services/service_manager/sandbox/mac/gpu_v2.sb.h"
-#include "services/service_manager/sandbox/mac/nacl_loader.sb.h"
-#include "services/service_manager/sandbox/mac/network.sb.h"
-#include "services/service_manager/sandbox/mac/ppapi.sb.h"
-#include "services/service_manager/sandbox/mac/print_compositor.sb.h"
-#include "services/service_manager/sandbox/mac/renderer.sb.h"
-#include "services/service_manager/sandbox/mac/utility.sb.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-#include "services/service_manager/sandbox/switches.h"
-
-namespace service_manager {
-
-// Static variable declarations.
-const char* SandboxMac::kSandboxBrowserPID = "BROWSER_PID";
-const char* SandboxMac::kSandboxBundlePath = "BUNDLE_PATH";
-const char* SandboxMac::kSandboxChromeBundleId = "BUNDLE_ID";
-const char* SandboxMac::kSandboxComponentPath = "COMPONENT_PATH";
-const char* SandboxMac::kSandboxDisableDenialLogging =
- "DISABLE_SANDBOX_DENIAL_LOGGING";
-const char* SandboxMac::kSandboxEnableLogging = "ENABLE_LOGGING";
-const char* SandboxMac::kSandboxHomedirAsLiteral = "USER_HOMEDIR_AS_LITERAL";
-const char* SandboxMac::kSandboxLoggingPathAsLiteral = "LOG_FILE_PATH";
-const char* SandboxMac::kSandboxOSVersion = "OS_VERSION";
-const char* SandboxMac::kSandboxElCapOrLater = "ELCAP_OR_LATER";
-const char* SandboxMac::kSandboxMacOS1013 = "MACOS_1013";
-const char* SandboxMac::kSandboxFieldTrialSeverName = "FIELD_TRIAL_SERVER_NAME";
-const char* SandboxMac::kSandboxBundleVersionPath = "BUNDLE_VERSION_PATH";
-
-// Warm up System APIs that empirically need to be accessed before the Sandbox
-// is turned on.
-// This method is layed out in blocks, each one containing a separate function
-// that needs to be warmed up. The OS version on which we found the need to
-// enable the function is also noted.
-// This function is tested on the following OS versions:
-// 10.5.6, 10.6.0
-
-// static
-void SandboxMac::Warmup(SandboxType sandbox_type) {
- DCHECK_EQ(sandbox_type, SandboxType::kGpu);
-
- @autoreleasepool {
- { // CGColorSpaceCreateWithName(), CGBitmapContextCreate() - 10.5.6
- base::ScopedCFTypeRef<CGColorSpaceRef> rgb_colorspace(
- CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB));
-
- // Allocate a 1x1 image.
- char data[4];
- base::ScopedCFTypeRef<CGContextRef> context(CGBitmapContextCreate(
- data, 1, 1, 8, 1 * 4, rgb_colorspace,
- kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host));
-
- // Load in the color profiles we'll need (as a side effect).
- ignore_result(base::mac::GetSRGBColorSpace());
- ignore_result(base::mac::GetSystemColorSpace());
-
- // CGColorSpaceCreateSystemDefaultCMYK - 10.6
- base::ScopedCFTypeRef<CGColorSpaceRef> cmyk_colorspace(
- CGColorSpaceCreateWithName(kCGColorSpaceGenericCMYK));
- }
-
- { // localtime() - 10.5.6
- time_t tv = {0};
- localtime(&tv);
- }
-
- { // Gestalt() tries to read
- // /System/Library/CoreServices/SystemVersion.plist
- // on 10.5.6
- int32_t tmp;
- base::SysInfo::OperatingSystemVersionNumbers(&tmp, &tmp, &tmp);
- }
-
- { // CGImageSourceGetStatus() - 10.6
- // Create a png with just enough data to get everything warmed up...
- char png_header[] = {0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};
- NSData* data = [NSData dataWithBytes:png_header
- length:base::size(png_header)];
- base::ScopedCFTypeRef<CGImageSourceRef> img(
- CGImageSourceCreateWithData((CFDataRef)data, NULL));
- CGImageSourceGetStatus(img);
- }
-
- {
- // Allow access to /dev/urandom.
- base::GetUrandomFD();
- }
-
- { // IOSurfaceLookup() - 10.7
- // Needed by zero-copy texture update framework - crbug.com/323338
- base::ScopedCFTypeRef<IOSurfaceRef> io_surface(IOSurfaceLookup(0));
- }
- }
-}
-
-// Load the appropriate template for the given sandbox type.
-// Returns the template as a string or an empty string on error.
-std::string LoadSandboxTemplate(SandboxType sandbox_type) {
- DCHECK_EQ(sandbox_type, SandboxType::kGpu);
- return kSeatbeltPolicyString_gpu;
-}
-
-// Turns on the OS X sandbox for this process.
-
-// static
-bool SandboxMac::Enable(SandboxType sandbox_type) {
- DCHECK_EQ(sandbox_type, SandboxType::kGpu);
-
- std::string sandbox_data = LoadSandboxTemplate(sandbox_type);
- if (sandbox_data.empty())
- return false;
-
- sandbox::SandboxCompiler compiler(sandbox_data);
-
- // Enable verbose logging if enabled on the command line. (See common.sb
- // for details).
- const base::CommandLine* command_line =
- base::CommandLine::ForCurrentProcess();
- bool enable_logging =
- command_line->HasSwitch(switches::kEnableSandboxLogging);
- if (!compiler.InsertBooleanParam(kSandboxEnableLogging, enable_logging))
- return false;
-
- // Without this, the sandbox will print a message to the system log every
- // time it denies a request. This floods the console with useless spew.
- if (!compiler.InsertBooleanParam(kSandboxDisableDenialLogging,
- !enable_logging))
- return false;
-
- // Splice the path of the user's home directory into the sandbox profile
- // (see renderer.sb for details).
- std::string home_dir = [NSHomeDirectory() fileSystemRepresentation];
- base::FilePath home_dir_canonical =
- GetCanonicalPath(base::FilePath(home_dir));
-
- if (!compiler.InsertStringParam(kSandboxHomedirAsLiteral,
- home_dir_canonical.value())) {
- return false;
- }
-
- if (!compiler.InsertStringParam(
- kSandboxFieldTrialSeverName,
- base::MachPortRendezvousClient::GetBootstrapName())) {
- return false;
- }
-
- bool elcap_or_later = base::mac::IsAtLeastOS10_11();
- if (!compiler.InsertBooleanParam(kSandboxElCapOrLater, elcap_or_later))
- return false;
-
- bool macos_1013 = base::mac::IsOS10_13();
- if (!compiler.InsertBooleanParam(kSandboxMacOS1013, macos_1013))
- return false;
-
- if (sandbox_type == service_manager::SandboxType::kGpu) {
- base::FilePath bundle_path =
- SandboxMac::GetCanonicalPath(base::mac::FrameworkBundlePath());
- if (!compiler.InsertStringParam(kSandboxBundleVersionPath,
- bundle_path.value()))
- return false;
- }
-
- // Initialize sandbox.
- std::string error_str;
- bool success = compiler.CompileAndApplyProfile(&error_str);
- DLOG_IF(FATAL, !success) << "Failed to initialize sandbox: " << error_str;
- return success;
-}
-
-// static
-base::FilePath SandboxMac::GetCanonicalPath(const base::FilePath& path) {
- base::ScopedFD fd(HANDLE_EINTR(open(path.value().c_str(), O_RDONLY)));
- if (!fd.is_valid()) {
- DPLOG(ERROR) << "GetCanonicalSandboxPath() failed for: " << path.value();
- return path;
- }
-
- base::FilePath::CharType canonical_path[MAXPATHLEN];
- if (HANDLE_EINTR(fcntl(fd.get(), F_GETPATH, canonical_path)) != 0) {
- DPLOG(ERROR) << "GetCanonicalSandboxPath() failed for: " << path.value();
- return path;
- }
-
- return base::FilePath(canonical_path);
-}
-
-// static
-std::string SandboxMac::GetSandboxProfile(SandboxType sandbox_type) {
- std::string profile =
- std::string(service_manager::kSeatbeltPolicyString_common);
-
- switch (sandbox_type) {
- case service_manager::SandboxType::kAudio:
- profile += service_manager::kSeatbeltPolicyString_audio;
- break;
- case service_manager::SandboxType::kCdm:
- profile += service_manager::kSeatbeltPolicyString_cdm;
- break;
- case service_manager::SandboxType::kGpu:
- profile += service_manager::kSeatbeltPolicyString_gpu_v2;
- break;
- case service_manager::SandboxType::kNaClLoader:
- profile += service_manager::kSeatbeltPolicyString_nacl_loader;
- break;
- case service_manager::SandboxType::kNetwork:
- profile += service_manager::kSeatbeltPolicyString_network;
- break;
- case service_manager::SandboxType::kPpapi:
- profile += service_manager::kSeatbeltPolicyString_ppapi;
- break;
- case service_manager::SandboxType::kPrintCompositor:
- profile += service_manager::kSeatbeltPolicyString_print_compositor;
- break;
- case service_manager::SandboxType::kUtility:
- profile += service_manager::kSeatbeltPolicyString_utility;
- break;
- case service_manager::SandboxType::kRenderer:
- profile += service_manager::kSeatbeltPolicyString_renderer;
- break;
- case service_manager::SandboxType::kNoSandbox:
- case service_manager::SandboxType::kVideoCapture:
- case service_manager::SandboxType::kSpeechRecognition:
- CHECK(false);
- break;
- }
- return profile;
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/mac/utility.sb b/chromium/services/service_manager/sandbox/mac/utility.sb
deleted file mode 100644
index c71837a0ca7..00000000000
--- a/chromium/services/service_manager/sandbox/mac/utility.sb
+++ /dev/null
@@ -1,26 +0,0 @@
-;;
-;; Copyright (c) 2011 The Chromium Authors. All rights reserved.
-;; Use of this source code is governed by a BSD-style license that can be
-;; found in the LICENSE file.
-;;
-; This is the Sandbox configuration file used for safeguarding the utility
-; process which is used for performing sandboxed operations that need to touch
-; the filesystem like decoding theme images and unpacking extensions.
-;
-; This configuration locks everything down, except access to one configurable
-; directory. This is different from other sandbox configuration files where
-; file system access is entireley restricted.
-
-; *** The contents of common.sb are implicitly included here. ***
-
-; No additional resource access needed.
-
-; This is available in 10.15+, and rolled out as a Finch experiment.
-(if (param-true? filter-syscalls-debug)
- (when (defined? 'syscall-unix)
- (deny syscall-unix (with send-signal SIGSYS))
- (allow syscall-unix
- (syscall-number SYS_psynch_cvwait)
- (syscall-number SYS_sendto)
- (syscall-number SYS_socketpair)
-)))
diff --git a/chromium/services/service_manager/sandbox/sandbox.cc b/chromium/services/service_manager/sandbox/sandbox.cc
deleted file mode 100644
index c1af5077d19..00000000000
--- a/chromium/services/service_manager/sandbox/sandbox.cc
+++ /dev/null
@@ -1,126 +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/sandbox/sandbox.h"
-
-#include "base/command_line.h"
-#include "build/build_config.h"
-#include "services/service_manager/sandbox/switches.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#endif // defined(OS_ANDROID)
-
-#if defined(OS_LINUX)
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#endif // defined(OS_LINUX)
-
-#if defined(OS_MACOSX)
-#include "sandbox/mac/seatbelt.h"
-#include "services/service_manager/sandbox/mac/sandbox_mac.h"
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_WIN)
-#include "base/process/process_info.h"
-#include "sandbox/win/src/sandbox.h"
-#include "services/service_manager/sandbox/win/sandbox_win.h"
-#endif // defined(OS_WIN)
-
-namespace service_manager {
-
-#if defined(OS_LINUX)
-bool Sandbox::Initialize(SandboxType sandbox_type,
- SandboxLinux::PreSandboxHook hook,
- const SandboxLinux::Options& options) {
- return SandboxLinux::GetInstance()->InitializeSandbox(
- sandbox_type, std::move(hook), options);
-}
-#endif // defined(OS_LINUX)
-
-#if defined(OS_MACOSX)
-bool Sandbox::Initialize(SandboxType sandbox_type, base::OnceClosure hook) {
- // Warm up APIs before turning on the sandbox.
- SandboxMac::Warmup(sandbox_type);
-
- // Execute the post warmup callback.
- if (!hook.is_null())
- std::move(hook).Run();
-
- // Actually sandbox the process.
- return SandboxMac::Enable(sandbox_type);
-}
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_WIN)
-bool Sandbox::Initialize(SandboxType sandbox_type,
- sandbox::SandboxInterfaceInfo* sandbox_info) {
- sandbox::BrokerServices* broker_services = sandbox_info->broker_services;
- if (broker_services) {
- if (!SandboxWin::InitBrokerServices(broker_services))
- return false;
-
- // IMPORTANT: This piece of code needs to run as early as possible in the
- // process because it will initialize the sandbox broker, which requires the
- // process to swap its window station. During this time all the UI will be
- // broken. This has to run before threads and windows are created.
- if (!IsUnsandboxedSandboxType(sandbox_type)) {
- // Precreate the desktop and window station used by the renderers.
- scoped_refptr<sandbox::TargetPolicy> policy =
- broker_services->CreatePolicy();
- sandbox::ResultCode result = policy->CreateAlternateDesktop(true);
- CHECK(sandbox::SBOX_ERROR_FAILED_TO_SWITCH_BACK_WINSTATION != result);
- }
- return true;
- }
- return IsUnsandboxedSandboxType(sandbox_type) ||
- SandboxWin::InitTargetServices(sandbox_info->target_services);
-}
-#endif // defined(OS_WIN)
-
-// static
-bool Sandbox::IsProcessSandboxed() {
- auto* command_line = base::CommandLine::ForCurrentProcess();
- bool is_browser = !command_line->HasSwitch(switches::kProcessType);
-
- if (!is_browser &&
- base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kNoSandbox)) {
- // When running with --no-sandbox, unconditionally report the process as
- // sandboxed. This lets code write |DCHECK(IsProcessSandboxed())| and not
- // break when testing with the --no-sandbox switch.
- return true;
- }
-
-#if defined(OS_ANDROID)
- // Note that this does not check the status of the Seccomp sandbox. Call
- // https://developer.android.com/reference/android/os/Process#isIsolated().
- JNIEnv* env = base::android::AttachCurrentThread();
- base::android::ScopedJavaLocalRef<jclass> process_class =
- base::android::GetClass(env, "android/os/Process");
- jmethodID is_isolated =
- base::android::MethodID::Get<base::android::MethodID::TYPE_STATIC>(
- env, process_class.obj(), "isIsolated", "()Z");
- return env->CallStaticBooleanMethod(process_class.obj(), is_isolated);
-#elif defined(OS_FUCHSIA)
- // TODO(https://crbug.com/1071420): Figure out what to do here. Process
- // launching controls the sandbox and there are no ambient capabilities, so
- // basically everything but the browser is considered sandboxed.
- return !is_browser;
-#elif defined(OS_LINUX)
- int status = SandboxLinux::GetInstance()->GetStatus();
- constexpr int kLayer1Flags = SandboxLinux::Status::kSUID |
- SandboxLinux::Status::kPIDNS |
- SandboxLinux::Status::kUserNS;
- constexpr int kLayer2Flags =
- SandboxLinux::Status::kSeccompBPF | SandboxLinux::Status::kSeccompTSYNC;
- return (status & kLayer1Flags) != 0 && (status & kLayer2Flags) != 0;
-#elif defined(OS_MACOSX)
- return sandbox::Seatbelt::IsSandboxed();
-#elif defined(OS_WIN)
- return base::GetCurrentProcessIntegrityLevel() < base::MEDIUM_INTEGRITY;
-#else
- return false;
-#endif
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/sandbox.h b/chromium/services/service_manager/sandbox/sandbox.h
deleted file mode 100644
index 535df983713..00000000000
--- a/chromium/services/service_manager/sandbox/sandbox.h
+++ /dev/null
@@ -1,73 +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 SERVICE_MANAGER_SANDBOX_SANDBOX_H_
-#define SERVICE_MANAGER_SANDBOX_SANDBOX_H_
-
-#include "build/build_config.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-#if defined(OS_LINUX)
-#include "services/service_manager/sandbox/linux/sandbox_linux.h"
-#endif
-
-#if defined(OS_MACOSX)
-#include "base/callback.h"
-#endif // defined(OS_MACOSX)
-
-namespace sandbox {
-struct SandboxInterfaceInfo;
-} // namespace sandbox
-
-namespace service_manager {
-
-// Interface to the service manager sandboxes across the various platforms.
-//
-// Ideally, this API would abstract away the platform differences, but there
-// are some major OS differences that shape this interface, including:
-// * Whether the sandboxing is performed by the launcher (Windows, Fuchsia
-// someday) or by the launchee (Linux, Mac).
-// * The means of specifying the additional resources that are permitted.
-// * The need to "warmup" other resources before engaing the sandbox.
-
-class SERVICE_MANAGER_SANDBOX_EXPORT Sandbox {
- public:
-#if defined(OS_LINUX)
- static bool Initialize(SandboxType sandbox_type,
- SandboxLinux::PreSandboxHook hook,
- const SandboxLinux::Options& options);
-#endif // defined(OS_LINUX)
-
-#if defined(OS_MACOSX)
- // Initialize the sandbox of |sandbox_type|. Runs |post_warmup_hook| if
- // non-empty after performing any sandbox warmup but immediately before
- // engaging the sandbox. Return true on success, false otherwise.
- static bool Initialize(SandboxType sandbox_type,
- base::OnceClosure post_warmup_hook);
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_WIN)
- static bool Initialize(service_manager::SandboxType sandbox_type,
- sandbox::SandboxInterfaceInfo* sandbox_info);
-#endif // defined(OS_WIN)
-
- // Returns true if the current process is running with a sandbox, and false
- // if the process is not sandboxed. This should be used to assert that code is
- // not running at high-privilege (e.g. in the browser process):
- //
- // DCHECK(service_manager::Sandbox::IsProcessSandboxed());
- //
- // The definition of what constitutes a sandbox, and the relative strength of
- // the restrictions placed on the process, and a per-platform implementation
- // detail.
- //
- // Except if the process is the browser, if the process is running with the
- // --no-sandbox flag, this unconditionally returns true.
- static bool IsProcessSandboxed();
-};
-
-} // namespace service_manager
-
-#endif // SERVICE_MANAGER_SANDBOX_SANDBOX_H_
diff --git a/chromium/services/service_manager/sandbox/sandbox_delegate.h b/chromium/services/service_manager/sandbox/sandbox_delegate.h
deleted file mode 100644
index 9d32a52ced9..00000000000
--- a/chromium/services/service_manager/sandbox/sandbox_delegate.h
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_DELEGATE_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_DELEGATE_H_
-
-#include <string>
-
-#include "base/process/process.h"
-#include "build/build_config.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-namespace sandbox {
-class TargetPolicy;
-}
-
-namespace service_manager {
-
-class SandboxDelegate {
- public:
- virtual ~SandboxDelegate() {}
-
- // Returns the SandboxType to enforce on the process, or
- // SandboxType::kNoSandbox to run without a sandbox policy.
- virtual service_manager::SandboxType GetSandboxType() = 0;
-
-#if defined(OS_WIN)
- // Whether to disable the default policy specified in
- // AddPolicyForSandboxedProcess.
- virtual bool DisableDefaultPolicy() = 0;
-
- // Get the AppContainer ID for the sandbox. If this returns false then the
- // AppContainer will not be enabled for the process.
- virtual bool GetAppContainerId(std::string* appcontainer_id) = 0;
-
- // Called right before spawning the process. Returns false on failure.
- virtual bool PreSpawnTarget(sandbox::TargetPolicy* policy) = 0;
-
- // Called right after the process is launched, but before its thread is run.
- virtual void PostSpawnTarget(base::ProcessHandle process) = 0;
-#endif // defined(OS_WIN)
-};
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_DELEGATE_H_
diff --git a/chromium/services/service_manager/sandbox/sandbox_type.cc b/chromium/services/service_manager/sandbox/sandbox_type.cc
deleted file mode 100644
index de79b63b7de..00000000000
--- a/chromium/services/service_manager/sandbox/sandbox_type.cc
+++ /dev/null
@@ -1,329 +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/sandbox/sandbox_type.h"
-
-#include <string>
-
-#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"
-
-namespace service_manager {
-
-bool IsUnsandboxedSandboxType(SandboxType sandbox_type) {
- switch (sandbox_type) {
- case SandboxType::kNoSandbox:
- return true;
-#if defined(OS_WIN)
- case SandboxType::kNoSandboxAndElevatedPrivileges:
- return true;
- case SandboxType::kXrCompositing:
- return !base::FeatureList::IsEnabled(
- service_manager::features::kXRSandbox);
- case SandboxType::kProxyResolver:
- case SandboxType::kPdfConversion:
- case SandboxType::kIconReader:
- return false;
-#endif
- case SandboxType::kAudio:
- return !IsAudioSandboxEnabled();
- case SandboxType::kVideoCapture:
-#if defined(OS_FUCHSIA)
- return false;
-#else
- return true;
-#endif
- case SandboxType::kNetwork:
-#if defined(OS_MACOSX)
- return false;
-#else
- return !base::FeatureList::IsEnabled(
- service_manager::features::kNetworkServiceSandbox);
-#endif // defined(OS_MACOSX)
- case SandboxType::kRenderer:
- case SandboxType::kUtility:
- case SandboxType::kGpu:
- case SandboxType::kPpapi:
- case SandboxType::kCdm:
- case SandboxType::kPrintCompositor:
-#if defined(OS_FUCHSIA)
- case SandboxType::kWebContext:
-#endif
-#if defined(OS_MACOSX)
- case SandboxType::kNaClLoader:
-#endif
-#if defined(OS_CHROMEOS)
- case SandboxType::kIme:
- case SandboxType::kTts:
-#endif
-#if !defined(OS_MACOSX)
- case SandboxType::kSharingService:
-#endif
-#if defined(OS_LINUX)
- case SandboxType::kZygoteIntermediateSandbox:
-#endif
- case SandboxType::kSpeechRecognition:
- return false;
- }
-}
-
-void SetCommandLineFlagsForSandboxType(base::CommandLine* command_line,
- SandboxType sandbox_type) {
- switch (sandbox_type) {
- case SandboxType::kNoSandbox:
- if (command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kUtilityProcess) {
- DCHECK(!command_line->HasSwitch(switches::kServiceSandboxType));
- command_line->AppendSwitchASCII(
- switches::kServiceSandboxType,
- StringFromUtilitySandboxType(sandbox_type));
- } else {
- command_line->AppendSwitch(switches::kNoSandbox);
- }
- break;
-#if defined(OS_WIN)
- case SandboxType::kNoSandboxAndElevatedPrivileges:
- command_line->AppendSwitch(switches::kNoSandboxAndElevatedPrivileges);
- break;
-#endif
- case SandboxType::kRenderer:
- DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kRendererProcess);
- break;
- case SandboxType::kGpu:
- DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kGpuProcess);
- break;
- case SandboxType::kPpapi:
- if (command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kUtilityProcess) {
- command_line->AppendSwitchASCII(switches::kServiceSandboxType,
- switches::kPpapiSandbox);
- } else {
- DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kPpapiPluginProcess);
- }
- break;
- case SandboxType::kUtility:
- case SandboxType::kNetwork:
- case SandboxType::kCdm:
- case SandboxType::kPrintCompositor:
- case SandboxType::kAudio:
- case SandboxType::kVideoCapture:
-#if defined(OS_WIN)
- 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:
-#endif
- case SandboxType::kSpeechRecognition:
- DCHECK(command_line->GetSwitchValueASCII(switches::kProcessType) ==
- switches::kUtilityProcess);
- DCHECK(!command_line->HasSwitch(switches::kServiceSandboxType));
- command_line->AppendSwitchASCII(
- switches::kServiceSandboxType,
- StringFromUtilitySandboxType(sandbox_type));
- break;
-#if defined(OS_FUCHSIA)
- case SandboxType::kWebContext:
- break;
-#endif // defined(OS_FUCHSIA)
-#if defined(OS_MACOSX)
- case SandboxType::kNaClLoader:
- break;
-#endif // defined(OS_MACOSX)
-#if defined(OS_LINUX)
- case SandboxType::kZygoteIntermediateSandbox:
- break;
-#endif
- }
-}
-
-SandboxType SandboxTypeFromCommandLine(const base::CommandLine& command_line) {
- if (command_line.HasSwitch(switches::kNoSandbox))
- return SandboxType::kNoSandbox;
-
-#if defined(OS_WIN)
- if (command_line.HasSwitch(switches::kNoSandboxAndElevatedPrivileges))
- return SandboxType::kNoSandboxAndElevatedPrivileges;
-#endif
-
- std::string process_type =
- command_line.GetSwitchValueASCII(switches::kProcessType);
- if (process_type.empty())
- return SandboxType::kNoSandbox;
-
- if (process_type == switches::kRendererProcess)
- return SandboxType::kRenderer;
-
- if (process_type == switches::kUtilityProcess) {
- return UtilitySandboxTypeFromString(
- command_line.GetSwitchValueASCII(switches::kServiceSandboxType));
- }
- if (process_type == switches::kGpuProcess) {
- if (command_line.HasSwitch(switches::kDisableGpuSandbox))
- return SandboxType::kNoSandbox;
- return SandboxType::kGpu;
- }
- if (process_type == switches::kPpapiBrokerProcess)
- return SandboxType::kNoSandbox;
-
- if (process_type == switches::kPpapiPluginProcess)
- return SandboxType::kPpapi;
-
- // NaCl tests on all platforms use the loader process.
- if (process_type == switches::kNaClLoaderProcess) {
-#if defined(OS_MACOSX)
- return SandboxType::kNaClLoader;
-#else
- return SandboxType::kUtility;
-#endif
- }
-
- if (process_type == switches::kNaClBrokerProcess)
- return SandboxType::kNoSandbox;
-
-#if defined(OS_LINUX)
- // Intermediate process gains a sandbox later.
- if (process_type == switches::kZygoteProcessType)
- return SandboxType::kZygoteIntermediateSandbox;
-#endif
-
- if (process_type == switches::kCloudPrintServiceProcess)
- return SandboxType::kNoSandbox;
-
- CHECK(false)
- << "Command line does not provide a valid sandbox configuration: "
- << command_line.GetCommandLineString();
- NOTREACHED();
- return SandboxType::kNoSandbox;
-}
-
-std::string StringFromUtilitySandboxType(SandboxType sandbox_type) {
- switch (sandbox_type) {
- case SandboxType::kNoSandbox:
- return switches::kNoneSandbox;
- case SandboxType::kNetwork:
- return switches::kNetworkSandbox;
- case SandboxType::kPpapi:
- return switches::kPpapiSandbox;
- case SandboxType::kCdm:
- return switches::kCdmSandbox;
- case SandboxType::kPrintCompositor:
- return switches::kPrintCompositorSandbox;
- case SandboxType::kUtility:
- return switches::kUtilitySandbox;
- case SandboxType::kAudio:
- return switches::kAudioSandbox;
- case SandboxType::kVideoCapture:
- return switches::kVideoCaptureSandbox;
-#if !defined(OS_MACOSX)
- case SandboxType::kSharingService:
- return switches::kSharingServiceSandbox;
-#endif
- case SandboxType::kSpeechRecognition:
- return switches::kSpeechRecognitionSandbox;
-#if defined(OS_WIN)
- case SandboxType::kXrCompositing:
- return switches::kXrCompositingSandbox;
- case SandboxType::kProxyResolver:
- 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:
- case SandboxType::kGpu:
-#if defined(OS_WIN)
- case SandboxType::kNoSandboxAndElevatedPrivileges:
-#endif // defined(OS_WIN)
-#if defined(OS_MACOSX)
- case SandboxType::kNaClLoader:
-#endif // defined(OS_MACOSX)
-#if defined(OS_FUCHSIA)
- case SandboxType::kWebContext:
-#endif // defined(OS_FUCHSIA)
-#if defined(OS_LINUX)
- case SandboxType::kZygoteIntermediateSandbox:
-#endif
- NOTREACHED();
- return std::string();
- }
-}
-
-SandboxType UtilitySandboxTypeFromString(const std::string& sandbox_string) {
- if (sandbox_string == switches::kNoneSandbox)
- return SandboxType::kNoSandbox;
- if (sandbox_string == switches::kNoneSandboxAndElevatedPrivileges) {
-#if defined(OS_WIN)
- return SandboxType::kNoSandboxAndElevatedPrivileges;
-#else
- return SandboxType::kNoSandbox;
-#endif
- }
- if (sandbox_string == switches::kNetworkSandbox)
- return SandboxType::kNetwork;
- if (sandbox_string == switches::kPpapiSandbox)
- return SandboxType::kPpapi;
- if (sandbox_string == switches::kCdmSandbox)
- return SandboxType::kCdm;
- if (sandbox_string == switches::kPrintCompositorSandbox)
- return SandboxType::kPrintCompositor;
-#if defined(OS_WIN)
- if (sandbox_string == switches::kXrCompositingSandbox)
- return SandboxType::kXrCompositing;
- if (sandbox_string == switches::kProxyResolverSandbox)
- 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;
- if (sandbox_string == switches::kSpeechRecognitionSandbox)
- return SandboxType::kSpeechRecognition;
- if (sandbox_string == switches::kVideoCaptureSandbox)
- return SandboxType::kVideoCapture;
-#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;
-}
-
-void EnableAudioSandbox(bool enable) {
- if (enable) {
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableAudioServiceSandbox);
- }
-}
-
-bool IsAudioSandboxEnabled() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableAudioServiceSandbox);
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/sandbox_type.h b/chromium/services/service_manager/sandbox/sandbox_type.h
deleted file mode 100644
index b35e3950ccf..00000000000
--- a/chromium/services/service_manager/sandbox/sandbox_type.h
+++ /dev/null
@@ -1,121 +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_SANDBOX_SANDBOX_TYPE_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_TYPE_H_
-
-#include <string>
-
-#include "base/command_line.h"
-#include "build/build_config.h"
-#include "services/service_manager/sandbox/export.h"
-
-namespace service_manager {
-
-// Defines the sandbox types known within the servicemanager.
-enum class SandboxType {
- // Do not apply any sandboxing to the process.
- kNoSandbox,
-
-#if defined(OS_WIN)
- // Do not apply any sandboxing and elevate the privileges of the process.
- kNoSandboxAndElevatedPrivileges,
-
- // The XR Compositing process.
- kXrCompositing,
-
- // The proxy resolver process.
- kProxyResolver,
-
- // The PDF conversion service process used in printing.
- kPdfConversion,
-
- // The icon reader service.
- kIconReader,
-#endif
-
-#if defined(OS_FUCHSIA)
- // Sandbox type for the web::Context process on Fuchsia. Functionally it's an
- // equivalent of the browser process on other platforms.
- kWebContext,
-#endif
-
- // Renderer or worker process. Most common case.
- kRenderer,
-
- // Utility processes. Used by most isolated services.
- kUtility,
-
- // GPU process.
- kGpu,
-
- // The PPAPI plugin process.
- kPpapi,
-
- // The network service process.
- kNetwork,
-
- // The CDM service process.
- kCdm,
-
-#if defined(OS_MACOSX)
- // The NaCl loader process.
- kNaClLoader,
-#endif // defined(OS_MACOSX)
-
- // The print compositor service process.
- kPrintCompositor,
-
- // The audio service process.
- kAudio,
-
-#if defined(OS_CHROMEOS)
- kIme,
- // Text-to-speech.
- kTts,
-#endif // defined(OS_CHROMEOS)
-
-#if defined(OS_LINUX)
- // Indicates that a process is a zygote and will get a real sandbox later.
- kZygoteIntermediateSandbox,
-#endif
-
-#if !defined(OS_MACOSX)
- // Hosts WebRTC for Sharing Service, uses kUtility on OS_MACOSX.
- kSharingService,
-#endif
-
- // The speech recognition service process.
- kSpeechRecognition,
-
- // Equivalent to no sandbox on all non-Fuchsia platforms.
- // Minimally privileged sandbox on Fuchsia.
- kVideoCapture,
-
- kMaxValue = kVideoCapture
-};
-
-SERVICE_MANAGER_SANDBOX_EXPORT bool IsUnsandboxedSandboxType(
- SandboxType sandbox_type);
-
-SERVICE_MANAGER_SANDBOX_EXPORT void SetCommandLineFlagsForSandboxType(
- base::CommandLine* command_line,
- SandboxType sandbox_type);
-
-SERVICE_MANAGER_SANDBOX_EXPORT SandboxType
-SandboxTypeFromCommandLine(const base::CommandLine& command_line);
-
-SERVICE_MANAGER_SANDBOX_EXPORT std::string StringFromUtilitySandboxType(
- SandboxType sandbox_type);
-
-SERVICE_MANAGER_SANDBOX_EXPORT SandboxType
-UtilitySandboxTypeFromString(const std::string& sandbox_string);
-
-SERVICE_MANAGER_SANDBOX_EXPORT void EnableAudioSandbox(bool enable);
-
-SERVICE_MANAGER_SANDBOX_EXPORT bool IsAudioSandboxEnabled();
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_SANDBOX_TYPE_H_
diff --git a/chromium/services/service_manager/sandbox/switches.cc b/chromium/services/service_manager/sandbox/switches.cc
deleted file mode 100644
index e635d4e8eed..00000000000
--- a/chromium/services/service_manager/sandbox/switches.cc
+++ /dev/null
@@ -1,139 +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/sandbox/switches.h"
-
-#include "build/build_config.h"
-
-#if defined(OS_WIN)
-#include "base/command_line.h"
-#include "base/win/windows_version.h"
-#endif
-
-namespace service_manager {
-namespace switches {
-
-// Type of sandbox to apply to the process running the service, one of the
-// values in the next block.
-const char kServiceSandboxType[] = "service-sandbox-type";
-
-// Must be in sync with "sandbox_type" values as used in service manager's
-// manifest.json catalog files.
-const char kNoneSandbox[] = "none";
-const char kNoneSandboxAndElevatedPrivileges[] = "none_and_elevated";
-const char kNetworkSandbox[] = "network";
-const char kPpapiSandbox[] = "ppapi";
-const char kUtilitySandbox[] = "utility";
-const char kCdmSandbox[] = "cdm";
-const char kPrintCompositorSandbox[] = "print_compositor";
-const char kAudioSandbox[] = "audio";
-const char kSharingServiceSandbox[] = "sharing_service";
-const char kSpeechRecognitionSandbox[] = "speech_recognition";
-const char kVideoCaptureSandbox[] = "video_capture";
-
-#if defined(OS_WIN)
-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.
-
-// Enables the sandboxed processes to run without a job object assigned to them.
-// This flag is required to allow Chrome to run in RemoteApps or Citrix. This
-// flag can reduce the security of the sandboxed processes and allow them to do
-// certain API calls like shut down Windows or access the clipboard. Also we
-// lose the chance to kill some processes until the outer job that owns them
-// finishes.
-const char kAllowNoSandboxJob[] = "allow-no-sandbox-job";
-
-// Allows debugging of sandboxed processes (see zygote_main_linux.cc).
-const char kAllowSandboxDebugging[] = "allow-sandbox-debugging";
-
-// Disables the GPU process sandbox.
-const char kDisableGpuSandbox[] = "disable-gpu-sandbox";
-
-// Disables usage of the namespace sandbox.
-const char kDisableNamespaceSandbox[] = "disable-namespace-sandbox";
-
-// Disable the seccomp filter sandbox (seccomp-bpf) (Linux only).
-const char kDisableSeccompFilterSandbox[] = "disable-seccomp-filter-sandbox";
-
-// Disable the setuid sandbox (Linux only).
-const char kDisableSetuidSandbox[] = "disable-setuid-sandbox";
-
-// Disables the Win32K process mitigation policy for child processes.
-const char kDisableWin32kLockDown[] = "disable-win32k-lockdown";
-
-// Command line flag to enable the audio service sandbox.
-const char kEnableAudioServiceSandbox[] = "enable-audio-service-sandbox";
-
-// Allows shmat() system call in the GPU sandbox.
-const char kGpuSandboxAllowSysVShm[] = "gpu-sandbox-allow-sysv-shm";
-
-// Makes GPU sandbox failures fatal.
-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)
-// Instructs the zygote to launch without a sandbox. Processes forked from this
-// type of zygote will apply their own custom sandboxes later.
-const char kNoZygoteSandbox[] = "no-zygote-sandbox";
-#endif
-
-#if defined(OS_WIN)
-// Allows third party modules to inject by disabling the BINARY_SIGNATURE
-// mitigation policy on Win10+. Also has other effects in ELF.
-const char kAllowThirdPartyModules[] = "allow-third-party-modules";
-
-// Add additional capabilities to the AppContainer sandbox on the GPU process.
-const char kAddGpuAppContainerCaps[] = "add-gpu-appcontainer-caps";
-
-// Disables the sandbox and gives the process elevated privileges.
-const char kNoSandboxAndElevatedPrivileges[] = "no-sandbox-and-elevated";
-
-// Add additional capabilities to the AppContainer sandbox used for XR
-// compositing.
-const char kAddXrAppContainerCaps[] = "add-xr-appcontainer-caps";
-#endif
-
-#if defined(OS_MACOSX)
-// Cause the OS X sandbox write to syslog every time an access to a resource
-// is denied by the sandbox.
-const char kEnableSandboxLogging[] = "enable-sandbox-logging";
-#endif
-
-// Flags spied upon from other layers.
-const char kGpuProcess[] = "gpu-process";
-const char kNaClBrokerProcess[] = "nacl-broker";
-const char kNaClLoaderProcess[] = "nacl-loader";
-const char kPpapiBrokerProcess[] = "ppapi-broker";
-const char kPpapiPluginProcess[] = "ppapi";
-const char kRendererProcess[] = "renderer";
-const char kUtilityProcess[] = "utility";
-const char kCloudPrintServiceProcess[] = "service";
-const char kZygoteProcessType[] = "zygote";
-
-} // namespace switches
-
-#if defined(OS_WIN)
-
-bool IsWin32kLockdownEnabled() {
- return base::win::GetVersion() >= base::win::Version::WIN8 &&
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableWin32kLockDown);
-}
-
-#endif
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/switches.h b/chromium/services/service_manager/sandbox/switches.h
deleted file mode 100644
index 6d66ab6c4f2..00000000000
--- a/chromium/services/service_manager/sandbox/switches.h
+++ /dev/null
@@ -1,93 +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_SANDBOX_SWITCHES_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_SWITCHES_H_
-
-#include "build/build_config.h"
-#include "services/service_manager/embedder/switches.h"
-#include "services/service_manager/sandbox/export.h"
-
-namespace service_manager {
-namespace switches {
-
-// Type of sandbox to apply to the process running the service, one of the
-// values in the next block.
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kServiceSandboxType[];
-
-// Must be in sync with "sandbox_type" values as used in service manager's
-// manifest.json catalog files.
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNoneSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char
- kNoneSandboxAndElevatedPrivileges[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNetworkSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPpapiSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kUtilitySandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kCdmSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPrintCompositorSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAudioSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kSharingServiceSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kSpeechRecognitionSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kVideoCaptureSandbox[];
-
-#if defined(OS_WIN)
-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.
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAllowNoSandboxJob[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAllowSandboxDebugging[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kDisableGpuSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kDisableNamespaceSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kDisableSeccompFilterSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kDisableSetuidSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kDisableWin32kLockDown[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kEnableAudioServiceSandbox[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kGpuSandboxAllowSysVShm[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kGpuSandboxFailuresFatal[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNoSandbox[];
-#if defined(OS_LINUX)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNoZygoteSandbox[];
-#endif
-#if defined(OS_WIN)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAllowThirdPartyModules[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAddGpuAppContainerCaps[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char
- kNoSandboxAndElevatedPrivileges[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kAddXrAppContainerCaps[];
-#endif
-#if defined(OS_MACOSX)
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kEnableSandboxLogging[];
-#endif
-
-// Flags spied upon from other layers.
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kGpuProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNaClBrokerProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kNaClLoaderProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPpapiBrokerProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kPpapiPluginProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kRendererProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kUtilityProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kCloudPrintServiceProcess[];
-SERVICE_MANAGER_SANDBOX_EXPORT extern const char kZygoteProcessType[];
-
-} // namespace switches
-
-#if defined(OS_WIN)
-// Returns whether Win32k lockdown is enabled for child processes or not.
-// Not really a switch, but uses one under the covers.
-SERVICE_MANAGER_SANDBOX_EXPORT bool IsWin32kLockdownEnabled();
-#endif
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_SWITCHES_H_
diff --git a/chromium/services/service_manager/sandbox/win/OWNERS b/chromium/services/service_manager/sandbox/win/OWNERS
deleted file mode 100644
index b875dc5b309..00000000000
--- a/chromium/services/service_manager/sandbox/win/OWNERS
+++ /dev/null
@@ -1,2 +0,0 @@
-set noparent
-file://sandbox/win/OWNERS
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.cc b/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.cc
deleted file mode 100644
index 140a9b1b53c..00000000000
--- a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.cc
+++ /dev/null
@@ -1,69 +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/sandbox/win/sandbox_diagnostics.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/json/json_reader.h"
-#include "base/values.h"
-
-namespace service_manager {
-namespace {
-// Runs on a non-sandbox thread to ensure that response callback is not
-// invoked from sandbox process and job tracker thread, and that conversion
-// work does not block process or job registration. Converts |policies|
-// into base::Value form, then invokes |response| on the same sequence.
-static void ConvertToValuesAndRespond(
- std::unique_ptr<sandbox::PolicyList> policies,
- base::OnceCallback<void(base::Value)> response) {
- base::Value policy_values(base::Value::Type::LIST);
- for (auto&& item : *policies) {
- auto snapshot = base::JSONReader::ReadAndReturnValueWithError(
- item->JsonString(), base::JSON_PARSE_RFC);
- CHECK(snapshot.value);
- policy_values.Append(std::move(snapshot.value.value()));
- }
- std::move(response).Run(std::move(policy_values));
-}
-
-// Runs on a non-sandbox thread to ensure that response callback is not
-// invoked from sandbox process and job tracker thread.
-static void RespondWithEmptyList(
- base::OnceCallback<void(base::Value)> response) {
- base::Value empty(base::Value::Type::LIST);
- std::move(response).Run(std::move(empty));
-}
-
-} // namespace
-
-ServiceManagerDiagnosticsReceiver::ServiceManagerDiagnosticsReceiver(
- scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
- base::OnceCallback<void(base::Value)> response)
- : response_(std::move(response)), origin_task_runner_(origin_task_runner) {}
-
-ServiceManagerDiagnosticsReceiver::~ServiceManagerDiagnosticsReceiver() {}
-
-// This is called by the sandbox's process and job tracking thread and must
-// return quickly.
-void ServiceManagerDiagnosticsReceiver::ReceiveDiagnostics(
- std::unique_ptr<sandbox::PolicyList> policies) {
- // Need to run the conversion work on the origin thread.
- origin_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&ConvertToValuesAndRespond, std::move(policies),
- std::move(response_)));
-}
-
-// This is called by the sandbox's process and job tracking thread and must
-// return quickly so we post to the origin thread.
-void ServiceManagerDiagnosticsReceiver::OnError(sandbox::ResultCode error) {
- origin_task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&RespondWithEmptyList, std::move(response_)));
-}
-
-} // namespace service_manager
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h b/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h
deleted file mode 100644
index 1f89e7ee7a9..00000000000
--- a/chromium/services/service_manager/sandbox/win/sandbox_diagnostics.h
+++ /dev/null
@@ -1,48 +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_SANDBOX_WIN_SANDBOX_DIAGNOSTICS_H_
-#define SERVICES_SERVICE_MANAGER_SANDBOX_WIN_SANDBOX_DIAGNOSTICS_H_
-
-#include "services/service_manager/sandbox/win/sandbox_win.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/sequenced_task_runner.h"
-#include "base/values.h"
-#include "sandbox/constants.h"
-#include "sandbox/win/src/sandbox.h"
-
-namespace service_manager {
-
-// Mediates response from sandbox::BrokerServices->GetPolicyDiagnostics.
-class ServiceManagerDiagnosticsReceiver
- : public sandbox::PolicyDiagnosticsReceiver {
- public:
- ~ServiceManagerDiagnosticsReceiver() final;
- ServiceManagerDiagnosticsReceiver(
- scoped_refptr<base::SequencedTaskRunner> origin_task_runner,
- base::OnceCallback<void(base::Value)> response);
-
- // This is called by the sandbox's process and job tracking thread and must
- // return quickly.
- void ReceiveDiagnostics(
- std::unique_ptr<sandbox::PolicyList> policies) override;
-
- // This is called by the sandbox's process and job tracking thread and must
- // return quickly.
- void OnError(sandbox::ResultCode error) override;
-
- private:
- base::OnceCallback<void(base::Value)> response_;
- scoped_refptr<base::SequencedTaskRunner> origin_task_runner_;
-};
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANAGER_SANDBOX_WIN_SANDBOX_DIAGNOSTICS_H_
diff --git a/chromium/services/service_manager/sandbox/win/sandbox_win.cc b/chromium/services/service_manager/sandbox/win/sandbox_win.cc
deleted file mode 100644
index cde75bd0710..00000000000
--- a/chromium/services/service_manager/sandbox/win/sandbox_win.cc
+++ /dev/null
@@ -1,1138 +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/sandbox/win/sandbox_win.h"
-
-#include <stddef.h>
-
-#include <string>
-#include <utility>
-#include <vector>
-
-#include "base/command_line.h"
-#include "base/debug/activity_tracker.h"
-#include "base/feature_list.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/hash/hash.h"
-#include "base/hash/sha1.h"
-#include "base/logging.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/no_destructor.h"
-#include "base/path_service.h"
-#include "base/process/launch.h"
-#include "base/stl_util.h"
-#include "base/strings/strcat.h"
-#include "base/strings/string16.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/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"
-#include "base/win/win_util.h"
-#include "base/win/windows_version.h"
-#include "sandbox/win/src/app_container_profile.h"
-#include "sandbox/win/src/job.h"
-#include "sandbox/win/src/process_mitigations.h"
-#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"
-#include "services/service_manager/sandbox/switches.h"
-#include "services/service_manager/sandbox/win/sandbox_diagnostics.h"
-
-namespace service_manager {
-namespace {
-
-sandbox::BrokerServices* g_broker_services = NULL;
-
-HANDLE g_job_object_handle = NULL;
-
-// The DLLs listed here are known (or under strong suspicion) of causing crashes
-// when they are loaded in the renderer. Note: at runtime we generate short
-// versions of the dll name only if the dll has an extension.
-// For more information about how this list is generated, and how to get off
-// of it, see:
-// https://sites.google.com/a/chromium.org/dev/Home/third-party-developers
-const wchar_t* const kTroublesomeDlls[] = {
- L"adialhk.dll", // Kaspersky Internet Security.
- L"acpiz.dll", // Unknown.
- L"activedetect32.dll", // Lenovo One Key Theater (crbug.com/536056).
- L"activedetect64.dll", // Lenovo One Key Theater (crbug.com/536056).
- L"airfoilinject3.dll", // Airfoil.
- L"akinsofthook32.dll", // Akinsoft Software Engineering.
- L"assistant_x64.dll", // Unknown.
- L"atcuf64.dll", // Bit Defender Internet Security x64.
- L"avcuf64.dll", // Bit Defender Internet Security x64.
- L"avgrsstx.dll", // AVG 8.
- L"babylonchromepi.dll", // Babylon translator.
- L"btkeyind.dll", // Widcomm Bluetooth.
- L"cmcsyshk.dll", // CMC Internet Security.
- L"cmsetac.dll", // Unknown (suspected malware).
- L"cooliris.dll", // CoolIris.
- L"cplushook.dll", // Unknown (suspected malware).
- L"dockshellhook.dll", // Stardock Objectdock.
- L"easyhook32.dll", // GDIPP and others.
- L"easyhook64.dll", // Symantec BlueCoat and others.
- L"esspd.dll", // Samsung Smart Security ESCORT.
- L"googledesktopnetwork3.dll", // Google Desktop Search v5.
- L"fwhook.dll", // PC Tools Firewall Plus.
- L"guard64.dll", // Comodo Internet Security x64.
- L"hookprocesscreation.dll", // Blumentals Program protector.
- L"hookterminateapis.dll", // Blumentals and Cyberprinter.
- L"hookprintapis.dll", // Cyberprinter.
- L"imon.dll", // NOD32 Antivirus.
- L"icatcdll.dll", // Samsung Smart Security ESCORT.
- L"icdcnl.dll", // Samsung Smart Security ESCORT.
- L"ioloHL.dll", // Iolo (System Mechanic).
- L"kloehk.dll", // Kaspersky Internet Security.
- L"lawenforcer.dll", // Spyware-Browser AntiSpyware (Spybro).
- L"libdivx.dll", // DivX.
- L"lvprcinj01.dll", // Logitech QuickCam.
- L"madchook.dll", // Madshi (generic hooking library).
- L"mdnsnsp.dll", // Bonjour.
- L"moonsysh.dll", // Moon Secure Antivirus.
- L"mpk.dll", // KGB Spy.
- L"n64hooks.dll", // Neilsen//NetRatings NetSight.
- L"npdivx32.dll", // DivX.
- L"npggNT.des", // GameGuard 2008.
- L"npggNT.dll", // GameGuard (older).
- L"nphooks.dll", // Neilsen//NetRatings NetSight.
- L"oawatch.dll", // Online Armor.
- L"pastali32.dll", // PastaLeads.
- L"pavhook.dll", // Panda Internet Security.
- L"pavlsphook.dll", // Panda Antivirus.
- L"pavshook.dll", // Panda Antivirus.
- L"pavshookwow.dll", // Panda Antivirus.
- L"pctavhook.dll", // PC Tools Antivirus.
- L"pctgmhk.dll", // PC Tools Spyware Doctor.
- L"picrmi32.dll", // PicRec.
- L"picrmi64.dll", // PicRec.
- L"prntrack.dll", // Pharos Systems.
- L"prochook.dll", // Unknown (GBill-Tools?) (crbug.com/974722).
- L"protector.dll", // Unknown (suspected malware).
- L"radhslib.dll", // Radiant Naomi Internet Filter.
- L"radprlib.dll", // Radiant Naomi Internet Filter.
- L"rapportnikko.dll", // Trustware Rapport.
- L"rlhook.dll", // Trustware Bufferzone.
- L"rooksdol.dll", // Trustware Rapport.
- L"rndlpepperbrowserrecordhelper.dll", // RealPlayer.
- L"rpchromebrowserrecordhelper.dll", // RealPlayer.
- L"r3hook.dll", // Kaspersky Internet Security.
- L"sahook.dll", // McAfee Site Advisor.
- L"sbrige.dll", // Unknown.
- L"sc2hook.dll", // Supercopier 2.
- L"sdhook32.dll", // Spybot - Search & Destroy Live Protection.
- L"sguard.dll", // Iolo (System Guard).
- L"smum32.dll", // Spyware Doctor version 6.
- L"smumhook.dll", // Spyware Doctor version 5.
- L"ssldivx.dll", // DivX.
- L"syncor11.dll", // SynthCore Midi interface.
- L"systools.dll", // Panda Antivirus.
- L"tfwah.dll", // Threatfire (PC tools).
- L"wblind.dll", // Stardock Object desktop.
- L"wbhelp.dll", // Stardock Object desktop.
- L"windowsapihookdll32.dll", // Lenovo One Key Theater (crbug.com/536056).
- L"windowsapihookdll64.dll", // Lenovo One Key Theater (crbug.com/536056).
- L"winstylerthemehelper.dll" // Tuneup utilities 2006.
-};
-
-// This is for finch. See also crbug.com/464430 for details.
-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
-// apply the rule to the subfiles and subfolders.
-bool AddDirectory(int path,
- const wchar_t* sub_dir,
- bool children,
- sandbox::TargetPolicy::Semantics access,
- sandbox::TargetPolicy* policy) {
- base::FilePath directory;
- if (!base::PathService::Get(path, &directory))
- return false;
-
- if (sub_dir)
- directory = base::MakeAbsoluteFilePath(directory.Append(sub_dir));
-
- sandbox::ResultCode result;
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, access,
- directory.value().c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return false;
-
- std::wstring directory_str = directory.value() + L"\\";
- if (children)
- directory_str += L"*";
- // Otherwise, add the version of the path that ends with a separator.
-
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES, access,
- directory_str.c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return false;
-
- return true;
-}
-#endif // !defined(NACL_WIN64)
-
-// Compares the loaded |module| file name matches |module_name|.
-bool IsExpandedModuleName(HMODULE module, const wchar_t* module_name) {
- wchar_t path[MAX_PATH];
- DWORD sz = ::GetModuleFileNameW(module, path, base::size(path));
- if ((sz == base::size(path)) || (sz == 0)) {
- // XP does not set the last error properly, so we bail out anyway.
- return false;
- }
- if (!::GetLongPathName(path, path, base::size(path)))
- return false;
- base::FilePath fname(path);
- return (fname.BaseName().value() == module_name);
-}
-
-std::vector<std::wstring> GetShortNameVariants(const std::wstring& name) {
- std::vector<std::wstring> alt_names;
- size_t period = name.rfind(L'.');
- DCHECK_NE(std::string::npos, period);
- DCHECK_LE(3U, (name.size() - period));
- if (period <= 8)
- return alt_names;
-
- // The module could have been loaded with a 8.3 short name. We check
- // the three most common cases: 'thelongname.dll' becomes
- // 'thelon~1.dll', 'thelon~2.dll' and 'thelon~3.dll'.
- alt_names.reserve(3);
- for (wchar_t ix = '1'; ix <= '3'; ++ix) {
- const wchar_t suffix[] = {'~', ix, 0};
- alt_names.push_back(
- base::StrCat({name.substr(0, 6), suffix, name.substr(period)}));
- }
- return alt_names;
-}
-
-// Adds a single dll by |module_name| into the |policy| blocklist.
-// If |check_in_browser| is true we only add an unload policy only if the dll
-// is also loaded in this process.
-void BlocklistAddOneDll(const wchar_t* module_name,
- bool check_in_browser,
- sandbox::TargetPolicy* policy) {
- if (check_in_browser) {
- HMODULE module = ::GetModuleHandleW(module_name);
- if (module) {
- policy->AddDllToUnload(module_name);
- DVLOG(1) << "dll to unload found: " << module_name;
- } else {
- for (const auto& alt_name : GetShortNameVariants(module_name)) {
- module = ::GetModuleHandleW(alt_name.c_str());
- // We found it, but because it only has 6 significant letters, we
- // want to make sure it is the right one.
- if (module && IsExpandedModuleName(module, module_name)) {
- // Found a match. We add both forms to the policy.
- policy->AddDllToUnload(alt_name.c_str());
- policy->AddDllToUnload(module_name);
- return;
- }
- }
- }
- } else {
- policy->AddDllToUnload(module_name);
- for (const auto& alt_name : GetShortNameVariants(module_name)) {
- policy->AddDllToUnload(alt_name.c_str());
- }
- }
-}
-
-// Adds policy rules for unloaded the known dlls that cause chrome to crash.
-// Eviction of injected DLLs is done by the sandbox so that the injected module
-// does not get a chance to execute any code.
-void AddGenericDllEvictionPolicy(sandbox::TargetPolicy* policy) {
- for (int ix = 0; ix != base::size(kTroublesomeDlls); ++ix)
- BlocklistAddOneDll(kTroublesomeDlls[ix], true, policy);
-}
-
-// Returns the object path prepended with the current logon session.
-base::string16 PrependWindowsSessionPath(const base::char16* object) {
- // Cache this because it can't change after process creation.
- static DWORD s_session_id = 0;
- if (s_session_id == 0) {
- HANDLE token;
- DWORD session_id_length;
- DWORD session_id = 0;
-
- CHECK(::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY, &token));
- CHECK(::GetTokenInformation(token, TokenSessionId, &session_id,
- sizeof(session_id), &session_id_length));
- CloseHandle(token);
- if (session_id)
- s_session_id = session_id;
- }
-
- return base::StringPrintf(L"\\Sessions\\%lu%ls", s_session_id, object);
-}
-
-// Checks if the sandbox can be let to run without a job object assigned.
-// Returns true if the job object has to be applied to the sandbox and false
-// otherwise.
-bool ShouldSetJobLevel(const base::CommandLine& cmd_line) {
- // Windows 8 allows nested jobs so we don't need to check if we are in other
- // job.
- if (base::win::GetVersion() >= base::win::Version::WIN8)
- return true;
-
- BOOL in_job = true;
- // Either there is no job yet associated so we must add our job,
- if (!::IsProcessInJob(::GetCurrentProcess(), NULL, &in_job))
- NOTREACHED() << "IsProcessInJob failed. " << GetLastError();
- if (!in_job)
- return true;
-
- // ...or there is a job but the JOB_OBJECT_LIMIT_BREAKAWAY_OK limit is set.
- JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = {};
- if (!::QueryInformationJobObject(NULL, JobObjectExtendedLimitInformation,
- &job_info, sizeof(job_info), NULL)) {
- NOTREACHED() << "QueryInformationJobObject failed. " << GetLastError();
- return true;
- }
- if (job_info.BasicLimitInformation.LimitFlags & JOB_OBJECT_LIMIT_BREAKAWAY_OK)
- return true;
-
- // Lastly in place of the flag which was supposed to be used only for running
- // Chrome in remote sessions we do this check explicitly here.
- // According to MS this flag can be false for a remote session only on Windows
- // Server 2012 and newer so if we do the check last we should be on the safe
- // side. See: https://msdn.microsoft.com/en-us/library/aa380798.aspx.
- if (!::GetSystemMetrics(SM_REMOTESESSION)) {
- // TODO(pastarmovj): Even though the number are low, this flag is still
- // necessary in some limited set of cases. Remove it once Windows 7 is no
- // longer supported together with the rest of the checks in this function.
- return !cmd_line.HasSwitch(service_manager::switches::kAllowNoSandboxJob);
- }
-
- // Allow running without the sandbox in this case. This slightly reduces the
- // ability of the sandbox to protect its children from spawning new processes
- // or preventing them from shutting down Windows or accessing the clipboard.
- return false;
-}
-
-// Adds the generic policy rules to a sandbox TargetPolicy.
-sandbox::ResultCode AddGenericPolicy(sandbox::TargetPolicy* policy) {
- sandbox::ResultCode result;
-
- // Add the policy for the client side of a pipe. It is just a file
- // in the \pipe\ namespace. We restrict it to pipes that start with
- // "chrome." so the sandboxed process cannot connect to system services.
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
- sandbox::TargetPolicy::FILES_ALLOW_ANY,
- L"\\??\\pipe\\chrome.*");
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- // Allow the server side of sync sockets, which are pipes that have
- // the "chrome.sync" namespace and a randomly generated suffix.
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_NAMED_PIPES,
- sandbox::TargetPolicy::NAMEDPIPES_ALLOW_ANY,
- L"\\\\.\\pipe\\chrome.sync.*");
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
-// Add the policy for debug message only in debug
-#ifndef NDEBUG
- base::FilePath app_dir;
- if (!base::PathService::Get(base::DIR_MODULE, &app_dir))
- return sandbox::SBOX_ERROR_GENERIC;
-
- wchar_t long_path_buf[MAX_PATH];
- DWORD long_path_return_value =
- GetLongPathName(app_dir.value().c_str(), long_path_buf, MAX_PATH);
- if (long_path_return_value == 0 || long_path_return_value >= MAX_PATH)
- return sandbox::SBOX_ERROR_NO_SPACE;
-
- base::FilePath debug_message(long_path_buf);
- debug_message = debug_message.AppendASCII("debug_message.exe");
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_PROCESS,
- sandbox::TargetPolicy::PROCESS_MIN_EXEC,
- debug_message.value().c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-#endif // NDEBUG
-
-// Add the policy for read-only PDB file access for stack traces.
-#if !defined(OFFICIAL_BUILD)
- base::FilePath exe;
- if (!base::PathService::Get(base::FILE_EXE, &exe))
- return sandbox::SBOX_ERROR_GENERIC;
- base::FilePath pdb_path = exe.DirName().Append(L"*.pdb");
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
- sandbox::TargetPolicy::FILES_ALLOW_READONLY,
- pdb_path.value().c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-#endif
-
-#if defined(SANITIZER_COVERAGE)
- DWORD coverage_dir_size =
- ::GetEnvironmentVariable(L"SANITIZER_COVERAGE_DIR", NULL, 0);
- if (coverage_dir_size == 0) {
- LOG(WARNING) << "SANITIZER_COVERAGE_DIR was not set, coverage won't work.";
- } else {
- std::wstring coverage_dir;
- wchar_t* coverage_dir_str =
- base::WriteInto(&coverage_dir, coverage_dir_size);
- coverage_dir_size = ::GetEnvironmentVariable(
- L"SANITIZER_COVERAGE_DIR", coverage_dir_str, coverage_dir_size);
- CHECK(coverage_dir.size() == coverage_dir_size);
- base::FilePath sancov_path =
- base::FilePath(coverage_dir).Append(L"*.sancov");
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
- sandbox::TargetPolicy::FILES_ALLOW_ANY,
- sancov_path.value().c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- }
-#endif
-
- AddGenericDllEvictionPolicy(policy);
- return sandbox::SBOX_ALL_OK;
-}
-
-void LogLaunchWarning(sandbox::ResultCode last_warning, DWORD last_error) {
- base::UmaHistogramSparse("Process.Sandbox.Launch.WarningResultCode",
- last_warning);
- base::UmaHistogramSparse("Process.Sandbox.Launch.Warning", last_error);
-}
-
-sandbox::ResultCode AddPolicyForSandboxedProcess(
- sandbox::TargetPolicy* policy) {
- sandbox::ResultCode result = sandbox::SBOX_ALL_OK;
-
- // Win8+ adds a device DeviceApi that we don't need.
- if (base::win::GetVersion() >= base::win::Version::WIN8)
- result = policy->AddKernelObjectToClose(L"File", L"\\Device\\DeviceApi");
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- // On 2003/Vista+ the initial token has to be restricted if the main
- // token is restricted.
- result = policy->SetTokenLevel(sandbox::USER_RESTRICTED_SAME_ACCESS,
- sandbox::USER_LOCKDOWN);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- // Prevents the renderers from manipulating low-integrity processes.
- result = policy->SetDelayedIntegrityLevel(sandbox::INTEGRITY_LEVEL_UNTRUSTED);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- result = policy->SetIntegrityLevel(sandbox::INTEGRITY_LEVEL_LOW);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- policy->SetLockdownDefaultDacl();
-
- result = policy->SetAlternateDesktop(true);
- if (result != sandbox::SBOX_ALL_OK) {
- // We ignore the result of setting the alternate desktop, however log
- // a launch warning.
- LogLaunchWarning(result, ::GetLastError());
- DLOG(WARNING) << "Failed to apply desktop security to the renderer";
- result = sandbox::SBOX_ALL_OK;
- }
-
- return result;
-}
-
-// This code is test only, and attempts to catch unsafe uses of
-// DuplicateHandle() that copy privileged handles into sandboxed processes.
-#if !defined(OFFICIAL_BUILD) && !defined(COMPONENT_BUILD)
-base::win::IATPatchFunction& GetIATPatchFunctionHandle() {
- static base::NoDestructor<base::win::IATPatchFunction>
- iat_patch_duplicate_handle;
- return *iat_patch_duplicate_handle;
-}
-
-typedef BOOL(WINAPI* DuplicateHandleFunctionPtr)(HANDLE source_process_handle,
- HANDLE source_handle,
- HANDLE target_process_handle,
- LPHANDLE target_handle,
- DWORD desired_access,
- BOOL inherit_handle,
- DWORD options);
-
-DuplicateHandleFunctionPtr g_iat_orig_duplicate_handle;
-
-NtQueryObject g_QueryObject = NULL;
-
-static const char* kDuplicateHandleWarning =
- "You are attempting to duplicate a privileged handle into a sandboxed"
- " process.\n Please contact security@chromium.org for assistance.";
-
-void CheckDuplicateHandle(HANDLE handle) {
- // Get the object type (32 characters is safe; current max is 14).
- BYTE buffer[sizeof(OBJECT_TYPE_INFORMATION) + 32 * sizeof(wchar_t)];
- OBJECT_TYPE_INFORMATION* type_info =
- reinterpret_cast<OBJECT_TYPE_INFORMATION*>(buffer);
- ULONG size = sizeof(buffer) - sizeof(wchar_t);
- NTSTATUS error;
- error = g_QueryObject(handle, ObjectTypeInformation, type_info, size, &size);
- CHECK(NT_SUCCESS(error));
- type_info->Name.Buffer[type_info->Name.Length / sizeof(wchar_t)] = L'\0';
-
- // Get the object basic information.
- OBJECT_BASIC_INFORMATION basic_info;
- size = sizeof(basic_info);
- error =
- g_QueryObject(handle, ObjectBasicInformation, &basic_info, size, &size);
- CHECK(NT_SUCCESS(error));
-
- CHECK(!(basic_info.GrantedAccess & WRITE_DAC)) << kDuplicateHandleWarning;
-
- if (0 == _wcsicmp(type_info->Name.Buffer, L"Process")) {
- const ACCESS_MASK kDangerousMask =
- ~static_cast<DWORD>(PROCESS_QUERY_LIMITED_INFORMATION | SYNCHRONIZE);
- CHECK(!(basic_info.GrantedAccess & kDangerousMask))
- << kDuplicateHandleWarning;
- }
-}
-
-BOOL WINAPI DuplicateHandlePatch(HANDLE source_process_handle,
- HANDLE source_handle,
- HANDLE target_process_handle,
- LPHANDLE target_handle,
- DWORD desired_access,
- BOOL inherit_handle,
- DWORD options) {
- // Duplicate the handle so we get the final access mask.
- if (!g_iat_orig_duplicate_handle(source_process_handle, source_handle,
- target_process_handle, target_handle,
- desired_access, inherit_handle, options))
- return FALSE;
-
- // We're not worried about broker handles or not crossing process boundaries.
- if (source_process_handle == target_process_handle ||
- target_process_handle == ::GetCurrentProcess())
- return TRUE;
-
- // Only sandboxed children are placed in jobs, so just check them.
- BOOL is_in_job = FALSE;
- if (!::IsProcessInJob(target_process_handle, NULL, &is_in_job)) {
- // We need a handle with permission to check the job object.
- if (ERROR_ACCESS_DENIED == ::GetLastError()) {
- HANDLE temp_handle;
- CHECK(g_iat_orig_duplicate_handle(
- ::GetCurrentProcess(), target_process_handle, ::GetCurrentProcess(),
- &temp_handle, PROCESS_QUERY_INFORMATION, FALSE, 0));
- base::win::ScopedHandle process(temp_handle);
- CHECK(::IsProcessInJob(process.Get(), NULL, &is_in_job));
- }
- }
-
- if (is_in_job) {
- // We never allow inheritable child handles.
- CHECK(!inherit_handle) << kDuplicateHandleWarning;
-
- // Duplicate the handle again, to get the final permissions.
- HANDLE temp_handle;
- CHECK(g_iat_orig_duplicate_handle(target_process_handle, *target_handle,
- ::GetCurrentProcess(), &temp_handle, 0,
- FALSE, DUPLICATE_SAME_ACCESS));
- base::win::ScopedHandle handle(temp_handle);
-
- // Callers use CHECK macro to make sure we get the right stack.
- CheckDuplicateHandle(handle.Get());
- }
-
- return TRUE;
-}
-#endif
-
-bool IsAppContainerEnabled() {
- if (base::win::GetVersion() < base::win::Version::WIN8)
- return false;
-
- return base::FeatureList::IsEnabled(
- {"RendererAppContainer", base::FEATURE_DISABLED_BY_DEFAULT});
-}
-
-sandbox::ResultCode SetJobMemoryLimit(const base::CommandLine& cmd_line,
- sandbox::TargetPolicy* policy) {
- DCHECK_NE(policy->GetJobLevel(), sandbox::JOB_NONE);
-
-#ifdef _WIN64
- size_t memory_limit = static_cast<size_t>(sandbox::kDataSizeLimit);
-
- // Note that this command line flag hasn't been fetched by all
- // callers of SetJobLevel, only those in this file.
- SandboxType sandbox_type =
- service_manager::SandboxTypeFromCommandLine(cmd_line);
- if (sandbox_type == SandboxType::kGpu ||
- sandbox_type == SandboxType::kRenderer) {
- int64_t GB = 1024 * 1024 * 1024;
- // Allow the GPU/RENDERER process's sandbox to access more physical memory
- // if it's available on the system.
- int64_t physical_memory = base::SysInfo::AmountOfPhysicalMemory();
- if (physical_memory > 16 * GB) {
- memory_limit = 16 * GB;
- } else if (physical_memory > 8 * GB) {
- memory_limit = 8 * GB;
- }
- }
- return policy->SetJobMemoryLimit(memory_limit);
-#else
- return sandbox::SBOX_ALL_OK;
-#endif
-}
-
-// Generate a unique sandbox AC profile for the appcontainer based on the SHA1
-// hash of the appcontainer_id. This does not need to be secure so using SHA1
-// isn't a security concern.
-base::string16 GetAppContainerProfileName(
- const std::string& appcontainer_id,
- service_manager::SandboxType sandbox_type) {
- DCHECK(sandbox_type == SandboxType::kGpu ||
- sandbox_type == SandboxType::kXrCompositing);
- auto sha1 = base::SHA1HashString(appcontainer_id);
- std::string sandbox_base_name = (sandbox_type == SandboxType::kXrCompositing)
- ? 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 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);
-}
-
-sandbox::ResultCode SetupAppContainerProfile(
- sandbox::AppContainerProfile* profile,
- const base::CommandLine& command_line,
- service_manager::SandboxType sandbox_type) {
- if (sandbox_type != SandboxType::kGpu &&
- sandbox_type != SandboxType::kXrCompositing)
- return sandbox::SBOX_ERROR_UNSUPPORTED;
-
- if (sandbox_type == SandboxType::kGpu &&
- !profile->AddImpersonationCapability(L"chromeInstallFiles")) {
- DLOG(ERROR) << "AppContainerProfile::AddImpersonationCapability("
- "chromeInstallFiles) failed";
- return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
- }
-
- if ((sandbox_type == SandboxType::kXrCompositing ||
- sandbox_type == SandboxType::kGpu) &&
- !profile->AddCapability(L"lpacPnpNotifications")) {
- DLOG(ERROR)
- << "AppContainerProfile::AddCapability(lpacPnpNotifications) failed";
- return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
- }
-
- if (sandbox_type == SandboxType::kXrCompositing &&
- !profile->AddCapability(L"chromeInstallFiles")) {
- DLOG(ERROR)
- << "AppContainerProfile::AddCapability(chromeInstallFiles) failed";
- return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
- }
-
- std::vector<base::string16> base_caps = {
- L"lpacChromeInstallFiles", L"registryRead",
- };
-
- if (sandbox_type == SandboxType::kGpu) {
- auto cmdline_caps = base::SplitString(
- command_line.GetSwitchValueNative(
- service_manager::switches::kAddGpuAppContainerCaps),
- L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- base_caps.insert(base_caps.end(), cmdline_caps.begin(), cmdline_caps.end());
- }
-
- if (sandbox_type == SandboxType::kXrCompositing) {
- auto cmdline_caps = base::SplitString(
- command_line.GetSwitchValueNative(
- service_manager::switches::kAddXrAppContainerCaps),
- L",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- base_caps.insert(base_caps.end(), cmdline_caps.begin(), cmdline_caps.end());
- }
-
- for (const auto& cap : base_caps) {
- if (!profile->AddCapability(cap.c_str())) {
- DLOG(ERROR) << "AppContainerProfile::AddCapability() failed";
- return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_CAPABILITY;
- }
- }
-
- // Enable LPAC for GPU process, but not for XRCompositor service.
- if (sandbox_type == SandboxType::kGpu &&
- base::FeatureList::IsEnabled(service_manager::features::kGpuLPAC)) {
- profile->SetEnableLowPrivilegeAppContainer(true);
- }
-
- return sandbox::SBOX_ALL_OK;
-}
-
-} // namespace
-
-// static
-sandbox::ResultCode SandboxWin::SetJobLevel(const base::CommandLine& cmd_line,
- sandbox::JobLevel job_level,
- uint32_t ui_exceptions,
- sandbox::TargetPolicy* policy) {
- if (!ShouldSetJobLevel(cmd_line))
- return policy->SetJobLevel(sandbox::JOB_NONE, 0);
-
- sandbox::ResultCode ret = policy->SetJobLevel(job_level, ui_exceptions);
- if (ret != sandbox::SBOX_ALL_OK)
- return ret;
-
- return SetJobMemoryLimit(cmd_line, policy);
-}
-
-// TODO(jschuh): Need get these restrictions applied to NaCl and Pepper.
-// Just have to figure out what needs to be warmed up first.
-// static
-sandbox::ResultCode SandboxWin::AddBaseHandleClosePolicy(
- sandbox::TargetPolicy* policy) {
- if (base::FeatureList::IsEnabled(kEnableCsrssLockdownFeature)) {
- // Close all ALPC ports.
- sandbox::ResultCode ret = policy->SetDisconnectCsrss();
- if (ret != sandbox::SBOX_ALL_OK) {
- return ret;
- }
- }
-
- // TODO(cpu): Add back the BaseNamedObjects policy.
- base::string16 object_path = PrependWindowsSessionPath(
- L"\\BaseNamedObjects\\windows_shell_global_counters");
- return policy->AddKernelObjectToClose(L"Section", object_path.data());
-}
-
-// static
-sandbox::ResultCode SandboxWin::AddAppContainerPolicy(
- sandbox::TargetPolicy* policy,
- const wchar_t* sid) {
- if (IsAppContainerEnabled())
- return policy->SetLowBox(sid);
- return sandbox::SBOX_ALL_OK;
-}
-
-// static
-sandbox::ResultCode SandboxWin::AddWin32kLockdownPolicy(
- sandbox::TargetPolicy* policy,
- bool enable_opm) {
-#if !defined(NACL_WIN64)
- if (!service_manager::IsWin32kLockdownEnabled())
- return sandbox::SBOX_ALL_OK;
-
- sandbox::MitigationFlags flags = policy->GetProcessMitigations();
- // Check not enabling twice. Should not happen.
- DCHECK_EQ(0U, flags & sandbox::MITIGATION_WIN32K_DISABLE);
-
- flags |= sandbox::MITIGATION_WIN32K_DISABLE;
- sandbox::ResultCode result = policy->SetProcessMitigations(flags);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- result =
- policy->AddRule(sandbox::TargetPolicy::SUBSYS_WIN32K_LOCKDOWN,
- enable_opm ? sandbox::TargetPolicy::IMPLEMENT_OPM_APIS
- : sandbox::TargetPolicy::FAKE_USER_GDI_INIT,
- nullptr);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- if (enable_opm)
- policy->SetEnableOPMRedirection();
-
- return result;
-#else
- return sandbox::SBOX_ALL_OK;
-#endif
-}
-
-// static
-sandbox::ResultCode SandboxWin::AddAppContainerProfileToPolicy(
- const base::CommandLine& command_line,
- service_manager::SandboxType sandbox_type,
- const std::string& appcontainer_id,
- sandbox::TargetPolicy* policy) {
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return sandbox::SBOX_ALL_OK;
- base::string16 profile_name =
- GetAppContainerProfileName(appcontainer_id, sandbox_type);
- sandbox::ResultCode result =
- policy->AddAppContainerProfile(profile_name.c_str(), true);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- scoped_refptr<sandbox::AppContainerProfile> profile =
- policy->GetAppContainerProfile();
- result = SetupAppContainerProfile(profile.get(), command_line, sandbox_type);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- DWORD granted_access;
- BOOL granted_access_status;
- bool access_check =
- profile->AccessCheck(command_line.GetProgram().value().c_str(),
- SE_FILE_OBJECT, GENERIC_READ | GENERIC_EXECUTE,
- &granted_access, &granted_access_status) &&
- granted_access_status;
- if (!access_check)
- return sandbox::SBOX_ERROR_CREATE_APPCONTAINER_PROFILE_ACCESS_CHECK;
-
- return sandbox::SBOX_ALL_OK;
-}
-
-// static
-bool SandboxWin::IsAppContainerEnabledForSandbox(
- const base::CommandLine& command_line,
- SandboxType sandbox_type) {
- if (sandbox_type != SandboxType::kGpu)
- return false;
- if (base::win::GetVersion() < base::win::Version::WIN10_RS1)
- return false;
- return base::FeatureList::IsEnabled(
- service_manager::features::kGpuAppContainer);
-}
-
-// static
-bool SandboxWin::InitBrokerServices(sandbox::BrokerServices* broker_services) {
- // TODO(abarth): DCHECK(CalledOnValidThread());
- // See <http://b/1287166>.
- DCHECK(broker_services);
- DCHECK(!g_broker_services);
- sandbox::ResultCode result = broker_services->Init();
- g_broker_services = broker_services;
-
-// In non-official builds warn about dangerous uses of DuplicateHandle. This
-// isn't useful under a component build, since there will be multiple modules,
-// each of which may have a slot to patch (if the symbol is even present).
-#if !defined(OFFICIAL_BUILD) && !defined(COMPONENT_BUILD)
- BOOL is_in_job = FALSE;
- CHECK(::IsProcessInJob(::GetCurrentProcess(), NULL, &is_in_job));
- if (!is_in_job && !GetIATPatchFunctionHandle().is_patched()) {
- HMODULE module = NULL;
- wchar_t module_name[MAX_PATH];
- CHECK(::GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
- reinterpret_cast<LPCWSTR>(InitBrokerServices),
- &module));
- DWORD result = ::GetModuleFileNameW(module, module_name, MAX_PATH);
- if (result && (result != MAX_PATH)) {
- ResolveNTFunctionPtr("NtQueryObject", &g_QueryObject);
- result = GetIATPatchFunctionHandle().Patch(
- module_name, "kernel32.dll", "DuplicateHandle",
- reinterpret_cast<void*>(DuplicateHandlePatch));
- CHECK_EQ(0u, result);
- g_iat_orig_duplicate_handle =
- reinterpret_cast<DuplicateHandleFunctionPtr>(
- GetIATPatchFunctionHandle().original_function());
- }
- }
-#endif
-
- return sandbox::SBOX_ALL_OK == result;
-}
-
-// static
-bool SandboxWin::InitTargetServices(sandbox::TargetServices* target_services) {
- DCHECK(target_services);
- sandbox::ResultCode result = target_services->Init();
- return sandbox::SBOX_ALL_OK == result;
-}
-
-// static
-sandbox::ResultCode SandboxWin::StartSandboxedProcess(
- base::CommandLine* cmd_line,
- const std::string& process_type,
- const base::HandlesToInheritVector& handles_to_inherit,
- service_manager::SandboxDelegate* delegate,
- base::Process* process) {
- const base::CommandLine& launcher_process_command_line =
- *base::CommandLine::ForCurrentProcess();
-
- // Propagate the --allow-no-job flag if present.
- if (launcher_process_command_line.HasSwitch(
- service_manager::switches::kAllowNoSandboxJob) &&
- !cmd_line->HasSwitch(service_manager::switches::kAllowNoSandboxJob)) {
- cmd_line->AppendSwitch(service_manager::switches::kAllowNoSandboxJob);
- }
-
- service_manager::SandboxType sandbox_type = delegate->GetSandboxType();
- if (service_manager::IsUnsandboxedSandboxType(sandbox_type) ||
- cmd_line->HasSwitch(service_manager::switches::kNoSandbox) ||
- launcher_process_command_line.HasSwitch(
- service_manager::switches::kNoSandbox)) {
- base::LaunchOptions options;
- options.handles_to_inherit = handles_to_inherit;
- BOOL in_job = true;
- // Prior to Windows 8 nested jobs aren't possible.
- if (sandbox_type == SandboxType::kNetwork &&
- (base::win::GetVersion() >= base::win::Version::WIN8 ||
- (::IsProcessInJob(::GetCurrentProcess(), nullptr, &in_job) &&
- !in_job))) {
- // Launch the process in a job to ensure that the network process doesn't
- // outlive the browser. This could happen if there is a lot of I/O on
- // process shutdown, in which case TerminateProcess would fail.
- // https://crbug.com/820996
- if (!g_job_object_handle) {
- sandbox::Job job_obj;
- DWORD result = job_obj.Init(sandbox::JOB_UNPROTECTED, nullptr, 0, 0);
- if (result != ERROR_SUCCESS)
- return sandbox::SBOX_ERROR_CANNOT_INIT_JOB;
- g_job_object_handle = job_obj.Take().Take();
- }
- options.job_handle = g_job_object_handle;
- }
- *process = base::LaunchProcess(*cmd_line, options);
- return sandbox::SBOX_ALL_OK;
- }
-
- scoped_refptr<sandbox::TargetPolicy> policy =
- g_broker_services->CreatePolicy();
-
- // Add any handles to be inherited to the policy.
- for (HANDLE handle : handles_to_inherit)
- policy->AddHandleToShare(handle);
-
- // Pre-startup mitigations.
- sandbox::MitigationFlags mitigations =
- sandbox::MITIGATION_HEAP_TERMINATE |
- sandbox::MITIGATION_BOTTOM_UP_ASLR |
- sandbox::MITIGATION_DEP |
- sandbox::MITIGATION_DEP_NO_ATL_THUNK |
- sandbox::MITIGATION_EXTENSION_POINT_DISABLE |
- sandbox::MITIGATION_SEHOP |
- sandbox::MITIGATION_NONSYSTEM_FONT_DISABLE |
- sandbox::MITIGATION_IMAGE_LOAD_NO_REMOTE |
- sandbox::MITIGATION_IMAGE_LOAD_NO_LOW_LABEL |
- sandbox::MITIGATION_RESTRICT_INDIRECT_BRANCH_PREDICTION;
-
- sandbox::ResultCode result = policy->SetProcessMitigations(mitigations);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
-#if !defined(NACL_WIN64)
- if (process_type == service_manager::switches::kRendererProcess &&
- service_manager::IsWin32kLockdownEnabled()) {
- result = SandboxWin::AddWin32kLockdownPolicy(policy.get(), false);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- }
-#endif
-
- // Post-startup mitigations.
- mitigations = sandbox::MITIGATION_DLL_SEARCH_ORDER;
- 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::kIconReader) {
- mitigations |= sandbox::MITIGATION_DYNAMIC_CODE_DISABLE;
- }
- // TODO(wfh): Relax strict handle checks for network process until root cause
- // for this crash can be resolved. See https://crbug.com/939590.
- if (sandbox_type != SandboxType::kNetwork)
- mitigations |= sandbox::MITIGATION_STRICT_HANDLE_CHECKS;
-
- result = policy->SetDelayedProcessMitigations(mitigations);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- result = SetJobLevel(*cmd_line, sandbox::JOB_LOCKDOWN, 0, policy.get());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
-
- if (!delegate->DisableDefaultPolicy()) {
- result = AddPolicyForSandboxedProcess(policy.get());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- }
-
- if (process_type == service_manager::switches::kGpuProcess &&
- base::FeatureList::IsEnabled(
- {"GpuLockdownDefaultDacl", base::FEATURE_ENABLED_BY_DEFAULT})) {
- policy->SetLockdownDefaultDacl();
- policy->AddRestrictingRandomSid();
- }
-
-#if !defined(NACL_WIN64)
- if (process_type == service_manager::switches::kRendererProcess ||
- process_type == service_manager::switches::kPpapiPluginProcess ||
- sandbox_type == SandboxType::kPrintCompositor) {
- AddDirectory(base::DIR_WINDOWS_FONTS, NULL, true,
- sandbox::TargetPolicy::FILES_ALLOW_READONLY, policy.get());
- }
-#endif
-
- result = AddGenericPolicy(policy.get());
- if (result != sandbox::SBOX_ALL_OK) {
- NOTREACHED();
- return result;
- }
-
- std::string appcontainer_id;
- if (IsAppContainerEnabledForSandbox(*cmd_line, sandbox_type) &&
- delegate->GetAppContainerId(&appcontainer_id)) {
- result = AddAppContainerProfileToPolicy(*cmd_line, sandbox_type,
- appcontainer_id, policy.get());
- DCHECK(result == sandbox::SBOX_ALL_OK);
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- }
-
- // Allow the renderer, gpu and utility processes to access the log file.
- if (process_type == service_manager::switches::kRendererProcess ||
- process_type == service_manager::switches::kGpuProcess ||
- process_type == service_manager::switches::kUtilityProcess) {
- if (logging::IsLoggingToFileEnabled()) {
- DCHECK(base::FilePath(logging::GetLogFileFullPath()).IsAbsolute());
- result = policy->AddRule(sandbox::TargetPolicy::SUBSYS_FILES,
- sandbox::TargetPolicy::FILES_ALLOW_ANY,
- logging::GetLogFileFullPath().c_str());
- if (result != sandbox::SBOX_ALL_OK)
- return result;
- }
- }
-
-#if !defined(OFFICIAL_BUILD)
- // If stdout/stderr point to a Windows console, these calls will
- // have no effect. These calls can fail with SBOX_ERROR_BAD_PARAMS.
- policy->SetStdoutHandle(GetStdHandle(STD_OUTPUT_HANDLE));
- policy->SetStderrHandle(GetStdHandle(STD_ERROR_HANDLE));
-#endif
-
- if (!delegate->PreSpawnTarget(policy.get()))
- return sandbox::SBOX_ERROR_DELEGATE_PRE_SPAWN;
-
- TRACE_EVENT_BEGIN0("startup", "StartProcessWithAccess::LAUNCHPROCESS");
-
- PROCESS_INFORMATION temp_process_info = {};
- sandbox::ResultCode last_warning = sandbox::SBOX_ALL_OK;
- DWORD last_error = ERROR_SUCCESS;
- result = g_broker_services->SpawnTarget(
- cmd_line->GetProgram().value().c_str(),
- cmd_line->GetCommandLineString().c_str(), policy, &last_warning,
- &last_error, &temp_process_info);
-
- 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)
- DPLOG(ERROR) << "Failed to launch process";
- else
- DLOG(ERROR) << "Failed to launch process. Error: " << result;
- return result;
- }
-
- base::debug::GlobalActivityTracker* tracker =
- base::debug::GlobalActivityTracker::Get();
- if (tracker) {
- tracker->RecordProcessLaunch(target.process_id(),
- cmd_line->GetCommandLineString());
- }
-
- if (sandbox::SBOX_ALL_OK != last_warning)
- LogLaunchWarning(last_warning, last_error);
-
- delegate->PostSpawnTarget(target.process_handle());
- CHECK(ResumeThread(target.thread_handle()) != static_cast<DWORD>(-1));
-
- *process = base::Process(target.TakeProcessHandle());
- return sandbox::SBOX_ALL_OK;
-}
-
-// static
-sandbox::ResultCode SandboxWin::GetPolicyDiagnostics(
- base::OnceCallback<void(base::Value)> response) {
- CHECK(g_broker_services);
- CHECK(!response.is_null());
- auto receiver = std::make_unique<ServiceManagerDiagnosticsReceiver>(
- base::SequencedTaskRunnerHandle::Get(), std::move(response));
- return g_broker_services->GetPolicyDiagnostics(std::move(receiver));
-}
-
-void BlocklistAddOneDllForTesting(const wchar_t* module_name,
- bool check_in_browser,
- sandbox::TargetPolicy* policy) {
- 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
deleted file mode 100644
index 6614a82461e..00000000000
--- a/chromium/services/service_manager/sandbox/win/sandbox_win.h
+++ /dev/null
@@ -1,102 +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_MANANGER_SANDBOX_WIN_SANDBOX_WIN_H_
-#define SERVICES_SERVICE_MANANGER_SANDBOX_WIN_SANDBOX_WIN_H_
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/callback_forward.h"
-#include "base/process/launch.h"
-#include "base/process/process_handle.h"
-#include "sandbox/win/src/sandbox_types.h"
-#include "sandbox/win/src/security_level.h"
-#include "services/service_manager/sandbox/export.h"
-#include "services/service_manager/sandbox/sandbox_delegate.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
-
-namespace base {
-class CommandLine;
-class Value;
-} // namespace base
-
-namespace sandbox {
-class BrokerServices;
-class TargetPolicy;
-class TargetServices;
-} // namespace sandbox
-
-namespace service_manager {
-
-class SERVICE_MANAGER_SANDBOX_EXPORT SandboxWin {
- public:
- static sandbox::ResultCode StartSandboxedProcess(
- base::CommandLine* cmd_line,
- const std::string& process_type,
- const base::HandlesToInheritVector& handles_to_inherit,
- SandboxDelegate* delegate,
- base::Process* process);
-
- // Wrapper around sandbox::TargetPolicy::SetJobLevel that checks if the
- // sandbox should be let to run without a job object assigned.
- static sandbox::ResultCode SetJobLevel(const base::CommandLine& cmd_line,
- sandbox::JobLevel job_level,
- uint32_t ui_exceptions,
- sandbox::TargetPolicy* policy);
-
- // Closes handles that are opened at process creation and initialization.
- static sandbox::ResultCode AddBaseHandleClosePolicy(
- sandbox::TargetPolicy* policy);
-
- // Add AppContainer policy for |sid| on supported OS.
- static sandbox::ResultCode AddAppContainerPolicy(
- sandbox::TargetPolicy* policy,
- const wchar_t* sid);
-
- // Add the win32k lockdown policy on supported OS.
- static sandbox::ResultCode AddWin32kLockdownPolicy(
- sandbox::TargetPolicy* policy,
- bool enable_opm);
-
- // Add the AppContainer sandbox profile to the policy. |sandbox_type|
- // determines what policy is enabled. |appcontainer_id| is used to create
- // a unique package SID, it can be anything the caller wants.
- static sandbox::ResultCode AddAppContainerProfileToPolicy(
- const base::CommandLine& command_line,
- service_manager::SandboxType sandbox_type,
- const std::string& appcontainer_id,
- sandbox::TargetPolicy* policy);
-
- // Returns whether the AppContainer sandbox is enabled or not for a specific
- // sandbox type from |command_line| and |sandbox_type|.
- static bool IsAppContainerEnabledForSandbox(
- const base::CommandLine& command_line,
- service_manager::SandboxType sandbox_type);
-
- static bool InitBrokerServices(sandbox::BrokerServices* broker_services);
- static bool InitTargetServices(sandbox::TargetServices* target_services);
-
- // Report diagnostic information about policies applied to sandboxed
- // processes. This is a snapshot and may describe processes which
- // have subsequently finished. This can be invoked on any sequence and posts
- // to |response| to the origin sequence on completion. |response|
- // 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
-void BlocklistAddOneDllForTesting(const wchar_t* module_name,
- bool check_in_browser,
- sandbox::TargetPolicy* policy);
-
-} // namespace service_manager
-
-#endif // SERVICES_SERVICE_MANANGER_SANDBOX_WIN_SANDBOX_WIN_H_
diff --git a/chromium/services/service_manager/service_instance.cc b/chromium/services/service_manager/service_instance.cc
index 2d5bb77181d..658754e4d0d 100644
--- a/chromium/services/service_manager/service_instance.cc
+++ b/chromium/services/service_manager/service_instance.cc
@@ -156,7 +156,7 @@ void ServiceInstance::StartWithRemote(
#if !defined(OS_IOS)
bool ServiceInstance::StartWithProcessHost(
std::unique_ptr<ServiceProcessHost> host,
- SandboxType sandbox_type) {
+ sandbox::policy::SandboxType sandbox_type) {
DCHECK(!service_remote_);
DCHECK(!process_host_);
@@ -473,6 +473,7 @@ void ServiceInstance::RegisterServiceInstance(
if (!service_manager_->RegisterService(identity, std::move(service_remote),
std::move(metadata_receiver))) {
std::move(callback).Run(mojom::ConnectResult::ACCESS_DENIED);
+ return;
}
std::move(callback).Run(mojom::ConnectResult::SUCCEEDED);
diff --git a/chromium/services/service_manager/service_instance.h b/chromium/services/service_manager/service_instance.h
index 20a3700f130..5600d48c5de 100644
--- a/chromium/services/service_manager/service_instance.h
+++ b/chromium/services/service_manager/service_instance.h
@@ -24,13 +24,13 @@
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/receiver_set.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "sandbox/policy/sandbox_type.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/manifest.h"
#include "services/service_manager/public/mojom/connector.mojom.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/public/mojom/service_control.mojom.h"
#include "services/service_manager/public/mojom/service_manager.mojom.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
namespace service_manager {
@@ -65,7 +65,7 @@ class ServiceInstance : public mojom::Connector,
#if !defined(OS_IOS)
// Starts this instance from a path to a service executable on disk.
bool StartWithProcessHost(std::unique_ptr<ServiceProcessHost> host,
- SandboxType sandbox_type);
+ sandbox::policy::SandboxType sandbox_type);
#endif // !defined(OS_IOS)
// Binds an endpoint for this instance to receive metadata about its
diff --git a/chromium/services/service_manager/service_manager.cc b/chromium/services/service_manager/service_manager.cc
index ceb1ea74f24..df2a4200202 100644
--- a/chromium/services/service_manager/service_manager.cc
+++ b/chromium/services/service_manager/service_manager.cc
@@ -20,6 +20,7 @@
#include "base/token.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "sandbox/policy/sandbox_type.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/service_manager/public/cpp/constants.h"
#include "services/service_manager/public/cpp/manifest_builder.h"
@@ -28,7 +29,6 @@
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/public/mojom/service_control.mojom.h"
#include "services/service_manager/public/mojom/service_manager.mojom.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/service_instance.h"
#include "services/service_manager/service_process_host.h"
@@ -77,16 +77,17 @@ class DefaultServiceProcessHost : public ServiceProcessHost {
~DefaultServiceProcessHost() override = default;
- mojo::PendingRemote<mojom::Service> Launch(const Identity& identity,
- SandboxType sandbox_type,
- const base::string16& display_name,
- LaunchCallback callback) override {
+ mojo::PendingRemote<mojom::Service> Launch(
+ const Identity& identity,
+ sandbox::policy::SandboxType sandbox_type,
+ const base::string16& display_name,
+ LaunchCallback callback) override {
#if defined(OS_IOS)
return mojo::NullRemote();
#else
// TODO(https://crbug.com/781334): Support sandboxing.
- CHECK_EQ(sandbox_type, SandboxType::kNoSandbox);
- return launcher_.Start(identity, SandboxType::kNoSandbox,
+ CHECK_EQ(sandbox_type, sandbox::policy::SandboxType::kNoSandbox);
+ return launcher_.Start(identity, sandbox::policy::SandboxType::kNoSandbox,
std::move(callback));
#endif // defined(OS_IOS)
}
@@ -160,7 +161,7 @@ ServiceManager::ServiceManager(const std::vector<Manifest>& manifests,
service_manager_instance_->SetPID(GetCurrentPid());
mojo::PendingRemote<mojom::Service> remote;
- service_binding_.Bind(remote.InitWithNewPipeAndPassReceiver());
+ service_receiver_.Bind(remote.InitWithNewPipeAndPassReceiver());
service_manager_instance_->StartWithRemote(std::move(remote));
}
@@ -308,10 +309,10 @@ ServiceInstance* ServiceManager::FindOrCreateMatchingTargetInstance(
case Manifest::ExecutionMode::kOutOfProcessBuiltin: {
auto process_host = delegate_->CreateProcessHostForBuiltinServiceInstance(
target_instance->identity());
- if (!process_host ||
- !target_instance->StartWithProcessHost(
- std::move(process_host),
- UtilitySandboxTypeFromString(manifest->options.sandbox_type))) {
+ if (!process_host || !target_instance->StartWithProcessHost(
+ std::move(process_host),
+ sandbox::policy::UtilitySandboxTypeFromString(
+ manifest->options.sandbox_type))) {
DestroyInstance(target_instance);
return nullptr;
}
@@ -324,10 +325,10 @@ ServiceInstance* ServiceManager::FindOrCreateMatchingTargetInstance(
auto process_host = delegate_->CreateProcessHostForServiceExecutable(
service_exe_root.AppendASCII(manifest->service_name +
kServiceExecutableExtension));
- if (!process_host ||
- !target_instance->StartWithProcessHost(
- std::move(process_host),
- UtilitySandboxTypeFromString(manifest->options.sandbox_type))) {
+ if (!process_host || !target_instance->StartWithProcessHost(
+ std::move(process_host),
+ sandbox::policy::UtilitySandboxTypeFromString(
+ manifest->options.sandbox_type))) {
DestroyInstance(target_instance);
return nullptr;
}
diff --git a/chromium/services/service_manager/service_manager.h b/chromium/services/service_manager/service_manager.h
index 4b456bed119..d4e84aba273 100644
--- a/chromium/services/service_manager/service_manager.h
+++ b/chromium/services/service_manager/service_manager.h
@@ -19,16 +19,16 @@
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
#include "mojo/public/cpp/bindings/remote_set.h"
+#include "sandbox/policy/sandbox_type.h"
#include "services/service_manager/catalog.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/cpp/manifest.h"
#include "services/service_manager/public/cpp/service.h"
-#include "services/service_manager/public/cpp/service_binding.h"
+#include "services/service_manager/public/cpp/service_receiver.h"
#include "services/service_manager/public/mojom/connector.mojom.h"
#include "services/service_manager/public/mojom/interface_provider.mojom.h"
#include "services/service_manager/public/mojom/service.mojom.h"
#include "services/service_manager/public/mojom/service_manager.mojom.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
#include "services/service_manager/service_instance_registry.h"
#include "services/service_manager/service_process_host.h"
@@ -194,7 +194,7 @@ class ServiceManager : public Service {
const std::unique_ptr<Delegate> delegate_;
- ServiceBinding service_binding_{this};
+ ServiceReceiver service_receiver_{this};
// Ownership of all ServiceInstances.
using InstanceMap =
diff --git a/chromium/services/service_manager/service_process_host.h b/chromium/services/service_manager/service_process_host.h
index 28700a4d189..d8482369915 100644
--- a/chromium/services/service_manager/service_process_host.h
+++ b/chromium/services/service_manager/service_process_host.h
@@ -11,9 +11,9 @@
#include "base/process/process_handle.h"
#include "base/strings/string16.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "sandbox/policy/sandbox_type.h"
#include "services/service_manager/public/cpp/identity.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/service_manager/sandbox/sandbox_type.h"
namespace service_manager {
@@ -37,7 +37,7 @@ class ServiceProcessHost {
using LaunchCallback = base::OnceCallback<void(base::ProcessId)>;
virtual mojo::PendingRemote<mojom::Service> Launch(
const Identity& identity,
- SandboxType sandbox_type,
+ sandbox::policy::SandboxType sandbox_type,
const base::string16& display_name,
LaunchCallback callback) = 0;
};
diff --git a/chromium/services/service_manager/service_process_launcher.cc b/chromium/services/service_manager/service_process_launcher.cc
index 2a738f1ab64..c424df90cea 100644
--- a/chromium/services/service_manager/service_process_launcher.cc
+++ b/chromium/services/service_manager/service_process_launcher.cc
@@ -31,12 +31,12 @@
#include "mojo/public/cpp/platform/platform_channel.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/cpp/system/invitation.h"
+#include "sandbox/policy/switches.h"
#include "services/service_manager/public/cpp/service_executable/switches.h"
#include "services/service_manager/public/mojom/service.mojom.h"
-#include "services/service_manager/sandbox/switches.h"
#include "services/service_manager/switches.h"
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
#include "sandbox/linux/services/namespace_sandbox.h"
#endif
@@ -56,7 +56,7 @@ class ServiceProcessLauncher::ProcessState
base::ProcessId LaunchInBackground(
const Identity& target,
- SandboxType sandbox_type,
+ sandbox::policy::SandboxType sandbox_type,
std::unique_ptr<base::CommandLine> child_command_line,
mojo::PlatformChannel::HandlePassingInfo handle_passing_info,
mojo::PlatformChannel channel,
@@ -95,7 +95,7 @@ ServiceProcessLauncher::~ServiceProcessLauncher() {
mojo::PendingRemote<mojom::Service> ServiceProcessLauncher::Start(
const Identity& target,
- SandboxType sandbox_type,
+ sandbox::policy::SandboxType sandbox_type,
ProcessReadyCallback callback) {
DCHECK(!state_);
@@ -131,7 +131,7 @@ mojo::PendingRemote<mojom::Service> ServiceProcessLauncher::Start(
if (!IsUnsandboxedSandboxType(sandbox_type)) {
child_command_line->AppendSwitchASCII(
- switches::kServiceSandboxType,
+ sandbox::policy::switches::kServiceSandboxType,
StringFromUtilitySandboxType(sandbox_type));
}
@@ -174,7 +174,7 @@ ServiceProcessLauncher::PassServiceRequestOnCommandLine(
base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
const Identity& target,
- SandboxType sandbox_type,
+ sandbox::policy::SandboxType sandbox_type,
std::unique_ptr<base::CommandLine> child_command_line,
mojo::PlatformChannel::HandlePassingInfo handle_passing_info,
mojo::PlatformChannel channel,
@@ -217,18 +217,18 @@ base::ProcessId ServiceProcessLauncher::ProcessState::LaunchInBackground(
{STDOUT_FILENO, STDOUT_FILENO},
{STDERR_FILENO, STDERR_FILENO},
};
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
options.fds_to_remap = fd_mapping;
options.mach_ports_for_rendezvous = handle_passing_info;
#else
handle_passing_info.insert(handle_passing_info.end(), fd_mapping.begin(),
fd_mapping.end());
options.fds_to_remap = handle_passing_info;
-#endif // defined(OS_MACOSX)
+#endif // defined(OS_MAC)
#endif
DVLOG(2) << "Launching child with command line: "
<< child_command_line->GetCommandLineString();
-#if defined(OS_LINUX)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS)
if (!IsUnsandboxedSandboxType(sandbox_type)) {
child_process_ =
sandbox::NamespaceSandbox::LaunchProcess(*child_command_line, options);
diff --git a/chromium/services/service_manager/service_process_launcher.h b/chromium/services/service_manager/service_process_launcher.h
index 1b0b04ff5c5..e45b0544aee 100644
--- a/chromium/services/service_manager/service_process_launcher.h
+++ b/chromium/services/service_manager/service_process_launcher.h
@@ -16,8 +16,8 @@
#include "base/process/process.h"
#include "base/sequenced_task_runner.h"
#include "mojo/public/cpp/bindings/pending_remote.h"
+#include "sandbox/policy/sandbox_type.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"
namespace mojo {
@@ -48,9 +48,10 @@ 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).
- mojo::PendingRemote<mojom::Service> Start(const Identity& target,
- SandboxType sandbox_type,
- ProcessReadyCallback callback);
+ mojo::PendingRemote<mojom::Service> Start(
+ const Identity& target,
+ sandbox::policy::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
diff --git a/chromium/services/service_manager/tests/BUILD.gn b/chromium/services/service_manager/tests/BUILD.gn
index 7bbd69673b5..4cef17398a9 100644
--- a/chromium/services/service_manager/tests/BUILD.gn
+++ b/chromium/services/service_manager/tests/BUILD.gn
@@ -31,7 +31,6 @@ test("service_manager_unittests") {
"//services/service_manager/public/mojom",
"//services/service_manager/tests/connect",
"//services/service_manager/tests/lifecycle",
- "//services/service_manager/tests/sandbox",
"//services/service_manager/tests/service_manager",
"//services/service_manager/tests/shutdown",
"//testing/gtest",
@@ -53,12 +52,12 @@ mojom("interfaces") {
"test_support.test-mojom",
]
- if (is_linux) {
+ if (is_linux || is_chromeos) {
sources += [ "sandbox_status.test-mojom" ]
}
}
-if (is_linux) {
+if (is_linux || is_chromeos) {
source_set("sandbox_status_service") {
testonly = true
sources = [
@@ -69,9 +68,9 @@ if (is_linux) {
deps = [
":interfaces",
"//base",
+ "//sandbox/policy",
"//services/service_manager/public/cpp",
"//services/service_manager/public/mojom",
- "//services/service_manager/sandbox:sandbox",
]
}
}
diff --git a/chromium/services/service_manager/tests/sandbox/BUILD.gn b/chromium/services/service_manager/tests/sandbox/BUILD.gn
deleted file mode 100644
index 4f8625df395..00000000000
--- a/chromium/services/service_manager/tests/sandbox/BUILD.gn
+++ /dev/null
@@ -1,24 +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.
-
-source_set("sandbox") {
- testonly = true
- sources = [ "sandbox_type_unittest.cc" ]
- deps = [
- "//base",
- "//base/test:test_support",
- "//services/service_manager/sandbox",
- "//testing/gtest",
- ]
-
- if (is_win) {
- sources += [ "sandbox_win_unittest.cc" ]
- deps += [ "//sandbox/win:sandbox" ]
- data = [
- "//base/test/data/pe_image/pe_image_test_32.dll",
- "//base/test/data/pe_image/pe_image_test_64.dll",
- "//base/test/data/pe_image/pe_image_test_arm64.dll",
- ]
- }
-}
diff --git a/chromium/services/shape_detection/BUILD.gn b/chromium/services/shape_detection/BUILD.gn
index 6b5de944119..32d99821235 100644
--- a/chromium/services/shape_detection/BUILD.gn
+++ b/chromium/services/shape_detection/BUILD.gn
@@ -32,7 +32,7 @@ source_set("lib") {
"text_detection_impl_mac.h",
"text_detection_impl_mac.mm",
]
- libs = [ "QuartzCore.framework" ]
+ frameworks = [ "QuartzCore.framework" ]
} else if (is_win) {
sources += [
"barcode_detection_provider_impl.cc",
@@ -122,7 +122,7 @@ source_set("tests") {
"text_detection_impl_win_unittest.cc",
]
if (is_mac) {
- libs = [
+ frameworks = [
"CoreFoundation.framework",
"CoreGraphics.framework",
"QuartzCore.framework",
diff --git a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java
index 4e5bb81862f..d6a7e2a68a3 100644
--- a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java
+++ b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/BarcodeDetectionImplTest.java
@@ -16,6 +16,7 @@ import org.chromium.base.test.params.ParameterAnnotations.UseRunnerDelegate;
import org.chromium.base.test.params.ParameterProvider;
import org.chromium.base.test.params.ParameterSet;
import org.chromium.base.test.params.ParameterizedRunner;
+import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
import org.chromium.shape_detection.mojom.BarcodeDetection;
import org.chromium.shape_detection.mojom.BarcodeDetectionProvider;
@@ -32,6 +33,7 @@ import java.util.concurrent.TimeUnit;
* Test suite for BarcodeDetectionImpl.
*/
@RunWith(ParameterizedRunner.class)
+@Batch(Batch.UNIT_TESTS)
@UseRunnerDelegate(BaseJUnit4RunnerDelegate.class)
public class BarcodeDetectionImplTest {
private static final org.chromium.skia.mojom.Bitmap QR_CODE_BITMAP =
diff --git a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java
index 85a7fdce814..ca26cabe414 100644
--- a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java
+++ b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/FaceDetectionImplTest.java
@@ -16,6 +16,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
import org.chromium.shape_detection.mojom.FaceDetection;
import org.chromium.shape_detection.mojom.FaceDetectionResult;
@@ -28,6 +29,7 @@ import java.util.concurrent.TimeUnit;
* Test suite for FaceDetectionImpl.
*/
@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
public class FaceDetectionImplTest {
private static final org.chromium.skia.mojom.Bitmap MONA_LISA_BITMAP =
TestUtils.mojoBitmapFromFile("mona_lisa.jpg");
diff --git a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java
index 953301ac851..11f8d760cff 100644
--- a/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java
+++ b/chromium/services/shape_detection/android/javatests/src/org/chromium/shape_detection/TextDetectionImplTest.java
@@ -11,6 +11,7 @@ import org.junit.Test;
import org.junit.runner.RunWith;
import org.chromium.base.test.BaseJUnit4ClassRunner;
+import org.chromium.base.test.util.Batch;
import org.chromium.base.test.util.Feature;
import org.chromium.gfx.mojom.RectF;
import org.chromium.shape_detection.mojom.TextDetection;
@@ -23,6 +24,7 @@ import java.util.concurrent.TimeUnit;
* Test suite for TextDetectionImpl.
*/
@RunWith(BaseJUnit4ClassRunner.class)
+@Batch(Batch.UNIT_TESTS)
public class TextDetectionImplTest {
private static final String[] DETECTION_EXPECTED_TEXT = {
"The quick brown fox jumped over the lazy dog.", "Helvetica Neue 36."};
diff --git a/chromium/services/shape_detection/face_detection_impl_mac_unittest.mm b/chromium/services/shape_detection/face_detection_impl_mac_unittest.mm
index 40ad1e9804d..ae8a01fa039 100644
--- a/chromium/services/shape_detection/face_detection_impl_mac_unittest.mm
+++ b/chromium/services/shape_detection/face_detection_impl_mac_unittest.mm
@@ -148,7 +148,8 @@ TEST_P(FaceDetectionImplMacTest, CreateAndDestroy) {
}
}
-TEST_P(FaceDetectionImplMacTest, ScanOneFace) {
+// Flakily fails on multiple configurations. https://crbug.com/1107962
+TEST_P(FaceDetectionImplMacTest, DISABLED_ScanOneFace) {
// Face detection test needs a GPU.
if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kUseGpuInTests)) {
diff --git a/chromium/services/shape_detection/shape_detection_service.cc b/chromium/services/shape_detection/shape_detection_service.cc
index e191a7b7832..f5238afa9ea 100644
--- a/chromium/services/shape_detection/shape_detection_service.cc
+++ b/chromium/services/shape_detection/shape_detection_service.cc
@@ -12,7 +12,7 @@
#if defined(OS_WIN)
#include "services/shape_detection/barcode_detection_provider_impl.h"
#include "services/shape_detection/face_detection_provider_win.h"
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
#include <dlfcn.h>
#include "services/shape_detection/barcode_detection_provider_mac.h"
#include "services/shape_detection/face_detection_provider_mac.h"
@@ -32,7 +32,7 @@ namespace shape_detection {
ShapeDetectionService::ShapeDetectionService(
mojo::PendingReceiver<mojom::ShapeDetectionService> receiver)
: receiver_(this, std::move(receiver)) {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
if (__builtin_available(macOS 10.13, *)) {
vision_framework_ =
dlopen("/System/Library/Frameworks/Vision.framework/Vision", RTLD_LAZY);
@@ -41,7 +41,7 @@ ShapeDetectionService::ShapeDetectionService(
}
ShapeDetectionService::~ShapeDetectionService() {
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
if (__builtin_available(macOS 10.13, *)) {
if (vision_framework_)
dlclose(vision_framework_);
@@ -55,7 +55,7 @@ void ShapeDetectionService::BindBarcodeDetectionProvider(
Java_InterfaceRegistrar_bindBarcodeDetectionProvider(
base::android::AttachCurrentThread(),
receiver.PassPipe().release().value());
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
BarcodeDetectionProviderMac::Create(std::move(receiver));
#else
BarcodeDetectionProviderImpl::Create(std::move(receiver));
@@ -68,7 +68,7 @@ void ShapeDetectionService::BindFaceDetectionProvider(
Java_InterfaceRegistrar_bindFaceDetectionProvider(
base::android::AttachCurrentThread(),
receiver.PassPipe().release().value());
-#elif defined(OS_MACOSX)
+#elif defined(OS_MAC)
FaceDetectionProviderMac::Create(std::move(receiver));
#elif defined(OS_WIN)
FaceDetectionProviderWin::Create(std::move(receiver));
diff --git a/chromium/services/shape_detection/shape_detection_service.h b/chromium/services/shape_detection/shape_detection_service.h
index 956e75bc31d..e9e265440f7 100644
--- a/chromium/services/shape_detection/shape_detection_service.h
+++ b/chromium/services/shape_detection/shape_detection_service.h
@@ -33,7 +33,7 @@ class ShapeDetectionService : public mojom::ShapeDetectionService {
private:
mojo::Receiver<mojom::ShapeDetectionService> receiver_;
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
void* vision_framework_;
#endif
diff --git a/chromium/services/tracing/BUILD.gn b/chromium/services/tracing/BUILD.gn
index bcb2fe7993d..e0d3e156649 100644
--- a/chromium/services/tracing/BUILD.gn
+++ b/chromium/services/tracing/BUILD.gn
@@ -86,6 +86,7 @@ source_set("tests") {
"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/trace_packet_tokenizer_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/perfetto/consumer_host.cc b/chromium/services/tracing/perfetto/consumer_host.cc
index 67a3d1b0e0f..7a80f83844f 100644
--- a/chromium/services/tracing/perfetto/consumer_host.cc
+++ b/chromium/services/tracing/perfetto/consumer_host.cc
@@ -23,9 +23,9 @@
#include "base/values.h"
#include "build/build_config.h"
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
-#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/perfetto/perfetto_session.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"
@@ -217,27 +217,35 @@ ConsumerHost::TracingSession::~TracingSession() {
void ConsumerHost::TracingSession::OnPerfettoEvents(
const perfetto::ObservableEvents& events) {
- if (!pending_enable_tracing_ack_pids_) {
+ if (!pending_enable_tracing_ack_pids_ ||
+ !events.instance_state_changes_size()) {
return;
}
for (const auto& state_change : events.instance_state_changes()) {
- if (state_change.state() !=
- perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED) {
- continue;
- }
-
- if (state_change.data_source_name() != mojom::kTraceEventDataSourceName) {
- continue;
- }
+ DataSourceHandle handle(state_change.producer_name(),
+ state_change.data_source_name());
+ data_source_states_[handle] =
+ state_change.state() ==
+ perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED;
+ }
+
+ // Data sources are first reported as being stopped before starting, so once
+ // all the data sources we know about have started we can declare tracing
+ // begun.
+ bool all_data_sources_started = std::all_of(
+ data_source_states_.cbegin(), data_source_states_.cend(),
+ [](std::pair<DataSourceHandle, bool> state) { return state.second; });
+ if (!all_data_sources_started)
+ return;
+ for (const auto& it : data_source_states_) {
// Attempt to parse the PID out of the producer name.
base::ProcessId pid;
- if (!PerfettoService::ParsePidFromProducerName(state_change.producer_name(),
+ if (!PerfettoService::ParsePidFromProducerName(it.first.producer_name(),
&pid)) {
continue;
}
-
pending_enable_tracing_ack_pids_->erase(pid);
}
MaybeSendEnableTracingAck();
@@ -396,7 +404,11 @@ void ConsumerHost::TracingSession::DisableTracingAndEmitJson(
perfetto::trace_processor::TraceProcessorStorage::CreateInstance(
processor_config);
- DisableTracing();
+ if (tracing_enabled_) {
+ DisableTracing();
+ } else {
+ host_->consumer_endpoint()->ReadBuffers();
+ }
}
void ConsumerHost::TracingSession::ExportJson() {
@@ -543,19 +555,8 @@ void ConsumerHost::TracingSession::OnTraceStats(
std::move(request_buffer_usage_callback_).Run(false, 0.0f, false);
return;
}
-
- const perfetto::TraceStats::BufferStats& buf_stats = stats.buffer_stats()[0];
- size_t bytes_in_buffer = buf_stats.bytes_written() - buf_stats.bytes_read() -
- buf_stats.bytes_overwritten() +
- buf_stats.padding_bytes_written() -
- buf_stats.padding_bytes_cleared();
- double percent_full =
- bytes_in_buffer / static_cast<double>(buf_stats.buffer_size());
- percent_full = base::ClampToRange(percent_full, 0.0, 1.0);
- bool data_loss = buf_stats.chunks_overwritten() > 0 ||
- buf_stats.chunks_discarded() > 0 ||
- buf_stats.abi_violations() > 0 ||
- buf_stats.trace_writer_packet_loss() > 0;
+ double percent_full = GetTraceBufferUsage(stats);
+ bool data_loss = HasLostData(stats);
std::move(request_buffer_usage_callback_).Run(true, percent_full, data_loss);
}
diff --git a/chromium/services/tracing/perfetto/consumer_host.h b/chromium/services/tracing/perfetto/consumer_host.h
index b8bc8e12e48..97c7e36f6f8 100644
--- a/chromium/services/tracing/perfetto/consumer_host.h
+++ b/chromium/services/tracing/perfetto/consumer_host.h
@@ -110,6 +110,13 @@ class ConsumerHost : public perfetto::Consumer, public mojom::ConsumerHost {
base::Optional<std::set<base::ProcessId>> pending_enable_tracing_ack_pids_;
base::OneShotTimer enable_tracing_ack_timer_;
+ struct DataSourceHandle : public std::pair<std::string, std::string> {
+ using std::pair<std::string, std::string>::pair;
+ const std::string& producer_name() const { return first; }
+ const std::string& data_source_name() const { return second; }
+ };
+ std::map<DataSourceHandle, bool /*started*/> data_source_states_;
+
SEQUENCE_CHECKER(sequence_checker_);
base::WeakPtrFactory<TracingSession> weak_factory_{this};
diff --git a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
index a95c7c97a36..c5b00b316c7 100644
--- a/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
+++ b/chromium/services/tracing/perfetto/perfetto_integration_unittest.cc
@@ -10,12 +10,16 @@
#include "base/bind.h"
#include "base/run_loop.h"
#include "base/strings/strcat.h"
+#include "base/test/bind_test_util.h"
#include "base/test/task_environment.h"
+#include "base/threading/thread.h"
#include "services/tracing/perfetto/perfetto_service.h"
#include "services/tracing/perfetto/producer_host.h"
#include "services/tracing/perfetto/test_utils.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
#include "services/tracing/public/cpp/perfetto/producer_client.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
#include "third_party/perfetto/protos/perfetto/common/commit_data_request.pb.h"
// TODO(crbug.com/961066): Fix memory leaks in tests and re-enable on LSAN.
@@ -38,9 +42,21 @@ std::string GetPerfettoProducerName() {
return base::StrCat({mojom::kPerfettoProducerNamePrefix, "123"});
}
+RebindableTaskRunner* GetPerfettoTaskRunner() {
+ static base::NoDestructor<RebindableTaskRunner> task_runner;
+ return task_runner.get();
+}
+
class PerfettoIntegrationTest : public testing::Test {
public:
void SetUp() override {
+ auto* perfetto_task_runner = GetPerfettoTaskRunner();
+ auto* perfetto_platform =
+ PerfettoTracedProcess::Get()->perfetto_platform_for_testing();
+ if (!perfetto_platform->did_start_task_runner())
+ perfetto_platform->StartTaskRunner(perfetto_task_runner);
+ perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get());
+
PerfettoTracedProcess::ResetTaskRunnerForTesting();
PerfettoTracedProcess::Get()->ClearDataSourcesForTesting();
data_source_ = TestDataSource::CreateAndRegisterDataSource(
@@ -363,6 +379,34 @@ TEST_F(PerfettoIntegrationTest,
(*client2)->shared_memory_for_testing());
}
+TEST_F(PerfettoIntegrationTest, PerfettoPlatformTest) {
+ auto* platform =
+ PerfettoTracedProcess::Get()->perfetto_platform_for_testing();
+ auto* tls = platform->GetOrCreateThreadLocalObject();
+ EXPECT_TRUE(tls);
+ EXPECT_EQ(tls, platform->GetOrCreateThreadLocalObject());
+
+ base::Thread thread("TestThread");
+ thread.Start();
+ thread.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&platform, &tls] {
+ auto* thread_tls = platform->GetOrCreateThreadLocalObject();
+ EXPECT_TRUE(thread_tls);
+ EXPECT_NE(tls, thread_tls);
+ }));
+ thread.Stop();
+}
+
+TEST_F(PerfettoIntegrationTest, PerfettoClientLibraryTest) {
+ PerfettoTracedProcess::Get()->SetupClientLibrary();
+ // Create a dummy tracing session without a real backend to check that
+ // the client library was initialized.
+ constexpr perfetto::BackendType kInvalidBackend(
+ static_cast<perfetto::BackendType>(1u << 31));
+ auto tracing_session = perfetto::Tracing::NewTrace(kInvalidBackend);
+ EXPECT_TRUE(tracing_session);
+}
+
} // namespace
} // namespace tracing
diff --git a/chromium/services/tracing/perfetto/perfetto_service.cc b/chromium/services/tracing/perfetto/perfetto_service.cc
index de5e660bbb6..359164ed2bf 100644
--- a/chromium/services/tracing/perfetto/perfetto_service.cc
+++ b/chromium/services/tracing/perfetto/perfetto_service.cc
@@ -125,6 +125,15 @@ void PerfettoService::RemoveActiveServicePid(base::ProcessId pid) {
}
}
+void PerfettoService::RemoveActiveServicePidIfNoActiveConnections(
+ base::ProcessId pid) {
+ const auto num_connections_it = num_active_connections_.find(pid);
+ if (num_connections_it == num_active_connections_.end() ||
+ num_connections_it->second == 0) {
+ RemoveActiveServicePid(pid);
+ }
+}
+
void PerfettoService::SetActiveServicePidsInitialized() {
active_service_pids_initialized_ = true;
for (auto* tracing_session : tracing_sessions_) {
diff --git a/chromium/services/tracing/perfetto/perfetto_service.h b/chromium/services/tracing/perfetto/perfetto_service.h
index edba7d6ab58..56f60c822ec 100644
--- a/chromium/services/tracing/perfetto/perfetto_service.h
+++ b/chromium/services/tracing/perfetto/perfetto_service.h
@@ -64,6 +64,7 @@ class PerfettoService : public mojom::PerfettoService {
// actively running services (whenever a service starts or stops).
void AddActiveServicePid(base::ProcessId pid);
void RemoveActiveServicePid(base::ProcessId pid);
+ void RemoveActiveServicePidIfNoActiveConnections(base::ProcessId pid);
void SetActiveServicePidsInitialized();
std::set<base::ProcessId> active_service_pids() const {
diff --git a/chromium/services/tracing/perfetto/producer_host.cc b/chromium/services/tracing/perfetto/producer_host.cc
index 31a907c7c8b..7d7d243213c 100644
--- a/chromium/services/tracing/perfetto/producer_host.cc
+++ b/chromium/services/tracing/perfetto/producer_host.cc
@@ -71,7 +71,9 @@ bool ProducerHost::Initialize(
base::ProcessId pid;
if (PerfettoService::ParsePidFromProducerName(name, &pid)) {
bool in_process = (pid == base::Process::Current().Pid());
- if (in_process) {
+ // TODO(skyostil): Implement arbiter binding for the client API.
+ if (in_process && !base::FeatureList::IsEnabled(
+ features::kEnablePerfettoClientApiProducer)) {
PerfettoTracedProcess::Get()
->producer_client()
->BindInProcessSharedMemoryArbiter(producer_endpoint_.get(),
diff --git a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
index f217e6d0103..0b6c066c2c2 100644
--- a/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
+++ b/chromium/services/tracing/perfetto/system_perfetto_unittest.cc
@@ -58,30 +58,32 @@ std::string RandomASCII(size_t length) {
return tmp;
}
-class SaveSystemProducerAndScopedRestore {
+class ClearAndRestoreSystemProducerScope {
public:
- SaveSystemProducerAndScopedRestore() {
+ ClearAndRestoreSystemProducerScope() {
+ base::RunLoop setup_loop;
PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
- FROM_HERE, base::BindLambdaForTesting([this] {
+ FROM_HERE, base::BindLambdaForTesting([this, &setup_loop] {
saved_producer_ =
PerfettoTracedProcess::Get()->SetSystemProducerForTesting(
- std::make_unique<DummyProducer>(
- PerfettoTracedProcess::GetTaskRunner()));
+ nullptr);
+ setup_loop.Quit();
}));
+ setup_loop.Run();
}
- ~SaveSystemProducerAndScopedRestore() {
- base::RunLoop destroy;
- PerfettoTracedProcess::GetTaskRunner()
- ->GetOrCreateTaskRunner()
- ->PostTaskAndReply(
- FROM_HERE, base::BindLambdaForTesting([this]() {
+ ~ClearAndRestoreSystemProducerScope() {
+ base::RunLoop destroy_loop;
+ PerfettoTracedProcess::GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
+ FROM_HERE,
+ base::BindLambdaForTesting(
+ [this, &destroy_loop]() {
PerfettoTracedProcess::Get()
->SetSystemProducerForTesting(std::move(saved_producer_))
.reset();
- }),
- destroy.QuitClosure());
- destroy.Run();
+ destroy_loop.Quit();
+ }));
+ destroy_loop.Run();
}
private:
@@ -889,18 +891,10 @@ TEST_F(SystemPerfettoTest, SystemToLowAPILevel) {
TEST_F(SystemPerfettoTest, EnabledOnDebugBuilds) {
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
- // We have to prevent destroying the system producer because we might have
- // created it on a different task environment (wrong sequence).
- SaveSystemProducerAndScopedRestore saved_system_producer;
- PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
- EXPECT_FALSE(PerfettoTracedProcess::Get()
- ->system_producer()
- ->IsDummySystemProducerForTesting());
+ EXPECT_TRUE(ShouldSetupSystemTracing());
} else {
- EXPECT_TRUE(PerfettoTracedProcess::Get()
- ->system_producer()
- ->IsDummySystemProducerForTesting());
+ EXPECT_FALSE(ShouldSetupSystemTracing());
}
}
#endif // defined(OS_ANDROID)
@@ -910,27 +904,19 @@ TEST_F(SystemPerfettoTest, RespectsFeatureList) {
if (base::android::BuildInfo::GetInstance()->is_debug_android()) {
// The feature list is ignored on debug android builds so we should have a
// real system producer so just bail out of this test.
- EXPECT_FALSE(PerfettoTracedProcess::Get()
- ->system_producer()
- ->IsDummySystemProducerForTesting());
+ EXPECT_TRUE(ShouldSetupSystemTracing());
return;
}
#endif // defined(OS_ANDROID)
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndEnableFeature(features::kEnablePerfettoSystemTracing);
- PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
- EXPECT_FALSE(PerfettoTracedProcess::Get()
- ->system_producer()
- ->IsDummySystemProducerForTesting());
+ EXPECT_TRUE(ShouldSetupSystemTracing());
}
{
base::test::ScopedFeatureList feature_list;
feature_list.InitAndDisableFeature(features::kEnablePerfettoSystemTracing);
- PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
- EXPECT_TRUE(PerfettoTracedProcess::Get()
- ->system_producer()
- ->IsDummySystemProducerForTesting());
+ EXPECT_FALSE(ShouldSetupSystemTracing());
}
}
@@ -951,7 +937,6 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
feature_list.InitAndDisableFeature(
features::kEnablePerfettoSystemTracing);
}
- PerfettoTracedProcess::ReconstructForTesting(producer_socket_.c_str());
std::string data_source_name = "temp_name";
@@ -1007,10 +992,26 @@ TEST_F(SystemPerfettoTest, RespectsFeaturePreAndroidPie) {
return system_consumer.received_test_packets();
};
- EXPECT_EQ(1u, run_test(/* enable_feature = */ true));
EXPECT_EQ(0u, run_test(/* enable_feature = */ false));
+ EXPECT_EQ(1u, run_test(/* enable_feature = */ true));
}
#endif // defined(OS_ANDROID)
+TEST_F(SystemPerfettoTest, SetupSystemTracing) {
+ ClearAndRestoreSystemProducerScope saved_system_producer;
+ EXPECT_FALSE(PerfettoTracedProcess::Get()->system_producer());
+ PerfettoTracedProcess::Get()->SetupSystemTracing();
+ EXPECT_TRUE(PerfettoTracedProcess::Get()->system_producer());
+#if defined(OS_POSIX)
+ EXPECT_FALSE(PerfettoTracedProcess::Get()
+ ->system_producer()
+ ->IsDummySystemProducerForTesting());
+#else // defined(OS_POSIX)
+ EXPECT_TRUE(PerfettoTracedProcess::Get()
+ ->system_producer()
+ ->IsDummySystemProducerForTesting());
+#endif // defined(OS_POSIX)
+}
+
} // namespace
-} // namespace tracing
+} // namespace tracing \ No newline at end of file
diff --git a/chromium/services/tracing/perfetto/test_utils.cc b/chromium/services/tracing/perfetto/test_utils.cc
index a8366d57819..074b557dcb2 100644
--- a/chromium/services/tracing/perfetto/test_utils.cc
+++ b/chromium/services/tracing/perfetto/test_utils.cc
@@ -410,6 +410,9 @@ MockProducer::MockProducer(const std::string& producer_name,
MockProducer::~MockProducer() = default;
+RebindableTaskRunner::RebindableTaskRunner() = default;
+RebindableTaskRunner::~RebindableTaskRunner() = default;
+
void MockProducer::WritePacketBigly(base::OnceClosure on_write_complete) {
PerfettoTracedProcess::Get()
->GetTaskRunner()
@@ -420,4 +423,22 @@ void MockProducer::WritePacketBigly(base::OnceClosure on_write_complete) {
std::move(on_write_complete));
}
+bool RebindableTaskRunner::PostDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) {
+ return task_runner_->PostDelayedTask(from_here, std::move(task), delay);
+}
+
+bool RebindableTaskRunner::PostNonNestableDelayedTask(
+ const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) {
+ return task_runner_->PostNonNestableDelayedTask(from_here, std::move(task),
+ delay);
+}
+
+bool RebindableTaskRunner::RunsTasksInCurrentSequence() const {
+ return task_runner_->RunsTasksInCurrentSequence();
+}
+
} // namespace tracing
diff --git a/chromium/services/tracing/perfetto/test_utils.h b/chromium/services/tracing/perfetto/test_utils.h
index c33d41c7f6b..7963a76a124 100644
--- a/chromium/services/tracing/perfetto/test_utils.h
+++ b/chromium/services/tracing/perfetto/test_utils.h
@@ -226,6 +226,31 @@ class MockProducer {
std::unique_ptr<MockProducerHost> producer_host_;
};
+// A proxy task runner which can be dynamically pointed to route tasks into a
+// different task runner.
+class RebindableTaskRunner : public base::SequencedTaskRunner {
+ public:
+ RebindableTaskRunner();
+
+ void set_task_runner(scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ task_runner_ = task_runner;
+ }
+
+ // base::SequecedTaskRunner implementation.
+ bool PostDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override;
+ bool PostNonNestableDelayedTask(const base::Location& from_here,
+ base::OnceClosure task,
+ base::TimeDelta delay) override;
+ bool RunsTasksInCurrentSequence() const override;
+
+ private:
+ ~RebindableTaskRunner() override;
+
+ scoped_refptr<base::SequencedTaskRunner> task_runner_;
+};
+
} // namespace tracing
#endif // SERVICES_TRACING_PERFETTO_TEST_UTILS_H_
diff --git a/chromium/services/tracing/public/cpp/BUILD.gn b/chromium/services/tracing/public/cpp/BUILD.gn
index 1cd4d42da6e..870afc29b6e 100644
--- a/chromium/services/tracing/public/cpp/BUILD.gn
+++ b/chromium/services/tracing/public/cpp/BUILD.gn
@@ -74,10 +74,16 @@ target(tracing_lib_type, "cpp") {
"perfetto/java_heap_profiler/java_heap_profiler_android.h",
"perfetto/perfetto_config.cc",
"perfetto/perfetto_config.h",
+ "perfetto/perfetto_platform.cc",
+ "perfetto/perfetto_platform.h",
"perfetto/perfetto_producer.cc",
"perfetto/perfetto_producer.h",
+ "perfetto/perfetto_session.cc",
+ "perfetto/perfetto_session.h",
"perfetto/perfetto_traced_process.cc",
"perfetto/perfetto_traced_process.h",
+ "perfetto/perfetto_tracing_backend.cc",
+ "perfetto/perfetto_tracing_backend.h",
"perfetto/producer_client.cc",
"perfetto/producer_client.h",
"perfetto/shared_memory.cc",
@@ -89,6 +95,8 @@ target(tracing_lib_type, "cpp") {
"perfetto/task_runner.h",
"perfetto/trace_event_data_source.cc",
"perfetto/trace_event_data_source.h",
+ "perfetto/trace_packet_tokenizer.cc",
+ "perfetto/trace_packet_tokenizer.h",
"perfetto/trace_time.cc",
"perfetto/trace_time.h",
"perfetto/traced_value_proto_writer.cc",
diff --git a/chromium/services/tracing/public/cpp/base_agent.h b/chromium/services/tracing/public/cpp/base_agent.h
index ab3d6ecb0a4..53894b743ad 100644
--- a/chromium/services/tracing/public/cpp/base_agent.h
+++ b/chromium/services/tracing/public/cpp/base_agent.h
@@ -19,6 +19,7 @@ class COMPONENT_EXPORT(TRACING_CPP) BaseAgent {
public:
virtual ~BaseAgent();
+ // May be called on any thread.
virtual void GetCategories(std::set<std::string>* category_set);
protected:
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
index 94edd835823..a9e1d680eaa 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.cc
@@ -24,7 +24,8 @@ perfetto::TraceConfig::DataSource* AddDataSourceConfig(
perfetto::TraceConfig* perfetto_config,
const char* name,
const std::string& chrome_config_string,
- bool privacy_filtering_enabled) {
+ bool privacy_filtering_enabled,
+ bool convert_to_legacy_json) {
auto* data_source = perfetto_config->add_data_sources();
auto* source_config = data_source->mutable_config();
source_config->set_name(name);
@@ -32,6 +33,7 @@ perfetto::TraceConfig::DataSource* AddDataSourceConfig(
auto* chrome_config = source_config->mutable_chrome_config();
chrome_config->set_trace_config(chrome_config_string);
chrome_config->set_privacy_filtering_enabled(privacy_filtering_enabled);
+ chrome_config->set_convert_to_legacy_json(convert_to_legacy_json);
return data_source;
}
@@ -40,7 +42,8 @@ void AddDataSourceConfigs(
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) {
+ bool privacy_filtering_enabled,
+ bool convert_to_legacy_json) {
const std::string chrome_config_string = stripped_config.ToString();
// Capture actual trace events.
@@ -48,7 +51,8 @@ void AddDataSourceConfigs(
source_names.count(tracing::mojom::kTraceEventDataSourceName) == 1) {
auto* trace_event_data_source = AddDataSourceConfig(
perfetto_config, tracing::mojom::kTraceEventDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
for (auto& enabled_pid : process_filters.included_process_ids()) {
*trace_event_data_source->add_producer_name_filter() = base::StrCat(
{mojom::kPerfettoProducerNamePrefix,
@@ -64,7 +68,8 @@ void AddDataSourceConfigs(
source_names.count(tracing::mojom::kSystemTraceDataSourceName) == 1) {
AddDataSourceConfig(perfetto_config,
tracing::mojom::kSystemTraceDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
#endif
@@ -73,7 +78,8 @@ void AddDataSourceConfigs(
source_names.count(tracing::mojom::kArcTraceDataSourceName) == 1) {
AddDataSourceConfig(perfetto_config,
tracing::mojom::kArcTraceDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
#endif
}
@@ -82,7 +88,8 @@ void AddDataSourceConfigs(
if (source_names.empty() ||
source_names.count(tracing::mojom::kMetaDataSourceName) == 1) {
AddDataSourceConfig(perfetto_config, tracing::mojom::kMetaDataSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
if (stripped_config.IsCategoryGroupEnabled(
@@ -92,7 +99,8 @@ void AddDataSourceConfigs(
source_names.count(tracing::mojom::kSamplerProfilerSourceName));
AddDataSourceConfig(perfetto_config,
tracing::mojom::kSamplerProfilerSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
if (stripped_config.IsCategoryGroupEnabled(
@@ -102,14 +110,16 @@ void AddDataSourceConfigs(
tracing::mojom::kJavaHeapProfilerSourceName));
AddDataSourceConfig(perfetto_config,
tracing::mojom::kJavaHeapProfilerSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
if (source_names.empty() ||
source_names.count(tracing::mojom::kReachedCodeProfilerSourceName) == 1) {
AddDataSourceConfig(perfetto_config,
tracing::mojom::kReachedCodeProfilerSourceName,
- chrome_config_string, privacy_filtering_enabled);
+ chrome_config_string, privacy_filtering_enabled,
+ convert_to_legacy_json);
}
}
@@ -117,16 +127,18 @@ void AddDataSourceConfigs(
perfetto::TraceConfig GetDefaultPerfettoConfig(
const base::trace_event::TraceConfig& chrome_config,
- bool privacy_filtering_enabled) {
- return GetPerfettoConfigWithDataSources(chrome_config, {},
- privacy_filtering_enabled);
+ bool privacy_filtering_enabled,
+ bool convert_to_legacy_json) {
+ return GetPerfettoConfigWithDataSources(
+ chrome_config, {}, privacy_filtering_enabled, convert_to_legacy_json);
}
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) {
+ bool privacy_filtering_enabled,
+ bool convert_to_legacy_json) {
perfetto::TraceConfig perfetto_config;
size_t size_limit = chrome_config.GetTraceBufferSizeInKb();
@@ -187,8 +199,8 @@ perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP)
stripped_config.SetTraceBufferSizeInEvents(0);
AddDataSourceConfigs(&perfetto_config, chrome_config.process_filter_config(),
- stripped_config, source_names,
- privacy_filtering_enabled);
+ stripped_config, source_names, privacy_filtering_enabled,
+ convert_to_legacy_json);
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 27d33a982c4..6f8b4a5b4f0 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_config.h
@@ -21,7 +21,8 @@ namespace tracing {
perfetto::TraceConfig COMPONENT_EXPORT(TRACING_CPP) GetDefaultPerfettoConfig(
const base::trace_event::TraceConfig& chrome_config,
- bool privacy_filtering_enabled = false);
+ bool privacy_filtering_enabled = false,
+ bool convert_to_legacy_json = 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
@@ -31,7 +32,8 @@ 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);
+ bool privacy_filtering_enabled = false,
+ bool convert_to_legacy_json = false);
} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.cc
new file mode 100644
index 00000000000..d56b2280987
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.cc
@@ -0,0 +1,57 @@
+// 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/perfetto_platform.h"
+
+#include "base/deferred_sequenced_task_runner.h"
+#include "base/task/task_traits.h"
+#include "base/task/thread_pool.h"
+#include "services/tracing/public/cpp/perfetto/task_runner.h"
+
+namespace tracing {
+
+PerfettoPlatform::PerfettoPlatform()
+ : deferred_task_runner_(new base::DeferredSequencedTaskRunner()),
+ thread_local_object_([](void* object) {
+ delete static_cast<ThreadLocalObject*>(object);
+ }) {}
+
+PerfettoPlatform::~PerfettoPlatform() = default;
+
+void PerfettoPlatform::StartTaskRunner(
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ DCHECK(!did_start_task_runner_);
+ deferred_task_runner_->StartWithTaskRunner(task_runner);
+ did_start_task_runner_ = true;
+}
+
+base::SequencedTaskRunner* PerfettoPlatform::task_runner() const {
+ return deferred_task_runner_.get();
+}
+
+PerfettoPlatform::ThreadLocalObject*
+PerfettoPlatform::GetOrCreateThreadLocalObject() {
+ auto* object = static_cast<ThreadLocalObject*>(thread_local_object_.Get());
+ if (!object) {
+ object = ThreadLocalObject::CreateInstance().release();
+ thread_local_object_.Set(object);
+ }
+ return object;
+}
+
+std::unique_ptr<perfetto::base::TaskRunner> PerfettoPlatform::CreateTaskRunner(
+ const CreateTaskRunnerArgs&) {
+ // We can't create a real task runner yet because the ThreadPool may not be
+ // initialized. Instead, we point Perfetto to a buffering task runner which
+ // will become active as soon as the thread pool is up (see StartTaskRunner).
+ return std::make_unique<PerfettoTaskRunner>(deferred_task_runner_);
+}
+
+std::string PerfettoPlatform::GetCurrentProcessName() {
+ // TODO(skyostil): Unimplemented since we're not registering producers through
+ // the client API yet.
+ return "";
+}
+
+} // namespace tracing \ No newline at end of file
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.h
new file mode 100644
index 00000000000..254ba9efca3
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_platform.h
@@ -0,0 +1,44 @@
+// 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_PERFETTO_PLATFORM_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PLATFORM_H_
+
+#include "third_party/perfetto/include/perfetto/tracing/platform.h"
+
+#include "base/component_export.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/threading/thread_local_storage.h"
+
+namespace base {
+class DeferredSequencedTaskRunner;
+} // namespace base
+
+namespace tracing {
+
+class COMPONENT_EXPORT(TRACING_CPP) PerfettoPlatform
+ : public perfetto::Platform {
+ public:
+ PerfettoPlatform();
+ ~PerfettoPlatform() override;
+
+ base::SequencedTaskRunner* task_runner() const;
+ bool did_start_task_runner() const { return did_start_task_runner_; }
+ void StartTaskRunner(scoped_refptr<base::SequencedTaskRunner>);
+
+ // perfetto::Platform implementation:
+ ThreadLocalObject* GetOrCreateThreadLocalObject() override;
+ std::unique_ptr<perfetto::base::TaskRunner> CreateTaskRunner(
+ const CreateTaskRunnerArgs&) override;
+ std::string GetCurrentProcessName() override;
+
+ private:
+ scoped_refptr<base::DeferredSequencedTaskRunner> deferred_task_runner_;
+ bool did_start_task_runner_ = false;
+ base::ThreadLocalStorage::Slot thread_local_object_;
+};
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_PLATFORM_H_ \ No newline at end of file
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
index 304d0472ad3..18dfa0e40a7 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_producer.h
@@ -110,7 +110,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoProducer {
bool IsStartupTracingActive();
- // TODO(oysteine): Find a good compromise between performance and
+ // TODO(crbug.com/839071): Find a good compromise between performance and
// data granularity (mainly relevant to running with small buffer sizes
// when we use background tracing) on Android.
#if defined(OS_ANDROID)
@@ -119,7 +119,7 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoProducer {
static constexpr size_t kSMBPageSizeBytes = 32 * 1024;
#endif
- // TODO(oysteine): Figure out a good buffer size.
+ // TODO(crbug.com/839071): Figure out a good buffer size.
static constexpr size_t kSMBSizeBytes = 4 * 1024 * 1024;
PerfettoTaskRunner* task_runner();
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_session.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.cc
new file mode 100644
index 00000000000..b3588ddc767
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.cc
@@ -0,0 +1,35 @@
+// 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/perfetto_session.h"
+
+#include "third_party/perfetto/protos/perfetto/common/trace_stats.gen.h"
+
+namespace tracing {
+
+double GetTraceBufferUsage(const perfetto::protos::gen::TraceStats& stats) {
+ // Chrome always uses a single tracing buffer.
+ if (stats.buffer_stats_size() != 1u)
+ return 0.f;
+ const perfetto::protos::gen::TraceStats::BufferStats& buf_stats =
+ stats.buffer_stats()[0];
+ size_t bytes_in_buffer = buf_stats.bytes_written() - buf_stats.bytes_read() -
+ buf_stats.bytes_overwritten() +
+ buf_stats.padding_bytes_written() -
+ buf_stats.padding_bytes_cleared();
+ return bytes_in_buffer / static_cast<double>(buf_stats.buffer_size());
+}
+
+bool HasLostData(const perfetto::protos::gen::TraceStats& stats) {
+ // Chrome always uses a single tracing buffer.
+ if (stats.buffer_stats_size() != 1u)
+ return false;
+ const perfetto::protos::gen::TraceStats::BufferStats& buf_stats =
+ stats.buffer_stats()[0];
+ return buf_stats.chunks_overwritten() > 0 ||
+ buf_stats.chunks_discarded() > 0 || buf_stats.abi_violations() > 0 ||
+ buf_stats.trace_writer_packet_loss() > 0;
+}
+
+} // namespace tracing \ No newline at end of file
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h
new file mode 100644
index 00000000000..9f6e0dd6779
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_session.h
@@ -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.
+
+#ifndef SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_SESSION_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_SESSION_H_
+
+#include <set>
+#include <string>
+
+#include "base/component_export.h"
+
+namespace perfetto {
+namespace protos {
+namespace gen {
+class TraceStats;
+} // namespace gen
+} // namespace protos
+} // namespace perfetto
+
+namespace tracing {
+
+// Helpers for deriving information from Perfetto's tracing session statistics.
+double COMPONENT_EXPORT(TRACING_CPP)
+ GetTraceBufferUsage(const perfetto::protos::gen::TraceStats&);
+bool COMPONENT_EXPORT(TRACING_CPP)
+ HasLostData(const perfetto::protos::gen::TraceStats&);
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_SESSION_H_ \ No newline at end of file
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
index b9d5d7cfff3..4bc5ac15547 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.cc
@@ -5,7 +5,6 @@
#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
#include "base/bind_helpers.h"
-#include "base/feature_list.h"
#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/sequenced_task_runner.h"
@@ -14,11 +13,15 @@
#include "base/trace_event/trace_log.h"
#include "build/build_config.h"
#include "services/tracing/public/cpp/perfetto/dummy_producer.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h"
#include "services/tracing/public/cpp/perfetto/producer_client.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_startup.h"
#include "services/tracing/public/cpp/tracing_features.h"
+#include "services/tracing/public/mojom/tracing_service.mojom.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
#if defined(OS_POSIX)
// As per 'gn help check':
@@ -38,10 +41,8 @@ namespace {
std::unique_ptr<SystemProducer> NewSystemProducer(PerfettoTaskRunner* runner,
const char* socket_name) {
#if defined(OS_POSIX)
- if (ShouldSetupSystemTracing()) {
- DCHECK(socket_name);
- return std::make_unique<PosixSystemProducer>(socket_name, runner);
- }
+ DCHECK(socket_name);
+ return std::make_unique<PosixSystemProducer>(socket_name, runner);
#endif // defined(OS_POSIX)
return std::make_unique<DummyProducer>(runner);
}
@@ -80,16 +81,32 @@ PerfettoTracedProcess* PerfettoTracedProcess::Get() {
}
PerfettoTracedProcess::PerfettoTracedProcess()
- : PerfettoTracedProcess(MaybeSocket()) {}
-
-PerfettoTracedProcess::PerfettoTracedProcess(const char* system_socket)
: producer_client_(std::make_unique<ProducerClient>(GetTaskRunner())),
- system_producer_(NewSystemProducer(GetTaskRunner(), system_socket)) {
+ platform_(std::make_unique<PerfettoPlatform>()),
+ tracing_backend_(std::make_unique<PerfettoTracingBackend>(*this)) {
DETACH_FROM_SEQUENCE(sequence_checker_);
}
PerfettoTracedProcess::~PerfettoTracedProcess() {}
+void PerfettoTracedProcess::SetConsumerConnectionFactory(
+ ConsumerConnectionFactory factory,
+ scoped_refptr<base::SequencedTaskRunner> task_runner) {
+ consumer_connection_factory_ = factory;
+ consumer_connection_task_runner_ = task_runner;
+}
+
+void PerfettoTracedProcess::ConnectProducer(
+ mojo::PendingRemote<mojom::PerfettoService> perfetto_service) {
+ if (base::FeatureList::IsEnabled(
+ features::kEnablePerfettoClientApiProducer)) {
+ DCHECK(pending_producer_callback_);
+ std::move(pending_producer_callback_).Run(std::move(perfetto_service));
+ } else {
+ producer_client_->Connect(std::move(perfetto_service));
+ }
+}
+
void PerfettoTracedProcess::ClearDataSourcesForTesting() {
base::AutoLock lock(data_sources_lock_);
data_sources_.clear();
@@ -120,6 +137,37 @@ void PerfettoTracedProcess::DeleteSoonForTesting(
FROM_HERE, std::move(perfetto_traced_process));
}
+void PerfettoTracedProcess::CreateProducerConnection(
+ base::OnceCallback<void(mojo::PendingRemote<mojom::PerfettoService>)>
+ callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Perfetto will attempt to create the producer connection as soon as the
+ // client library is initialized, which is before we have a a connection to
+ // the tracing service. Store the connection callback until ConnectProducer()
+ // is called.
+ DCHECK(!pending_producer_callback_);
+ pending_producer_callback_ = std::move(callback);
+}
+
+void PerfettoTracedProcess::CreateConsumerConnection(
+ base::OnceCallback<void(mojo::PendingRemote<mojom::ConsumerHost>)>
+ callback) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ consumer_connection_task_runner_->PostTask(
+ FROM_HERE,
+ base::BindOnce(
+ [](ConsumerConnectionFactory factory,
+ base::OnceCallback<void(mojo::PendingRemote<mojom::ConsumerHost>)>
+ callback) {
+ auto& tracing_service = factory();
+ mojo::PendingRemote<mojom::ConsumerHost> consumer_host_remote;
+ tracing_service.BindConsumerHost(
+ consumer_host_remote.InitWithNewPipeAndPassReceiver());
+ std::move(callback).Run(std::move(consumer_host_remote));
+ },
+ consumer_connection_factory_, std::move(callback)));
+}
+
// We never destroy the taskrunner as we may need it for cleanup
// of TraceWriters in TLS, which could happen after the PerfettoTracedProcess
// is deleted.
@@ -149,34 +197,14 @@ void PerfettoTracedProcess::ResetTaskRunnerForTesting(
PerfettoTracedProcess::Get()
->producer_client()
->ResetSequenceForTesting();
- PerfettoTracedProcess::Get()
- ->system_producer()
- ->ResetSequenceForTesting();
+ if (PerfettoTracedProcess::Get()->system_producer()) {
+ PerfettoTracedProcess::Get()
+ ->system_producer()
+ ->ResetSequenceForTesting();
+ }
}));
}
-// static
-void PerfettoTracedProcess::ReconstructForTesting(const char* socket_name) {
- base::RunLoop finished_reconstruction_runloop;
- // The Get() call ensures that the construct has run and any required tasks
- // have been completed before this lambda below is executed.
- Get()->GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
- FROM_HERE,
- base::BindOnce(
- [](base::OnceClosure on_finish, const char* socket_name) {
- PerfettoTracedProcess::Get()->~PerfettoTracedProcess();
- new (PerfettoTracedProcess::Get()) PerfettoTracedProcess(
- socket_name ? socket_name : MaybeSocket());
- // The constructor and destructor needs to be run on the proper
- // sequence, but the constructor also calls PostTask so we need to
- // place a task afterwards to block until everything is initialized.
- GetTaskRunner()->GetOrCreateTaskRunner()->PostTaskAndReply(
- FROM_HERE, base::DoNothing(), std::move(on_finish));
- },
- finished_reconstruction_runloop.QuitClosure(), socket_name));
- finished_reconstruction_runloop.Run();
-}
-
void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) {
bool inserted;
{
@@ -194,8 +222,10 @@ void PerfettoTracedProcess::AddDataSource(DataSourceBase* data_source) {
PerfettoTracedProcess::Get();
traced_process->producer_client()->NewDataSourceAdded(
data_source);
- traced_process->system_producer()->NewDataSourceAdded(
- data_source);
+ if (traced_process->system_producer()) {
+ traced_process->system_producer()
+ ->NewDataSourceAdded(data_source);
+ }
},
base::Unretained(data_source)));
}
@@ -212,7 +242,7 @@ bool PerfettoTracedProcess::SetupStartupTracing(
const base::trace_event::TraceConfig& trace_config,
bool privacy_filtering_enabled) {
if (producer_client_->IsTracingActive() ||
- system_producer_->IsTracingActive()) {
+ (system_producer_ && system_producer_->IsTracingActive())) {
LOG(WARNING) << "Cannot setup startup tracing - tracing is already active";
return false;
}
@@ -225,6 +255,14 @@ bool PerfettoTracedProcess::SetupStartupTracing(
return true;
}
+void PerfettoTracedProcess::SetupClientLibrary() {
+ perfetto::TracingInitArgs init_args;
+ init_args.platform = platform_.get();
+ init_args.custom_backend = tracing_backend_.get();
+ init_args.backends |= perfetto::kCustomBackend;
+ perfetto::Tracing::Initialize(init_args);
+}
+
void PerfettoTracedProcess::OnThreadPoolAvailable() {
// Create our task runner now, so that ProducerClient/SystemProducer are
// notified about future data source registrations and schedule any necessary
@@ -232,19 +270,45 @@ void PerfettoTracedProcess::OnThreadPoolAvailable() {
GetTaskRunner()->GetOrCreateTaskRunner();
producer_client_->OnThreadPoolAvailable();
+ if (system_producer_)
+ system_producer_->OnThreadPoolAvailable();
+ if (!platform_->did_start_task_runner())
+ platform_->StartTaskRunner(GetTaskRunner()->GetOrCreateTaskRunner());
+}
+
+void PerfettoTracedProcess::SetupSystemTracing(
+ base::Optional<const char*> system_socket) {
+ // Note: Not checking for a valid sequence here so that we don't inadvertently
+ // bind this object on the wrong sequence during early initialization.
+ DCHECK(!system_producer_);
+ system_producer_ = NewSystemProducer(
+ GetTaskRunner(), system_socket ? *system_socket : MaybeSocket());
+ // If the thread pool is available, register all the known data sources with
+ // the system producer too.
+ if (!GetTaskRunner()->HasTaskRunner())
+ return;
system_producer_->OnThreadPoolAvailable();
+ GetTaskRunner()->GetOrCreateTaskRunner()->PostTask(
+ FROM_HERE, base::BindOnce([]() {
+ PerfettoTracedProcess* traced_process = PerfettoTracedProcess::Get();
+ base::AutoLock lock(traced_process->data_sources_lock_);
+ for (auto* data_source : traced_process->data_sources_) {
+ traced_process->system_producer()->NewDataSourceAdded(data_source);
+ }
+ }));
}
bool PerfettoTracedProcess::CanStartTracing(
PerfettoProducer* producer,
base::OnceCallback<void()> start_tracing) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(producer);
// If the |producer| asking is the local producer_client_ it has priority so
// even if the other endpoint is tracing shut down the other endpoint and let
// the |producer_client_| go. The system Producer will periodically attempt to
// reconnect if we call DisconnectWithReply().
if (producer == producer_client_.get()) {
- if (system_producer_->IsTracingActive()) {
+ if (system_producer_ && system_producer_->IsTracingActive()) {
system_producer_->DisconnectWithReply(std::move(start_tracing));
return true;
}
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
index 03f02da072c..be55393a4d2 100644
--- a/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_traced_process.h
@@ -10,6 +10,7 @@
#include "base/sequence_checker.h"
#include "base/sequenced_task_runner.h"
#include "base/synchronization/lock.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h"
#include "services/tracing/public/cpp/perfetto/task_runner.h"
namespace base {
@@ -19,7 +20,11 @@ class TraceConfig;
} // namespace base
namespace tracing {
+namespace mojom {
+class TracingService;
+} // namespace mojom
+class PerfettoPlatform;
class PerfettoProducer;
class ProducerClient;
class SystemProducer;
@@ -35,7 +40,8 @@ class SystemProducer;
// * Register the data source with Perfetto in ProducerHost::OnConnect.
// * Construct the new implementation when requested to
// in PerfettoProducer::StartDataSource.
-class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
+class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final
+ : public PerfettoTracingBackend::Delegate {
public:
// If not noted otherwise, a DataSourceBase's methods are only called on
// PerfettoTracedProcess::GetTaskRunner()'s sequence.
@@ -94,10 +100,21 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
// Returns the process-wide instance of the PerfettoTracedProcess.
static PerfettoTracedProcess* Get();
+ // Provide a factory for lazily creating mojo consumer connections to the
+ // tracing service. Allows using Perfetto's Client API for recording traces.
+ using ConsumerConnectionFactory = mojom::TracingService& (*)();
+ void SetConsumerConnectionFactory(ConsumerConnectionFactory,
+ scoped_refptr<base::SequencedTaskRunner>);
+
+ // Connect the current process to the mojo trace producer API. Depending on
+ // the configuration, this will either set up the Perfetto Client API or the
+ // legacy TraceLog to become the trace producer for this process.
+ void ConnectProducer(mojo::PendingRemote<mojom::PerfettoService>);
+
ProducerClient* producer_client() const;
- SystemProducer* system_producer() const;
+ SystemProducer* system_producer() const; // May be null.
- ~PerfettoTracedProcess();
+ ~PerfettoTracedProcess() override;
// Returns the task runner used by any Perfetto service. Can be called on any
// thread.
@@ -119,9 +136,19 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
const base::trace_event::TraceConfig&,
bool privacy_filtering_enabled);
+ // Initialize the Perfetto client library (i.e., perfetto::Tracing) for this
+ // process. Should be called early during startup.
+ void SetupClientLibrary();
+
// Called on the process's main thread once the thread pool is ready.
void OnThreadPoolAvailable();
+ // Called to initialize system tracing, i.e., connecting to a system Perfetto
+ // daemon as a producer. If |system_socket| isn't provided, Perfetto's default
+ // socket name is used.
+ void SetupSystemTracing(base::Optional<const char*> system_socket =
+ base::Optional<const char*>());
+
// If the provided |producer| can begin tracing then |start_tracing| will be
// invoked (unless cancelled by the Perfetto service) at some point later
// using the GetTaskRunner()'s sequence and this function will return true.
@@ -150,12 +177,22 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
void ClearDataSourcesForTesting();
static void DeleteSoonForTesting(std::unique_ptr<PerfettoTracedProcess>);
- static void ReconstructForTesting(const char* system_socket);
+
+ PerfettoPlatform* perfetto_platform_for_testing() const {
+ return platform_.get();
+ }
+
+ // PerfettoTracingBackend::Delegate implementation.
+ void CreateProducerConnection(
+ base::OnceCallback<void(mojo::PendingRemote<mojom::PerfettoService>)>)
+ override;
+ void CreateConsumerConnection(
+ base::OnceCallback<void(mojo::PendingRemote<mojom::ConsumerHost>)>)
+ override;
protected:
// protected for testing.
PerfettoTracedProcess();
- explicit PerfettoTracedProcess(const char* system_socket);
private:
friend class base::NoDestructor<PerfettoTracedProcess>;
@@ -173,6 +210,16 @@ class COMPONENT_EXPORT(TRACING_CPP) PerfettoTracedProcess final {
// calls will be noops.
std::unique_ptr<SystemProducer> system_producer_;
+ // Platform implementation for the Perfetto client library.
+ std::unique_ptr<PerfettoPlatform> platform_;
+ std::unique_ptr<PerfettoTracingBackend> tracing_backend_;
+
+ scoped_refptr<base::SequencedTaskRunner> consumer_connection_task_runner_;
+ ConsumerConnectionFactory consumer_connection_factory_;
+
+ base::OnceCallback<void(mojo::PendingRemote<mojom::PerfettoService>)>
+ pending_producer_callback_;
+
SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(PerfettoTracedProcess);
};
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc
new file mode 100644
index 00000000000..808421e4cc7
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.cc
@@ -0,0 +1,654 @@
+// 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/perfetto_tracing_backend.h"
+
+#include "base/containers/flat_map.h"
+#include "base/containers/flat_set.h"
+#include "base/memory/weak_ptr.h"
+#include "base/task/post_task.h"
+#include "build/build_config.h"
+#include "mojo/public/cpp/system/data_pipe_drainer.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_producer.h"
+#include "services/tracing/public/cpp/perfetto/shared_memory.h"
+#include "services/tracing/public/cpp/perfetto/trace_event_data_source.h"
+#include "services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/tracing_service.mojom.h"
+#include "third_party/perfetto/include/perfetto/base/task_runner.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/consumer.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/producer.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/shared_memory_arbiter.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_stats.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_writer.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/tracing_service.h"
+#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
+
+namespace tracing {
+namespace {
+
+// TODO(crbug.com/83907): Find a good compromise between performance and
+// data granularity (mainly relevant to running with small buffer sizes
+// when we use background tracing) on Android.
+#if defined(OS_ANDROID)
+constexpr size_t kDefaultSMBPageSizeBytes = 4 * 1024;
+#else
+constexpr size_t kDefaultSMBPageSizeBytes = 32 * 1024;
+#endif
+
+// TODO(crbug.com/839071): Figure out a good buffer size.
+constexpr size_t kDefaultSMBSizeBytes = 4 * 1024 * 1024;
+
+} // namespace
+
+// Implements Perfetto's ProducerEndpoint interface on top of the
+// PerfettoService mojo service.
+class ProducerEndpoint : public perfetto::ProducerEndpoint,
+ public mojom::ProducerClient {
+ public:
+ ProducerEndpoint(PerfettoTracingBackend::Delegate& delegate,
+ const std::string& producer_name,
+ perfetto::Producer* producer,
+ perfetto::base::TaskRunner* producer_task_runner,
+ size_t shmem_size_hint_bytes,
+ size_t shmem_page_size_hint_bytes)
+ : producer_(producer) {
+ // The producers's task runner must match where the endpoint is
+ // constructed; otherwise we can't safely use a weak pointer to send
+ // events back to the producer. |producer_task_runner| is also assumed to
+ // outlive this endpoint.
+ DCHECK(producer_task_runner->RunsTasksOnCurrentThread());
+ delegate.CreateProducerConnection(
+ base::BindOnce(&ProducerEndpoint::OnConnected,
+ weak_factory_.GetWeakPtr(), producer_task_runner,
+ shmem_size_hint_bytes, shmem_page_size_hint_bytes));
+ }
+
+ ~ProducerEndpoint() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_->OnDisconnect();
+ }
+
+ // perfetto::ProducerEndpoint implementation:
+ void RegisterDataSource(
+ const perfetto::DataSourceDescriptor& descriptor) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_host_->RegisterDataSource(descriptor);
+ }
+
+ void UnregisterDataSource(const std::string& name) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement data source unregistering.
+ NOTREACHED();
+ }
+
+ void RegisterTraceWriter(uint32_t writer_id,
+ uint32_t target_buffer) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_host_->RegisterTraceWriter(writer_id, target_buffer);
+ }
+
+ void UnregisterTraceWriter(uint32_t writer_id) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_host_->UnregisterTraceWriter(writer_id);
+ }
+
+ void CommitData(const perfetto::CommitDataRequest& commit,
+ CommitDataCallback callback = {}) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto commit_callback =
+ callback
+ ? base::BindOnce(
+ [](perfetto::ProducerEndpoint::CommitDataCallback callback) {
+ callback();
+ },
+ callback)
+ : mojom::ProducerHost::CommitDataCallback();
+ // We need to make sure the CommitData IPC is sent off without triggering
+ // any trace events, as that could stall waiting for SMB chunks to be freed
+ // up which requires the tracing service to receive the IPC.
+ if (!TraceEventDataSource::GetThreadIsInTraceEventTLS()->Get()) {
+ AutoThreadLocalBoolean thread_is_in_trace_event(
+ TraceEventDataSource::GetThreadIsInTraceEventTLS());
+ producer_host_->CommitData(commit, std::move(commit_callback));
+ return;
+ }
+ producer_host_->CommitData(commit, std::move(commit_callback));
+ }
+
+ perfetto::SharedMemory* shared_memory() const override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return shared_memory_.get();
+ }
+
+ size_t shared_buffer_page_size_kb() const override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ return shared_buffer_page_size_kb_;
+ }
+
+ std::unique_ptr<perfetto::TraceWriter> CreateTraceWriter(
+ perfetto::BufferID target_buffer,
+ perfetto::BufferExhaustedPolicy) override {
+ // Can be called from any thread.
+ // Chromium uses BufferExhaustedPolicy::kDrop to avoid stalling trace
+ // writers when the chunks in the SMB are exhausted. Stalling could
+ // otherwise lead to deadlocks in chromium, because a stalled mojo IPC
+ // thread could prevent CommitRequest messages from reaching the perfetto
+ // service.
+ return MaybeSharedMemoryArbiter()->CreateTraceWriter(
+ target_buffer, perfetto::BufferExhaustedPolicy::kDrop);
+ }
+
+ perfetto::SharedMemoryArbiter* MaybeSharedMemoryArbiter() override {
+ // Can be called from any thread.
+ return shared_memory_arbiter_.get();
+ }
+
+ bool IsShmemProvidedByProducer() const override { return true; }
+
+ void NotifyFlushComplete(perfetto::FlushRequestID flush_request_id) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ perfetto::CommitDataRequest commit;
+ commit.set_flush_request_id(flush_request_id);
+ producer_host_->CommitData(commit,
+ mojom::ProducerHost::CommitDataCallback());
+ }
+
+ void NotifyDataSourceStarted(
+ perfetto::DataSourceInstanceID instance_id) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = ds_start_callbacks_.find(instance_id);
+ if (it == ds_start_callbacks_.end())
+ return;
+ auto callback = std::move(it->second);
+ ds_start_callbacks_.erase(it);
+ std::move(callback).Run();
+ }
+
+ void NotifyDataSourceStopped(
+ perfetto::DataSourceInstanceID instance_id) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ auto it = ds_stop_callbacks_.find(instance_id);
+ if (it == ds_stop_callbacks_.end())
+ return;
+ auto callback = std::move(it->second);
+ ds_stop_callbacks_.erase(it);
+ std::move(callback).Run();
+ }
+
+ void ActivateTriggers(const std::vector<std::string>&) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement.
+ NOTREACHED();
+ }
+
+ void Sync(std::function<void()> callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement.
+ NOTREACHED();
+ }
+
+ // mojom::ProducerClient implementation.
+ void OnTracingStart() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_->OnTracingSetup();
+ }
+
+ void StartDataSource(uint64_t id,
+ const perfetto::DataSourceConfig& data_source_config,
+ StartDataSourceCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(ds_start_callbacks_.find(id) == ds_start_callbacks_.end());
+ ds_start_callbacks_[id] = std::move(callback);
+ auto it_and_inserted = ds_instances_.insert(id);
+ DCHECK(it_and_inserted.second);
+ producer_->SetupDataSource(id, data_source_config);
+ producer_->StartDataSource(id, data_source_config);
+ }
+
+ void StopDataSource(uint64_t id, StopDataSourceCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(ds_stop_callbacks_.find(id) == ds_stop_callbacks_.end());
+ ds_stop_callbacks_[id] = std::move(callback);
+ ds_instances_.erase(id);
+ producer_->StopDataSource(id);
+ }
+
+ void Flush(uint64_t flush_request_id,
+ const std::vector<uint64_t>& data_source_ids) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_->Flush(flush_request_id, data_source_ids.data(),
+ data_source_ids.size());
+ }
+
+ void ClearIncrementalState() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ std::vector<perfetto::DataSourceInstanceID> ds_instances;
+ for (auto id : ds_instances_)
+ ds_instances.push_back(id);
+ producer_->ClearIncrementalState(ds_instances.data(), ds_instances.size());
+ }
+
+ private:
+ struct EndpointBindings {
+ mojo::PendingReceiver<mojom::ProducerClient> client_receiver;
+ mojo::PendingRemote<mojom::ProducerHost> host_remote;
+ std::unique_ptr<MojoSharedMemory> shared_memory;
+ };
+
+ static void OnConnected(
+ base::WeakPtr<ProducerEndpoint> weak_endpoint,
+ perfetto::base::TaskRunner* producer_task_runner,
+ size_t shmem_size_bytes,
+ size_t shmem_page_size_bytes,
+ mojo::PendingRemote<mojom::PerfettoService> perfetto_service) {
+ // Called on the connection's sequence -- |this| may have been deleted.
+ auto bindings = std::make_unique<EndpointBindings>();
+
+ // TODO(skyostil): Make it possible to pass the shared memory allocation
+ // from the client library to here (for startup tracing).
+ if (!shmem_size_bytes)
+ shmem_size_bytes = kDefaultSMBSizeBytes;
+ if (!shmem_page_size_bytes)
+ shmem_page_size_bytes = kDefaultSMBPageSizeBytes;
+ bindings->shared_memory =
+ std::make_unique<MojoSharedMemory>(shmem_size_bytes);
+
+ if (!bindings->shared_memory->shared_buffer().is_valid()) {
+ // There's no way to do tracing after an SMB allocation failure, so let's
+ // disconnect Perfetto.
+ // TODO(skyostil): Record failure in UMA.
+ producer_task_runner->PostTask([weak_endpoint] {
+ if (!weak_endpoint)
+ return;
+ DCHECK_CALLED_ON_VALID_SEQUENCE(weak_endpoint->sequence_checker_);
+ weak_endpoint->producer_->OnDisconnect();
+ });
+ return;
+ }
+
+ mojo::PendingRemote<mojom::ProducerClient> client;
+ bindings->client_receiver = client.InitWithNewPipeAndPassReceiver();
+ mojo::Remote<mojom::PerfettoService>(std::move(perfetto_service))
+ ->ConnectToProducerHost(
+ std::move(client),
+ bindings->host_remote.InitWithNewPipeAndPassReceiver(),
+ bindings->shared_memory->Clone(), shmem_page_size_bytes);
+
+ // Bind the interfaces on Perfetto's sequence so we can avoid extra thread
+ // hops.
+ producer_task_runner->PostTask([weak_endpoint, producer_task_runner,
+ raw_bindings = bindings.release(),
+ shmem_size_bytes, shmem_page_size_bytes]() {
+ auto bindings = base::WrapUnique(raw_bindings);
+ // Called on the endpoint's sequence -- |endpoint| may be deleted.
+ if (!weak_endpoint)
+ return;
+ weak_endpoint->BindConnectionOnSequence(
+ producer_task_runner, std::move(bindings), shmem_size_bytes,
+ shmem_page_size_bytes);
+ });
+ }
+
+ void BindConnectionOnSequence(
+ perfetto::base::TaskRunner* producer_task_runner,
+ std::unique_ptr<EndpointBindings> bindings,
+ size_t shmem_size_bytes,
+ size_t shmem_page_size_bytes) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ producer_host_.Bind(std::move(bindings->host_remote));
+ producer_host_.reset_on_disconnect();
+ receiver_ = std::make_unique<mojo::Receiver<mojom::ProducerClient>>(
+ this, std::move(bindings->client_receiver));
+ receiver_->set_disconnect_handler(base::BindOnce(
+ [](ProducerEndpoint* endpoint) { endpoint->receiver_->reset(); },
+ base::Unretained(this)));
+
+ shared_memory_ = std::move(bindings->shared_memory);
+ shared_buffer_page_size_kb_ = shmem_size_bytes / 1024;
+ shared_memory_arbiter_ = perfetto::SharedMemoryArbiter::CreateInstance(
+ shared_memory_.get(), shmem_page_size_bytes, this,
+ producer_task_runner);
+ producer_->OnConnect();
+ }
+
+ SEQUENCE_CHECKER(sequence_checker_);
+
+ perfetto::Producer* const producer_;
+
+ base::flat_map<perfetto::DataSourceInstanceID, StartDataSourceCallback>
+ ds_start_callbacks_;
+ base::flat_map<perfetto::DataSourceInstanceID, StopDataSourceCallback>
+ ds_stop_callbacks_;
+ base::flat_set<perfetto::DataSourceInstanceID> ds_instances_;
+
+ std::unique_ptr<mojo::Receiver<mojom::ProducerClient>> receiver_;
+ mojo::Remote<mojom::ProducerHost> producer_host_;
+
+ size_t shared_buffer_page_size_kb_ = 0;
+
+ // Accessed on arbitrary threads after setup.
+ std::unique_ptr<MojoSharedMemory> shared_memory_;
+ std::unique_ptr<perfetto::SharedMemoryArbiter> shared_memory_arbiter_;
+
+ base::WeakPtrFactory<ProducerEndpoint> weak_factory_{this};
+};
+
+// Implements Perfetto's ConsumerEndpoint interface on top of the
+// ConsumerHost mojo service.
+class ConsumerEndpoint : public perfetto::ConsumerEndpoint,
+ public mojom::TracingSessionClient,
+ public mojo::DataPipeDrainer::Client {
+ public:
+ ConsumerEndpoint(PerfettoTracingBackend::Delegate& delegate,
+ perfetto::Consumer* consumer,
+ perfetto::base::TaskRunner* consumer_task_runner)
+ : consumer_{consumer} {
+ // To avoid extra thread hops, the consumer's task runner must match where
+ // the endpoint is constructed.
+ DCHECK(consumer_task_runner->RunsTasksOnCurrentThread());
+ delegate.CreateConsumerConnection(
+ base::BindOnce(&ConsumerEndpoint::OnConnected,
+ weak_factory_.GetWeakPtr(), consumer_task_runner));
+ }
+
+ ~ConsumerEndpoint() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ consumer_->OnDisconnect();
+ }
+
+ // perfetto::ConsumerEndpoint implementation.
+ void EnableTracing(const perfetto::TraceConfig& trace_config,
+ perfetto::base::ScopedFile file) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!file); // Direct tracing to a file isn't supported.
+ trace_config_ = trace_config;
+ if (!trace_config.deferred_start())
+ StartTracing();
+ }
+
+ void ChangeTraceConfig(const perfetto::TraceConfig& trace_config) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ trace_config_ = trace_config;
+ tracing_session_host_->ChangeTraceConfig(trace_config);
+ }
+
+ void StartTracing() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Don't hardcode the session's priority.
+ consumer_host_->EnableTracing(
+ tracing_session_host_.BindNewPipeAndPassReceiver(),
+ tracing_session_client_.BindNewPipeAndPassRemote(), trace_config_,
+ tracing::mojom::TracingClientPriority::kUserInitiated);
+ tracing_session_host_.set_disconnect_handler(base::BindOnce(
+ &ConsumerEndpoint::OnTracingFailed, base::Unretained(this)));
+ tracing_session_client_.set_disconnect_handler(base::BindOnce(
+ &ConsumerEndpoint::OnTracingFailed, base::Unretained(this)));
+ }
+
+ void DisableTracing() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ tracing_session_host_->DisableTracing();
+ }
+
+ void Flush(uint32_t timeout_ms, FlushCallback callback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement flushing.
+ NOTREACHED();
+ }
+
+ void ReadBuffers() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!tracing_session_host_ || !tracing_session_client_.is_bound()) {
+ OnTracingFailed();
+ return;
+ }
+ mojo::ScopedDataPipeProducerHandle producer_handle;
+ mojo::ScopedDataPipeConsumerHandle consumer_handle;
+ MojoResult result =
+ mojo::CreateDataPipe(nullptr, &producer_handle, &consumer_handle);
+ if (result != MOJO_RESULT_OK) {
+ OnTracingFailed();
+ return;
+ }
+ drainer_ = std::make_unique<mojo::DataPipeDrainer>(
+ this, std::move(consumer_handle));
+ trace_data_complete_ = false;
+ read_buffers_complete_ = false;
+
+ // Convert to legacy JSON if needed.
+ for (const auto& data_source : trace_config_.data_sources()) {
+ if (data_source.config().has_chrome_config() &&
+ data_source.config().chrome_config().convert_to_legacy_json()) {
+ tracing_session_host_->DisableTracingAndEmitJson(
+ /*agent_label_filter=*/"", std::move(producer_handle),
+ /*privacy_filter_enabled=*/false,
+ base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete,
+ base::Unretained(this)));
+ return;
+ }
+ }
+
+ tokenizer_ = std::make_unique<TracePacketTokenizer>();
+ tracing_session_host_->ReadBuffers(
+ std::move(producer_handle),
+ base::BindOnce(&ConsumerEndpoint::OnReadBuffersComplete,
+ base::Unretained(this)));
+ }
+
+ void FreeBuffers() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ tracing_session_host_.reset();
+ tracing_session_client_.reset();
+ drainer_.reset();
+ tokenizer_.reset();
+ }
+
+ void Detach(const std::string& key) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ NOTREACHED() << "Detaching session not supported";
+ }
+
+ void Attach(const std::string& key) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ NOTREACHED() << "Attaching session not supported";
+ }
+
+ void GetTraceStats() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // Capturing |this| is safe, because the callback will be cancelled if the
+ // connection terminates.
+ tracing_session_host_->RequestBufferUsage(base::BindOnce(
+ [](ConsumerEndpoint* endpoint, bool success, float percent_full,
+ bool data_loss) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(endpoint->sequence_checker_);
+ // Since we only get a few basic stats from the service, synthesize
+ // just enough trace statistics to be able to show a buffer usage
+ // indicator.
+ // TODO(skyostil): Plumb the entire TraceStats objects from the
+ // service to avoid this.
+ uint64_t buffer_size = 0;
+ if (endpoint->trace_config_.buffers_size() >= 1) {
+ buffer_size = endpoint->trace_config_.buffers()[0].size_kb() * 1024;
+ }
+ perfetto::TraceStats stats;
+ if (success && buffer_size) {
+ auto* buf_stats = stats.add_buffer_stats();
+ buf_stats->set_buffer_size(buffer_size);
+ buf_stats->set_bytes_written(
+ static_cast<uint64_t>(percent_full * buffer_size));
+ if (data_loss)
+ buf_stats->set_trace_writer_packet_loss(1);
+ }
+ endpoint->consumer_->OnTraceStats(success, stats);
+ },
+ base::Unretained(this)));
+ }
+
+ void ObserveEvents(uint32_t events_mask) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ DCHECK(!(events_mask &
+ ~perfetto::ObservableEvents::TYPE_DATA_SOURCES_INSTANCES));
+ observed_events_mask_ = events_mask;
+ }
+
+ void QueryServiceState(QueryServiceStateCallback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement service state querying.
+ NOTREACHED();
+ }
+
+ void QueryCapabilities(QueryCapabilitiesCallback) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Implement capability querying.
+ NOTREACHED();
+ }
+
+ // tracing::mojom::TracingSessionClient implementation:
+ void OnTracingEnabled() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Wire up full data source state. For now Perfetto just
+ // needs to know all data sources have started.
+ if (observed_events_mask_ &
+ perfetto::ObservableEvents::TYPE_DATA_SOURCES_INSTANCES) {
+ perfetto::ObservableEvents events;
+ events.add_instance_state_changes()->set_state(
+ perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STARTED);
+ consumer_->OnObservableEvents(events);
+ }
+ }
+
+ void OnTracingDisabled() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Wire up full data source state. For now Perfetto just
+ // needs to know all data sources have stopped.
+ if (observed_events_mask_ &
+ perfetto::ObservableEvents::TYPE_DATA_SOURCES_INSTANCES) {
+ perfetto::ObservableEvents events;
+ events.add_instance_state_changes()->set_state(
+ perfetto::ObservableEvents::DATA_SOURCE_INSTANCE_STATE_STOPPED);
+ consumer_->OnObservableEvents(events);
+ }
+ consumer_->OnTracingDisabled();
+ }
+
+ // mojo::DataPipeDrainer::Client implementation:
+ void OnDataAvailable(const void* data, size_t num_bytes) override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (tokenizer_) {
+ // Protobuf-format data.
+ auto packets =
+ tokenizer_->Parse(reinterpret_cast<const uint8_t*>(data), num_bytes);
+ if (!packets.empty())
+ consumer_->OnTraceData(std::move(packets), /*has_more=*/true);
+ } else {
+ // Legacy JSON-format data.
+ std::vector<perfetto::TracePacket> packets;
+ packets.emplace_back();
+ packets.back().AddSlice(data, num_bytes);
+ consumer_->OnTraceData(std::move(packets), /*has_more=*/true);
+ }
+ }
+
+ void OnDataComplete() override {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (tokenizer_) {
+ DCHECK(!tokenizer_->has_more());
+ tokenizer_.reset();
+ }
+ trace_data_complete_ = true;
+ MaybeFinishTraceData();
+ }
+
+ private:
+ static void OnConnected(
+ base::WeakPtr<ConsumerEndpoint> weak_endpoint,
+ perfetto::base::TaskRunner* consumer_task_runner,
+ mojo::PendingRemote<mojom::ConsumerHost> consumer_host_remote) {
+ // Called on the connection's sequence -- |this| may have been deleted.
+ auto wrapped_remote =
+ std::make_unique<mojo::PendingRemote<mojom::ConsumerHost>>(
+ std::move(consumer_host_remote));
+
+ // Bind the interfaces on Perfetto's sequence so we can avoid extra thread
+ // hops.
+ consumer_task_runner->PostTask([weak_endpoint,
+ raw_remote = wrapped_remote.release()]() {
+ auto consumer_host_remote = base::WrapUnique(raw_remote);
+ // Called on the endpoint's sequence -- |endpoint| may be deleted.
+ if (!weak_endpoint)
+ return;
+ weak_endpoint->BindConnectionOnSequence(std::move(*consumer_host_remote));
+ });
+ }
+
+ void BindConnectionOnSequence(
+ mojo::PendingRemote<mojom::ConsumerHost> consumer_host_remote) {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ consumer_host_.Bind(std::move(consumer_host_remote));
+ consumer_host_.reset_on_disconnect();
+ consumer_->OnConnect();
+ }
+
+ void OnTracingFailed() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ // TODO(skyostil): Inform the crew.
+ tracing_session_host_.reset();
+ tracing_session_client_.reset();
+ drainer_.reset();
+ tokenizer_.reset();
+ }
+
+ void OnReadBuffersComplete() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ read_buffers_complete_ = true;
+ MaybeFinishTraceData();
+ }
+
+ void MaybeFinishTraceData() {
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+ if (!read_buffers_complete_ || !trace_data_complete_)
+ return;
+ consumer_->OnTraceData({}, /*has_more=*/false);
+ }
+
+ SEQUENCE_CHECKER(sequence_checker_);
+ perfetto::Consumer* const consumer_;
+ mojo::Remote<tracing::mojom::ConsumerHost> consumer_host_;
+ mojo::Remote<tracing::mojom::TracingSessionHost> tracing_session_host_;
+ mojo::Receiver<tracing::mojom::TracingSessionClient> tracing_session_client_{
+ this};
+ std::unique_ptr<mojo::DataPipeDrainer> drainer_;
+ perfetto::TraceConfig trace_config_;
+
+ std::unique_ptr<TracePacketTokenizer> tokenizer_;
+ bool read_buffers_complete_ = false;
+ bool trace_data_complete_ = false;
+ uint32_t observed_events_mask_ = 0;
+
+ base::WeakPtrFactory<ConsumerEndpoint> weak_factory_{this};
+};
+
+PerfettoTracingBackend::PerfettoTracingBackend(Delegate& delegate)
+ : delegate_(delegate) {}
+
+PerfettoTracingBackend::~PerfettoTracingBackend() = default;
+PerfettoTracingBackend::Delegate::~Delegate() = default;
+
+std::unique_ptr<perfetto::ConsumerEndpoint>
+PerfettoTracingBackend::ConnectConsumer(const ConnectConsumerArgs& args) {
+ return std::make_unique<ConsumerEndpoint>(delegate_, args.consumer,
+ args.task_runner);
+}
+
+std::unique_ptr<perfetto::ProducerEndpoint>
+PerfettoTracingBackend::ConnectProducer(const ConnectProducerArgs& args) {
+ return std::make_unique<ProducerEndpoint>(
+ delegate_, args.producer_name, args.producer, args.task_runner,
+ args.shmem_size_hint_bytes, args.shmem_page_size_hint_bytes);
+}
+
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h
new file mode 100644
index 00000000000..87e7d3c901a
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/perfetto_tracing_backend.h
@@ -0,0 +1,67 @@
+// 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_PERFETTO_TRACING_BACKEND_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_PERFETTO_TRACING_BACKEND_H_
+
+#include "base/sequence_checker.h"
+#include "mojo/public/cpp/bindings/remote.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing_backend.h"
+
+namespace tracing {
+namespace mojom {
+class ConsumerHost;
+class PerfettoService;
+} // namespace mojom
+
+// The Perfetto tracing backend mediates between the Perfetto client library and
+// the mojo-based tracing service. It allows any process to emit trace data
+// through Perfetto and privileged processes (i.e., the browser) to start
+// tracing sessions and read back the resulting data.
+//
+// Perfetto : Tracing backend : Tracing service
+// : :
+// : mojo
+// calls : .------------------. : .--------------.
+// .---------->| ConsumerEndpoint |<--->| ConsumerHost |
+// .--------------. : `------------------' : `--------------'
+// | TracingMuxer | : :
+// `--------------' : .------------------. : .--------------.
+// `---------->| ProducerEndpoint |<--->| ProducerHost |
+// : `------------------' : `--------------'
+// : :
+class PerfettoTracingBackend : public perfetto::TracingBackend {
+ public:
+ class Delegate {
+ public:
+ virtual ~Delegate();
+
+ // Called to establish a consumer connection to the tracing service. The
+ // callback may be called on an arbitrary sequence.
+ virtual void CreateConsumerConnection(
+ base::OnceCallback<void(mojo::PendingRemote<mojom::ConsumerHost>)>) = 0;
+
+ // Called to establish a producer connection to the tracing service. The
+ // callback may be called on an arbitrary sequence.
+ virtual void CreateProducerConnection(
+ base::OnceCallback<
+ void(mojo::PendingRemote<mojom::PerfettoService>)>) = 0;
+ };
+
+ explicit PerfettoTracingBackend(Delegate&);
+ ~PerfettoTracingBackend() override;
+
+ // perfetto::TracingBackend implementation:
+ std::unique_ptr<perfetto::ProducerEndpoint> ConnectProducer(
+ const ConnectProducerArgs&) override;
+ std::unique_ptr<perfetto::ConsumerEndpoint> ConnectConsumer(
+ const ConnectConsumerArgs&) override;
+
+ private:
+ Delegate& delegate_;
+};
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PERFETTO_PUBLIC_CPP_PERFETTO_TRACING_BACKEND_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
index edbda2af892..8df88a0c9e9 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.cc
@@ -7,7 +7,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/debug/dump_without_crashing.h"
#include "base/metrics/histogram_functions.h"
#include "base/no_destructor.h"
#include "base/process/process.h"
@@ -398,18 +397,6 @@ bool ProducerClient::InitSharedMemoryIfNeeded() {
base::UmaHistogramBoolean(kSharedBufferIsValidMetricName, valid);
if (!valid) {
- // TODO(crbug.com/1074115): Investigate why Breakpad doesn't seem to
- // generate reports on some ChromeOS boards.
- if (pre_dump_error_callback_) {
- pre_dump_error_callback_.Run();
- }
-
- bool dump_with_crashing_result = base::debug::DumpWithoutCrashing();
-
- if (post_dump_error_callback_) {
- post_dump_error_callback_.Run(dump_with_crashing_result);
- }
-
LOG(ERROR) << "Failed to create tracing SMB";
shared_memory_.reset();
return false;
@@ -469,12 +456,4 @@ 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 63a010f43ac..5f6e5c4d376 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_client.h
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_client.h
@@ -109,13 +109,6 @@ 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();
@@ -150,12 +143,6 @@ 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
index 7ec9798e28a..f9fc7a85d29 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.cc
@@ -13,6 +13,7 @@
#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/root_message.h"
namespace tracing {
@@ -41,7 +42,7 @@ class DummyTraceWriter : public perfetto::TraceWriter {
uint64_t written() const override { return 0u; }
private:
- perfetto::protos::pbzero::TracePacket trace_packet_;
+ protozero::RootMessage<perfetto::protos::pbzero::TracePacket> trace_packet_;
protozero::ScatteredStreamWriterNullDelegate delegate_;
protozero::ScatteredStreamWriter stream_;
};
diff --git a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
index bbab71f84da..a00d767070b 100644
--- a/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
+++ b/chromium/services/tracing/public/cpp/perfetto/producer_test_utils.h
@@ -13,6 +13,7 @@
#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/root_message.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"
@@ -64,7 +65,7 @@ class TestProducerClient : public ProducerClient {
legacy_metadata_packets_;
std::vector<std::unique_ptr<perfetto::protos::TracePacket>>
proto_metadata_packets_;
- perfetto::protos::pbzero::TracePacket trace_packet_;
+ protozero::RootMessage<perfetto::protos::pbzero::TracePacket> trace_packet_;
protozero::ScatteredStreamWriterNullDelegate delegate_;
protozero::ScatteredStreamWriter stream_;
std::unique_ptr<PerfettoTaskRunner> main_thread_task_runner_;
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 88506ec5207..ea32fad393a 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
@@ -301,7 +301,7 @@ void TraceEventMetadataSource::GenerateMetadata(
trace_packet->set_timestamp_clock_id(kTraceClockId);
auto* chrome_metadata = trace_packet->set_chrome_metadata();
for (auto& generator : *proto_generators) {
- generator.Run(chrome_metadata, privacy_filtering_enabled_);
+ generator.Run(chrome_metadata, privacy_filtering_enabled);
}
if (privacy_filtering_enabled) {
@@ -463,11 +463,19 @@ void TraceEventDataSource::RegisterStartupHooks() {
&TraceEventDataSource::OnAddTypedTraceEvent);
}
-void TraceEventDataSource::RegisterWithTraceLog() {
+void TraceEventDataSource::RegisterWithTraceLog(
+ const base::trace_event::TraceConfig& trace_config) {
TraceLog::GetInstance()->SetAddTraceEventOverrides(
&TraceEventDataSource::OnAddLegacyTraceEvent,
&TraceEventDataSource::FlushCurrentThread,
&TraceEventDataSource::OnUpdateDuration);
+
+ if (trace_config.IsCategoryGroupEnabled(
+ TRACE_DISABLED_BY_DEFAULT("histogram_samples"))) {
+ base::StatisticsRecorder::SetGlobalSampleCallback(
+ &TraceEventDataSource::OnMetricsSampleCallback);
+ }
+
base::AutoLock l(lock_);
is_enabled_ = true;
}
@@ -577,7 +585,6 @@ void TraceEventDataSource::SetupStartupTracing(
trace_writer_ = CreateTraceWriterLocked();
}
EmitTrackDescriptor();
- RegisterWithTraceLog();
base::trace_event::TraceConfig config_for_trace_log(trace_config);
// Perfetto backend configures buffer sizes when tracing is started in the
@@ -590,6 +597,9 @@ void TraceEventDataSource::SetupStartupTracing(
if (!trace_config.event_filters().empty()) {
modes |= base::trace_event::TraceLog::FILTERING_MODE;
}
+
+ RegisterWithTraceLog(config_for_trace_log);
+
base::trace_event::TraceLog::GetInstance()->SetEnabled(trace_config, modes);
}
@@ -741,6 +751,9 @@ void TraceEventDataSource::StartTracingInternal(
}
}
+ auto trace_config =
+ TraceConfig(data_source_config.chrome_config().trace_config());
+
// SetupStartupTracing() will not setup a new startup session after we set
// |producer_| above, so accessing |startup_tracing_active| outside the lock
// is safe.
@@ -752,24 +765,17 @@ void TraceEventDataSource::StartTracingInternal(
producer->BindStartupTargetBuffer(session_id,
data_source_config.target_buffer());
} else {
- RegisterWithTraceLog();
+ RegisterWithTraceLog(trace_config);
}
// We emit the track/process descriptor another time even if we were
// previously startup tracing, because the process name may have changed.
EmitTrackDescriptor();
- auto trace_config =
- TraceConfig(data_source_config.chrome_config().trace_config());
TraceLog::GetInstance()->SetEnabled(trace_config, TraceLog::RECORDING_MODE);
ResetHistograms(trace_config);
if (trace_config.IsCategoryGroupEnabled(
- TRACE_DISABLED_BY_DEFAULT("histogram_samples"))) {
- base::StatisticsRecorder::SetGlobalSampleCallback(
- &TraceEventDataSource::OnMetricsSampleCallback);
- }
- if (trace_config.IsCategoryGroupEnabled(
TRACE_DISABLED_BY_DEFAULT("user_action_samples"))) {
auto task_runner = base::GetRecordActionTaskRunner();
if (task_runner) {
@@ -1017,26 +1023,29 @@ void TraceEventDataSource::OnMetricsSampleCallback(
const char* histogram_name,
uint64_t name_hash,
base::HistogramBase::Sample sample) {
- // TODO(oysteine): Write an interned histogram name during local dev tracing
- // when we're less space constrained.
TRACE_EVENT_INSTANT(
TRACE_DISABLED_BY_DEFAULT("histogram_samples"), "HistogramSample",
TRACE_EVENT_SCOPE_THREAD, [&](perfetto::EventContext ctx) {
+ bool privacy_filtering_enabled =
+ TraceEventDataSource::GetInstance()->IsPrivacyFilteringEnabled();
perfetto::protos::pbzero::ChromeHistogramSample* new_sample =
ctx.event()->set_chrome_histogram_sample();
new_sample->set_name_hash(name_hash);
new_sample->set_sample(sample);
+ if (!privacy_filtering_enabled) {
+ new_sample->set_name(histogram_name);
+ }
});
}
void TraceEventDataSource::OnUserActionSampleCallback(
const std::string& action,
base::TimeTicks action_time) {
- bool privacy_filtering_enabled =
- TraceEventDataSource::GetInstance()->IsPrivacyFilteringEnabled();
TRACE_EVENT_INSTANT(
TRACE_DISABLED_BY_DEFAULT("user_action_samples"), "UserAction",
TRACE_EVENT_SCOPE_GLOBAL, [&](perfetto::EventContext ctx) {
+ bool privacy_filtering_enabled =
+ TraceEventDataSource::GetInstance()->IsPrivacyFilteringEnabled();
perfetto::protos::pbzero::ChromeUserEvent* new_sample =
ctx.event()->set_chrome_user_event();
if (!privacy_filtering_enabled) {
@@ -1081,6 +1090,10 @@ void TraceEventDataSource::ReturnTraceWriter(
}
void TraceEventDataSource::EmitTrackDescriptor() {
+ // Prevent reentrancy into tracing code (flushing the trace writer sends a
+ // mojo message which can result in additional trace events).
+ AutoThreadLocalBoolean thread_is_in_trace_event(GetThreadIsInTraceEventTLS());
+
AutoLockWithDeferredTaskPosting lock(lock_);
int process_id = TraceLog::GetInstance()->process_id();
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 ad6943fb834..9de35c76c4f 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
@@ -204,7 +204,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TraceEventDataSource
PerfettoProducer* producer_client,
const perfetto::DataSourceConfig& data_source_config);
- void RegisterWithTraceLog();
+ void RegisterWithTraceLog(const base::trace_event::TraceConfig& trace_config);
void OnStopTracingDone();
std::unique_ptr<perfetto::TraceWriter> CreateTraceWriterLocked();
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc
new file mode 100644
index 00000000000..25f13212b05
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.cc
@@ -0,0 +1,99 @@
+// 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/trace_packet_tokenizer.h"
+
+#include "base/check.h"
+#include "base/check_op.h"
+#include "base/macros.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
+
+namespace tracing {
+namespace {
+
+static constexpr uint8_t kPacketTag =
+ protozero::proto_utils::MakeTagLengthDelimited(
+ perfetto::TracePacket::kPacketFieldNumber);
+
+} // namespace
+
+TracePacketTokenizer::TracePacketTokenizer() = default;
+TracePacketTokenizer::~TracePacketTokenizer() = default;
+TracePacketTokenizer::Packet::Packet() = default;
+TracePacketTokenizer::Packet::~Packet() = default;
+
+std::vector<perfetto::TracePacket> TracePacketTokenizer::Parse(
+ const uint8_t* data,
+ size_t size) {
+ std::vector<perfetto::TracePacket> packets;
+ const uint8_t* data_end = data + size;
+ const uint8_t* packet_ptr = data;
+
+ // Only one fragmented packet can be finalized per call to Parse(), so clear
+ // any previous one.
+ assembled_packet_ = Packet();
+
+ while (packet_ptr < data_end) {
+ // First parse the packet header, i.e., the one byte field tag and the
+ // variable sized packet length field.
+ if (!next_packet_.parsed_size) {
+ // Parse the field tag.
+ auto prev_header_size = next_packet_.header->size();
+ size_t bytes_to_copy = kMaxHeaderSize - prev_header_size;
+ next_packet_.header->insert(
+ next_packet_.header->end(), packet_ptr,
+ std::min(packet_ptr + bytes_to_copy, data_end));
+ DCHECK(next_packet_.header->size() <= kMaxHeaderSize);
+ if (next_packet_.header->size() < kMinHeaderSize) {
+ // Not enough data -- try again later.
+ return packets;
+ }
+ DCHECK_EQ(kPacketTag, next_packet_.header[0]);
+
+ // Parse the size field.
+ const auto* size_begin = &next_packet_.header[1];
+ const auto* size_end = protozero::proto_utils::ParseVarInt(
+ size_begin, &*next_packet_.header->end(), &next_packet_.parsed_size);
+ size_t size_field_size = size_end - size_begin;
+ if (!size_field_size) {
+ // Size field overflows to next chunk. Try again later.
+ return packets;
+ }
+ // Find the start of the packet data after the size field.
+ packet_ptr += sizeof(kPacketTag) + size_field_size - prev_header_size;
+ }
+
+ // We've now parsed the the proto preamble and the size field for our
+ // packet. Let's see if the packet fits completely into this chunk.
+ DCHECK(next_packet_.parsed_size);
+ size_t remaining_size =
+ next_packet_.parsed_size - next_packet_.partial_data->size();
+ if (packet_ptr + remaining_size > data_end) {
+ // Save remaining bytes into overflow buffer and try again later.
+ next_packet_.partial_data->insert(next_packet_.partial_data->end(),
+ packet_ptr, data_end);
+ return packets;
+ }
+
+ // The packet is now complete. It can have a slice overflowing from the
+ // previous chunk(s) as well a a slice in the current chunk.
+ packets.emplace_back();
+ if (!next_packet_.partial_data->empty()) {
+ DCHECK(assembled_packet_.partial_data->empty());
+ assembled_packet_ = std::move(next_packet_);
+ packets.back().AddSlice(&assembled_packet_.partial_data[0],
+ assembled_packet_.partial_data->size());
+ }
+ CHECK_LE(packet_ptr + remaining_size, data_end);
+ packets.back().AddSlice(packet_ptr, remaining_size);
+ packet_ptr += remaining_size;
+
+ // Start a new packet.
+ next_packet_ = Packet();
+ }
+ DCHECK_EQ(packet_ptr, data_end);
+ return packets;
+}
+
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h
new file mode 100644
index 00000000000..62f7f503f4c
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h
@@ -0,0 +1,78 @@
+// 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_TRACE_PACKET_TOKENIZER_H_
+#define SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_PACKET_TOKENIZER_H_
+
+#include <vector>
+
+#include "base/component_export.h"
+#include "base/containers/stack_container.h"
+#include "third_party/perfetto/include/perfetto/protozero/proto_utils.h"
+
+namespace perfetto {
+class TracePacket;
+} // namespace perfetto
+
+namespace tracing {
+
+// Converts between a raw stream of perfetto::TracePacket bytes and a tokenized
+// vector of delineated packets.
+//
+// The tracing service provides us with serialized proto bytes, while the
+// Perfetto consumer expects a vector of TracePackets (i.e., without the field
+// number and size header) without partial or truncated packets. To translate
+// between the two, we find the position of each TracePacket and construct a
+// vector pointing to the original data at the corresponding offsets.
+//
+// To make matters more complicated, mojo can split the data chunks
+// arbitrarily, including in the middle of trace packets. To work around
+// this, we tokenize as much data as we can and buffer any unprocessed bytes as
+// long as needed.
+class COMPONENT_EXPORT(TRACING_CPP) TracePacketTokenizer {
+ public:
+ TracePacketTokenizer();
+ ~TracePacketTokenizer();
+
+ // Given a chunk of trace data, tokenize as many trace packets as possible
+ // (could be zero) and return the result. Note that the tokenized packets have
+ // pointers to |data| as well as |this|, so they won't be valid after another
+ // call to Parse().
+ std::vector<perfetto::TracePacket> Parse(const uint8_t* data, size_t size);
+
+ // Returns |true| if there is more data left to be consumed in the tokenizer.
+ bool has_more() const {
+ return !next_packet_.header->empty() || next_packet_.parsed_size ||
+ !next_packet_.partial_data->empty();
+ }
+
+ private:
+ static constexpr size_t kMinHeaderSize = sizeof(uint8_t) + sizeof(uint8_t);
+ static constexpr size_t kMaxHeaderSize =
+ sizeof(uint8_t) + protozero::proto_utils::kMessageLengthFieldSize;
+
+ struct Packet {
+ Packet();
+ ~Packet();
+
+ // Most trace packets are very small, so avoid heap allocations in the
+ // common case where one packet straddles the boundary between chunks.
+ base::StackVector<uint8_t, 64> partial_data;
+
+ uint64_t parsed_size = 0;
+ base::StackVector<uint8_t, kMaxHeaderSize> header;
+ };
+
+ // Packet currently being parsed.
+ Packet next_packet_;
+
+ // Most recently completed packet which spanned multiple chunks. Kept as a
+ // member so that the memory remains valid while the caller is processing the
+ // results.
+ Packet assembled_packet_;
+};
+
+} // namespace tracing
+
+#endif // SERVICES_TRACING_PUBLIC_CPP_PERFETTO_TRACE_PACKET_TOKENIZER_H_
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer_unittest.cc b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer_unittest.cc
new file mode 100644
index 00000000000..9afa3bde2a2
--- /dev/null
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_packet_tokenizer_unittest.cc
@@ -0,0 +1,143 @@
+// 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/trace_packet_tokenizer.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace.pb.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace_packet.pb.h"
+
+#include <list>
+
+namespace tracing {
+namespace {
+
+constexpr char kTestString[] = "This little packet went to the market";
+
+class TracePacketTokenizerTest : public testing::Test {
+ protected:
+ // Parse a trace chunk using an indirect memory allocation so ASAN can detect
+ // any out-of-bounds reads.
+ std::vector<perfetto::TracePacket> ParseChunk(const uint8_t* data,
+ size_t size) {
+ input_chunks_.emplace_back(data, data + size);
+ auto& it = input_chunks_.back();
+ return tokenizer_.Parse(it.data(), it.size());
+ }
+
+ void Reset() {
+ input_chunks_.clear();
+ tokenizer_ = TracePacketTokenizer();
+ }
+
+ TracePacketTokenizer& tokenizer() { return tokenizer_; }
+
+ private:
+ std::list<std::vector<uint8_t>> input_chunks_;
+ TracePacketTokenizer tokenizer_;
+};
+
+TEST_F(TracePacketTokenizerTest, Basic) {
+ perfetto::protos::Trace trace;
+ auto* packet = trace.add_packet();
+ packet->mutable_for_testing()->set_str(kTestString);
+ auto packet_data = trace.SerializeAsString();
+
+ auto packets = ParseChunk(
+ reinterpret_cast<const uint8_t*>(packet_data.data()), packet_data.size());
+ EXPECT_EQ(1u, packets.size());
+ perfetto::protos::TracePacket parsed_packet;
+ EXPECT_TRUE(
+ parsed_packet.ParseFromString(packets[0].GetRawBytesForTesting()));
+ EXPECT_EQ(kTestString, parsed_packet.for_testing().str());
+ EXPECT_FALSE(tokenizer().has_more());
+}
+
+TEST_F(TracePacketTokenizerTest, PartialParse) {
+ perfetto::protos::Trace trace;
+ auto* packet = trace.add_packet();
+ packet->mutable_for_testing()->set_str(kTestString);
+ auto packet_data = trace.SerializeAsString();
+
+ auto packets =
+ ParseChunk(reinterpret_cast<const uint8_t*>(packet_data.data()),
+ packet_data.size() / 2);
+ EXPECT_TRUE(packets.empty());
+ EXPECT_TRUE(tokenizer().has_more());
+
+ packets = ParseChunk(reinterpret_cast<const uint8_t*>(packet_data.data() +
+ packet_data.size() / 2),
+ packet_data.size() / 2);
+ EXPECT_EQ(1u, packets.size());
+ perfetto::protos::TracePacket parsed_packet;
+ EXPECT_TRUE(
+ parsed_packet.ParseFromString(packets[0].GetRawBytesForTesting()));
+ EXPECT_EQ(kTestString, parsed_packet.for_testing().str());
+ EXPECT_FALSE(tokenizer().has_more());
+}
+
+TEST_F(TracePacketTokenizerTest, MultiplePackets) {
+ constexpr size_t kPacketCount = 32;
+ perfetto::protos::Trace trace;
+ for (size_t i = 0; i < kPacketCount; i++) {
+ auto* packet = trace.add_packet();
+ packet->set_timestamp(i);
+ packet->mutable_for_testing()->set_str(kTestString);
+ }
+ auto packet_data = trace.SerializeAsString();
+
+ auto packets = ParseChunk(
+ reinterpret_cast<const uint8_t*>(packet_data.data()), packet_data.size());
+ EXPECT_EQ(kPacketCount, packets.size());
+
+ for (size_t i = 0; i < kPacketCount; i++) {
+ perfetto::protos::TracePacket parsed_packet;
+ EXPECT_TRUE(
+ parsed_packet.ParseFromString(packets[i].GetRawBytesForTesting()));
+ EXPECT_EQ(i, parsed_packet.timestamp());
+ EXPECT_EQ(kTestString, parsed_packet.for_testing().str());
+ }
+ EXPECT_FALSE(tokenizer().has_more());
+}
+
+TEST_F(TracePacketTokenizerTest, Fragmentation) {
+ constexpr size_t kPacketCount = 17;
+ perfetto::protos::Trace trace;
+ for (size_t i = 0; i < kPacketCount; i++) {
+ auto* packet = trace.add_packet();
+ packet->set_timestamp(i + 1);
+ packet->mutable_for_testing()->set_str(kTestString);
+ }
+ auto packet_data = trace.SerializeAsString();
+
+ for (size_t chunk_size = 1; chunk_size < packet_data.size(); chunk_size++) {
+ size_t packet_count = 0;
+ for (size_t offset = 0; offset < packet_data.size(); offset += chunk_size) {
+ const auto* chunk_start =
+ reinterpret_cast<const uint8_t*>(packet_data.data()) + offset;
+ const auto* chunk_end =
+ std::min(chunk_start + chunk_size,
+ reinterpret_cast<const uint8_t*>(&*packet_data.end()));
+ auto packets = ParseChunk(chunk_start, chunk_end - chunk_start);
+ if (packets.empty())
+ continue;
+ packet_count += packets.size();
+
+ for (auto& packet : packets) {
+ perfetto::protos::TracePacket parsed_packet;
+ EXPECT_TRUE(
+ parsed_packet.ParseFromString(packet.GetRawBytesForTesting()));
+ EXPECT_GT(parsed_packet.timestamp(), 0u);
+ EXPECT_EQ(kTestString, parsed_packet.for_testing().str());
+ }
+ }
+ EXPECT_EQ(kPacketCount, packet_count);
+ EXPECT_FALSE(tokenizer().has_more());
+ Reset();
+ }
+}
+
+} // namespace
+} // namespace tracing
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_time.cc b/chromium/services/tracing/public/cpp/perfetto/trace_time.cc
index a8319c7ff06..0fc56753416 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_time.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_time.cc
@@ -12,7 +12,8 @@ namespace tracing {
int64_t TraceBootTicksNow() {
// On Windows and Mac, TRACE_TIME_TICKS_NOW() behaves like boottime already.
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID) || \
+ defined(OS_FUCHSIA)
struct timespec ts;
int res = clock_gettime(CLOCK_BOOTTIME, &ts);
if (res != -1)
diff --git a/chromium/services/tracing/public/cpp/perfetto/trace_time.h b/chromium/services/tracing/public/cpp/perfetto/trace_time.h
index 34a60632258..c2ef710d758 100644
--- a/chromium/services/tracing/public/cpp/perfetto/trace_time.h
+++ b/chromium/services/tracing/public/cpp/perfetto/trace_time.h
@@ -10,7 +10,8 @@
namespace tracing {
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_FUCHSIA)
+#if defined(OS_LINUX) || defined(OS_CHROMEOS) || 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::BuiltinClock kTraceClockId =
diff --git a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
index 863fb3ed28c..4eb9fd2e4f5 100644
--- a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer.cc
@@ -11,6 +11,7 @@
#include "base/trace_event/trace_event.h"
#include "base/trace_event/traced_value.h"
#include "third_party/perfetto/include/perfetto/protozero/message_handle.h"
+#include "third_party/perfetto/include/perfetto/protozero/root_message.h"
#include "third_party/perfetto/include/perfetto/protozero/scattered_heap_buffer.h"
#include "third_party/perfetto/include/perfetto/protozero/scattered_stream_writer.h"
#include "third_party/perfetto/protos/perfetto/trace/track_event/debug_annotation.pbzero.h"
@@ -241,7 +242,7 @@ class ProtoWriter final : public TracedValue::Writer {
std::stack<ProtoValueHandle> node_stack_;
- ProtoValue proto_;
+ protozero::RootMessage<ProtoValue> proto_;
protozero::ScatteredHeapBuffer buffer_;
protozero::ScatteredStreamWriter stream_;
};
diff --git a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
index 1eaec32c640..301d52abb72 100644
--- a/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
+++ b/chromium/services/tracing/public/cpp/perfetto/traced_value_proto_writer_unittest.cc
@@ -107,19 +107,12 @@ bool IsValue(const NestedValue* proto_value, const char* value) {
}
NestedValue GetProtoFromTracedValue(TracedValue* traced_value) {
- protozero::ScatteredHeapBuffer buffer(100);
- protozero::ScatteredStreamWriter stream(&buffer);
- perfetto::protos::pbzero::DebugAnnotation proto;
- proto.Reset(&stream);
- buffer.set_writer(&stream);
-
- PerfettoProtoAppender proto_appender(&proto);
+ protozero::HeapBuffered<perfetto::protos::pbzero::DebugAnnotation> proto;
+ PerfettoProtoAppender proto_appender(proto.get());
EXPECT_TRUE(traced_value->AppendToProto(&proto_appender));
- uint32_t size = proto.Finalize();
- ProtoInputStream proto_stream(&buffer);
DebugAnnotation full_proto;
- EXPECT_TRUE(full_proto.ParseFromBoundedZeroCopyStream(&proto_stream, size));
+ EXPECT_TRUE(full_proto.ParseFromString(proto.SerializeAsString()));
EXPECT_TRUE(full_proto.has_nested_value());
return full_proto.nested_value();
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
index 5cf87745ba6..210e6853e6d 100644
--- 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
@@ -83,7 +83,14 @@ TEST_F(ReachedCodeDataSourceTest, ProfilerDisabled) {
EXPECT_EQ(producer()->GetFinalizedPacketCount(), 0u);
}
-TEST_F(ReachedCodeDataSourceTest, ProfilerOutput) {
+// This test crashes on the android-asan bot.
+// TODO(https://crbug.com/1100216): Enable this again on the bot.
+#if defined(ADDRESS_SANITIZER)
+#define MAYBE_ProfilerOutput DISABLED_ProfilerOutput
+#else
+#define MAYBE_ProfilerOutput ProfilerOutput
+#endif
+TEST_F(ReachedCodeDataSourceTest, MAYBE_ProfilerOutput) {
if (!base::android::IsReachedCodeProfilerSupported())
return;
base::CommandLine::ForCurrentProcess()->AppendSwitch(
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 b99bda52188..c918f150441 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
@@ -35,10 +35,6 @@
#include "base/android/reached_code_profiler.h"
#endif
-#if defined(OS_MACOSX)
-#include "base/mac/mac_util.h"
-#endif
-
#if defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \
defined(OFFICIAL_BUILD)
#include <dlfcn.h>
@@ -58,6 +54,9 @@ namespace tracing {
namespace {
+// Pointer to the main thread instance, if any.
+TracingSamplerProfiler* g_main_thread_instance = nullptr;
+
class TracingSamplerProfilerDataSource
: public PerfettoTracedProcess::DataSourceBase {
public:
@@ -525,7 +524,7 @@ void TracingSamplerProfiler::TracingProfileBuilder::SampleLoaderLock() {
// static
void TracingSamplerProfiler::MangleModuleIDIfNeeded(std::string* module_id) {
-#if defined(OS_ANDROID) || defined(OS_LINUX)
+#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
// Linux ELF module IDs are 160bit integers, which we need to mangle
// down to 128bit integers to match the id that Breakpad outputs.
// Example on version '66.0.3359.170' x64:
@@ -553,6 +552,11 @@ TracingSamplerProfiler::CreateOnMainThread() {
InitializeLoaderLockSampling();
profiler->EnableLoaderLockSampling();
#endif
+ // If running in single process mode, there may be multiple "main thread"
+ // profilers created. In this case, we assume the first created one is the
+ // browser one.
+ if (!g_main_thread_instance)
+ g_main_thread_instance = profiler.get();
return profiler;
}
@@ -577,6 +581,12 @@ void TracingSamplerProfiler::RegisterDataSource() {
TracingSamplerProfilerDataSource::Get());
}
+void TracingSamplerProfiler::SetAuxUnwinderFactoryOnMainThread(
+ const base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>& factory) {
+ DCHECK(g_main_thread_instance);
+ g_main_thread_instance->SetAuxUnwinderFactory(factory);
+}
+
// static
void TracingSamplerProfiler::StartTracingForTesting(
PerfettoProducer* producer) {
@@ -615,6 +625,16 @@ TracingSamplerProfiler::TracingSamplerProfiler(
TracingSamplerProfiler::~TracingSamplerProfiler() {
TracingSamplerProfilerDataSource::Get()->UnregisterProfiler(this);
+ if (g_main_thread_instance == this)
+ g_main_thread_instance = nullptr;
+}
+
+void TracingSamplerProfiler::SetAuxUnwinderFactory(
+ const base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>& factory) {
+ base::AutoLock lock(lock_);
+ aux_unwinder_factory_ = factory;
+ if (profiler_)
+ profiler_->AddAuxUnwinder(aux_unwinder_factory_.Run());
}
void TracingSamplerProfiler::SetSampleCallbackForTesting(
@@ -641,13 +661,8 @@ void TracingSamplerProfiler::StartTracing(
return;
#endif
-#if defined(OS_MACOSX)
- // TODO(https://crbug.com/1098119): Fix unwinding on OS X 10.16. The OS has
- // moved all system libraries into the dyld shared cache and this seems to
- // break the sampling profiler.
- if (base::mac::IsOSLaterThan10_15_DontCallThis())
+ if (!base::StackSamplingProfiler::IsSupported())
return;
-#endif
base::StackSamplingProfiler::SamplingParams params;
params.samples_per_profile = std::numeric_limits<int>::max();
@@ -675,6 +690,8 @@ void TracingSamplerProfiler::StartTracing(
#else // defined(OS_ANDROID)
profiler_ = std::make_unique<base::StackSamplingProfiler>(
sampled_thread_token_, params, std::move(profile_builder));
+ if (aux_unwinder_factory_)
+ profiler_->AddAuxUnwinder(aux_unwinder_factory_.Run());
profiler_->Start();
#endif // defined(OS_ANDROID)
}
diff --git a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
index c78647609d4..b1ab4154130 100644
--- a/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
+++ b/chromium/services/tracing/public/cpp/stack_sampling/tracing_sampler_profiler.h
@@ -17,6 +17,7 @@
#include "base/memory/weak_ptr.h"
#include "base/profiler/sampling_profiler_thread_token.h"
#include "base/profiler/stack_sampling_profiler.h"
+#include "base/profiler/unwinder.h"
#include "base/sequence_checker.h"
#include "base/threading/platform_thread.h"
#include "build/build_config.h"
@@ -150,6 +151,12 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
// Registers the TracingSamplerProfiler as a Perfetto data source
static void RegisterDataSource();
+ // Sets a callback to create auxiliary unwinders on the main thread profiler,
+ // for handling additional, non-native-code unwind scenarios.
+ static void SetAuxUnwinderFactoryOnMainThread(
+ const base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>&
+ factory);
+
// For tests.
static void SetupStartupTracingForTesting();
static void DeleteOnChildThreadForTesting();
@@ -160,7 +167,7 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
// Returns whether of not the sampler profiling is able to unwind the stack
// on this platform.
constexpr static bool IsStackUnwindingSupported() {
-#if defined(OS_MACOSX) || defined(OS_WIN) && defined(_WIN64) || \
+#if defined(OS_MAC) || defined(OS_WIN) && defined(_WIN64) || \
(defined(OS_ANDROID) && BUILDFLAG(CAN_UNWIND_WITH_CFI_TABLE) && \
defined(OFFICIAL_BUILD))
return true;
@@ -173,6 +180,13 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
base::SamplingProfilerThreadToken sampled_thread_token);
virtual ~TracingSamplerProfiler();
+ // Sets a callback to create auxiliary unwinders, for handling additional,
+ // non-native-code unwind scenarios. Currently used to support
+ // unwinding V8 JavaScript frames.
+ void SetAuxUnwinderFactory(
+ const base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>&
+ factory);
+
// The given callback will be called for every received sample, and can be
// called on any thread. Must be called before tracing is started.
void SetSampleCallbackForTesting(
@@ -185,6 +199,9 @@ class COMPONENT_EXPORT(TRACING_CPP) TracingSamplerProfiler {
private:
const base::SamplingProfilerThreadToken sampled_thread_token_;
+ base::RepeatingCallback<std::unique_ptr<base::Unwinder>()>
+ aux_unwinder_factory_;
+
base::Lock lock_;
std::unique_ptr<base::StackSamplingProfiler> profiler_; // under |lock_|
TracingProfileBuilder* profile_builder_ = nullptr;
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 f619fa85099..8ca971b203d 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
@@ -26,6 +26,10 @@
#include "services/tracing/public/cpp/stack_sampling/loader_lock_sampler_win.h"
#endif
+#if defined(OS_MAC)
+#include "base/mac/mac_util.h"
+#endif
+
namespace tracing {
namespace {
@@ -179,9 +183,25 @@ class TestModule : public base::ModuleCache::Module {
std::string id_;
};
+bool ShouldSkipTestForMacOS11() {
+#if defined(OS_MAC)
+ // The sampling profiler does not work on macOS 11 and is disabled.
+ // See https://crbug.com/1101399 and https://crbug.com/1098119.
+ // DCHECK here so that when the sampling profiler is re-enabled on macOS 11,
+ // these tests are also re-enabled.
+ if (base::mac::IsAtLeastOS11()) {
+ DCHECK(!base::StackSamplingProfiler::IsSupported());
+ return true;
+ }
+#endif
+ return false;
+}
+
} // namespace
TEST_F(TracingSampleProfilerTest, OnSampleCompleted) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
BeginTrace();
base::RunLoop().RunUntilIdle();
@@ -192,6 +212,8 @@ TEST_F(TracingSampleProfilerTest, OnSampleCompleted) {
}
TEST_F(TracingSampleProfilerTest, JoinRunningTracing) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
BeginTrace();
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
base::RunLoop().RunUntilIdle();
@@ -202,6 +224,8 @@ TEST_F(TracingSampleProfilerTest, JoinRunningTracing) {
}
TEST_F(TracingSampleProfilerTest, TestStartupTracing) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
TracingSamplerProfiler::SetupStartupTracingForTesting();
base::RunLoop().RunUntilIdle();
@@ -236,6 +260,8 @@ TEST_F(TracingSampleProfilerTest, TestStartupTracing) {
}
TEST_F(TracingSampleProfilerTest, JoinStartupTracing) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
TracingSamplerProfiler::SetupStartupTracingForTesting();
base::RunLoop().RunUntilIdle();
auto profiler = TracingSamplerProfiler::CreateOnMainThread();
@@ -270,6 +296,8 @@ TEST_F(TracingSampleProfilerTest, JoinStartupTracing) {
}
TEST_F(TracingSampleProfilerTest, SamplingChildThread) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
base::Thread sampled_thread("sampling_profiler_test");
sampled_thread.Start();
sampled_thread.task_runner()->PostTask(
@@ -288,6 +316,8 @@ TEST_F(TracingSampleProfilerTest, SamplingChildThread) {
#if BUILDFLAG(ENABLE_LOADER_LOCK_SAMPLING)
TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnMainThread) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
LoaderLockEventAnalyzer event_analyzer;
bool lock_held = false;
@@ -316,6 +346,8 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnMainThread) {
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockAlwaysHeld) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
LoaderLockEventAnalyzer event_analyzer;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
@@ -334,6 +366,8 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockAlwaysHeld) {
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockNeverHeld) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
LoaderLockEventAnalyzer event_analyzer;
EXPECT_CALL(mock_loader_lock_sampler_, IsLoaderLockHeld())
@@ -351,6 +385,8 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockNeverHeld) {
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnChildThread) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
LoaderLockEventAnalyzer event_analyzer;
// Loader lock should only be sampled on main thread.
@@ -373,6 +409,8 @@ TEST_F(TracingSampleProfilerTest, SampleLoaderLockOnChildThread) {
}
TEST_F(TracingSampleProfilerTest, SampleLoaderLockWithoutMock) {
+ if (ShouldSkipTestForMacOS11())
+ GTEST_SKIP() << "Stack sampler is not supported on macOS 11";
// Use the real loader lock sampler. This tests that it is initialized
// correctly in TracingSamplerProfiler.
TracingSamplerProfiler::SetLoaderLockSamplerForTesting(nullptr);
@@ -427,7 +465,7 @@ TEST_F(TracingProfileBuilderTest, InvalidModule) {
base::TimeTicks());
}
-#if defined(OS_ANDROID) || defined(OS_LINUX)
+#if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS)
TEST_F(TracingProfileBuilderTest, MangleELFModuleID) {
TestModule module;
// See explanation for the module_id mangling in
diff --git a/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc
index 23be6e65ff1..eab6ffc9823 100644
--- a/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc
+++ b/chromium/services/tracing/public/cpp/trace_event_args_allowlist.cc
@@ -108,6 +108,7 @@ const AllowlistEntry kEventArgsAllowlist[] = {
{nullptr, nullptr, nullptr}};
const char* kMetadataAllowlist[] = {"chrome-bitness",
+ "chrome-dcheck-on",
"chrome-library-name",
"clock-domain",
"config",
diff --git a/chromium/services/tracing/public/cpp/trace_startup.cc b/chromium/services/tracing/public/cpp/trace_startup.cc
index 188d127cd43..7629795bd2d 100644
--- a/chromium/services/tracing/public/cpp/trace_startup.cc
+++ b/chromium/services/tracing/public/cpp/trace_startup.cc
@@ -38,8 +38,11 @@ void EnableStartupTracingIfNeeded() {
*base::CommandLine::ForCurrentProcess();
TraceEventDataSource::GetInstance()->RegisterStartupHooks();
- // TODO(eseckler): Initialize the entire perfetto client library instead.
- perfetto::internal::TrackRegistry::InitializeInstance();
+
+ // Initialize the Perfetto client library now that we're past the zygote's
+ // fork point. This is important to ensure Perfetto's track registry gets a
+ // unique uuid for generating track ids.
+ PerfettoTracedProcess::Get()->SetupClientLibrary();
// TODO(oysteine): Support startup tracing to a perfetto protobuf trace. This
// should also enable TraceLog and call SetupStartupTracing().
@@ -61,6 +64,7 @@ void EnableStartupTracingIfNeeded() {
PerfettoTracedProcess::Get()->producer_client();
if (startup_config->GetSessionOwner() ==
TraceStartupConfig::SessionOwner::kSystemTracing) {
+ PerfettoTracedProcess::Get()->SetupSystemTracing();
producer = PerfettoTracedProcess::Get()->system_producer();
}
@@ -102,6 +106,8 @@ void InitTracingPostThreadPoolStartAndFeatureList() {
// Connect to system service if available (currently a no-op except on
// Posix). Has to happen on the producer's sequence, as all communication
// with the system Perfetto service should occur on a single sequence.
+ if (!PerfettoTracedProcess::Get()->system_producer())
+ PerfettoTracedProcess::Get()->SetupSystemTracing();
PerfettoTracedProcess::Get()
->GetTaskRunner()
->GetOrCreateTaskRunner()
@@ -130,8 +136,10 @@ void PropagateTracingFlagsToChildProcessCmdLine(base::CommandLine* cmd_line) {
// (Posix)SystemProducer doesn't currently support startup tracing, so don't
// attempt to enable startup tracing in child processes if system tracing is
// active.
- if (PerfettoTracedProcess::Get()->system_producer()->IsTracingActive())
+ if (PerfettoTracedProcess::Get()->system_producer() &&
+ PerfettoTracedProcess::Get()->system_producer()->IsTracingActive()) {
return;
+ }
// The child process startup may race with a concurrent disabling of the
// tracing session by the tracing service. To avoid being stuck in startup
diff --git a/chromium/services/tracing/public/cpp/traced_process_impl.cc b/chromium/services/tracing/public/cpp/traced_process_impl.cc
index 4f4668f7093..f8cadd85c7f 100644
--- a/chromium/services/tracing/public/cpp/traced_process_impl.cc
+++ b/chromium/services/tracing/public/cpp/traced_process_impl.cc
@@ -95,7 +95,7 @@ void TracedProcessImpl::ConnectToTracingService(
// Ensure the TraceEventAgent has been created.
TraceEventAgent::GetInstance();
- PerfettoTracedProcess::Get()->producer_client()->Connect(
+ PerfettoTracedProcess::Get()->ConnectProducer(
std::move(request->perfetto_service));
}
diff --git a/chromium/services/tracing/public/cpp/tracing_features.cc b/chromium/services/tracing/public/cpp/tracing_features.cc
index accc5b28b6f..95980dd22f3 100644
--- a/chromium/services/tracing/public/cpp/tracing_features.cc
+++ b/chromium/services/tracing/public/cpp/tracing_features.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_number_conversions.h"
+#include "base/tracing_buildflags.h"
#include "build/build_config.h"
#include "build/chromecast_buildflags.h"
#include "components/tracing/common/tracing_switches.h"
@@ -37,6 +38,17 @@ const base::Feature kTracingServiceInProcess {
const base::Feature kEnablePerfettoSystemTracing{
"EnablePerfettoSystemTracing", base::FEATURE_DISABLED_BY_DEFAULT};
+// Controls whether trace points are implemented using Perfetto's client library
+// (enabled) or legacy TraceLog (disabled).
+const base::Feature kEnablePerfettoClientApiProducer {
+ "EnablePerfettoClientApiProducer",
+#if BUILDFLAG(USE_PERFETTO_CLIENT_LIBRARY)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
} // namespace features
namespace tracing {
diff --git a/chromium/services/tracing/public/cpp/tracing_features.h b/chromium/services/tracing/public/cpp/tracing_features.h
index d93d07437e3..795b20e0735 100644
--- a/chromium/services/tracing/public/cpp/tracing_features.h
+++ b/chromium/services/tracing/public/cpp/tracing_features.h
@@ -24,6 +24,9 @@ extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
kEnablePerfettoSystemTracing;
+extern const COMPONENT_EXPORT(TRACING_CPP) base::Feature
+ kEnablePerfettoClientApiProducer;
+
} // namespace features
namespace tracing {
diff --git a/chromium/services/tracing/public/mojom/BUILD.gn b/chromium/services/tracing/public/mojom/BUILD.gn
index 471b688e4c1..95051f89eab 100644
--- a/chromium/services/tracing/public/mojom/BUILD.gn
+++ b/chromium/services/tracing/public/mojom/BUILD.gn
@@ -14,13 +14,86 @@ mojom_component("mojom") {
"tracing_service.mojom",
]
+ public_deps = [ "//mojo/public/mojom/base" ]
+
if (!is_nacl && !is_ios) {
enabled_features = [ "is_perfetto_supported_os" ]
sources += [
"constants.mojom",
"perfetto_service.mojom",
]
- }
- public_deps = [ "//mojo/public/mojom/base" ]
+ cpp_typemaps = [
+ {
+ types = [
+ {
+ mojom = "tracing.mojom.BufferFillPolicy"
+ cpp = "::perfetto::TraceConfig::BufferConfig::FillPolicy"
+ },
+ {
+ mojom = "tracing.mojom.CommitDataRequest"
+ cpp = "::perfetto::CommitDataRequest"
+ },
+ {
+ mojom = "tracing.mojom.ChunksToMove"
+ cpp = "::perfetto::CommitDataRequest::ChunksToMove"
+ },
+ {
+ mojom = "tracing.mojom.ChunkPatch"
+ cpp = "::perfetto::CommitDataRequest::ChunkToPatch::Patch"
+ },
+ {
+ mojom = "tracing.mojom.ChunkToPatch"
+ cpp = "::perfetto::CommitDataRequest::ChunkToPatch"
+ },
+ {
+ mojom = "tracing.mojom.DataSourceConfig"
+ cpp = "::perfetto::DataSourceConfig"
+ },
+ {
+ mojom = "tracing.mojom.ChromeConfig"
+ cpp = "::perfetto::ChromeConfig"
+ },
+ {
+ mojom = "tracing.mojom.DataSourceRegistration"
+ cpp = "::perfetto::DataSourceDescriptor"
+ },
+ {
+ mojom = "tracing.mojom.PerfettoBuiltinDataSource"
+ cpp = "::perfetto::TraceConfig::BuiltinDataSource"
+ },
+ {
+ mojom = "tracing.mojom.IncrementalStateConfig"
+ cpp = "::perfetto::TraceConfig::IncrementalStateConfig"
+ },
+ {
+ mojom = "tracing.mojom.TraceConfig"
+ cpp = "::perfetto::TraceConfig"
+ },
+ ]
+ traits_headers = [
+ "//third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h",
+ "//third_party/perfetto/include/perfetto/tracing/core/data_source_config.h",
+ "//third_party/perfetto/include/perfetto/tracing/core/data_source_descriptor.h",
+ "//third_party/perfetto/include/perfetto/tracing/core/chrome_config.h",
+ "//third_party/perfetto/include/perfetto/tracing/core/trace_config.h",
+ ]
+ traits_private_headers = [
+ "chrome_config_mojom_traits.h",
+ "commit_data_request_mojom_traits.h",
+ "data_source_config_mojom_traits.h",
+ "data_source_descriptor_mojom_traits.h",
+ "trace_config_mojom_traits.h",
+ ]
+ traits_sources = [
+ "chrome_config_mojom_traits.cc",
+ "commit_data_request_mojom_traits.cc",
+ "data_source_config_mojom_traits.cc",
+ "data_source_descriptor_mojom_traits.cc",
+ "trace_config_mojom_traits.cc",
+ ]
+ traits_public_deps = [ "//third_party/perfetto:libperfetto" ]
+ },
+ ]
+ }
}
diff --git a/chromium/services/tracing/public/mojom/OWNERS b/chromium/services/tracing/public/mojom/OWNERS
index ae29a36aac8..1feb5149750 100644
--- a/chromium/services/tracing/public/mojom/OWNERS
+++ b/chromium/services/tracing/public/mojom/OWNERS
@@ -2,5 +2,3 @@ per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
per-file *_mojom_traits*.*=set noparent
per-file *_mojom_traits*.*=file://ipc/SECURITY_OWNERS
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h
index 1deafb3e761..87729c34656 100644
--- a/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h
+++ b/chromium/services/tracing/public/mojom/chrome_config_mojom_traits.h
@@ -11,7 +11,7 @@
#include <string>
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom-shared.h"
#include "third_party/perfetto/include/perfetto/tracing/core/chrome_config.h"
namespace mojo {
diff --git a/chromium/services/tracing/public/mojom/commit_data_request_mojom_traits.h b/chromium/services/tracing/public/mojom/commit_data_request_mojom_traits.h
index e10f4857bb0..98b344fde1d 100644
--- a/chromium/services/tracing/public/mojom/commit_data_request_mojom_traits.h
+++ b/chromium/services/tracing/public/mojom/commit_data_request_mojom_traits.h
@@ -12,7 +12,7 @@
#include <vector>
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom-shared.h"
#include "third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h"
namespace mojo {
diff --git a/chromium/services/tracing/public/mojom/data_source_config_mojom_traits.h b/chromium/services/tracing/public/mojom/data_source_config_mojom_traits.h
index e749282cfc6..44e23078f8f 100644
--- a/chromium/services/tracing/public/mojom/data_source_config_mojom_traits.h
+++ b/chromium/services/tracing/public/mojom/data_source_config_mojom_traits.h
@@ -11,7 +11,7 @@
#include <string>
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom-shared.h"
#include "third_party/perfetto/include/perfetto/tracing/core/chrome_config.h"
#include "third_party/perfetto/include/perfetto/tracing/core/data_source_config.h"
diff --git a/chromium/services/tracing/public/mojom/data_source_descriptor_mojom_traits.h b/chromium/services/tracing/public/mojom/data_source_descriptor_mojom_traits.h
index b98db418224..4d407486ac6 100644
--- a/chromium/services/tracing/public/mojom/data_source_descriptor_mojom_traits.h
+++ b/chromium/services/tracing/public/mojom/data_source_descriptor_mojom_traits.h
@@ -11,7 +11,7 @@
#include <string>
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom-shared.h"
#include "third_party/perfetto/include/perfetto/tracing/core/data_source_descriptor.h"
namespace mojo {
diff --git a/chromium/services/tracing/public/mojom/perfetto_service.typemap b/chromium/services/tracing/public/mojom/perfetto_service.typemap
deleted file mode 100644
index b55ed90693d..00000000000
--- a/chromium/services/tracing/public/mojom/perfetto_service.typemap
+++ /dev/null
@@ -1,43 +0,0 @@
-mojom = "//services/tracing/public/mojom/perfetto_service.mojom"
-public_headers = [
- "//third_party/perfetto/include/perfetto/ext/tracing/core/commit_data_request.h",
- "//third_party/perfetto/include/perfetto/tracing/core/data_source_config.h",
- "//third_party/perfetto/include/perfetto/tracing/core/data_source_descriptor.h",
- "//third_party/perfetto/include/perfetto/tracing/core/chrome_config.h",
- "//third_party/perfetto/include/perfetto/tracing/core/trace_config.h",
-]
-traits_headers = [
- "//services/tracing/public/mojom/commit_data_request_mojom_traits.h",
- "//services/tracing/public/mojom/data_source_config_mojom_traits.h",
- "//services/tracing/public/mojom/data_source_descriptor_mojom_traits.h",
- "//services/tracing/public/mojom/chrome_config_mojom_traits.h",
- "//services/tracing/public/mojom/trace_config_mojom_traits.h",
-]
-sources = [
- "//services/tracing/public/mojom/chrome_config_mojom_traits.cc",
- "//services/tracing/public/mojom/chrome_config_mojom_traits.h",
- "//services/tracing/public/mojom/commit_data_request_mojom_traits.cc",
- "//services/tracing/public/mojom/commit_data_request_mojom_traits.h",
- "//services/tracing/public/mojom/data_source_config_mojom_traits.cc",
- "//services/tracing/public/mojom/data_source_config_mojom_traits.h",
- "//services/tracing/public/mojom/data_source_descriptor_mojom_traits.cc",
- "//services/tracing/public/mojom/data_source_descriptor_mojom_traits.h",
- "//services/tracing/public/mojom/trace_config_mojom_traits.cc",
- "//services/tracing/public/mojom/trace_config_mojom_traits.h",
-]
-public_deps = [
- "//third_party/perfetto:libperfetto",
-]
-type_mappings = [
- "tracing.mojom.BufferFillPolicy=::perfetto::TraceConfig::BufferConfig::FillPolicy",
- "tracing.mojom.CommitDataRequest=::perfetto::CommitDataRequest",
- "tracing.mojom.ChunksToMove=::perfetto::CommitDataRequest::ChunksToMove",
- "tracing.mojom.ChunkPatch=::perfetto::CommitDataRequest::ChunkToPatch::Patch",
- "tracing.mojom.ChunkToPatch=::perfetto::CommitDataRequest::ChunkToPatch",
- "tracing.mojom.DataSourceConfig=::perfetto::DataSourceConfig",
- "tracing.mojom.ChromeConfig=::perfetto::ChromeConfig",
- "tracing.mojom.DataSourceRegistration=::perfetto::DataSourceDescriptor",
- "tracing.mojom.PerfettoBuiltinDataSource=::perfetto::TraceConfig::BuiltinDataSource",
- "tracing.mojom.IncrementalStateConfig=::perfetto::TraceConfig::IncrementalStateConfig",
- "tracing.mojom.TraceConfig=::perfetto::TraceConfig",
-]
diff --git a/chromium/services/tracing/public/mojom/trace_config_mojom_traits.h b/chromium/services/tracing/public/mojom/trace_config_mojom_traits.h
index 05b2aaea494..87d73c76921 100644
--- a/chromium/services/tracing/public/mojom/trace_config_mojom_traits.h
+++ b/chromium/services/tracing/public/mojom/trace_config_mojom_traits.h
@@ -13,7 +13,7 @@
#include "mojo/public/cpp/bindings/enum_traits.h"
#include "mojo/public/cpp/bindings/struct_traits.h"
-#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/perfetto_service.mojom-shared.h"
#include "third_party/perfetto/include/perfetto/tracing/core/trace_config.h"
namespace mojo {
diff --git a/chromium/services/tracing/public/mojom/typemaps.gni b/chromium/services/tracing/public/mojom/typemaps.gni
deleted file mode 100644
index 1544fb1844f..00000000000
--- a/chromium/services/tracing/public/mojom/typemaps.gni
+++ /dev/null
@@ -1 +0,0 @@
-typemaps = [ "//services/tracing/public/mojom/perfetto_service.typemap" ]
diff --git a/chromium/services/tracing/tracing_service.cc b/chromium/services/tracing/tracing_service.cc
index 8001350a646..fa0bc1fbec4 100644
--- a/chromium/services/tracing/tracing_service.cc
+++ b/chromium/services/tracing/tracing_service.cc
@@ -15,21 +15,28 @@ namespace tracing {
namespace {
+void OnProcessConnectFailed(PerfettoService* perfetto_service, uint32_t pid) {
+ perfetto_service->RemoveActiveServicePidIfNoActiveConnections(pid);
+}
+
void OnProcessConnected(
+ PerfettoService* perfetto_service,
mojo::Remote<mojom::TracedProcess> traced_process,
uint32_t pid,
mojo::PendingReceiver<mojom::PerfettoService> service_receiver) {
- PerfettoService::GetInstance()->BindReceiver(std::move(service_receiver),
- pid);
+ perfetto_service->BindReceiver(std::move(service_receiver), pid);
}
} // namespace
-TracingService::TracingService() = default;
+TracingService::TracingService(PerfettoService* perfetto_service)
+ : perfetto_service_(perfetto_service ? perfetto_service
+ : PerfettoService::GetInstance()) {}
TracingService::TracingService(
mojo::PendingReceiver<mojom::TracingService> receiver)
- : receiver_(this, std::move(receiver)) {}
+ : receiver_(this, std::move(receiver)),
+ perfetto_service_(PerfettoService::GetInstance()) {}
TracingService::~TracingService() = default;
@@ -37,28 +44,38 @@ void TracingService::Initialize(std::vector<mojom::ClientInfoPtr> clients) {
for (auto& client : clients) {
AddClient(std::move(client));
}
- PerfettoService::GetInstance()->SetActiveServicePidsInitialized();
+ perfetto_service_->SetActiveServicePidsInitialized();
}
void TracingService::AddClient(mojom::ClientInfoPtr client) {
- PerfettoService::GetInstance()->AddActiveServicePid(client->pid);
-
mojo::Remote<mojom::TracedProcess> process(std::move(client->process));
+
+ perfetto_service_->AddActiveServicePid(client->pid);
+
+ // If the remote traced process goes away before ConnectToTracingService
+ // responds, the PID should be removed from the list of active service PID.
+ // Note that the perfetto service will start monitoring disconnects after the
+ // service receiver is bound to it in OnProcessConnected().
+ process.set_disconnect_handler(
+ base::BindOnce(&OnProcessConnectFailed,
+ base::Unretained(perfetto_service_), client->pid));
+
auto new_connection_request = mojom::ConnectToTracingRequest::New();
auto service_receiver =
new_connection_request->perfetto_service.InitWithNewPipeAndPassReceiver();
+
mojom::TracedProcess* raw_process = process.get();
raw_process->ConnectToTracingService(
std::move(new_connection_request),
- base::BindOnce(&OnProcessConnected, std::move(process), client->pid,
+ base::BindOnce(&OnProcessConnected, base::Unretained(perfetto_service_),
+ std::move(process), client->pid,
std::move(service_receiver)));
}
#if !defined(OS_NACL) && !defined(OS_IOS)
void TracingService::BindConsumerHost(
mojo::PendingReceiver<mojom::ConsumerHost> receiver) {
- ConsumerHost::BindConsumerReceiver(PerfettoService::GetInstance(),
- std::move(receiver));
+ ConsumerHost::BindConsumerReceiver(perfetto_service_, std::move(receiver));
}
#endif
diff --git a/chromium/services/tracing/tracing_service.h b/chromium/services/tracing/tracing_service.h
index 0b29b2d6499..9651aec1db0 100644
--- a/chromium/services/tracing/tracing_service.h
+++ b/chromium/services/tracing/tracing_service.h
@@ -12,9 +12,11 @@
namespace tracing {
+class PerfettoService;
+
class TracingService : public mojom::TracingService {
public:
- TracingService();
+ explicit TracingService(PerfettoService* = nullptr);
explicit TracingService(
mojo::PendingReceiver<mojom::TracingService> receiver);
TracingService(const TracingService&) = delete;
@@ -31,6 +33,7 @@ class TracingService : public mojom::TracingService {
private:
mojo::Receiver<mojom::TracingService> receiver_{this};
+ PerfettoService* perfetto_service_;
};
} // namespace tracing
diff --git a/chromium/services/tracing/tracing_service_unittest.cc b/chromium/services/tracing/tracing_service_unittest.cc
index e33db3956bb..6e5cb97b84b 100644
--- a/chromium/services/tracing/tracing_service_unittest.cc
+++ b/chromium/services/tracing/tracing_service_unittest.cc
@@ -6,31 +6,130 @@
#include <utility>
#include "base/bind.h"
+#include "base/json/json_reader.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_feature_list.h"
#include "base/test/task_environment.h"
+#include "base/test/test_simple_task_runner.h"
+#include "base/threading/thread.h"
#include "mojo/public/cpp/bindings/receiver.h"
#include "mojo/public/cpp/bindings/remote.h"
+#include "services/tracing/perfetto/test_utils.h"
#include "services/tracing/public/cpp/perfetto/perfetto_config.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_platform.h"
+#include "services/tracing/public/cpp/perfetto/perfetto_traced_process.h"
+#include "services/tracing/public/cpp/perfetto/trace_packet_tokenizer.h"
+#include "services/tracing/public/cpp/traced_process_impl.h"
+#include "services/tracing/public/cpp/tracing_features.h"
#include "services/tracing/public/mojom/perfetto_service.mojom.h"
+#include "services/tracing/public/mojom/traced_process.mojom.h"
#include "services/tracing/public/mojom/tracing_service.mojom.h"
#include "services/tracing/tracing_service.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/perfetto/include/perfetto/ext/tracing/core/trace_packet.h"
+#include "third_party/perfetto/include/perfetto/tracing/data_source.h"
+#include "third_party/perfetto/include/perfetto/tracing/tracing.h"
+#include "third_party/perfetto/protos/perfetto/common/trace_stats.pb.h"
+#include "third_party/perfetto/protos/perfetto/trace/test_event.pbzero.h"
+#include "third_party/perfetto/protos/perfetto/trace/trace.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 {
+namespace {
+
+RebindableTaskRunner* GetPerfettoTaskRunner() {
+ static base::NoDestructor<RebindableTaskRunner> task_runner;
+ return task_runner.get();
+}
+
+} // namespace
class TracingServiceTest : public testing::Test {
public:
- TracingServiceTest() = default;
+ TracingServiceTest() : service_(&perfetto_service_) {
+ // Since Perfetto's platform backend can only be initialized once in a
+ // process, we give it a task runner that can outlive the per-test task
+ // environment.
+ auto* perfetto_task_runner = GetPerfettoTaskRunner();
+ auto* perfetto_platform =
+ PerfettoTracedProcess::Get()->perfetto_platform_for_testing();
+ if (!perfetto_platform->did_start_task_runner())
+ perfetto_platform->StartTaskRunner(perfetto_task_runner);
+ perfetto_task_runner->set_task_runner(base::ThreadTaskRunnerHandle::Get());
+
+ // Also tell PerfettoTracedProcess to use the current task environment.
+ PerfettoTracedProcess::ResetTaskRunnerForTesting(
+ base::ThreadTaskRunnerHandle::Get());
+ PerfettoTracedProcess::Get()->SetupClientLibrary();
+ perfetto_service()->SetActiveServicePidsInitialized();
+ }
~TracingServiceTest() override = default;
protected:
+ PerfettoService* perfetto_service() { return &perfetto_service_; }
mojom::TracingService* service() { return &service_; }
+ void EnableClientApiConsumer() {
+ // Tell PerfettoTracedProcess how to connect to the service. This enables
+ // the consumer part of the client API.
+ static mojom::TracingService* s_service;
+ s_service = service();
+ auto factory = []() -> mojom::TracingService& { return *s_service; };
+ PerfettoTracedProcess::Get()->SetConsumerConnectionFactory(
+ factory, base::SequencedTaskRunnerHandle::Get());
+ }
+
+ void EnableClientApiProducer() {
+ // Connect the producer part of the client API. AddClient() will end up
+ // calling TracedProcessImpl::ConnectToTracingService(), which will in turn
+ // route the PerfettoService interface to the client API backend.
+ mojo::PendingRemote<tracing::mojom::TracedProcess> traced_process_remote;
+ traced_process_receiver_ =
+ std::make_unique<mojo::Receiver<tracing::mojom::TracedProcess>>(
+ tracing::TracedProcessImpl::GetInstance());
+ traced_process_receiver_->Bind(
+ traced_process_remote.InitWithNewPipeAndPassReceiver());
+ auto client_info = mojom::ClientInfo::New(base::GetCurrentProcId(),
+ std::move(traced_process_remote));
+ service()->AddClient(std::move(client_info));
+ perfetto_service()->SetActiveServicePidsInitialized();
+ }
+
+ size_t ReadAndCountTestPackets(perfetto::TracingSession& session) {
+ size_t test_packet_count = 0;
+ base::RunLoop wait_for_data_loop;
+ session.ReadTrace(
+ [&wait_for_data_loop, &test_packet_count](
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ if (args.size) {
+ perfetto::protos::Trace trace;
+ EXPECT_TRUE(trace.ParseFromArray(args.data, args.size));
+ for (const auto& packet : trace.packet()) {
+ if (packet.has_for_testing()) {
+ EXPECT_EQ(kPerfettoTestString, packet.for_testing().str());
+ test_packet_count++;
+ }
+ }
+ }
+ if (!args.has_more)
+ wait_for_data_loop.Quit();
+ });
+ wait_for_data_loop.Run();
+ return test_packet_count;
+ }
+
private:
base::test::TaskEnvironment task_environment_;
+ PerfettoService perfetto_service_;
TracingService service_;
+ std::unique_ptr<mojo::Receiver<tracing::mojom::TracedProcess>>
+ traced_process_receiver_;
+
DISALLOW_COPY_AND_ASSIGN(TracingServiceTest);
};
@@ -55,11 +154,20 @@ class TestTracingClient : public mojom::TracingSessionClient {
std::move(on_tracing_enabled)));
}
+ void StopTracing(base::OnceClosure on_tracing_stopped) {
+ tracing_disabled_callback_ = std::move(on_tracing_stopped);
+ tracing_session_host_->DisableTracing();
+ }
+
// tracing::mojom::TracingSessionClient implementation:
void OnTracingEnabled() override {}
- void OnTracingDisabled() override {}
+ void OnTracingDisabled() override {
+ std::move(tracing_disabled_callback_).Run();
+ }
private:
+ base::OnceClosure tracing_disabled_callback_;
+
mojo::Remote<mojom::ConsumerHost> consumer_host_;
mojo::Remote<mojom::TracingSessionHost> tracing_session_host_;
mojo::Receiver<mojom::TracingSessionClient> receiver_{this};
@@ -71,6 +179,205 @@ TEST_F(TracingServiceTest, TracingServiceInstantiate) {
base::RunLoop tracing_started;
tracing_client.StartTracing(service(), tracing_started.QuitClosure());
tracing_started.Run();
+
+ base::RunLoop tracing_stopped;
+ tracing_client.StopTracing(tracing_stopped.QuitClosure());
+ tracing_stopped.Run();
+}
+
+TEST_F(TracingServiceTest, PerfettoClientConsumer) {
+ // Set up API bindings.
+ EnableClientApiConsumer();
+
+ // Register a mock producer with an in-process Perfetto service.
+ auto pid = 123;
+ size_t kNumPackets = 10;
+ base::RunLoop wait_for_start;
+ base::RunLoop wait_for_registration;
+ std::unique_ptr<MockProducer> producer = std::make_unique<MockProducer>(
+ std::string("org.chromium-") + base::NumberToString(pid),
+ "com.example.mock_data_source", perfetto_service(),
+ wait_for_registration.QuitClosure(), wait_for_start.QuitClosure(),
+ kNumPackets);
+ wait_for_registration.Run();
+
+ // Start a tracing session using the client API.
+ auto session = perfetto::Tracing::NewTrace();
+ perfetto::TraceConfig perfetto_config;
+ perfetto_config.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = perfetto_config.add_data_sources()->mutable_config();
+ ds_cfg->set_name("com.example.mock_data_source");
+ session->Setup(perfetto_config);
+ session->Start();
+ wait_for_start.Run();
+
+ // Stop the session and wait for it to stop. Note that we can't use the
+ // blocking API here because the service runs on the current sequence.
+ base::RunLoop wait_for_stop_loop;
+ session->SetOnStopCallback(
+ [&wait_for_stop_loop] { wait_for_stop_loop.Quit(); });
+ session->Stop();
+ wait_for_stop_loop.Run();
+
+ // Verify tracing session statistics.
+ base::RunLoop wait_for_stats_loop;
+ perfetto::protos::TraceStats stats;
+ auto stats_callback =
+ [&wait_for_stats_loop,
+ &stats](perfetto::TracingSession::GetTraceStatsCallbackArgs args) {
+ EXPECT_TRUE(args.success);
+ EXPECT_TRUE(stats.ParseFromArray(args.trace_stats_data.data(),
+ args.trace_stats_data.size()));
+ wait_for_stats_loop.Quit();
+ };
+ session->GetTraceStats(std::move(stats_callback));
+ wait_for_stats_loop.Run();
+ EXPECT_EQ(1024u * 1024u, stats.buffer_stats(0).buffer_size());
+ EXPECT_GT(stats.buffer_stats(0).bytes_written(), 0u);
+ EXPECT_EQ(0u, stats.buffer_stats(0).trace_writer_packet_loss());
+
+ // Read and verify the data.
+ EXPECT_EQ(kNumPackets, ReadAndCountTestPackets(*session));
+}
+
+TEST_F(TracingServiceTest, PerfettoClientConsumerLegacyJson) {
+ // Set up API bindings.
+ EnableClientApiConsumer();
+
+ // Start a tracing session with legacy JSON exporting.
+ auto session = perfetto::Tracing::NewTrace();
+ perfetto::TraceConfig perfetto_config = GetDefaultPerfettoConfig(
+ base::trace_event::TraceConfig(), /*privacy_filtering_enabled=*/false,
+ /*convert_to_legacy_json=*/true);
+ session->Setup(perfetto_config);
+ session->Start();
+
+ // Stop the session and wait for it to stop. Note that we can't use the
+ // blocking API here because the service runs on the current sequence.
+ base::RunLoop wait_for_stop_loop;
+ session->SetOnStopCallback(
+ [&wait_for_stop_loop] { wait_for_stop_loop.Quit(); });
+ session->Stop();
+ wait_for_stop_loop.Run();
+
+ // Read and verify the JSON data.
+ base::RunLoop wait_for_data_loop;
+ TracePacketTokenizer tokenizer;
+ std::string json;
+ session->ReadTrace([&wait_for_data_loop, &tokenizer, &json](
+ perfetto::TracingSession::ReadTraceCallbackArgs args) {
+ if (args.size) {
+ auto packets = tokenizer.Parse(
+ reinterpret_cast<const uint8_t*>(args.data), args.size);
+ for (const auto& packet : packets) {
+ for (const auto& slice : packet.slices()) {
+ json += std::string(reinterpret_cast<const char*>(slice.start),
+ slice.size);
+ }
+ }
+ }
+ if (!args.has_more)
+ wait_for_data_loop.Quit();
+ });
+ wait_for_data_loop.Run();
+ DCHECK(!tokenizer.has_more());
+
+ auto result = base::DictionaryValue::From(
+ base::Value::ToUniquePtrValue(*base::JSONReader::Read(json)));
+ EXPECT_TRUE(result->HasKey("traceEvents"));
+}
+
+class CustomDataSource : public perfetto::DataSource<CustomDataSource> {
+ public:
+ struct Events {
+ base::RunLoop wait_for_setup_loop;
+ base::RunLoop wait_for_start_loop;
+ base::RunLoop wait_for_stop_loop;
+ };
+
+ static void set_events(Events* events) { events_ = events; }
+
+ void OnSetup(const SetupArgs&) override {
+ events_->wait_for_setup_loop.Quit();
+ }
+ void OnStart(const StartArgs&) override {
+ events_->wait_for_start_loop.Quit();
+ }
+ void OnStop(const StopArgs&) override { events_->wait_for_stop_loop.Quit(); }
+
+ private:
+ static Events* events_;
+};
+
+CustomDataSource::Events* CustomDataSource::events_;
+
+TEST_F(TracingServiceTest, PerfettoClientProducer) {
+ // Use the client API as the producer for this process instead of
+ // ProducerClient.
+ base::test::ScopedFeatureList scoped_feature_list;
+ scoped_feature_list.InitAndEnableFeature(
+ features::kEnablePerfettoClientApiProducer);
+
+ // Set up API bindings.
+ EnableClientApiConsumer();
+ EnableClientApiProducer();
+
+ perfetto::DataSourceDescriptor dsd;
+ dsd.set_name("com.example.custom_data_source");
+ CustomDataSource::Events ds_events;
+ CustomDataSource::set_events(&ds_events);
+ CustomDataSource::Register(dsd);
+
+ // Start a tracing session using the client API.
+ auto session = perfetto::Tracing::NewTrace();
+ perfetto::TraceConfig perfetto_config;
+ perfetto_config.add_buffers()->set_size_kb(1024);
+ auto* ds_cfg = perfetto_config.add_data_sources()->mutable_config();
+ ds_cfg->set_name("com.example.custom_data_source");
+ session->Setup(perfetto_config);
+ session->Start();
+
+ ds_events.wait_for_setup_loop.Run();
+ ds_events.wait_for_start_loop.Run();
+
+ // Write more data to check the commit flow works too.
+ size_t kNumPackets = 1000;
+ CustomDataSource::Trace([kNumPackets](CustomDataSource::TraceContext ctx) {
+ for (size_t i = 0; i < kNumPackets / 2; i++) {
+ ctx.NewTracePacket()->set_for_testing()->set_str(
+ tracing::kPerfettoTestString);
+ }
+ ctx.Flush();
+ });
+
+ // Write half of the data from another thread to check TLS is hooked up
+ // properly.
+ base::Thread thread("TestThread");
+ thread.Start();
+ thread.task_runner()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([kNumPackets] {
+ CustomDataSource::Trace(
+ [kNumPackets](CustomDataSource::TraceContext ctx) {
+ for (size_t i = 0; i < kNumPackets / 2; i++) {
+ ctx.NewTracePacket()->set_for_testing()->set_str(
+ tracing::kPerfettoTestString);
+ }
+ ctx.Flush();
+ });
+ }));
+ thread.Stop();
+
+ // Stop the session and wait for it to stop. Note that we can't use the
+ // blocking variants here because the service runs on the current sequence.
+ base::RunLoop wait_for_stop_loop;
+ session->SetOnStopCallback(
+ [&wait_for_stop_loop] { wait_for_stop_loop.Quit(); });
+ session->Stop();
+ ds_events.wait_for_stop_loop.Run();
+ wait_for_stop_loop.Run();
+
+ // Read and verify the data.
+ EXPECT_EQ(kNumPackets, ReadAndCountTestPackets(*session));
}
} // namespace tracing
diff --git a/chromium/services/video_capture/public/uma/video_capture_service_event.cc b/chromium/services/video_capture/public/uma/video_capture_service_event.cc
index 57a93e292fe..4d3096d1bbb 100644
--- a/chromium/services/video_capture/public/uma/video_capture_service_event.cc
+++ b/chromium/services/video_capture/public/uma/video_capture_service_event.cc
@@ -57,7 +57,7 @@ void LogDurationUntilReconnectAfterCapture(base::TimeDelta duration) {
DVLOG(4) << "Logged DurationUntilReconnectAfterCapture";
}
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
void LogMacbookRetryGetDeviceInfosEvent(MacbookRetryGetDeviceInfosEvent event) {
UMA_HISTOGRAM_ENUMERATION(
"Media.VideoCapture.MacBook.RetryGetDeviceInfosEvent", event,
diff --git a/chromium/services/video_capture/public/uma/video_capture_service_event.h b/chromium/services/video_capture/public/uma/video_capture_service_event.h
index 554dd4f8ec5..5683fd808bd 100644
--- a/chromium/services/video_capture/public/uma/video_capture_service_event.h
+++ b/chromium/services/video_capture/public/uma/video_capture_service_event.h
@@ -29,7 +29,7 @@ enum VideoCaptureServiceEvent {
NUM_VIDEO_CAPTURE_SERVICE_EVENT
};
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
enum MacbookRetryGetDeviceInfosEvent {
PROVIDER_RECEIVED_ZERO_INFOS_STOPPING_SERVICE = 0,
PROVIDER_SERVICE_STOPPED_ISSUING_RETRY = 1,
@@ -61,7 +61,7 @@ void LogDurationFromLastConnectToConnectionLost(base::TimeDelta duration);
void LogDurationUntilReconnectAfterEnumerationOnly(base::TimeDelta duration);
void LogDurationUntilReconnectAfterCapture(base::TimeDelta duration);
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
void LogMacbookRetryGetDeviceInfosEvent(MacbookRetryGetDeviceInfosEvent event);
#endif
diff --git a/chromium/services/video_capture/texture_virtual_device_mojo_adapter.cc b/chromium/services/video_capture/texture_virtual_device_mojo_adapter.cc
index e04babecbb9..fed38116008 100644
--- a/chromium/services/video_capture/texture_virtual_device_mojo_adapter.cc
+++ b/chromium/services/video_capture/texture_virtual_device_mojo_adapter.cc
@@ -9,7 +9,6 @@
#include "base/memory/ptr_util.h"
#include "media/base/bind_to_current_loop.h"
#include "mojo/public/cpp/bindings/callback_helpers.h"
-#include "mojo/public/cpp/bindings/strong_binding.h"
#include "services/video_capture/public/mojom/constants.mojom.h"
#include "services/video_capture/public/mojom/scoped_access_permission.mojom.h"
diff --git a/chromium/services/video_capture/video_capture_service_impl.cc b/chromium/services/video_capture/video_capture_service_impl.cc
index 0d5b3a1468c..27844d6f531 100644
--- a/chromium/services/video_capture/video_capture_service_impl.cc
+++ b/chromium/services/video_capture/video_capture_service_impl.cc
@@ -27,23 +27,12 @@
#include "services/video_capture/virtual_device_enabled_device_factory.h"
#include "services/viz/public/cpp/gpu/gpu.h"
-#if defined(OS_MACOSX)
+#if defined(OS_MAC)
#include "media/capture/video/mac/video_capture_device_factory_mac.h"
#endif
namespace video_capture {
-namespace {
-
-// Used to assess the impact of running the video capture service at background
-// priority. If the experiment confirms that running the video capture service
-// at background priority causes jank, change the code to use a foreground
-// priority by default. See https://crbug.com/1066137.
-const base::Feature kForegroundVideoCaptureService{
- "ForegroundVideoCaptureService", base::FEATURE_DISABLED_BY_DEFAULT};
-
-} // namespace
-
// Intended usage of this class is to instantiate on any sequence, and then
// operate and release the instance on the task runner exposed via
// GetTaskRunner() via WeakPtrs provided via GetWeakPtr(). To this end,
@@ -52,13 +41,8 @@ const base::Feature kForegroundVideoCaptureService{
class VideoCaptureServiceImpl::GpuDependenciesContext {
public:
GpuDependenciesContext() {
- const base::TaskPriority priority =
- base::FeatureList::IsEnabled(kForegroundVideoCaptureService)
- ? base::TaskPriority::USER_BLOCKING
- : base::TaskPriority::BEST_EFFORT;
-
gpu_io_task_runner_ = base::ThreadPool::CreateSequencedTaskRunner(
- {priority, base::MayBlock()});
+ {base::TaskPriority::USER_BLOCKING, base::MayBlock()});
}
~GpuDependenciesContext() {
@@ -158,8 +142,8 @@ void VideoCaptureServiceImpl::ConnectToVideoSourceProvider(
}
void VideoCaptureServiceImpl::SetRetryCount(int32_t count) {
-#if defined(OS_MACOSX)
- media::VideoCaptureDeviceFactoryMac::SetGetDeviceDescriptorsRetryCount(count);
+#if defined(OS_MAC)
+ media::VideoCaptureDeviceFactoryMac::SetGetDevicesInfoRetryCount(count);
#endif
}
diff --git a/chromium/services/viz/PRESUBMIT.py b/chromium/services/viz/PRESUBMIT.py
index babbf3fe2a0..2d7842caaef 100644
--- a/chromium/services/viz/PRESUBMIT.py
+++ b/chromium/services/viz/PRESUBMIT.py
@@ -12,5 +12,5 @@ def CheckChangeOnUpload(input_api, output_api):
'components', 'viz')]
import presubmit_checks as ps
- white_list=(r'^services[\\/]viz[\\/].*\.(cc|h)$',)
- return ps.RunAllChecks(input_api, output_api, white_list)
+ allowlist=(r'^services[\\/]viz[\\/].*\.(cc|h)$',)
+ return ps.RunAllChecks(input_api, output_api, allowlist)
diff --git a/chromium/services/viz/privileged/mojom/compositing/BUILD.gn b/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
index 53af38d06f5..84ad1023325 100644
--- a/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
+++ b/chromium/services/viz/privileged/mojom/compositing/BUILD.gn
@@ -29,6 +29,8 @@ mojom("compositing") {
"//ui/latency/mojom",
]
+ traits_public_deps = [ "//ui/base:features" ]
+
enabled_features = []
if (use_ozone) {
enabled_features += [ "use_ozone" ]
@@ -44,10 +46,14 @@ mojom("compositing") {
mojom = "viz.mojom.RendererSettings"
cpp = "::viz::RendererSettings"
},
+ {
+ mojom = "viz.mojom.DebugRendererSettings"
+ cpp = "::viz::DebugRendererSettings"
+ },
]
traits_headers = [ "//services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h" ]
traits_sources = [ "//services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc" ]
- traits_public_deps = [
+ traits_public_deps += [
"//cc",
"//ui/gfx/geometry/mojom",
]
diff --git a/chromium/services/viz/privileged/mojom/compositing/DEPS b/chromium/services/viz/privileged/mojom/compositing/DEPS
index b81a4a4e7bc..131cc87bdec 100644
--- a/chromium/services/viz/privileged/mojom/compositing/DEPS
+++ b/chromium/services/viz/privileged/mojom/compositing/DEPS
@@ -1,4 +1,5 @@
include_rules = [
"+ui/gfx/geometry/mojom/geometry_mojom_traits.h",
"+ui/gfx/mojom/color_space_mojom_traits.h",
+ "+ui/base/ui_base_features.h",
]
diff --git a/chromium/services/viz/privileged/mojom/compositing/display_private.mojom b/chromium/services/viz/privileged/mojom/compositing/display_private.mojom
index d88fab3b7d0..0c9686f3c80 100644
--- a/chromium/services/viz/privileged/mojom/compositing/display_private.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/display_private.mojom
@@ -14,6 +14,7 @@ import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/latency/mojom/latency_info.mojom";
import "services/viz/privileged/mojom/compositing/layered_window_updater.mojom";
import "services/viz/privileged/mojom/compositing/vsync_parameter_observer.mojom";
+import "services/viz/public/mojom/compositing/delegated_ink_point.mojom";
// The DisplayPrivate is used by privileged clients to talk to Display.
interface DisplayPrivate {
@@ -71,6 +72,11 @@ interface DisplayPrivate {
// support multiple observers.
AddVSyncParameterObserver(
pending_remote<VSyncParameterObserver> observer);
+
+ // Bind an interface between browser process and viz for ink points to be
+ // sent to viz and stored, to be used when drawing a delegated ink trail.
+ SetDelegatedInkPointRenderer(
+ pending_receiver<DelegatedInkPointRenderer> receiver);
};
interface DisplayClient {
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 c7a8c1e6f02..195bd5568af 100644
--- a/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/frame_sink_manager.mojom
@@ -35,6 +35,9 @@ struct RootCompositorFrameSinkParams {
[EnableIf=is_android]
float refresh_rate;
+ [EnableIf=is_win]
+ bool set_present_duration_allowed = false;
+
pending_associated_receiver<CompositorFrameSink> compositor_frame_sink;
pending_remote<CompositorFrameSinkClient> compositor_frame_sink_client;
@@ -122,6 +125,19 @@ interface FrameSinkManager {
// Marks the given SurfaceIds for destruction.
EvictSurfaces(array<SurfaceId> surface_ids);
+ // Starts throttling the frame sinks specified by |frame_sink_ids| and all
+ // their descendant sinks to send BeginFrames at an interval of |interval|.
+ // |interval| should be greater than zero. Calling this function before
+ // calling EndThrottling() to end a previous throttling operation will
+ // automatically end the previous operation before applying the current
+ // throttling operation.
+ StartThrottling(
+ array<FrameSinkId> frame_sink_ids,
+ mojo_base.mojom.TimeDelta interval);
+
+ // Ends all previously throttled frame sinks.
+ EndThrottling();
+
// Takes a snapshot of |surface_id| or a newer surface with the same
// FrameSinkId. The request will be queued up until such surface exists and is
// reachable from the root surface.
@@ -141,6 +157,10 @@ interface FrameSinkManager {
[Sync]
EvictBackBuffer(uint32 cache_id) => ();
+
+ // This allows dynamic manipulation of the viz debug options stored in
+ // |debug_settings| (show_overdraw_feedback, etc.).
+ UpdateDebugRendererSettings(DebugRendererSettings debug_settings);
};
// The FrameSinkManagerClient interface is implemented by the Display
diff --git a/chromium/services/viz/privileged/mojom/compositing/renderer_settings.mojom b/chromium/services/viz/privileged/mojom/compositing/renderer_settings.mojom
index 3974ab6072b..36a5d07d757 100644
--- a/chromium/services/viz/privileged/mojom/compositing/renderer_settings.mojom
+++ b/chromium/services/viz/privileged/mojom/compositing/renderer_settings.mojom
@@ -12,20 +12,16 @@ struct RendererSettings {
bool allow_antialiasing;
bool force_antialiasing;
bool force_blending_with_shaders;
- bool tint_gl_composited_content;
int32 highp_threshold_min;
bool partial_swap_enabled;
bool release_overlay_resources_after_gpu_query;
bool should_clear_root_render_pass;
- bool show_overdraw_feedback;
- bool show_aggregated_damage;
int32 slow_down_compositing_scale_factor;
bool use_skia_renderer;
bool record_sk_picture;
bool allow_overlays;
bool auto_resize_output_surface;
bool requires_alpha_channel;
- bool show_dc_layer_debug_borders;
[EnableIf=is_android]
gfx.mojom.Size initial_screen_size;
@@ -36,3 +32,10 @@ struct RendererSettings {
[EnableIf=use_ozone]
array<OverlayStrategy> overlay_strategies;
};
+
+struct DebugRendererSettings {
+ bool tint_composited_content;
+ bool show_overdraw_feedback;
+ bool show_dc_layer_debug_borders;
+ bool show_aggregated_damage;
+};
diff --git a/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc b/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc
index c5430439c18..eed93b40ba8 100644
--- a/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc
+++ b/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.cc
@@ -5,6 +5,7 @@
#include "services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h"
#include "services/viz/public/cpp/compositing/resource_settings_mojom_traits.h"
+#include "ui/base/ui_base_features.h"
#if defined(OS_ANDROID)
#include "ui/gfx/mojom/color_space_mojom_traits.h"
@@ -13,6 +14,18 @@
namespace mojo {
// static
+bool StructTraits<viz::mojom::DebugRendererSettingsDataView,
+ viz::DebugRendererSettings>::
+ Read(viz::mojom::DebugRendererSettingsDataView data,
+ viz::DebugRendererSettings* out) {
+ out->tint_composited_content = data.tint_composited_content();
+ out->show_overdraw_feedback = data.show_overdraw_feedback();
+ out->show_dc_layer_debug_borders = data.show_dc_layer_debug_borders();
+ out->show_aggregated_damage = data.show_aggregated_damage();
+ return true;
+}
+
+// static
bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>::
Read(viz::mojom::RendererSettingsDataView data,
viz::RendererSettings* out) {
@@ -23,9 +36,6 @@ bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>::
out->should_clear_root_render_pass = data.should_clear_root_render_pass();
out->release_overlay_resources_after_gpu_query =
data.release_overlay_resources_after_gpu_query();
- out->tint_gl_composited_content = data.tint_gl_composited_content();
- out->show_overdraw_feedback = data.show_overdraw_feedback();
- out->show_aggregated_damage = data.show_aggregated_damage();
out->highp_threshold_min = data.highp_threshold_min();
out->slow_down_compositing_scale_factor =
data.slow_down_compositing_scale_factor();
@@ -34,7 +44,6 @@ bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>::
out->allow_overlays = data.allow_overlays();
out->auto_resize_output_surface = data.auto_resize_output_surface();
out->requires_alpha_channel = data.requires_alpha_channel();
- out->show_dc_layer_debug_borders = data.show_dc_layer_debug_borders();
#if defined(OS_ANDROID)
if (!data.ReadInitialScreenSize(&out->initial_screen_size))
@@ -45,7 +54,8 @@ bool StructTraits<viz::mojom::RendererSettingsDataView, viz::RendererSettings>::
#endif
#if defined(USE_OZONE)
- if (!data.ReadOverlayStrategies(&out->overlay_strategies))
+ if (features::IsUsingOzonePlatform() &&
+ !data.ReadOverlayStrategies(&out->overlay_strategies))
return false;
#endif
diff --git a/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h b/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h
index 5cb17bdd2ec..09efec4657f 100644
--- a/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h
+++ b/chromium/services/viz/privileged/mojom/compositing/renderer_settings_mojom_traits.h
@@ -18,6 +18,30 @@
namespace mojo {
template <>
+struct StructTraits<viz::mojom::DebugRendererSettingsDataView,
+ viz::DebugRendererSettings> {
+ static bool tint_composited_content(const viz::DebugRendererSettings& input) {
+ return input.tint_composited_content;
+ }
+
+ static bool show_overdraw_feedback(const viz::DebugRendererSettings& input) {
+ return input.show_overdraw_feedback;
+ }
+
+ static bool show_dc_layer_debug_borders(
+ const viz::DebugRendererSettings& input) {
+ return input.show_dc_layer_debug_borders;
+ }
+
+ static bool show_aggregated_damage(const viz::DebugRendererSettings& input) {
+ return input.show_aggregated_damage;
+ }
+
+ static bool Read(viz::mojom::DebugRendererSettingsDataView data,
+ viz::DebugRendererSettings* out);
+};
+
+template <>
struct StructTraits<viz::mojom::RendererSettingsDataView,
viz::RendererSettings> {
static bool allow_antialiasing(const viz::RendererSettings& input) {
@@ -46,18 +70,6 @@ struct StructTraits<viz::mojom::RendererSettingsDataView,
return input.release_overlay_resources_after_gpu_query;
}
- static bool tint_gl_composited_content(const viz::RendererSettings& input) {
- return input.tint_gl_composited_content;
- }
-
- static bool show_overdraw_feedback(const viz::RendererSettings& input) {
- return input.show_overdraw_feedback;
- }
-
- static bool show_aggregated_damage(const viz::RendererSettings& input) {
- return input.show_aggregated_damage;
- }
-
static int highp_threshold_min(const viz::RendererSettings& input) {
return input.highp_threshold_min;
}
@@ -87,10 +99,6 @@ struct StructTraits<viz::mojom::RendererSettingsDataView,
return input.requires_alpha_channel;
}
- static bool show_dc_layer_debug_borders(const viz::RendererSettings& input) {
- return input.show_dc_layer_debug_borders;
- }
-
#if defined(OS_ANDROID)
static gfx::Size initial_screen_size(const viz::RendererSettings& input) {
return input.initial_screen_size;
diff --git a/chromium/services/viz/privileged/mojom/mojom_traits_unittest.cc b/chromium/services/viz/privileged/mojom/mojom_traits_unittest.cc
index d1625920954..9790ccbaa01 100644
--- a/chromium/services/viz/privileged/mojom/mojom_traits_unittest.cc
+++ b/chromium/services/viz/privileged/mojom/mojom_traits_unittest.cc
@@ -25,7 +25,6 @@ TEST_F(StructTraitsTest, RendererSettings) {
input.partial_swap_enabled = true;
input.should_clear_root_render_pass = false;
input.release_overlay_resources_after_gpu_query = true;
- input.show_overdraw_feedback = true;
input.highp_threshold_min = -1;
input.use_skia_renderer = true;
@@ -41,13 +40,27 @@ TEST_F(StructTraitsTest, RendererSettings) {
output.should_clear_root_render_pass);
EXPECT_EQ(input.release_overlay_resources_after_gpu_query,
output.release_overlay_resources_after_gpu_query);
- EXPECT_EQ(input.tint_gl_composited_content,
- output.tint_gl_composited_content);
- EXPECT_EQ(input.show_overdraw_feedback, output.show_overdraw_feedback);
EXPECT_EQ(input.highp_threshold_min, output.highp_threshold_min);
EXPECT_EQ(input.use_skia_renderer, output.use_skia_renderer);
}
+TEST_F(StructTraitsTest, DebugRendererSettings) {
+ DebugRendererSettings input;
+
+ // Set |input| to non-default values.
+ input.show_overdraw_feedback = true;
+ input.tint_composited_content = true;
+ input.show_dc_layer_debug_borders = true;
+
+ DebugRendererSettings output;
+ mojom::DebugRendererSettings::Deserialize(
+ mojom::DebugRendererSettings::Serialize(&input), &output);
+ EXPECT_EQ(input.show_overdraw_feedback, output.show_overdraw_feedback);
+ EXPECT_EQ(input.tint_composited_content, output.tint_composited_content);
+ EXPECT_EQ(input.show_dc_layer_debug_borders,
+ output.show_dc_layer_debug_borders);
+}
+
} // namespace
} // namespace viz
diff --git a/chromium/services/viz/privileged/mojom/viz_main.mojom b/chromium/services/viz/privileged/mojom/viz_main.mojom
index dd2ac152395..f13ce4558fe 100644
--- a/chromium/services/viz/privileged/mojom/viz_main.mojom
+++ b/chromium/services/viz/privileged/mojom/viz_main.mojom
@@ -8,6 +8,7 @@ import "components/discardable_memory/public/mojom/discardable_shared_memory_man
import "services/network/public/mojom/tcp_socket.mojom";
import "services/viz/public/mojom/compositing/compositing_mode_watcher.mojom";
import "services/viz/privileged/mojom/compositing/frame_sink_manager.mojom";
+import "services/viz/privileged/mojom/compositing/renderer_settings.mojom";
import "services/viz/privileged/mojom/gl/gpu_host.mojom";
[EnableIf=is_win]
import "services/viz/privileged/mojom/gl/info_collection_gpu_service.mojom";
@@ -30,6 +31,8 @@ struct FrameSinkManagerParams {
// Viz to host interface.
pending_remote<FrameSinkManagerClient> frame_sink_manager_client;
+
+ DebugRendererSettings debug_renderer_settings;
};
struct VizDevToolsParams {
diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.cc
new file mode 100644
index 00000000000..5f58bc9f5e1
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.cc
@@ -0,0 +1,17 @@
+// 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_point_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<
+ viz::mojom::DelegatedInkPointDataView,
+ viz::DelegatedInkPoint>::Read(viz::mojom::DelegatedInkPointDataView data,
+ viz::DelegatedInkPoint* out) {
+ return data.ReadPoint(&out->point_) && data.ReadTimestamp(&out->timestamp_);
+}
+
+} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.h
new file mode 100644
index 00000000000..628773b2d8f
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.h
@@ -0,0 +1,32 @@
+// 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_POINT_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_POINT_MOJOM_TRAITS_H_
+
+#include "components/viz/common/delegated_ink_point.h"
+#include "mojo/public/cpp/base/time_mojom_traits.h"
+#include "services/viz/public/mojom/compositing/delegated_ink_point.mojom-shared.h"
+#include "ui/gfx/geometry/mojom/geometry_mojom_traits.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<viz::mojom::DelegatedInkPointDataView,
+ viz::DelegatedInkPoint> {
+ static const gfx::PointF& point(const viz::DelegatedInkPoint& input) {
+ return input.point();
+ }
+
+ static base::TimeTicks timestamp(const viz::DelegatedInkPoint& input) {
+ return input.timestamp();
+ }
+
+ static bool Read(viz::mojom::DelegatedInkPointDataView data,
+ viz::DelegatedInkPoint* out);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_DELEGATED_INK_POINT_MOJOM_TRAITS_H_
diff --git a/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc b/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
index 1c4605ba931..9b6ea592fb2 100644
--- a/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
+++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_perftest.cc
@@ -27,9 +27,9 @@
namespace viz {
namespace {
-static const int kTimeLimitMillis = 2000;
+static const auto kTimeLimit = base::TimeDelta::FromSeconds(2);
static const int kNumWarmupRuns = 20;
-static const int kTimeCheckInterval = 10;
+static const int kNumRunsPerTimeRecord = 10;
enum class UseSingleSharedQuadState { YES, NO };
@@ -73,14 +73,12 @@ class VizSerializationPerfTest : public testing::Test {
message.payload(), message.payload_num_bytes(), &compositor_frame);
}
- base::TimeTicks start = base::TimeTicks::Now();
- base::TimeTicks end =
- start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis);
- base::TimeTicks now = start;
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks end = now + kTimeLimit;
base::TimeDelta min_time;
size_t count = 0;
- while (start < end) {
- for (int i = 0; i < kTimeCheckInterval; ++i) {
+ for (base::TimeTicks start = now; start < end; start = now) {
+ for (int i = 0; i < kNumRunsPerTimeRecord; ++i) {
CompositorFrame compositor_frame;
mojom::CompositorFrame::Deserialize(
message.payload(), message.payload_num_bytes(), &compositor_frame);
@@ -92,14 +90,13 @@ class VizSerializationPerfTest : public testing::Test {
if (now - start < min_time || min_time.is_zero())
min_time = now - start;
- start = now;
}
auto reporter = SetUpReporter(story, single_sqs);
reporter.AddResult(kMetricStructDeserializationTimeUs,
- min_time.InMicrosecondsF() / kTimeCheckInterval);
+ min_time.InMicrosecondsF() / kNumRunsPerTimeRecord);
reporter.AddResult(kMetricStructDeserializationThroughputRunsPerS,
- count * 1000 / kTimeLimitMillis);
+ count * kTimeLimit.ToHz());
}
static void RunSerializationTestStructTraits(
@@ -111,14 +108,12 @@ class VizSerializationPerfTest : public testing::Test {
mojom::CompositorFrame::SerializeAsMessage(&frame);
}
- base::TimeTicks start = base::TimeTicks::Now();
- base::TimeTicks end =
- start + base::TimeDelta::FromMilliseconds(kTimeLimitMillis);
- base::TimeTicks now = start;
+ base::TimeTicks now = base::TimeTicks::Now();
+ base::TimeTicks end = now + kTimeLimit;
base::TimeDelta min_time;
size_t count = 0;
- while (start < end) {
- for (int i = 0; i < kTimeCheckInterval; ++i) {
+ for (base::TimeTicks start = now; start < end; start = now) {
+ for (int i = 0; i < kNumRunsPerTimeRecord; ++i) {
mojo::Message message =
mojom::CompositorFrame::SerializeAsMessage(&frame);
now = base::TimeTicks::Now();
@@ -129,14 +124,13 @@ class VizSerializationPerfTest : public testing::Test {
if (now - start < min_time || min_time.is_zero())
min_time = now - start;
- start = now;
}
auto reporter = SetUpReporter(story, single_sqs);
reporter.AddResult(kMetricStructSerializationTimeUs,
- min_time.InMicrosecondsF() / kTimeCheckInterval);
+ min_time.InMicrosecondsF() / kNumRunsPerTimeRecord);
reporter.AddResult(kMetricStructSerializationThroughputRunsPerS,
- count * 1000 / kTimeLimitMillis);
+ count / kTimeLimit.InSecondsF());
}
static void RunComplexCompositorFrameTest(const std::string& story) {
@@ -199,7 +193,7 @@ class VizSerializationPerfTest : public testing::Test {
SkScalar arbitrary_sigma = SkFloatToScalar(2.0f);
gfx::ContentColorUsage arbitrary_content_color_usage =
gfx::ContentColorUsage::kSRGB;
- int root_id = 14;
+ RenderPassId root_id{14};
cc::FilterOperations arbitrary_filters1;
arbitrary_filters1.Append(
@@ -308,7 +302,8 @@ class VizSerializationPerfTest : public testing::Test {
for (uint32_t i = 0; i < num_passes; ++i) {
std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(20, 20), gfx::Rect(), gfx::Transform());
+ render_pass->SetNew(RenderPassId{1}, gfx::Rect(20, 20), gfx::Rect(),
+ gfx::Transform());
for (uint32_t j = 0; j < num_quads; ++j) {
if (j == 0 || single_sqs == UseSingleSharedQuadState::NO)
render_pass->CreateAndAppendSharedQuadState();
diff --git a/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc b/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
index 8398354593f..867733f09a0 100644
--- a/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
+++ b/chromium/services/viz/public/cpp/compositing/mojom_traits_unittest.cc
@@ -448,7 +448,8 @@ TEST_F(StructTraitsTest, SharedQuadState) {
// RenderPass, and QuadListBasic unit tests.
TEST_F(StructTraitsTest, CompositorFrame) {
std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(5, 6), gfx::Rect(2, 3), gfx::Transform());
+ render_pass->SetNew(RenderPassId{1}, gfx::Rect(5, 6), gfx::Rect(2, 3),
+ gfx::Transform());
// SharedQuadState.
const gfx::Transform sqs_quad_to_target_transform(
@@ -589,7 +590,7 @@ TEST_F(StructTraitsTest, SurfaceInfo) {
}
TEST_F(StructTraitsTest, ReturnedResource) {
- const RenderPassId id = 1337u;
+ const unsigned id = 1337u;
const gpu::CommandBufferNamespace command_buffer_namespace = gpu::IN_PROCESS;
const gpu::CommandBufferId command_buffer_id(
gpu::CommandBufferId::FromUnsafeValue(0xdeadbeef));
@@ -698,7 +699,7 @@ TEST_F(StructTraitsTest, RenderPass) {
// The CopyOutputRequest struct traits require a TaskRunner.
base::test::TaskEnvironment task_environment;
- const RenderPassId render_pass_id = 3u;
+ const RenderPassId render_pass_id{3u};
const gfx::Rect output_rect(45, 22, 120, 13);
const gfx::Transform transform_to_root =
gfx::Transform(1.0, 0.5, 0.5, -0.5, -1.0, 0.0);
@@ -855,7 +856,7 @@ TEST_F(StructTraitsTest, RenderPass) {
}
TEST_F(StructTraitsTest, RenderPassWithEmptySharedQuadStateList) {
- const RenderPassId render_pass_id = 3u;
+ const RenderPassId render_pass_id{3u};
const gfx::Rect output_rect(45, 22, 120, 13);
const gfx::Rect damage_rect(56, 123, 19, 43);
const gfx::Transform transform_to_root =
@@ -892,7 +893,8 @@ TEST_F(StructTraitsTest, RenderPassWithEmptySharedQuadStateList) {
TEST_F(StructTraitsTest, QuadListBasic) {
std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(), gfx::Rect(), gfx::Transform());
+ render_pass->SetNew(RenderPassId{1}, gfx::Rect(), gfx::Rect(),
+ gfx::Transform());
SharedQuadState* sqs = render_pass->CreateAndAppendSharedQuadState();
@@ -926,7 +928,7 @@ TEST_F(StructTraitsTest, QuadListBasic) {
const gfx::Rect rect4(1234, 5678, 91012, 13141);
const bool needs_blending = true;
const ResourceId resource_id4(1337);
- const RenderPassId render_pass_id = 1234u;
+ const RenderPassId render_pass_id{1234u};
const gfx::RectF mask_uv_rect(0, 0, 1337.1f, 1234.2f);
const gfx::Size mask_texture_size(1234, 5678);
gfx::Vector2dF filters_scale(1234.1f, 4321.2f);
@@ -1120,7 +1122,8 @@ TEST_F(StructTraitsTest, TransferableResource) {
TEST_F(StructTraitsTest, YUVDrawQuad) {
std::unique_ptr<RenderPass> render_pass = RenderPass::Create();
- render_pass->SetNew(1, gfx::Rect(), gfx::Rect(), gfx::Transform());
+ render_pass->SetNew(RenderPassId{1}, gfx::Rect(), gfx::Rect(),
+ gfx::Transform());
const DrawQuad::Material material = DrawQuad::Material::kYuvVideoContent;
const gfx::Rect rect(1234, 4321, 1357, 7531);
diff --git a/chromium/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
index 5da0674505e..6a8155c776a 100644
--- a/chromium/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
+++ b/chromium/services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc
@@ -47,11 +47,11 @@ bool StructTraits<viz::mojom::PaintFilterDataView, sk_sp<cc::PaintFilter>>::
}
// We don't need to populate the DeserializeOptions here since the security
- // constraints explicitly disable serializing images using the transfer cache
- // and serialization of PaintRecords.
+ // constraints explicitly disable serializing images using the transfer
+ // cache/gpu::Mailbox and serialization of PaintRecords.
std::vector<uint8_t> scratch_buffer;
cc::PaintOp::DeserializeOptions options(nullptr, nullptr, nullptr,
- &scratch_buffer, false);
+ &scratch_buffer, false, nullptr);
cc::PaintOpReader reader(buffer->data(), buffer->size(), options,
true /* enable_security_constraints */);
sk_sp<cc::PaintFilter> filter;
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 c99d11f218a..a0e9a99df38 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/compositing/render_pass_id_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"
@@ -73,17 +74,17 @@ bool StructTraits<viz::mojom::RenderPassQuadStateDataView, viz::DrawQuad>::Read(
quad->resources.ids[viz::RenderPassDrawQuad::kMaskResourceIdIndex] =
data.mask_resource_id();
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) {
- 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) ||
!data.ReadFiltersOrigin(&quad->filters_origin) ||
- !data.ReadTexCoordRect(&quad->tex_coord_rect)) {
+ !data.ReadTexCoordRect(&quad->tex_coord_rect) ||
+ !data.ReadRenderPassId(&quad->render_pass_id)) {
+ return false;
+ }
+ // RenderPass ids are never zero.
+ if (!quad->render_pass_id) {
+ viz::SetDeserializationCrashKeyString("Draw quad invalid render pass ID");
return false;
}
quad->force_anti_aliasing_off = data.force_anti_aliasing_off();
@@ -157,6 +158,7 @@ bool StructTraits<viz::mojom::TextureQuadStateDataView, viz::DrawQuad>::Read(
quad->y_flipped = data.y_flipped();
quad->nearest_neighbor = data.nearest_neighbor();
quad->secure_output_only = data.secure_output_only();
+ quad->is_video_frame = data.is_video_frame();
return true;
}
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 a690016318a..fb60ffff732 100644
--- a/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/quads_mojom_traits.h
@@ -198,7 +198,7 @@ struct StructTraits<viz::mojom::DebugBorderQuadStateDataView, viz::DrawQuad> {
template <>
struct StructTraits<viz::mojom::RenderPassQuadStateDataView, viz::DrawQuad> {
- static uint64_t render_pass_id(const viz::DrawQuad& input) {
+ static viz::RenderPassId render_pass_id(const viz::DrawQuad& input) {
const viz::RenderPassDrawQuad* quad =
viz::RenderPassDrawQuad::MaterialCast(&input);
DCHECK(quad->render_pass_id);
@@ -409,6 +409,12 @@ struct StructTraits<viz::mojom::TextureQuadStateDataView, viz::DrawQuad> {
return quad->secure_output_only;
}
+ static bool is_video_frame(const viz::DrawQuad& input) {
+ const viz::TextureDrawQuad* quad =
+ viz::TextureDrawQuad::MaterialCast(&input);
+ return quad->is_video_frame;
+ }
+
static gfx::ProtectedVideoType protected_video_type(
const viz::DrawQuad& input) {
const viz::TextureDrawQuad* quad =
diff --git a/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.cc b/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.cc
new file mode 100644
index 00000000000..dd04b80256a
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.cc
@@ -0,0 +1,25 @@
+// 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/render_pass_id_mojom_traits.h"
+
+#include "components/viz/common/quads/render_pass.h"
+
+namespace mojo {
+
+// static
+uint64_t StructTraits<viz::mojom::RenderPassIdDataView,
+ viz::RenderPassId>::value(const viz::RenderPassId& id) {
+ return static_cast<uint64_t>(id);
+}
+
+// static
+bool StructTraits<viz::mojom::RenderPassIdDataView, viz::RenderPassId>::Read(
+ viz::mojom::RenderPassIdDataView data,
+ viz::RenderPassId* out) {
+ *out = viz::RenderPassId{data.value()};
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h
new file mode 100644
index 00000000000..fb875678915
--- /dev/null
+++ b/chromium/services/viz/public/cpp/compositing/render_pass_id_mojom_traits.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_VIZ_PUBLIC_CPP_COMPOSITING_RENDER_PASS_ID_MOJOM_TRAITS_H_
+#define SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RENDER_PASS_ID_MOJOM_TRAITS_H_
+
+#include "components/viz/common/quads/render_pass.h"
+#include "services/viz/public/mojom/compositing/render_pass_id.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<viz::mojom::RenderPassIdDataView, viz::RenderPassId> {
+ static uint64_t value(const viz::RenderPassId& id);
+
+ static bool Read(viz::mojom::RenderPassIdDataView data,
+ viz::RenderPassId* out);
+};
+
+} // namespace mojo
+
+#endif // SERVICES_VIZ_PUBLIC_CPP_COMPOSITING_RENDER_PASS_ID_MOJOM_TRAITS_H_
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 e704ba1005d..b56bb984209 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,8 @@
#include "services/viz/public/cpp/compositing/render_pass_mojom_traits.h"
#include "base/numerics/safe_conversions.h"
+#include "components/viz/common/quads/render_pass.h"
+#include "services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h"
#include "services/viz/public/cpp/crash_keys.h"
#include "ui/gfx/mojom/display_color_spaces_mojom_traits.h"
@@ -23,10 +25,10 @@ bool StructTraits<viz::mojom::RenderPassDataView,
!data.ReadBackdropFilters(&(*out)->backdrop_filters) ||
!data.ReadBackdropFilterBounds(&(*out)->backdrop_filter_bounds) ||
!data.ReadContentColorUsage(&(*out)->content_color_usage) ||
- !data.ReadCopyRequests(&(*out)->copy_requests)) {
+ !data.ReadCopyRequests(&(*out)->copy_requests) ||
+ !data.ReadId(&(*out)->id)) {
return false;
}
- (*out)->id = data.id();
// RenderPass ids are never zero.
if (!(*out)->id) {
viz::SetDeserializationCrashKeyString("Invalid render pass ID");
diff --git a/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h b/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
index 4153d90cf16..8301911110e 100644
--- a/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
+++ b/chromium/services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h
@@ -71,6 +71,10 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, OptSharedQuadState> {
static float de_jelly_delta_y(const OptSharedQuadState& input) {
return input.sqs->de_jelly_delta_y;
}
+
+ static bool no_damage(const OptSharedQuadState& input) {
+ return input.sqs->no_damage;
+ }
};
template <>
@@ -124,6 +128,10 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, viz::SharedQuadState> {
return sqs.de_jelly_delta_y;
}
+ static bool no_damage(const viz::SharedQuadState& sqs) {
+ return sqs.no_damage;
+ }
+
static bool Read(viz::mojom::SharedQuadStateDataView data,
viz::SharedQuadState* out) {
if (!data.ReadQuadToTargetTransform(&out->quad_to_target_transform) ||
@@ -143,6 +151,7 @@ struct StructTraits<viz::mojom::SharedQuadStateDataView, viz::SharedQuadState> {
out->sorting_context_id = data.sorting_context_id();
out->is_fast_rounded_corner = data.is_fast_rounded_corner();
out->de_jelly_delta_y = data.de_jelly_delta_y();
+ out->no_damage = data.no_damage();
return true;
}
};
diff --git a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
index 0ed0af524d7..3e02b1983c0 100644
--- a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
+++ b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
@@ -45,7 +45,7 @@
#include "services/viz/public/cpp/gpu/command_buffer_metrics.h"
#include "skia/buildflags.h"
#include "third_party/skia/include/core/SkTraceMemoryDump.h"
-#include "third_party/skia/include/gpu/GrContext.h"
+#include "third_party/skia/include/gpu/GrDirectContext.h"
#include "ui/gl/trace_util.h"
class SkDiscardableMemory;
@@ -374,7 +374,7 @@ gpu::ContextSupport* ContextProviderCommandBuffer::ContextSupport() {
return impl_;
}
-class GrContext* ContextProviderCommandBuffer::GrContext() {
+class GrDirectContext* ContextProviderCommandBuffer::GrContext() {
DCHECK(bind_tried_);
DCHECK_EQ(bind_result_, gpu::ContextResult::kSuccess);
DCHECK(support_grcontext_);
diff --git a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
index 18918b5494e..22d80baf765 100644
--- a/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
+++ b/chromium/services/viz/public/cpp/gpu/context_provider_command_buffer.h
@@ -92,7 +92,7 @@ class ContextProviderCommandBuffer
gpu::gles2::GLES2Interface* ContextGL() override;
gpu::raster::RasterInterface* RasterInterface() override;
gpu::ContextSupport* ContextSupport() override;
- class GrContext* GrContext() override;
+ class GrDirectContext* GrContext() override;
gpu::SharedImageInterface* SharedImageInterface() override;
ContextCacheController* CacheController() override;
base::Lock* GetLock() override;
diff --git a/chromium/services/viz/public/mojom/BUILD.gn b/chromium/services/viz/public/mojom/BUILD.gn
index d6d676deaba..1cec0dae39d 100644
--- a/chromium/services/viz/public/mojom/BUILD.gn
+++ b/chromium/services/viz/public/mojom/BUILD.gn
@@ -16,6 +16,7 @@ mojom("mojom") {
"compositing/copy_output_request.mojom",
"compositing/copy_output_result.mojom",
"compositing/delegated_ink_metadata.mojom",
+ "compositing/delegated_ink_point.mojom",
"compositing/filter_operation.mojom",
"compositing/filter_operations.mojom",
"compositing/frame_deadline.mojom",
@@ -26,6 +27,7 @@ mojom("mojom") {
"compositing/paint_filter.mojom",
"compositing/quads.mojom",
"compositing/render_pass.mojom",
+ "compositing/render_pass_id.mojom",
"compositing/resource_settings.mojom",
"compositing/returned_resource.mojom",
"compositing/selection.mojom",
@@ -129,6 +131,16 @@ mojom("mojom") {
"//ui/gfx/geometry/mojom",
]
},
+ {
+ types = [
+ {
+ mojom = "viz.mojom.LocalSurfaceIdAllocation"
+ cpp = "::viz::LocalSurfaceIdAllocation"
+ },
+ ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/local_surface_id_allocation_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
]
cpp_typemaps = shared_cpp_typemaps
@@ -240,6 +252,17 @@ mojom("mojom") {
{
types = [
{
+ mojom = "viz.mojom.DelegatedInkPoint"
+ cpp = "::viz::DelegatedInkPoint"
+ },
+ ]
+ traits_sources = [ "//services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.cc" ]
+ traits_headers = [ "//services/viz/public/cpp/compositing/delegated_ink_point_mojom_traits.h" ]
+ traits_public_deps = [ "//components/viz/common" ]
+ },
+ {
+ types = [
+ {
mojom = "viz.mojom.FilterOperation"
cpp = "::cc::FilterOperation"
},
@@ -309,27 +332,32 @@ mojom("mojom") {
{
types = [
{
- mojom = "viz.mojom.LocalSurfaceIdAllocation"
- cpp = "::viz::LocalSurfaceIdAllocation"
+ mojom = "viz.mojom.PaintFilter"
+ cpp = "::sk_sp<::cc::PaintFilter>"
},
]
- traits_headers = [ "//services/viz/public/cpp/compositing/local_surface_id_allocation_mojom_traits.h" ]
- traits_public_deps = [ "//components/viz/common" ]
+ traits_sources = [
+ "//services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc",
+ ]
+ traits_headers = [
+ "//services/viz/public/cpp/compositing/paint_filter_mojom_traits.h",
+ ]
+ traits_public_deps = [ "//cc/paint" ]
},
{
types = [
{
- mojom = "viz.mojom.PaintFilter"
- cpp = "::sk_sp<::cc::PaintFilter>"
+ mojom = "viz.mojom.RenderPassId"
+ cpp = "::viz::RenderPassId"
},
]
traits_sources = [
- "//services/viz/public/cpp/compositing/paint_filter_mojom_traits.cc",
+ "//services/viz/public/cpp/compositing/render_pass_id_mojom_traits.cc",
]
traits_headers = [
- "//services/viz/public/cpp/compositing/paint_filter_mojom_traits.h",
+ "//services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h",
]
- traits_public_deps = [ "//cc/paint" ]
+ traits_public_deps = [ "//components/viz/common" ]
},
{
types = [
@@ -509,6 +537,7 @@ mojom("mojom") {
"//services/viz/public/cpp/compositing/filter_operation_mojom_traits.h",
"//services/viz/public/cpp/compositing/filter_operations_mojom_traits.h",
"//services/viz/public/cpp/compositing/quads_mojom_traits.h",
+ "//services/viz/public/cpp/compositing/render_pass_id_mojom_traits.h",
"//services/viz/public/cpp/compositing/render_pass_mojom_traits.h",
"//services/viz/public/cpp/compositing/selection_mojom_traits.h",
"//services/viz/public/cpp/compositing/shared_quad_state_mojom_traits.h",
diff --git a/chromium/services/viz/public/mojom/compositing/delegated_ink_point.mojom b/chromium/services/viz/public/mojom/compositing/delegated_ink_point.mojom
new file mode 100644
index 00000000000..1335e5e9ab7
--- /dev/null
+++ b/chromium/services/viz/public/mojom/compositing/delegated_ink_point.mojom
@@ -0,0 +1,25 @@
+// 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 "ui/gfx/geometry/mojom/geometry.mojom";
+
+// See components/viz/common/delegated_ink_point.h.
+struct DelegatedInkPoint {
+ gfx.mojom.PointF point;
+ mojo_base.mojom.TimeTicks timestamp;
+};
+
+// This interface is used to connect the browser process to viz to support
+// delegated ink trails. A delegated ink point will be produced in the
+// browser process and sent to viz to be held until DrawAndSwap occurs, at
+// which point any delegated ink points that arrived may be used to draw the
+// ink trail.
+interface DelegatedInkPointRenderer {
+ // Used to send the DelegatedInkPoint that was created in the browser process
+ // to viz in order to be drawn as part of the delegated ink trail.
+ StoreDelegatedInkPoint(DelegatedInkPoint point);
+};
diff --git a/chromium/services/viz/public/mojom/compositing/quads.mojom b/chromium/services/viz/public/mojom/compositing/quads.mojom
index ba8bac8ee6b..58ec1757c9a 100644
--- a/chromium/services/viz/public/mojom/compositing/quads.mojom
+++ b/chromium/services/viz/public/mojom/compositing/quads.mojom
@@ -5,6 +5,7 @@
module viz.mojom;
import "mojo/public/mojom/base/unguessable_token.mojom";
+import "services/viz/public/mojom/compositing/render_pass_id.mojom";
import "services/viz/public/mojom/compositing/shared_quad_state.mojom";
import "services/viz/public/mojom/compositing/surface_range.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
@@ -26,7 +27,7 @@ struct DebugBorderQuadState {
};
struct RenderPassQuadState {
- uint64 render_pass_id;
+ RenderPassId render_pass_id;
// If nonzero, resource id of mask to use when drawing this pass.
uint32 mask_resource_id;
@@ -86,6 +87,7 @@ struct TextureQuadState {
bool y_flipped;
bool nearest_neighbor;
bool secure_output_only;
+ bool is_video_frame;
ProtectedVideoState protected_video_type;
};
diff --git a/chromium/services/viz/public/mojom/compositing/render_pass.mojom b/chromium/services/viz/public/mojom/compositing/render_pass.mojom
index ab38c6396ae..3590a80fd7e 100644
--- a/chromium/services/viz/public/mojom/compositing/render_pass.mojom
+++ b/chromium/services/viz/public/mojom/compositing/render_pass.mojom
@@ -7,6 +7,7 @@ module viz.mojom;
import "services/viz/public/mojom/compositing/copy_output_request.mojom";
import "services/viz/public/mojom/compositing/filter_operations.mojom";
import "services/viz/public/mojom/compositing/quads.mojom";
+import "services/viz/public/mojom/compositing/render_pass_id.mojom";
import "ui/gfx/geometry/mojom/geometry.mojom";
import "ui/gfx/mojom/display_color_spaces.mojom";
import "ui/gfx/mojom/rrect_f.mojom";
@@ -14,7 +15,7 @@ import "ui/gfx/mojom/transform.mojom";
// See components/viz/common/quads/render_pass.h.
struct RenderPass {
- uint64 id;
+ RenderPassId id;
gfx.mojom.Rect output_rect;
gfx.mojom.Rect damage_rect;
gfx.mojom.Transform transform_to_root_target;
diff --git a/chromium/services/viz/public/mojom/compositing/render_pass_id.mojom b/chromium/services/viz/public/mojom/compositing/render_pass_id.mojom
new file mode 100644
index 00000000000..b82f2034e85
--- /dev/null
+++ b/chromium/services/viz/public/mojom/compositing/render_pass_id.mojom
@@ -0,0 +1,9 @@
+// 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;
+
+struct RenderPassId {
+ uint64 value;
+};
diff --git a/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom b/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom
index 12062fb582a..214f508b306 100644
--- a/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom
+++ b/chromium/services/viz/public/mojom/compositing/shared_quad_state.mojom
@@ -43,4 +43,9 @@ struct SharedQuadState {
// The y offset by which to skew quads in this layer. For experimental
// de-jelly effect.
float de_jelly_delta_y;
+
+ // If true, indicates that the quads do not contribute damage to their
+ // render pass's damage; if false, whether or not the quads contribute
+ // damage is unknown.
+ bool no_damage;
};